您的位置:首页 > 运维架构 > Linux

linux2.4内核启动流程简述及2410主频修改

2010-08-20 12:32 363 查看
内核版本2.4.18 一、linux2.4内核启动流程 arch/arm/boot/compressed/head.s ----->调用arch/arm/boot/compressed/misc.c的decompress_kernel()
函数解压内核。---->arch/arm/kernel/head-armv.s 初始化 --->
init/main.c的asmlinkage void __init start_kernel(void) 二、修改2410linux主频 (1)代码修改

在内核启动之时切换CPU主频arch/arm/boot/compressed/head.S,代码如下(主频设为264M):
ldr r8, =0x4C000000
ldr r9, =0xffffff
str r9, [r8]

ldr r8, =0x4C000014
mov r9, #3
str r9, [r8] ldr r8, =0x4C000004
ldr r9, =0xa8021
str r9, [r8] ldr r8, =0x50000028
ldr r9, =0x23
str r9, [r8]

(2)问题及bug。若将2410的主频设为266M等其他,内核启动都会停在: Uncompressing Linux......................................................................................................................... done, booting the kernel. 网上很多人遇到的情况与此不同,很多都是启动参数配置错误导致或CPU的id与内核不匹配导致。 此因修改了2410的主频原因导致,根本原因不是2410(尾数为20)不能支持这么高的频率 也不是内存clk频率过高而导致的不稳定。而是kernel的start_kernel()函数中对timer的

初始化有bug。

./arch/arm/kernel/time.c:void __init time_init(void)

include/asm-arm/arch-s3c2410/time.h:static inline void setup_timer(void)

在第二个函数中代码修改如下:

-----------------

static inline void setup_timer(void)
{
struct timer_counts *timer_count = count_values;
unsigned long pclk; gettimeoffset = s3c2410_gettimeoffset;
set_rtc = s3c2410_set_rtc;
xtime.tv_sec = s3c2410_get_rtc_time(); /* set timer interrupt */
/*TCFG0 = (TCFG0_DZONE(0) | TCFG0_PRE1(15) | TCFG0_PRE0(0));*/ TCFG0 = (15<<8)|32; pclk = s3c2410_get_bus_clk(GET_PCLK)/1000; /*(TCFG0_DZONE(0) | TCFG0_PRE1(30) | TCFG0_PRE0(((pclk/2000000)-1)));*/ //while (timer_count != 0) { //---------------fix bug------------leaven
while(timer_count->freq != 0){
if (pclk == timer_count->freq) {
printk("DEBUG: timer count %d\n", timer_count->count);
TCNTB4 = timer_count->count;
break;
}
timer_count++;
} //if (timer_count == 0) { //------------------fix bug---------leaven
if(timer_count->freq==0){
/* Error, assume that PCLK is 50 Mhz */
TCNTB4 = 15626; /* down-counter, maximum value is 65535 (2^16) */
} TCON = (TCON_4_AUTO | TCON_4_UPDATE | COUNT_4_OFF);
timer_irq.handler = s3c2410_timer_interrupt;
setup_arm_irq(IRQ_TIMER4, &timer_irq);
TCON = (TCON_4_AUTO | COUNT_4_ON);
} -----------------

从如下代码中可以看到linux2410默认支持的主频是有限的,如要设置自己的频率需要加入新的成员至数组中:

-----------------

/*
* priod = (prescaler value + 1) * (divider value) * buffer count / PCLK = 10 ms
*
* e.g.; PCLK = 50 Mhz
* 10 ms = (15 + 1) * 2 * 15625 / (50000 * 1000)
* 15626 = 10 ms * (50000 * 1000) / 2 / (15 + 1)
*
* Other values
* 5156 = 10 ms * ( 16.5 * 1,000,000) / 2 / (15+1)
* 6250 = 10 ms * ( 20 * 1,000,000) / 2 / (15+1)
* 10312 = 10 ms * ( 33 * 1,000,000) / 2 / (15+1)
* 20625 = 10 ms * ( 66 * 1,000,000) / 2 / (15+1) //for 264M
* 21875 = 10 ms * ( 70 * 1,000,000) / 2 / (15+1)
* 23437 = 10 ms * ( 75 * 1,000,000) / 2 / (15+1)
* 25000 = 10 ms * ( 80 * 1,000,000) / 2 / (15+1)
* 28125 = 10 ms * ( 90 * 1,000,000) / 2 / (15+1)
* 31250 = 10 ms * ( 100 * 1,000,000) / 2 / (15+1)
*/
struct timer_counts count_values[] = {
{ 16500, 5156 },
{ 20000, 6250 },
{ 33000, 10312 },
{ 50000, 15626 },
{ 66000, 20625 },
{ 70000, 21875 },
{ 75000, 23437 },
{ 80000, 25000 },
{ 90000, 28125 },
{ 100000, 31250 },
{ 0, 0 } /* last entry */
}; -----------------

arch/arm/kernel/Makefile中对time.c的编译十分特别,别的都是*.o 而其为time.module
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: