龙芯软件开发(20)-- 频率和初始化实时时钟
来源:互联网 发布:终极一班3 网络点击率 编辑:程序博客网 时间:2024/06/05 07:48
前面已经介绍进入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和北桥的运行频率,以及初始化南桥的实时时钟。
- 龙芯软件开发(20)-- 频率和初始化实时时钟
- cpu时钟频率和MIPS
- 时钟频率详解和编程
- 关于时钟频率和带宽
- 龙芯软件开发(22)-- 初始化环境参数
- 龙芯软件开发(23)-- PCI设备初始化
- 龙芯软件开发(24)-- PCI设备初始化2
- 龙芯软件开发(25)-- PCI设备初始化3
- 龙芯软件开发(26)-- PCI设备初始化4
- 龙芯软件开发(27)-- 网络初始化
- 龙芯软件开发(28)-- 显示卡初始化
- 龙芯软件开发(29)-- 键盘初始化
- 时钟频率
- u-boot 初始化时钟频率
- STM32时钟设置和运行频率
- CMOS 内存和实时时钟
- CMOS 内存和实时时钟
- 实时时钟、系统时钟和CPU时钟的区别
- vsftp:500 OOPS: could not bind listening IPv4 socket 解决办法
- 初学Apache V2.2+PHP5服务器的若干心得
- Missing Swing Widgets
- 《算法导论》 上的计数排序
- 关于网络投票
- 龙芯软件开发(20)-- 频率和初始化实时时钟
- 了解ASP.NET底层架构
- CaliberRM 2005 R2 SP1升级一波三折(后记)
- 可拍照手机趋势探析,图像传感与处理是否集成?
- Asp.NET(vb.net)常用函数
- 用指向基类对象的指针输出数据
- 嵌入式系统开发要素的选择分析
- 博客开张了
- Stooge-sort排序