TQ2440改成设备树启动kernel5.4成功--Apple的学习笔记

一,前言,

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: 
[] (dump_backtrace) from [] (show_stack+0x18/0x1c)
 r6:00000000 r5:0000ffff r4:00000000
[] (show_stack) from [] (dump_stack+0x20/0x28)
[] (dump_stack) from [] (__div0+0x18/0x20)
[] (__div0) from [] (Ldiv0_64+0x8/0x18)
[] (__clocksource_update_freq_scale) from [] (__clocksource_register_scale+0x18/0xc4)
 r10:00000000 r9:00000002 r8:00000019 r7:00000000 r6:f6300040 r5:c0736934
 r4:c0725584
[] (__clocksource_register_scale) from [] (_samsung_pwm_clocksource_init+0x2fc/0x320)
 r5:c0736880 r4:c076cfa8
[] (_samsung_pwm_clocksource_init) from [] (samsung_pwm_alloc+0x130/0x16c)
 r9:00000001 r8:c05d541c r7:c0686390 r6:c0711008 r5:c3f78668 r4:c076cfa8
[] (samsung_pwm_alloc) from [] (s3c2410_pwm_clocksource_init+0x14/0x1c)
 r10:c0701a30 r9:00000001 r8:c06862ec r7:c070bb50 r6:c0711008 r5:00000000
 r4:c3f78668
[] (s3c2410_pwm_clocksource_init) from [] (timer_probe+0x6c/0xe0)
[] (timer_probe) from [] (time_init+0x34/0x3c)
 r8:00000000 r7:c0743000 r6:c0711000 r5:c0711008 r4:c0701a30
[] (time_init) from [] (start_kernel+0x294/0x44c)
[] (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: 
[] (dump_backtrace) from [] (show_stack+0x18/0x1c)
 r6:00989680 r5:c0757c80 r4:00000000
[] (show_stack) from [] (dump_stack+0x20/0x28)
[] (dump_stack) from [] (__div0+0x18/0x20)
[] (__div0) from [] (Ldiv0_64+0x8/0x18)
[] (tk_setup_internals.constprop.6) from [] (timekeeping_notify+0x84/0xec)
 r10:00000000 r9:c07257c8 r8:c07257c8 r7:800000d3 r6:80000053 r5:c0736934
 r4:c0757c80
[] (timekeeping_notify) from [] (__clocksource_select+0xa0/0x118)
 r8:c0736934 r7:00000000 r6:c0757f30 r5:c0725778 r4:c0736934
[] (__clocksource_select) from [] (clocksource_done_booting+0x34/0x4c)
 r10:00000000 r9:c0743000 r8:ffffe000 r7:00000000 r6:c06e381c r5:c0711008
 r4:c0725768
[] (clocksource_done_booting) from [] (do_one_initcall+0x7c/0x1f4)
 r4:c0743000
[] (do_one_initcall) from [] (kernel_init_freeable+0x10c/0x1c0)
 r8:c070182c r7:c0743000 r6:c070184c r5:000000b2 r4:c070c818
[] (kernel_init_freeable) from [] (kernel_init+0x10/0xec)
 r10:00000000 r9:00000000 r8:00000000 r7:00000000 r6:00000000 r5:c05927b4
 r4:00000000
[] (kernel_init) from [] (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 : []    lr : []    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)
---
[] (rpc_release_client) from [] (rpcb_getport_async+0x284/0x458)
 r6:c073d008 r5:c35a1d00 r4:c36ac400
[] (rpcb_getport_async) from [] (call_bind+0x6c/0xbc)
 r10:c35a1d00 r9:00000690 r8:c073d008 r7:fffffe00 r6:00000000 r5:c2c32000
 r4:c35a1d00
[] (call_bind) from [] (__rpc_execute+0x80/0x3c4)
 r5:c07a111c r4:00000000
[] (__rpc_execute) from [] (rpc_execute+0x78/0x84)
 r10:c2c31ae0 r9:c3423d7c r8:c073d008 r7:c2c46e00 r6:c3423b60 r5:00000000
 r4:c35a1d00
[] (rpc_execute) from [] (rpc_run_task+0x148/0x160)
 r5:c2c46e00 r4:c35a1d00
[] (rpc_run_task) from [] (rpc_call_sync+0x5c/0xe4)
 r6:c3423ba8 r5:c073d008 r4:00000610
[] (rpc_call_sync) from [] (rpc_create_xprt+0x114/0x1fc)
 r7:c2c2a980 r6:c073d008 r5:c3423c74 r4:c2c46e00
[] (rpc_create_xprt) from [] (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不支持设备树的启动kernel很顺利,大数nfs挂载不了。我抓包看看通信,UDP, bad length 2576 > 132。只是大概了解了nfs会用到rpc协议。就是函数参数通过tcp或udp传给主机,然后主机调用函数将返回结果再通过tcp或udp传给客户端。这个主机就是ubuntu,客户端就是tq2440开发板。可能是dm9000移植有问题吧。然后直接烧写jffs到nand启动也移植报nand ecc error。然后又尝试了ramdisk启动,报错can not start 0。3种方法都无法系统文件系统。算了,我先放弃了,这个已经背离了我的学习目标。之后有空再研究吧!

root@applecaiHP:/home/applecai/studybr/buildroot-2020.05.2/images# tcpdump -i eno1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eno1, link-type EN10MB (Ethernet), capture size 262144 bytes
14:19:43.979363 IP6 :: > ff02::16: HBH ICMP6, multicast listener report v2, 1 group record(s), length 28
14:19:44.102299 ARP, Request who-has applecaiHP tell 192.168.0.17, length 46
14:19:44.102334 ARP, Reply applecaiHP is-at c4:34:6b:01:04:10 (oui Unknown), length 28
14:19:44.102796 IP 192.168.0.17.51569 > applecaiHP.sunrpc: UDP, length 88
14:19:44.103150 IP applecaiHP.sunrpc > 192.168.0.17.51569: UDP, length 28
14:19:44.106574 IP 192.168.0.17 > applecaiHP: udp
14:19:44.399599 IP6 :: > ff02::1:ff49:c1b2: ICMP6, neighbor solicitation, who has ::803b:f8ff:fe49:eb2, length 32
14:19:45.460057 IP6 fe80::803b:f8ff:fe49:c1b2 > ff02::16: HBH ip-proto-5 12
14:19:45.460554 IP6 truncated-ip6 - 15087 bytes missing!fe80::803b:f8ff:fe49:c1b2 > ip6-allrouters: ICMP6, router solicitation, length 15103
14:19:46.339933 IP6 fe80::803b:f8ff:fe49:ff02 > ff02::16: HBH ICMP6, unknown icmp6 type (117), length 28
    0x0000:  75d5 75d5 0000 0001 0400 0000 ff02 0000
    0x0010:  0000 0000 0000 0001 ff49 c1b2
14:19:49.141167 IP 192.168.0.17.784 > applecaiHP.52634: UDP, length 40
14:19:49.141667 IP applecaiHP.52634 > 192.168.0.17.784: UDP, length 24
14:19:49.143598 IP 192.168.0.17 > applecaiHP:  trunk-2 140
14:19:54.182520 82:3b:f8:49:c1:b2 (oui Unknown) > c4:34:6b:01:04:10 (oui Unknown), ethertype Unknown (0x4500), length 174: 
    0x0000:  4500 00a0 d9d9 4000 4011 dea3 c0a8 0011  E.....@.@.......
    0x0010:  c0a8 006e 0310 cd9a 008c 0a18 d621 7097  ...n.........!p.
    0x0020:  0000 0000 0000 0001 0001 86a5 0000 0003  ................
    0x0030:  0000 0001 0000 0001 0000 0020 0000 0000  ................
    0x0040:  0000 000c 3139 322e 3136 382e 302e 3137  ....192.168.0.17
    0x0050:  0000 0000 0000 0000 0000 0000 0000 0000  ................
    0x0060:  0000 0000 0000 0038 2f68 6f6d 652f 6170  .......8/home/ap
    0x0070:  706c 6563 6169 2f73 7475 6479 6272 2f62  plecai/studybr/b
    0x0080:  7569 6c64 726f 6f74 2d32 3032 302e 3035  uildroot-2020.05
    0x0090:  2e32 2f69 6d61 6765 732f 726f 6f74 6673  .2/images/rootfs
14:19:57.782886 IP6 fe80::803b:f8ff:fe49:ff02 > ip6-allrouters: ICMP6, router solicitation, length 16
14:20:04.825296 IP 192.168.0.17.784 > applecaiHP.52634: UDP, bad length 2576 > 132

你可能感兴趣的:(TQ2440改成设备树启动kernel5.4成功--Apple的学习笔记)