美文网首页BB-black开发板[Linux arm-v8]
TQ2440改成设备树启动kernel5.4成功--Apple的

TQ2440改成设备树启动kernel5.4成功--Apple的

作者: applecai | 来源:发表于2021-01-06 20:18 被阅读0次

    一,前言,

    uboot已经移植成功了,接着就是要用kernel 5.4,而且要用设备树。一开始网上看了下,评估下难度,看上去不难。然后我就开始了menuconfig参考smkd2410_defconfig,然后设备树都是基于smdk2410-s3c2416.dts修改。

    二,问题记录

    1. uboot需要支持设备树。
      参考网上教程在include/configs/smdk2440.h文件添加:
      #define CONFIG_OF_LIBFDT make之后发现:
      image-fdt.c:194: undefined reference to `set_working_fdt_addr’
      发现set_working_fdt_addr是在fdt.c文件里,检查发现是没有被编译,查看Makefile可知需要添加配置:
      make menuconfig
      选上:Library routines --->[ ] Enable the FDT library。同时把smdk2440.h中的#define CONFIG_OF_LIBFDT删除。否则警告重复定义。
      2.start kernel后就没了
    Starting kernel ...
    Error: unrecognized/unsupported device tree compatible list:
    [ 'samsung,s3c2416' 'SMDK2440' ]
    
    Available machine support:
    
    ID (hex)        NAME
    000000c1        SMDK2410
    00000695        SMDK2416
    000007cf        MINI2440
    0000016a        SMDK2440
    

    找到源码,添加early_print支持。然后在源码中添加调试信息early_print("match=%s\n",*match);

    static const void * __init arch_get_next_mach(const char *const **match)
    {
        static const struct machine_desc *mdesc = __arch_info_begin;
        const struct machine_desc *m = mdesc;
    
        if (m >= __arch_info_end)
            return NULL;
    
        mdesc++;
        *match = m->dt_compat;
        early_print("match=%s\n",*match);
        return m;
    }
    

    可以看出dtb识别大端是正确的,前4个字节为d0 0d fe ed,但是match都是null。

    Starting kernel ...
    
    Uncompressing Linux... done, booting the kernel.
      r1=0x000000a8, r2=0x33b14000
      r2[]=d0 0d fe ed 00 00 20 00 00 00 00 48 00 00 15 dc
    1
    match=(null)
    match=(null)
    match=(null)
    match=(null)
    
    Error: unrecognized/unsupported device tree compatible list:
    [ 'samsung,s3c2416' 'SMDK2440' ]
    
    Available machine support:
    
    ID (hex)        NAME
    000000c1        SMDK2410
    00000695        SMDK2416
    000007cf        MINI2440
    0000016a        SMDK2440
    

    c文件的.dt_compat数组内容为空?想起来了,搜索下dtb中的root为samsung,s3c2416。对应的c文件名称为mach-s3c2416-dt.o,需要配置CONFIG_MACH_S3C2416_DT,但是我没配置导致的。配置完后,dt_compat能匹配到设备树中的samsung,s3c2416。

    ## Transferring control to Linux (at address 30008000)...
    
    Starting kernel ...
    
    Uncompressing Linux... done, booting the kernel.
      r1=0x000000a8, r2=0x33b14000
      r2[]=d0 0d fe ed 00 00 20 00 00 00 00 48 00 00 15 d0
    1
    name=Samsung S3C2416 (Flattened Device Tree) Machine model: SMDK2416
    setup_arch done
    
    Uncompressing Linux... done, booting the kernel.
      r1=0x000000a8, r2=0x33b14000
      r2[]=d0 0d fe ed 00 00 20 00 00 00 00 48 00 00 15 d0
    1
    name=Samsung S3C2416 (Flattened Device Tree) match=pXd
    
    1. 解决了dtb设备问题,但是串口无输出
      由于early_print函数是可以使用的,我就看看卡在哪里,通过main.c的start_kernel函数中慢慢添加,最后添加到do_initialcall函数来打印指针。
    do_initcall_level1 fn=0xc070c9bc
    do_initcall_level2
    do_initcall_level1 fn=0xc070c9c0
    do_initcall_level2
    do_initcall_level1 fn=0xc070c9c4
    ǤbǤbǤbǤbǤbǤbǤbǤbǤFfŤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤbǤEffbǤbǤbǤb
    

    arch_call_rest_init();没有运行完,通过在map文件查看c070c9c4地址对应的函数,确认了串口初始化samsung_serial_driver函数的问题。

    c070c9bc t __initcall_sysrq_init6
    c070c9c0 t __initcall_serial8250_init6
    c070c9c4 t __initcall_samsung_serial_driver_init6
    

    然后通过调试发现,运行如下几句后,先打印乱码,然后没了。上面的注释显示通过此次先注释串口clk,然后在pm-callback函数打开。通过先注释如下3行,probe函数能结束,但是do_basic_setup没有走完。但是do_basic_setup看上去没有走完。
    //clk_disable_unprepare(ourport->clk);
    //if (!IS_ERR(ourport->baudclk))
    // clk_disable_unprepare(ourport->baudclk);
    修改后输出如下,至少early_print能正常输出。

    setup_arch done
    kernel_init
    do_basic_setup1
    do_basic_setup2
    s3c24xx_serial_probe
    s3c24xx_serial_probe((ptrval)) 0
    s3c24xx_serial_probe: initialising port (ptrval)...
    s3c24xx_serial_probe: adding port
    uart_add_one_port done
    done
    

    通过initialcall前后添加的打印函数。发现运行此句后停止c070cb20 t __initcall_clk_disable_unused7s
    do_initcall_level1 fn=0xc070cb1c
    do_initcall_level2
    do_initcall_level1 fn=0xc070cb20
    然后在clk_disable_unused函数中添加clk_ignore_unused = true;这样driver/clk/clk.c就不会禁止相关clock。
    但是我突然想到do_initiallcall还没有调用的时候,其实应该kernel就有输出的。但是为什么也没有呢?dts我也改过,应该是对的,突然想到是boot参数里面定义了tty1(LCD)显示还是串口显示。所以去检查pri输出发现bootargs为空bootcmd为bootargs的内容。原因我之前先设置为none,重新设置bootargs传入参数console=ttySAC0是必须要有的,就可以解决此问题然后刚刚串口初始化中probe的3行注释还原,clk_ignore_unused = true还是要加的。就成功了哦!

    1. clock配置不对导致的问题
    sched_clock: 16 bits at 0 Hz, resolution 0ns, wraps every 0ns
    Division by zero in kernel.
    CPU: 0 PID: 0 Comm: swapper Tainted: G        W         5.4.61 #41
    Hardware name: Samsung S3C2416 (Flattened Device Tree)
    Backtrace: 
    [<c00198b8>] (dump_backtrace) from [<c0019b2c>] (show_stack+0x18/0x1c)
     r6:00000000 r5:0000ffff r4:00000000
    [<c0019b14>] (show_stack) from [<c057a4e4>] (dump_stack+0x20/0x28)
    [<c057a4c4>] (dump_stack) from [<c0019a14>] (__div0+0x18/0x20)
    [<c00199fc>] (__div0) from [<c0577fdc>] (Ldiv0_64+0x8/0x18)
    [<c006f404>] (__clocksource_update_freq_scale) from [<c006f648>] (__clocksource_register_scale+0x18/0xc4)
     r10:00000000 r9:00000002 r8:00000019 r7:00000000 r6:f6300040 r5:c0736934
     r4:c0725584
    [<c006f630>] (__clocksource_register_scale) from [<c06f32d0>] (_samsung_pwm_clocksource_init+0x2fc/0x320)
     r5:c0736880 r4:c076cfa8
    [<c06f2fd4>] (_samsung_pwm_clocksource_init) from [<c06f3424>] (samsung_pwm_alloc+0x130/0x16c)
     r9:00000001 r8:c05d541c r7:c0686390 r6:c0711008 r5:c3f78668 r4:c076cfa8
    [<c06f32f4>] (samsung_pwm_alloc) from [<c06f3474>] (s3c2410_pwm_clocksource_init+0x14/0x1c)
     r10:c0701a30 r9:00000001 r8:c06862ec r7:c070bb50 r6:c0711008 r5:00000000
     r4:c3f78668
    [<c06f3460>] (s3c2410_pwm_clocksource_init) from [<c06f2f60>] (timer_probe+0x6c/0xe0)
    [<c06f2ef4>] (timer_probe) from [<c06dd5fc>] (time_init+0x34/0x3c)
     r8:00000000 r7:c0743000 r6:c0711000 r5:c0711008 r4:c0701a30
    [<c06dd5c8>] (time_init) from [<c06d9c90>] (start_kernel+0x294/0x44c)
    [<c06d99fc>] (start_kernel) from [<00000000>] (0x0)
     r10:c0007177 r9:41129200 r8:33b14000 r7:000000a8 r6:00003135 r5:00000053
     r4:c06d9330
    clocksource: samsung_clocksource_timer: mask: 0xffff max_cycles: 0x0, max_idle_ns: 0 ns
    Console: colour dummy device 80x30
    Calibrating delay loop... 1305.80 BogoMIPS (lpj=6529024)
    pid_max: default: 32768 minimum: 301
    Mount-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
    Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
    CPU: Testing write buffer coherency: ok
    Setting up static identity map for 0x30008400 - 0x3000847c
    clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
    futex hash table entries: 256 (order: -1, 3072 bytes, linear)
    pinctrl core: initialized pinctrl subsystem
    NET: Registered protocol family 16
    DMA: preallocated 256 KiB pool for atomic coherent allocations
    s3c2416_dt_machine_init
    S3C Power Management, Copyright 2004 Simtec Electronics
    S3C2440: Initialising architecture
    SCSI subsystem initialized
    usbcore: registered new interface driver usbfs
    usbcore: registered new interface driver hub
    usbcore: registered new device driver usb
    Advanced Linux Sound Architecture Driver Initialized.
    Division by zero in kernel.
    CPU: 0 PID: 1 Comm: swapper Tainted: G        W         5.4.61 #41
    Hardware name: Samsung S3C2416 (Flattened Device Tree)
    Backtrace: 
    [<c00198b8>] (dump_backtrace) from [<c0019b2c>] (show_stack+0x18/0x1c)
     r6:00989680 r5:c0757c80 r4:00000000
    [<c0019b14>] (show_stack) from [<c057a4e4>] (dump_stack+0x20/0x28)
    [<c057a4c4>] (dump_stack) from [<c0019a14>] (__div0+0x18/0x20)
    [<c00199fc>] (__div0) from [<c0577fdc>] (Ldiv0_64+0x8/0x18)
    [<c006bbf8>] (tk_setup_internals.constprop.6) from [<c006d384>] (timekeeping_notify+0x84/0xec)
     r10:00000000 r9:c07257c8 r8:c07257c8 r7:800000d3 r6:80000053 r5:c0736934
     r4:c0757c80
    [<c006d300>] (timekeeping_notify) from [<c006f104>] (__clocksource_select+0xa0/0x118)
     r8:c0736934 r7:00000000 r6:c0757f30 r5:c0725778 r4:c0736934
    [<c006f064>] (__clocksource_select) from [<c06e3850>] (clocksource_done_booting+0x34/0x4c)
     r10:00000000 r9:c0743000 r8:ffffe000 r7:00000000 r6:c06e381c r5:c0711008
     r4:c0725768
    [<c06e381c>] (clocksource_done_booting) from [<c000a664>] (do_one_initcall+0x7c/0x1f4)
     r4:c0743000
    [<c000a5e8>] (do_one_initcall) from [<c06d9f54>] (kernel_init_freeable+0x10c/0x1c0)
     r8:c070182c r7:c0743000 r6:c070184c r5:000000b2 r4:c070c818
    [<c06d9e48>] (kernel_init_freeable) from [<c05927c4>] (kernel_init+0x10/0xec)
     r10:00000000 r9:00000000 r8:00000000 r7:00000000 r6:00000000 r5:c05927b4
     r4:00000000
    [<c05927b4>] (kernel_init) from [<c00090e0>] (ret_from_fork+0x14/0x34)
    Exception stack(0xc3421fb0 to 0xc3421ff8)
    1fa0:                                     00000000 00000000 00000000 00000000
    1fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
    1fe0: 00000000 00000000 00000000 00000000 00000013 00000000
     r4:00000000
    clocksource: Switched to clocksource samsung_clocksource_timer
    

    虽然可以继续运行,但是打印这些信息看着就是bug验证。没有timer了。
    后来查看了第一个出现此问题的log,最后dump是调用了dump_stack函数。
    clk_hw_register->samsung_pll6552_recalc_rate->do_div->__div64_32->__do_div64->__div0
    s3c2443_common_clk_init里面些参数到底要改成什么样,我还不清楚。直接设备树修改为2410不行,打印都没了。traps.c中我先注释掉dump_stack。

    asmlinkage void __div0(void)
    {
        pr_err("Division by zero in kernel.\n");
        dump_stack();
    }
    

    6.无法挂载rootfs。VFS: Mounted root都没有打印出来。
    添加了dm9000的设备树,网上找的参考,修改了下地址0x20000300和0x20000304

        srom-cs4@20000000 {
            compatible = "simple-bus";
            #address-cells = <1>;
            #size-cells = <1>;
            reg = <0x20000000 0x8000000>;
            ranges;
            ethernet@18000000 {
                compatible = "davicom,dm9000";
                reg = <0x20000300 0x2 0x20000304 0x2>;
                interrupt-parent = <&gpf>;
                interrupts = <7 4>;
                local-mac-address = [00 00 de ad be ef];
                davicom,no-eeprom;
            };
        };
    

    dm9000看上去正常。但是No soundcards found后就不走了。代码又卡到哪里了呢?

    NET: Registered protocol family 10
    Segment Routing with IPv6
    sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
    NET: Registered protocol family 17
    Loading compiled-in X.509 certificates
    dm9000 20000300.ethernet eth0: link up, 100Mbps, full-duplex, lpa 0xCDE1
    IP-Config: Complete:
         device=eth0, hwaddr=00:00:de:ad:be:ef, ipaddr=192.168.0.17, mask=255.255.255.0, gw=192.168.0.1
         host=192.168.0.17, domain=, nis-domain=(none)
         bootserver=192.168.0.110, rootserver=192.168.0.110, rootpath=
    clk: Not disabling unused clocks
    ALSA device list:
      No soundcards found.
    

    添加printk调试信息。最后找到rpc_create_xprt中return clnt; 但是又没return。搞不懂,直接我改成return 0;cInt.c中rpc_create我修改后。

        clnt = rpc_create_xprt(args, xprt);
        if (IS_ERR(clnt) || args->nconnect <= 1)
        {
            printk("rpc_create 4 IS_ERR(clnt) =%d,clnt=0x%8x\n",IS_ERR(clnt),clnt );
            //return clnt;  by apple
            return 0;
        }
    

    然后说当前PC为rpc_release_client,看来有多线程及睡眠唤醒相关了。

    nfs_mount 3
    rpc_create 1 
    rpc_create 2 
    rpc_create 3 
    rpc_create_xprt 1
    rpc_create 1 
    rpc_create 2 
    rpc_create 3 
    rpc_create_xprt 1
    rpc_create_xprt 2
    rpc_create 4 IS_ERR(clnt) =0,clnt=0xc2c4ac00
    8<--- cut here ---
    Unable to handle kernel NULL pointer dereference at virtual address 00000010
    pgd = (ptrval)
    [00000010] *pgd=00000000
    Internal error: Oops: 5 [#1] ARM
    Modules linked in:
    CPU: 0 PID: 1 Comm: swapper Tainted: G        W         5.4.61 #75
    Hardware name: Samsung S3C2416 (Flattened Device Tree)
    PC is at rpc_release_client+0x2c/0x100
    LR is at rpcb_getport_async+0x284/0x458
    pc : [<c05714c8>]    lr : [<c0583ce4>]    psr: 60000013
    sp : c34239f8  ip : c3423a14  fp : c3423a10
    r10: c0601590  r9 : 00000000  r8 : c07a111c
    r7 : c2c32000  r6 : c073d008  r5 : c35a1d00  r4 : 00000000
    r3 : 00000000  r2 : 48baebf2  r1 : c3428be0  r0 : 00000000
    Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
    Control: c000717f  Table: 30004000  DAC: 00000053
    Process swapper (pid: 1, stack limit = 0x(ptrval))
    Stack: (0xc34239f8 to 0xc3424000)
    ---
    [<c057149c>] (rpc_release_client) from [<c0583ce4>] (rpcb_getport_async+0x284/0x458)
     r6:c073d008 r5:c35a1d00 r4:c36ac400
    [<c0583a60>] (rpcb_getport_async) from [<c056ea4c>] (call_bind+0x6c/0xbc)
     r10:c35a1d00 r9:00000690 r8:c073d008 r7:fffffe00 r6:00000000 r5:c2c32000
     r4:c35a1d00
    [<c056e9e0>] (call_bind) from [<c057a104>] (__rpc_execute+0x80/0x3c4)
     r5:c07a111c r4:00000000
    [<c057a084>] (__rpc_execute) from [<c057abec>] (rpc_execute+0x78/0x84)
     r10:c2c31ae0 r9:c3423d7c r8:c073d008 r7:c2c46e00 r6:c3423b60 r5:00000000
     r4:c35a1d00
    [<c057ab74>] (rpc_execute) from [<c05708fc>] (rpc_run_task+0x148/0x160)
     r5:c2c46e00 r4:c35a1d00
    [<c05707b4>] (rpc_run_task) from [<c0570970>] (rpc_call_sync+0x5c/0xe4)
     r6:c3423ba8 r5:c073d008 r4:00000610
    [<c0570914>] (rpc_call_sync) from [<c0571d5c>] (rpc_create_xprt+0x114/0x1fc)
     r7:c2c2a980 r6:c073d008 r5:c3423c74 r4:c2c46e00
    [<c0571c48>] (rpc_create_xprt) from [<c057200c>] (rpc_create+0x1c8/0x284)
    

    kernel算是启动成功吧,但是文件系统挂载宣告失败,暂时不去调试nfs挂载了然后尝试nandflash烧写后启动时候,发现之前TQ2440之前的是yaffs2,现在的内核5.4不支持此格式。

    1. ramdisk启动失败
      在内核配置中将文件系统的路径添加后,重新编译然后就可以看到文件系统编译到了内核中。这样通过ramdisk启动,结果依然失败。
      首先出错Loading Kernel Image ... Image too large: increase CONFIG_SYS_BOOTM_LEN
      在config/smdk2440.h添加宏定义值为0xA00000. 把8M改成10M的意思解决此问题。但是依然无法启动ram,网上搜索了下需要修改linuxrc的名字为init
      mv linuxrc init后重新编译kernel,能识别了,但是报错Kernel panic - not syncing,然后查看网上解决方案:(4096) Default RAM disk size (kbytes)改大,我是10M所以是10240K,把4096改成10240,问题依旧。Kernel panic,网上还查到肯能原因是gcc编译器版本太高了。
    Freeing unused kernel memory: 5868K
    This architecture does not have kernel memory protection.
    kernel_init2
    kernel_init3
    Run /init as init process
    Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000004
    CPU: 0 PID: 1 Comm: init Tainted: G        W         5.4.61 #82
    

    三,总结

    本来想想蛮简单的事情,结果搞了我一周也只是启动了kernel(timer都没打印出来),文件系统没有启动。好吧!过程中我也学习了些调试技巧,启动流程中的关键函数我也更加熟悉了,时间花的值。不过我搭建的目的是学习framebuffer的LCD,这个平台搭建超时了,所以我修改了方案,之后我依然用5.4Kernel,但是会采用非设备树启动TQ2440,虽然是在折腾,但是千万不能跑题,以后要做自制内核启动专题的时候再回来玩也不迟,哈哈~

    相关文章

      网友评论

        本文标题:TQ2440改成设备树启动kernel5.4成功--Apple的

        本文链接:https://www.haomeiwen.com/subject/jcjboktx.html