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
函数解压内核。---->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
相关文章推荐
- linux2.6内核启动流程简述
- Linux内核启动流程
- linux命令:chroot ldd init系统启动流程,修改启动背景图
- linux、内核源码、内核编译与配置、内核模块开发、内核启动流程
- ARM Linux启动流程分析——内核自解压阶段
- Linux0.11的内核引导启动流程
- arm linux 启动流程之 进入内核
- 国嵌视频学习---linux内核启动流程
- 内核启动流程分析(基于韦东山视频修改)
- Linux 用户、目录的作用以、启动流程以及内核服务管理
- ARM-Linux内核移植之(一)——内核启动流程分析
- Linux2.6.38内核启动流程分析
- linux内核启动流程
- 全面解析Linux 内核 3.10.x - initramfs 启动流程
- linux启动流程分析-内核解压缩过程
- 嵌入式Linux启动流程之启动内核(基于Arm)
- Linux-Linux 内核启动流程
- ARM-Linux——内核启动流程分析
- Arm linux 内核启动流程
- IMX6Solo启动流程-Linux 内核启动 二