uboot2013或新版uboot启动内核失败问题的解决

来源:互联网 发布:林立雯的淘宝店 编辑:程序博客网 时间:2024/05/29 13:36

uboot2013或新版uboot启动内核失败问题的解决

uboot201310版本的移植,最后启动内核时会失败,start kernel…之后就没有了,查过一些资料,都没有解决问题,后来问题搁置,看完了内核移植的视频之后,对内核代码有了一些了解,再回头看这个问题,uboot的代码在执行kernel_entry(0, machid, r2);之后,就进入内核代码了。

内核代码刚开始是一段解压代码,从解压代码入手一步步跟踪代码,最终确定了问题点是在decompress_kernel函数(arch/arm/boot/compressed/misc.c)的打印代码putstr(“Uncompressing Linux…”)。我们一直想看到的打印信息,本身就有问题,屏蔽掉这两行打印代码之后,编译出的内核顺利启动。

为什么打印信息会有问题呢?代码跟下去,发现问题出在了putc函数(arch/arm/plat-samsung/include/plat/uncompress.h),

static void putc(int ch){    if (uart_rd(S3C2410_UFCON) & S3C2410_UFCON_FIFOMODE)     {        int level;        while (1)        {            level = uart_rd(S3C2410_UFSTAT);            level &= fifo_mask;            if (level < fifo_max)                break;        }    }     else     {        /* not using fifos */        while ((uart_rd(S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE) != S3C2410_UTRSTAT_TXE)            barrier();    }    /* write byte to transmission register */    uart_wr(S3C2410_UTXH, ch);}

九鼎uboot启动内核走的是else语句之后的代码,也就是不用fifo模式,而uboot2101310读出的UFCON寄存器的值居然是0x1,也就是用了fifo模式,而fifo_mask和fifo_max都是没有赋初值的全局变量,值为0,if (level < fifo_max)不成立,所以在while循环中出不去,代码也就死在这里了。

uboot201310的串口居然是fifo模式,自己明明配的是not using fifos啊。回看uboot201310的代码,我们在lowevel_init.S中添加了串口初始化的代码,且UFCON寄存器配置成了0,现在变成了1,肯定有我们没有注意到的地方,回想可能出问题的地方,应该是init_sequence这个函数指针数组了,里面有很多的硬件初始化代码,其中有serial_init函数,跟下去

serial_init:drivers/serial/serial.c
get_current:drivers/serial/serial.c
default_serial_console:drivers/serial/serial_s5p.c
.start = s5p_serial2_init:
serial_init_dev:drivers/serial/serial_s5p.c
串口初始化函数为:

int serial_init_dev(const int dev_index){    struct s5p_uart *const uart = s5p_get_base_uart(dev_index);    /* enable FIFOs */    writel(1, &uart->ufcon);    writel(0, &uart->umcon);    /* 8N1 */    writel(0x3, &uart->ulcon);    /* No interrupts, no DMA, pure polling */    writel(0x245, &uart->ucon);    serial_setbrg_dev(dev_index);    return 0;}

至此,找到了问题的根源,串口在这里被使能了FIFOS,导致了启动内核时的卡死,我在试着将ufcon配成0时,编译烧录执行后,串口输出会乱码,对照之前的初始化代码再把ucon寄存器设置为0x3c5或者0x5,还是会乱码,不知道为什么,也不想追下去了,解决办法就是在cleanup_before_linux()函数执行之前加一个自己写的dis_uart_fifo()函数,将ufcon配成0,配成0之前要delay一段时间,否则最后的输出可能会乱码。

编译烧录执行,完美启动内核,且uboot201310自带bootz命令,用于启动zImage。

经验:在没有成功打印出调试代码之前,可靠的调试手段是点灯。

2 0