龙芯软件开发(20)-- 频率和初始化实时时钟

 
前面已经介绍进入 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 和北桥的运行频率,以及初始化南桥的实时时钟。
 

你可能感兴趣的:(软件开发)