移植Linux-3.4.2过程学习笔记1——串口打印乱码问题

本文跟随着韦东山老师的毕业班移植内核视频进行学习。
首先

tar -xjf linux-3.4.2.tar.bz2
cd linux-3.4.2

修改顶层Makefile:

ARCH            ?= arm
CROSS_COMPILE   ?= arm-linux-

选择类似的开发板配置文件进行配置:

make s3c2410_defconfig
make uImage

将编译好的uImage烧到开发板中,启动发现乱码,说明串口已经有输出,根据https://blog.csdn.net/weixin_41354745/article/details/82381790文章中linux的启启动流程分析,先考虑机器id是否能够匹配,查看uboot传入的机器id:
在cmd_bootm.c中,

U_BOOT_CMD(
    bootm,  CONFIG_SYS_MAXARGS, 1,  do_bootm,
);

查看do_bootm函数:

boot_fn = boot_os[images.os.os];

boot_os是一个指针数组,由于宏CONFIG_BOOTM_LINUX被定义,我们执行的是do_bootm_linux:

static boot_os_fn *boot_os[] = {
#ifdef CONFIG_BOOTM_LINUX
    [IH_OS_LINUX] = do_bootm_linux,
#endif
#ifdef CONFIG_BOOTM_NETBSD
    [IH_OS_NETBSD] = do_bootm_netbsd,
#endif
#ifdef CONFIG_LYNXKDI
    [IH_OS_LYNXOS] = do_bootm_lynxkdi,
#endif
#ifdef CONFIG_BOOTM_RTEMS
    [IH_OS_RTEMS] = do_bootm_rtems,
#endif
#if defined(CONFIG_BOOTM_OSE)
    [IH_OS_OSE] = do_bootm_ose,
#endif
#if defined(CONFIG_CMD_ELF)
    [IH_OS_VXWORKS] = do_bootm_vxworks,
    [IH_OS_QNX] = do_bootm_qnxelf,
#endif
#ifdef CONFIG_INTEGRITY
    [IH_OS_INTEGRITY] = do_bootm_integrity,
#endif
};
int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
{
    ......
    boot_jump_linux(images);
    return 0;
}
/* 在boot_jump_linux函数中 */
static void boot_jump_linux(bootm_headers_t *images)
{
    unsigned long machid = gd->bd->bi_arch_number;
    ......
    s = getenv("machid");
    ......
    r2 = gd->bd->bi_boot_params;
    kernel_entry(0, machid, r2);
}

从上面代码看到machid可以从环境变量获得,也可以自己设置,搜索bi_arch_number,发现在board/samsung/smdk2440/smdk2410.c(当初移植uboot的时候,没有改文件名)中有定义机器id:

int board_init(void)
{
    /* arch number of SMDK2410-Board */
    gd->bd->bi_arch_number = MACH_TYPE_S3C2440;   /* id = 362 */

    /* adress of boot parameters */
    gd->bd->bi_boot_params = 0x30000100;
    ......
    return 0;
}

假定是由于机器id造成的乱码,尝试将机器id修改为MINI2440的7CF:

set machid 7CF
save 
nfs 32000000 192.168.1.16:/work/nfs_root/uImage_new
bootm 32000000

启动,还是出现乱码,说明乱码问题跟机器id无关(因为内核已完全支持MINI2440),考虑原因是在启动参数中没有设置串口波特率,因此在uboot阶段设置参数:

set bootargs console=ttySAC0,115200......
save

注意,此时的machid是mini2440的,乱码问题解决。但视频中未重新将machid设置为SMDK2440的,无法确定smdk2440是不是也是由于启动参数造成的(由于开发板不在身边,此问题会留到后期实验,但正常情况下应该也会是乱码)。


Question:
这里对uboot的启动参数有一个疑问,也是学习过程中没有掌握的知识点,启动参数中设置波特率,与后面要改的晶振时钟两者之间的联系。如果启动参数中没有设置115200,只是对晶振的初始值修改为12MHz,能否解决乱码问题?
Answer:
需要拿开发板进行试验。


查看函数mach-smdk2440.c中的代码:

MACHINE_START(S3C2440, "SMDK2440")
    /* Maintainer: Ben Dooks  */
    .atag_offset    = 0x100,

    .init_irq   = s3c24xx_init_irq,
    .map_io     = smdk2440_map_io,
    .init_machine   = smdk2440_machine_init,
    .timer      = &s3c24xx_timer,
    .restart    = s3c244x_restart,
MACHINE_END

发现在smdk2440_map_io函数中:

static void __init smdk2440_map_io(void)
{
    ......
    s3c24xx_init_clocks(16934400);  /* 这是晶振时钟 */
    ......
}
void __init s3c24xx_init_clocks(int xtal)
{
    if (xtal == 0)
        xtal = 12*1000*1000;    /* 12MHz */

    if (cpu == NULL)
        panic("s3c24xx_init_clocks: no cpu setup?\n");

    if (cpu->init_clocks == NULL)
        panic("s3c24xx_init_clocks: cpu has no clock init\n");
    else
        (cpu->init_clocks)(xtal);
}

由于电路用的是12M的晶振,所以将该函数参数进行修改,把入口参数修改为0即可,重新配置、编译内核,使用新的uImage,乱码问题解决。

make s3c2410_defconfig
make uImage

你可能感兴趣的:(Linux内核学习笔记)