JZ2440支持設備樹(1)-添加設備樹之后kernel的啟動參數跟dts里面不一致


在做之前參考了如下博客文章,再次非常感謝:

http://www.cnblogs.com/pengdonglin137/p/6241895.html

Uboot中需要在config中添加如下宏:

#define CONFIG_FIT        1 

 在內核里面make menuconfig之后配置支持設備樹:

Boot options-> 
[*] Flattened Device Tree support

然后分別編譯uboot和kernel,最后按照網上介紹制作dtb文件,將uboot通過jlink直接燒到nor flash的0地址處,然后用tftp將kernel下載到內存的30000000,將dtb文件燒到內存的31000000,然后用bootm 30000000 - 31000000啟動系統,但只能看到:

SMDK2440 # bootm 30000000 - 31000000
## Booting kernel from Legacy Image at 30000000 ...
   Image Name:   Linux-4.15.1-gc1aaab686-dirty
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    3498656 Bytes = 3.3 MiB
   Load Address: 30108000
   Entry Point:  30108000
   Verifying Checksum ... OK
## Flattened Device Tree blob at 31000000
   Booting using the fdt blob at 0x31000000
   Loading Kernel Image ... OK
   Loading Device Tree to 33ba6000, end 33baa6ea ... OK

Starting kernel ...

因為之前使用tags內核能正確啟動,所以目前就是懷疑dtb文件沒有正確傳到linux,但是在uboot的/include/common.h里面添加#define DEBUG將uboot的所以調試信息打開,能看到dtb文件已經被uboot識別並且拷貝到內存的另一個地方了,如果按下開發板上的reset按鍵再一次進到uboot的console,在用dm.w去看dtb,能正確的看到dtb的內容,所以目前懷疑2點:

1.設備樹不被kernel識別。

2.設備樹被正確識別,但bootargs沒有被正確讀取,到處串口沒有正確配置。

 

解決問題:

1.剛開始無法定位在linux kernel哪里掛掉的,於是添加了led燈,在沒有開啟MMU之前,可以直接操作物理地址,一直查到:

ENTRY(__turn_mmu_on)
    mov    r0, r0
    instr_sync
    mcr    p15, 0, r0, c1, c0, 0        @ write control reg
    mrc    p15, 0, r3, c0, c0, 0        @ read id reg
    instr_sync
    mov    r3, r3
    mov    r3, r13
    ret    r3

這里的MMU被打開了,就不能直接操作物理地址了,再往后執行就是調用__mmap_switched,因為很早就有ldr r13, =__mmap_switched @ address to jump to after然后在__mmap_switched的最后就是執行C代碼入口b start_kernel

於是斷定肯定執行到了c階段,但此時MMU已經開啟,不清楚如何調試,於是又想到了earlyprintk,不爽的就是earlyprintk需要添加到bootargs里面,因為kernel C代碼里面回去解析,暫時還沒分析為什么非要uboot傳過來。

我現在的問題就很有可能uboot的bootargs沒有正確傳過來,本來想動腦筋在代碼里面寫死bootargs里面有earlyprintk的,后來突然想到make menuconfig有一個默認的Default kernel command string,於是我配置如下:

 

再次編譯內核,燒到板子上運行,終於有進步了:

SMDK2440 # bootm 30000000 - 31000000
## Booting kernel from Legacy Image at 30000000 ...
   Image Name:   Linux-4.15.1-gc1aaab686-dirty
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    3498656 Bytes = 3.3 MiB
   Load Address: 30108000
   Entry Point:  30108000
   Verifying Checksum ... OK
## Flattened Device Tree blob at 31000000
   Booting using the fdt blob at 0x31000000
   Loading Kernel Image ... OK
   Loading Device Tree to 33ba6000, end 33baa6ea ... OK

Starting kernel ...

Uncompressing Linux... done, booting the kernel.

我在misc.c里面添加了寫打印信息,如下:
static void puthex(const int dat)
{
	char c;
    unsigned char temp[4]={0};
    
	temp[0] = dat/1000 + 0x30;
	temp[1] = dat%1000/100 + 0x30;
	temp[2] = dat%100/10 + 0x30;	
	temp[3] = dat%10 + 0x30;
	putc(temp[0]);	
	putc(temp[1]);	
	putc(temp[2]);	
	putc(temp[3]);	
	putc('\r');
	putc('\n');    
	flush();
}

void DispDeviceTree(int arch_id,unsigned long* dev_tree)
{
    char temp_str[100];
	
    sprintf(temp_str,"machid=%d",arch_id);
	putstr(temp_str);
	sprintf(temp_str,"devTree=%s",dev_tree);	
	putstr(temp_str);
}
 
         

然后在head.s里面添加了加上這個函數

/*
 * The C runtime environment should now be setup sufficiently.
 * Set up some pointers, and start decompressing.
 *   r4  = kernel execution address
 *   r7  = architecture ID
 *   r8  = atags pointer
 */
		mov	r0, r4
		mov	r1, sp			@ malloc space above stack
		add	r2, sp, #0x10000	@ 64k max
		mov	r3, r7
		bl	decompress_kernel

        mov r0, r7
        mov r1, r8
        bl  DispDeviceTree
        mov r0, r4
        mov r1, sp

居然打印出了,說明我破壞了寄存器里面的值,導致連設備樹都找不到了,machine id的值不需要關心,因為我們是用dts來匹配的,現在的kernel是支持兩種匹配方式的,所以在兩種都找不到的情況下就報錯了,相信以后kernel會完全刪除tags的方式的。

Starting kernel ...

Uncompressing Linux... done, booting the kernel.
Machid=0362

dev tree:

Error: unrecognized/unsupported device tree compatible list:
[ 'samsung,s3c2440' 'samsung,jz2440' ]

Available machine support:

ID (hex)        NAME
00000400        AML_M5900
0000014b        Simtec-BAST
0000015b        IPAQ-H1940
0000039f        Acer-N35
00000290        Acer-N30
000002a8        Nex Vision - Otom 1.1
00000454        QT2410
000000c1        SMDK2410
000005b4        TCT_HAMMER
000001db        Thorcom-VR1000
000005d2        JIVE
000003fe        SMDK2413
000003f1        SMDK2412
00000377        S3C2413
00000474        VSTMS
00000695        SMDK2416
000002de        Simtec-Anubis
00000707        AT2440EVB
000007cf        MINI2440
000002a9        NexVision - Nexcoder 2440
0000034a        Simtec-OSIRIS
00000250        IPAQ-RX3715
00000518        GTA02
000003b8        HP iPAQ RX1950
0000043c        SMDK2443

Please check your kernel config and/or bootloader.
后來我將misc.c和head.S還原,還是打印了這些信息,挺好的。

SMDK2440 # bootm 30000000 - 31000000
## Booting kernel from Legacy Image at 30000000 ...
   Image Name:   Linux-4.15.1-gc1aaab686-dirty
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    3488904 Bytes = 3.3 MiB
   Load Address: 30008000
   Entry Point:  30008000
   Verifying Checksum ... OK
## Flattened Device Tree blob at 31000000
   Booting using the fdt blob at 0x31000000
   Loading Kernel Image ... OK
   Loading Device Tree to 33ba6000, end 33baa506 ... OK

Starting kernel ...

Uncompressing Linux... done, booting the kernel.
bootcmd line:
arch/arm/kernel/devtree.c:setup_machine_fdt __machine_arch_type=ffffffff
bootcmd line:noinitrd console=ttySAC0,115200 root=/dev/mtdblock3 rootfstype=
jffs2 earlyprintk

find fdt,and tags
r1=0xffffffff, r2=0x33ba6000
machine name:Samsung S3C2440 (Flattened Device Tree)
Booting Linux on physical CPU 0x0
Linux version 4.15.1-gc1aaab686-dirty (kent@hu) (gcc version 4.4.3 (ctng-1.6.1
)) #27 Mon Sep 3 22:21:31 CST 2018
CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c000717f
CPU: VIVT data cache, VIVT instruction cache
OF: fdt: Machine model: JZ2440
bootcmd line:
arch/arm/kernel/devtree.c:setup_machine_fdt __machine_arch_type=ffffffff
bootcmd line:noinitrd console=ttySAC0,115200 root=/dev/mtdblock3 rootfstype=
jffs2 earlyprintk

find fdt,and tags
r1=0xffffffff, r2=0x33ba6000
machine name:Samsung S3C2440 (Flattened Device Tree)
bootconsole [earlycon0] enabled
Memory policy: Data cache writeback
CPU S3C2440A (id 0x32440001)
DT missing boot CPU MPIDR[23:0], fall back to default cpu_logical_map
random: fast init done
Built 1 zonelists, mobility grouping on.  Total pages: 16256
Kernel command line: noinitrd console=ttySAC0,115200 root=/dev/mtdblock3 
rootfstype=jffs2 earlyprintk
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 57764K/65536K available (5319K kernel code, 216K rwdata, 1164K rodata
, 204K init, 203K bss, 7772K reserved, 0K cma-reserved)
Virtual kernel memory layout:
    vector  : 0xffff0000 - 0xffff1000   (   4 kB)
    fixmap  : 0xffc00000 - 0xfff00000   (3072 kB)
    vmalloc : 0xc4800000 - 0xff800000   ( 944 MB)
    lowmem  : 0xc0000000 - 0xc4000000   (  64 MB)
    modules : 0xbf000000 - 0xc0000000   (  16 MB)
      .text : 0x(ptrval) - 0x(ptrval)   (5321 kB)
      .init : 0x(ptrval) - 0x(ptrval)   ( 204 kB)
      .data : 0x(ptrval) - 0x(ptrval)   ( 217 kB)
       .bss : 0x(ptrval) - 0x(ptrval)   ( 204 kB)
NR_IRQS: 103
_get_rate: could not find clock xti
sched_clock: 32 bits at 100 Hz, resolution 10000000ns, wraps every 
21474836475000000ns
Console: colour dummy device 80x30

這里注意到,打印的command line不是我在dts里面定義的,我當時懷疑是不是kernel沒識別dts里面的bootargs成員,因為打印出了OF: fdt: Machine model: JZ2440,說明確實是找到了設備樹,於是我在arch\arm\kernel\devtree.c中的setup_machine_fdt函數里面根據實際地址和虛擬地址將內存里面的設備樹以08x的形式全部打印出來了,然后跟我編譯出來的dts做對比,發現確實不一樣,后來懷疑是uboot傳錯了,於是去查uboot。

將uboot中的include/common.h里面的debug打開,這樣就可以看到更多的信息,於是看到打印出了以下信息:

SMDK2440 # bootm 30000000 - 31000000
## Current stack ends at 0x33ba7ba0 *  kernel: cmdline image address = 0x30000000
## Booting kernel from Legacy Image at 30000000 ...
   Image Name:   Linux-4.15.1-gc1aaab686-dirty
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    3489048 Bytes = 3.3 MiB
   Load Address: 30008000
   Entry Point:  30008000
   Verifying Checksum ... OK
   kernel data at 0x30000040, len = 0x00353d18 (3489048)
## Skipping init Ramdisk
## No init Ramdisk
   ramdisk start = 0x00000000, ramdisk end = 0x00000000
*  fdt: cmdline image address = 0x31000000
## Checking for 'FDT'/'FDT Image' at 31000000
*  fdt: raw FDT blob
## Flattened Device Tree blob at 31000000
   Booting using the fdt blob at 0x31000000
   of_flat_tree at 0x31000000 size 0x00001507
Initial value for argc=3
Final value for argc=3
   Loading Kernel Image ... OK
   kernel loaded at 0x30008000, end = 0x3035bd18
images.os.start = 0x30000000, images.os.end = 0x30353d58
images.os.load = 0x30008000, load_end = 0x3035bd18
using: FDT
## initrd_high = 0xffffffff, copy_to_ram = 1
   ramdisk load start = 0x00000000, ramdisk load end = 0x00000000
## device tree at 31000000 ... 31001506 (len=17671 [0x4507])
   Loading Device Tree to 33ba2000, end 33ba6506 ... OK

Initial value for argc=3
Final value for argc=3
No alias for ethernet0
## Transferring control to Linux (at address 30008000)...

Starting kernel ...

Uncompressing Linux... done, booting the kernel.
phys:33ba2000
virt:c3ba2000

最后兩句是我加在arch\arm\kernel\devtree.c中的setup_machine_fdt函數里面的:

說明kernel是從uboot傳給它的地址去取的dts,難道真是uboot傳錯dts了?

於是在uboot里面的common\image-fdt.c里的boot_relocate_fdt函數里添加打印信息,將dts全部打印出來,發現dts還是錯的,而且很明顯是跟在configs/smdk2440.h里面定義的CONFIG_BOOTARGS完全一樣,於是猜想,是不是uboot優先取CONFIG_BOOTARGS定義的bootargs,於是將其屏蔽,將存在nand上面的環境變量全部刪除,再次將編譯出來的uboot.bin通過jlink燒到nor上啟動,在uboot的界面下通過tftp下載kernel和dts到ddr,再次執行bootm 30000000 - 31000000

這次kernel里面打印的bootargs跟我在dts里面定義的一致,至此才敢確定的說,我的JZ2440支持設備樹了。

  

  

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM