在作以前參考了以下博客文章,再次很是感謝:html
http://www.cnblogs.com/pengdonglin137/p/6241895.htmlnode
Uboot中須要在config中添加以下宏:linux
#define CONFIG_FIT 1
在內核裏面make menuconfig以後配置支持設備樹:xcode
Boot options->
[*] Flattened Device Tree support
而後分別編譯uboot和kernel,最後按照網上介紹製做dtb文件,將uboot經過jlink直接燒到nor flash的0地址處,而後用tftp將kernel下載到內存的30000000,將dtb文件燒到內存的31000000,而後用bootm 30000000 - 31000000啓動系統,但只能看到:dom
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識別。ui
2.設備樹被正確識別,但bootargs沒有被正確讀取,處處串口沒有正確配置。spa
解決問題:debug
1.剛開始沒法定位在linux kernel哪裏掛掉的,因而添加了led燈,在沒有開啓MMU以前,能夠直接操做物理地址,一直查到:3d
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支持設備樹了。