前面已经介绍进入C语言世界,就会实现更多的功能,支持更多的应用。现在就来仔细地分析源程序,并且理解各部份功能实现。
首先来看看下面的函数:
/*
* Returns the external clock frequency, usually the bus clock
*/
int
tgt_cpufreq()
{
if(md_cpufreq == 0) {
_probe_frequencies();
}
return(md_cpufreq);
}
这个函数实现检测CPU运行的频率和总线的频率。这里又调用函数_probe_frequencies()来探测CPU和总线的频率,再跟踪到那个函数的实现。如下:
static void
_probe_frequencies()
{
下面定义使用的临时变量。
#ifdef HAVE_TOD
int i, timeout, cur, sec, cnt;
#endif
SBD_DISPLAY ("FREQ", CHKPNT_FREQ);
#if 0
md_pipefreq = 300000000; /* Defaults */
md_cpufreq = 66000000;
#else
md_pipefreq = 120000000; /* NB FPGA*/
md_cpufreq = 40000000;
上面定义缺省的北桥运行频率和CPU运行的频率。
#endif
clk_invalid = 1;
下面开始探测CPU和北桥的频率。
#ifdef HAVE_TOD
init_legacy_rtc();
上面初始化RTC,就是CMOS时钟,掉电后时钟也会继续运行的。
SBD_DISPLAY ("FREI", CHKPNT_FREQ);
/*
* Do the next twice for two reasons. First make sure we run from
* cache. Second make sure synched on second update. (Pun intended!)
*/
for(i = 2; i != 0; i--) {
cnt = CPU_GetCOUNT();
timeout = 10000000;
while(CMOS_READ(DS_REG_CTLA) & DS_CTLA_UIP);
sec = CMOS_READ(DS_REG_SEC);
do {
timeout--;
while(CMOS_READ(DS_REG_CTLA) & DS_CTLA_UIP);
cur = CMOS_READ(DS_REG_SEC);
} while(timeout != 0 && cur == sec);
cnt = CPU_GetCOUNT() - cnt;
if(timeout == 0) {
break; /* Get out if clock is not running */
}
}
上面代码第一次运行,把有所有指令都加载到缓存,第二次运行时,通过读取CP0的计数器值在1分钟内存的差值来计算北桥的频率。
/*
* Calculate the external bus clock frequency.
*/
if (timeout != 0) {
clk_invalid = 0;
md_pipefreq = cnt / 10000;
md_pipefreq *= 20000;
/* we have no simple way to read multiplier value
*/
md_cpufreq = 66000000;
}
上面代码就是计算出来北桥频率和CPU频率。
#endif /* HAVE_TOD */
}
到这里就已经把北桥和CPU运行频率计算出来了。在这个函数里还初始化了南桥芯片上的RTC时钟,调用函数init_legacy_rtc()实现的。
static void init_legacy_rtc(void)
{
int year, month, date, hour, min, sec;
CMOS_WRITE(DS_CTLA_DV1, DS_REG_CTLA);
CMOS_WRITE(DS_CTLB_24 | DS_CTLB_DM | DS_CTLB_SET, DS_REG_CTLB);
CMOS_WRITE(0, DS_REG_CTLC);
CMOS_WRITE(0, DS_REG_CTLD);
year = CMOS_READ(DS_REG_YEAR);
month = CMOS_READ(DS_REG_MONTH);
date = CMOS_READ(DS_REG_DATE);
hour = CMOS_READ(DS_REG_HOUR);
min = CMOS_READ(DS_REG_MIN);
sec = CMOS_READ(DS_REG_SEC);
if( (year > 99) || (month < 1 || month > 12) ||
(date < 1 || date > 31) || (hour > 23) || (min > 59) ||
(sec > 59) ){
/*
printf("RTC time invalid, reset to epoch.\n");*/
CMOS_WRITE(3, DS_REG_YEAR);
CMOS_WRITE(1, DS_REG_MONTH);
CMOS_WRITE(1, DS_REG_DATE);
CMOS_WRITE(0, DS_REG_HOUR);
CMOS_WRITE(0, DS_REG_MIN);
CMOS_WRITE(0, DS_REG_SEC);
}
CMOS_WRITE(DS_CTLB_24 | DS_CTLB_DM, DS_REG_CTLB);
//printf("RTC: %02d-%02d-%02d %02d:%02d:%02d\n",
// year, month, date, hour, min, sec);
}
上面初始化时间来24小时、二进制的方式返回时钟数据。后面的系统,就可以读取这里的时间作为系统时间了。
上面分析了怎么样探测CPU和北桥的运行频率,以及初始化南桥的实时时钟。
查看本文来源