这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » 内核无法解压的问题

共4条 1/1 1 跳转至

内核无法解压的问题

工程师
2008-03-18 12:13:17     打赏

每次碰上问题,都要花上很长时间去寻找答案。从上周五开始到今天,除去周末两天回家,我一直被一个blamed bug困扰。其实这个问题不能叫做bug,只是因为碰到的bug太多叫习惯了,应该称之为a mistake更贴切些。

调试了两天依然没个结果,昨天憋不住了,只好向各大论坛还有QQ群求助,却许久无人应答,无果。心不甘,于是继续奋斗ing。

具体症状如我在论坛中所述:
bootloader已经能正常工作,但是当加载内核映像时就没反应了。
连“Uncompressing Linux...”都没有出现。
一些设置:
内核2.6.14
make的是zImage
ZTEXTADDR 0x00010000
ZREALADDR 0x0C008000
ZBSSADDR 0x0C400000
把decompress_kernel改为putstr("test");后仍然不能打印出字符。
不知问题出在哪里?或者给个思路?

在这之前已经查阅了许多文章,知道了可能的原因(找不到原文出处):

在 boot loader 程序的设计与实现中,没有什么能够比从串口终端正确地收到打印信息能更令人激动了。此外,向串口终端打印信息也是一个非常重要而又有效的调试手段。但是,我们经常会碰到串口终端显示乱码或根本没有显示的问题。造成这个问题主要有两种原因:(1) boot loader 对串口的初始化设置不正确。(2) 运行在 host 端的终端仿真程序对串口的设置不正确,这包括:波特率、奇偶校验、数据位和停止位等方面的设置。

此外,有时也会碰到这样的问题,那就是:在 boot loader 的运行过程中我们可以正确地向串口终端输出信息,但当 boot loader 启动内核后却无法看到内核的启动输出信息。对这一问题的原因可以从以下几个方面来考虑:

(1) 首先请确认你的内核在编译时配置了对串口终端的支持,并配置了正确的串口驱动程序。

(2) 你的 boot loader 对串口的初始化设置可能会和内核对串口的初始化设置不一致。此外,对于诸如 s3c44b0x 这样的 CPU,CPU 时钟频率的设置也会影响串口,因此如果 boot loader 和内核对其 CPU 时钟频率的设置不一致,也会使串口终端无法正确显示信息。

(3) 最后,还要确认 boot loader 所用的内核基地址必须和内核映像在编译时所用的运行基地址一致,尤其是对于 uClinux 而言。假设你的内核映像在编译时用的基地址是 0xc0008000,但你的 boot loader 却将它加载到 0xc0010000 处去执行,那么内核映像当然不能正确地执行了。 在bootloader的运行过程中已经可以正确地向串口终端输出信息,但是我的情况并不是其中所述的任何一种:
(1) 内核配置时已经设置了CONFIG_SERIAL_S3C44B0X和CONFIG_SERIAL_S3C44B0X_CONSOLE,即内核已支持串口端。
(2) 因为bootloader中已经能正常使用串口,所以内核中就没有再对串口进行初始化设置,因此不存在设置不一致的问题。而CPU的时钟频率我统一设置为60MHz。
(3) 内核尚未解压,因此该问题不用考虑。

 

冥思苦想……仍找不出症结所在。

把bootloader中的打印函数移到内核中,命名为test_serial,并设置head.S中start的第一句为bl test_serial,但是仍然没有字符出现。
接着分析了bootloader中串口的写入地址:

if(data=='\n')
	{
	    while(!(rUTRSTAT0 & 0x2));
	    Delay(10);	//because the slow response of hyper_terminal 
	    WrUTXH0('\r');
	}
	while(!(rUTRSTAT0 & 0x2)); //Wait until THR is empty.
	Delay(5);
	WrUTXH0(data);
其中WrUTXH0宏定义为:
#define WrUTXH0(ch)	(*(volatile unsigned char *)(0x1d00023))=(unsigned char)(ch)
即写入地址为0x01d00023。
而在内核中写入的地址:
文件linux-2.6.x/include/asm/arch/uncompress.c:
12 static int s3c44b0x_putc(char c)
     13 {
     14         while (!(SYSREG_GET(S3C44B0X_UTRSTAT0) & 0x2));
     15         SYSREG_SETB(S3C44B0X_UTXH0, c);
     16         if(c == '\n')
     17                 s3c44b0x_putc('\r');
     18 }
S3C44B0X_UTXH0在文件linux-2.6.x/include/asm/arch/s3c44b0x.h中定义:
287 #ifdef CONFIG_CPU_BIG_ENDIAN
    288 #define S3C44B0X_UTXH0                  0x01d00023
    289 #define S3C44B0X_URXH0                  0x01d00027
    290 #else
    291 #define S3C44B0X_UTXH0                  0x01d00020
    292 #define S3C44B0X_URXH0                  0x01d00024
    293 #endif
没找到CONFIG_CPU_BIG_ENDIAN,应该是LITTLE ENDIAN,发现地址和bootloader中不一样:0x01d00020。
这就是问题所在吗?
好吧,那咱就把地址改为0x01d00023再瞧瞧:
287 #ifdef CONFIG_CPU_BIG_ENDIAN
    288 #define S3C44B0X_UTXH0                  0x01d00023
    289 #define S3C44B0X_URXH0                  0x01d00027
    290 #else
    291 #define S3C44B0X_UTXH0                  0x01d00023
    292 #define S3C44B0X_URXH0                  0x01d00027
    293 #endif
可惜还是没有任何反应,顿时傻掉……

 

将要放弃前试了最后一招,对比了2.4.x中的串口写入函数:

15 static int s3c44b0_putc(char c)
     16 {
     17         CSR_WRITE(DEBUG_TX_BUFF_BASE, c);
     18         while(!(CSR_READ(DEBUG_CHK_STAT_BASE) & DEBUG_TX_DONE_CHECK_BIT));
     19
     20         if(c == '\n')
     21                 s3c44b0_putc('\r');
     22 }
DEBUG_TX_BUFF_BASE在linux-2.4.x/include/asm/arch/hardware.h中定义:
#define DEBUG_TX_BUFF_BASE	(Base_Addr+0x104020)	
	#define DEBUG_RX_BUFF_BASE	(Base_Addr+0x104024)
	#define DEBUG_UARTLCON_BASE	(Base_Addr+0x104000)
	#define DEBUG_UARTCONT_BASE	(Base_Addr+0x104004)
	#define DEBUG_UARTBRD_BASE	(Base_Addr+0x104028)
	#define DEBUG_CHK_STAT_BASE	(Base_Addr+0x104010)
其中Base_Addr为(0x1c00000),故DEBUG_TX_BUFF_BASE值为0x01d04020。发现它和2.6.x中的地址一致,于是把linux-2.6.x/include/asm/arch/uncompress.c中串口写入函数改为:
12 static int s3c44b0x_putc(char c)
     13 {
     14         while (!(SYSREG_GET(S3C44B0X_UTRSTAT1) & 0x2));
     15         SYSREG_SETB(S3C44B0X_UTXH1, c);
     16         if(c == '\n')
     17                 s3c44b0x_putc('\r');
     18 }

 

make后终于看到那行激动人心的字符:

Uncompressing Linux............................. done, booting the kernel.
虽然没有成功启动内核,但总算是跳过了这一坎,往前进了一步。
庆幸自己没有放弃……

来源:http://blog.iyi.cn/hily/archives/2006/09/post_13.html



关键词: 内核     无法     解压     问题     设置     串口     S3C44B0    

助工
2008-03-18 23:13:45     打赏
2楼

到这个时候问题肯定出现在console_init前,建议1、make menuconfig 在kernel hacking中确定debug的输出口是否是串口0;2、在start_kernel前用汇编的打印函数调试;3、在start_kernel后到console_init任然用汇编中提供的打印函数调试。


助工
2008-03-19 09:30:23     打赏
3楼
好久没配置2.6内核了,以现在配置2.4内核的经验看来,启动信息出不来的原因应该是串口驱动的问题。

菜鸟
2010-04-15 09:35:51     打赏
4楼
请问后来有解决嘛?怎解决的阿?
我也碰到一样情况...

共4条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]