1. 程式人生 > >基於tiny4412的Linux核心移植(支援device tree)(三)

基於tiny4412的Linux核心移植(支援device tree)(三)

https://www.cnblogs.com/pengdonglin137/p/5146791.html
閱讀目錄(Content)

作者資訊
平臺簡介
注意
一、裝置樹反編譯
二、在u-boot列印資訊
三、開啟Linux核心啟動早期的log
四、在核心自解壓時dump記憶體
五、CONFIG_ARM_APPENDED_DTB
回到頂部(go to top)
作者資訊
作者: 彭東林

郵箱:[email protected]

QQ:405728433

回到頂部(go to top)
平臺簡介
開發板:tiny4412ADK + S700 + 4GB Flash

要移植的核心版本:Linux-4.4.0 (支援device tree)

u-boot版本:友善之臂自帶的 U-Boot 2010.12 (為支援uImage啟動,做了少許改動)

busybox版本:busybox 1.25

交叉編譯工具鏈: arm-none-linux-gnueabi-gcc

  (gcc version 4.8.3 20140320 (prerelease) (Sourcery CodeBench Lite 2014.05-29))

回到頂部(go to top)
注意
繼續上文。

到目前為止,板子已經可以起來了,接下來就可以針對板子的情況移植驅動程式了。這個放在以後再做,下面是我折騰過程中得到的一些知識,分享一下。

一、裝置樹反編譯
在核心目錄下當我們執行make dtbs後,就會在arch/arm/boot/dts下生成一些.dtb檔案,那這個檔案裡是什麼東西呢?我們可以用dtc命令反編譯這些dtb檔案,這裡的可執行程式dtc在Linux核心原始碼中已經提供了,具體路徑是:scripts/dtc/,可以使用下面的命令從Linux原始碼中編譯出這個工具:

make CROSS_COMPILE=arm-none-linux-gnueabi- ARCH=arm scripts
這樣就會在scripts/dtc下生成可執行程式dtc。

當然,如果沒有Linux原始碼,也可以使用apt-get命令安裝這個工具,命令如下:

sudo apt-get install device-tree-compiler
下面以exynos4412-tiny4412.dtb為例:

命令:

dtc -I dtb -O dts -o tiny4412.dts arch/arm/boot/dts/exynos4412-tiny4412.dtb
然後就會生成反編譯後的檔案 tiny4412.dts,部分內容如下:

/dts-v1/;

/ {
#address-cells = <;0x1>;
#size-cells = <;0x1>;
interrupt-parent = <;0x1>;
compatible = “friendlyarm,tiny4412”, “samsung,exynos4412”, “samsung,exynos4”;
model = “FriendlyARM TINY4412 board based on Exynos4412”;

chosen {
    stdout-path = "/[email protected]";
    bootargs = "root=/dev/ram0 rw rootfstype=ext4 console=ttySAC0,115200 init=/linuxrc earlyprintk";
};

aliases {
    spi0 = "/[email protected]";
    spi1 = "/[email protected]";
    spi2 = "/[email protected]";
    i2c0 = "/[email protected]";
    i2c1 = "/[email protected]";
    i2c2 = "/[email protected]";
    i2c3 = "/[email protected]";
    i2c4 = "/[email protected]";
    i2c5 = "/[email protected]";
    i2c6 = "/[email protected]";
    i2c7 = "/[email protected]";
    i2c8 = "/[email protected]";
    csis0 = "/camera/[email protected]";
    csis1 = "/camera/[email protected]";
    fimc0 = "/camera/[email protected]";
    fimc1 = "/camera/[email protected]";
    fimc2 = "/camera/[email protected]";
    fimc3 = "/camera/[email protected]";
    serial0 = "/[email protected]";
    serial1 = "/[email protected]";
    serial2 = "/[email protected]";
    serial3 = "/[email protected]";
    pinctrl0 = "/[email protected]";
    pinctrl1 = "/[email protected]";
    pinctrl2 = "/[email protected]";
    pinctrl3 = "/[email protected]";
    fimc-lite0 = "/camera/[email protected]";
    fimc-lite1 = "/camera/[email protected]";
    mshc0 = "/[email protected]";
};

memory {
    device_type = "memory";
    reg = <0x40000000 0x40000000>;
};

[email protected] {
    compatible = "samsung,exynos4210-audss-clock";
    reg = <0x3810000 0xc>;
    #clock-cells = <;0x1>;
    linux,phandle = <;0x2>;
    phandle = <;0x2>;
};
[email protected] {

這個方法對於學習裝置樹很有幫助。
二、在u-boot列印資訊
在u-boot中很多檔案中是通過debug(… …)來列印資訊,預設情況下這些log是打印不出來的。這個函式的定義是在include/common.h中:

#ifdef DEBUG
#define debug(fmt,args…) printf (fmt ,##args)
#define debugX(level,fmt,args…) if (DEBUG>=level) printf(fmt,##args);
#else
#define debug(fmt,args…)
#define debugX(level,fmt,args…)
#endif /* DEBUG */
所以可以在呼叫debug函式的C檔案的最上面新增 #define DEBUG 即可。這個方法在Linux核心以及Android當中也很常用。

三、開啟Linux核心啟動早期的log
有時會遇到當在u-boot中執行完bootm後,打印出start kernel後串列埠就沒有再輸出任何資訊了。此時就需要開啟核心早期的log:

make menuconfig

Kernel hacking —>

  [*] Kernel low-level debugging functions (read help!)

         Kernel low-level debugging port (Use Samsung S3C UART 0 for low-level debug)

  [*] Early printk

對於earlyprintk,還需要在bootargs中新增引數earlyprintk才能生效,有了上面這幾個配置,會有下面幾個巨集生效:

CONFIG_DEBUG_LL=y

CONFIG_DEBUG_S3C_UART0=y

CONFIG_DEBUG_LL_INCLUDE=“debug/exynos.S”

CONFIG_DEBUG_UNCOMPRESS=y
CONFIG_UNCOMPRESS_INCLUDE=“debug/uncompress.h”
CONFIG_EARLY_PRINTK=y

關於earlyprintk的解析在檔案arch/arm/kernel/early_printk.c中:

1: extern void printch(int);
2:
3: static void early_write(const char *s, unsigned n)
4: {
5: while (n-- >; 0) {
6: if (*s == ‘\n’)
7: printch(’\r’);
8: printch(*s);
9: s++;
10: }
11: }
12:
13: static void early_console_write(struct console *con, const char *s, unsigned n)
14: {
15: early_write(s, n);
16: }
17:
18: static struct console early_console_dev = {
19: .name = “earlycon”,
20: .write = early_console_write,
21: .flags = CON_PRINTBUFFER | CON_BOOT,
22: .index = -1,
23: };
24:
25: static int __init setup_early_printk(char *buf)
26: {
27: early_console = &;early_console_dev;
28: register_console(&;early_console_dev);
29: return 0;
30: }
31:
32: early_param(“earlyprintk”, setup_early_printk);
其中printch都是通過組合語言實現的。

在arch/arm/Kconfig.debug中可以看到:

config DEBUG_LL
bool “Kernel low-level debugging functions (read help!)”
depends on DEBUG_KERNEL
help
Say Y here to include definitions of printascii, printch, printhex
in the kernel. This is helpful if you are debugging code that
executes before the console is initialized.

config DEBUG_S3C_UART0
depends on PLAT_SAMSUNG
select DEBUG_EXYNOS_UART if ARCH_EXYNOS
select DEBUG_S3C24XX_UART if ARCH_S3C24XX
select DEBUG_S5PV210_UART if ARCH_S5PV210
bool “Use Samsung S3C UART 0 for low-level debug”
help
Say Y here if you want the debug print routines to direct
their output to UART 0. The port must have been initialised
by the boot-loader before use.

config DEBUG_LL_INCLUDE
string
……
default “debug/exynos.S” if DEBUG_EXYNOS_UART

config EARLY_PRINTK
bool “Early printk”
depends on DEBUG_LL
help
Say Y here if you want to have an early console using the
kernel low-level debugging functions. Add earlyprintk to your
kernel parameters to enable this console.

從上面的資訊我們可以知道:

在串列埠終端尚未註冊時,核心定義了printascii、printch以及printhex用於除錯;
early console使用的也是上面定義的函式,需要在傳遞給核心的引數中新增earlyprintk引數
Linux核心早期的print函式的輸出串列埠要跟u-boot下使用的一致,即核心不再負責初始化了,讓u-boot來做,所以二者一定要一致,否則那些print函式以及earlyprintk都沒法輸出資訊;
可以參考arch/arm/kernel/debug.S,printascii、printch以及printhex都是在這裡定義的;
在kernel進入C函式(start_kernel)後可以呼叫early_print來列印資訊,它是在arch/arm/kernel/setup.c中定義的:
1: void __init early_print(const char *str, …)
2: {
3: extern void printascii(const char *);
4: char buf[256];
5: va_list ap;
6:
7: va_start(ap, str);
8: vsnprintf(buf, sizeof(buf), str, ap);
9: va_end(ap);
10:
11: #ifdef CONFIG_DEBUG_LL
12: printascii(buf);
13: #endif
14: printk("%s", buf);
15: }
可以看到,early_print也會呼叫printascii和printk,意思是用early_print列印的資訊可能會重複出現在終端上(printk會緩衝一部分,當bootconsole註冊後,會將printk緩衝區中的內容輸出)。

上面所說的列印函式只能在核心自解壓後的函式中才能使用,那麼核心自解壓過程中的資訊是不是也可以列印呢?可以,核心自解壓相關的檔案在arch/arm/boot/compressed/下面,我們所熟知的:

Uncompressing Linux… done, booting the kernel.

就是這個目錄下的程式碼打印出來的,具體程式碼如下:

arch/arm/boot/compressed/misc.c

1: void
2: decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
3: unsigned long free_mem_ptr_end_p,
4: int arch_id)
5: {
6: …
7: putstr(“Uncompressing Linux…”);
8: ret = do_decompress(input_data, input_data_end - input_data,
9: output_data, error);
10: …
11: putstr(" done, booting the kernel.\n");
12: }
其中,putstr的定義如下:

1: static void putstr(const char *ptr)
2: {
3: char c;
4:
5: while ((c = *ptr++) != ‘\0’) {
6: if (c == ‘\n’)
7: putc(’\r’);
8: putc©;
9: }
10:
11: flush();
12: }
putc是彙編實現的,arch/arm/boot/compressed/debug.S:

1: #include CONFIG_DEBUG_LL_INCLUDE
2:
3: ENTRY(putc)
4: addruart r1, r2, r3
5: waituart r3, r1
6: senduart r0, r1
7: busyuart r3, r1
8: mov pc, lr
9: ENDPROC(putc)
10:
11:
其中addruart的實現因soc的不同而不同,對於exynos4412,它的實現是(arch/arm/include/debug/exynos.S):

1: .macro addruart, rp, rv, tmp
2: mrc p15, 0, \tmp, c0, c0, 0
3: and \tmp, \tmp, #0xf0
4: teq \tmp, #0xf0 @@ A15
5: ldreq \rp, =EXYNOS5_PA_UART
6: movne \rp, #EXYNOS4_PA_UART @@ EXYNOS4
7: ldr \rv, =S3C_VA_UART
8: CONFIG_DEBUG_S3C_UART != 0
9: add \rp, \rp, #(0x10000 * CONFIG_DEBUG_S3C_UART)
10: add \rv, \rv, #(0x10000 * CONFIG_DEBUG_S3C_UART)
11: if
12: .endm
這個函式的目的就是獲得控制除錯uart的暫存器的物理基地址(rp)和虛擬基地址(rv),這裡也沒有初始化uart的程式碼,所以必須跟u-boot使用的串列埠一致。

四、在核心自解壓時dump記憶體
這是在除錯裝置樹在記憶體中的映象被自解壓後的核心覆蓋時發現的。下面是使用方法:

首先需要按照上面的一節配置核心開啟那幾個巨集
修改arch/arm/boot/compressed/head.S,如下:
1: diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
2: index 06e983f…7ecde2e 100644
3: — a/arch/arm/boot/compressed/head.S
4: +++ b/arch/arm/boot/compressed/head.S
5: @@ -22,6 +22,8 @@
6: * 100% relocatable. Any attempt to do so will result in a crash.
7: * Please select one of the following when turning on debugging.
8: */
9: +#define DEBUG
10: +
11: #ifdef DEBUG
12:
13: #if defined(CONFIG_DEBUG_ICEDCC)
14: @@ -65,7 +67,7 @@
15: .endm
16: #else
17: .macro loadsp, rb, tmp
18: - addruart \rb, \tmp
19: + addruart \rb, \tmp, \tmp
20: .endm
21: #endif
22: #endif
23: @@ -536,6 +538,24 @@ not_relocated: mov r0, #0
24: * r7 = architecture ID
25: * r8 = atags pointer
26: /
27: + stmfd sp!, {r0-r3, r10-r12, lr}
28: + kputc #’\n’
29: + kputc #‘a’
30: + kputc #‘t’
31: + kputc #‘a’
32: + kputc #‘g’
33: + kputc #‘s’
34: + kputc #’:’
35: + kputc #’ ’
36: + kputc #‘0’
37: + kputc #‘x’
38: + kphex r8, 8 /
atags pointer /
39: + kputc #’\n’
40: + mov r0, r8
41: + bl memdump /
dump 256 bytes at start of kernel /
42: + kputc #’\n’
43: + ldmfd sp!, {r0-r3, r10-r12, lr}
44: +
45: mov r0, r4
46: mov r1, sp @ malloc space above stack
47: add r2, sp, #0x10000 @ 64k max
48: @@ -546,6 +566,26 @@ not_relocated: mov r0, #0
49: mov r1, r7 @ restore architecture number
50: mov r2, r8 @ restore atags pointer
51:
52: + stmfd sp!, {r0-r3, r10-r12, lr}
53: + kputc #’\n’
54: + kputc #’\n’
55: + kputc #‘a’
56: + kputc #‘t’
57: + kputc #‘a’
58: + kputc #‘g’
59: + kputc #‘s’
60: + kputc #’:’
61: + kputc #’ ’
62: + kputc #‘0’
63: + kputc #‘x’
64: + kphex r8, 8 /
atags pointer /
65: + kputc #’\n’
66: + mov r0, r8
67: + bl memdump /
dump 256 bytes at start of kernel */
68: + kputc #’\n’
69: + ldmfd sp!, {r0-r3, r10-r12, lr}
70: +
71: +
72: #ifdef CONFIG_ARM_VIRT_EXT
73: mrs r0, spsr @ Get saved CPU boot mode
74: and r0, r0, #MODE_MASK
可以使用kputc打印出一個字元,kphex用於列印一個指定位寬的十六進位制數,將需要dump的內粗地址存放入r0,然後呼叫memdump即可,memdump會dump出256B的內容。u-boot在跳轉到核心的時候傳遞三個引數,分別給了r0、r1、r2,在沒有裝置樹之前,傳給r0,r1和r2的分別是0,machid以及u-boot傳給Linux核心引數的地址(如0x40000100),在有了裝置樹之後,傳給r0的是0,傳給r1的值無所謂,傳給r2的是裝置樹映象在記憶體中的地址。效果如下:

U-Boot 2010.12-00000-gb391276-dirty (Jan 17 2016 - 06:03:22) for TINY4412

CPU: S5PC220 [Samsung SOC on SMP Platform Base on ARM CortexA9]
APLL = 1400MHz, MPLL = 800MHz

Board: TINY4412
DRAM: 1023 MiB

vdd_arm: 1.2
vdd_int: 1.0
vdd_mif: 1.1

BL1 version: N/A (TrustZone Enabled BSP)

Checking Boot Mode … SDMMC
REVISION: 1.1
MMC Device 0: 3803 MB
MMC Device 1: 3728 MB
MMC Device 2: N/A
*** Warning - using default environment

Net: No ethernet found.
Hit any key to stop autoboot: 0
TINY4412 #
TINY4412 # dnw 0x40000000
OTG cable Connected!
Now, Waiting for DNW to transmit data
Download Done!! Download Address: 0x40000000, Download Filesize:0x43bde8
Checksum is being calculated…
Checksum O.K.
TINY4412 # dnw 0x41000000
OTG cable Connected!
Now, Waiting for DNW to transmit data
Download Done!! Download Address: 0x41000000, Download Filesize:0x27752e
Checksum is being calculated…
Checksum O.K.
TINY4412 # dnw 0x42000000
OTG cable Connected!
Now, Waiting for DNW to transmit data
Download Done!! Download Address: 0x42000000, Download Filesize:0xa53a
Checksum is being calculated.
Checksum O.K.
TINY4412 # bootm 0x40000000 0x41000000 0x42000000

Booting kernel from Legacy Image at 40000000 …

Image Name: Linux-4.4.0-gbd49c0f-dirty
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 4439464 Bytes = 4335 KiB
Load Address: 40008000
Entry Point: 40008000
Verifying Checksum … OK

Loading init Ramdisk from Legacy Image at 41000000 …

Image Name: ramdisk
Image Type: ARM Linux RAMDisk Image (gzip compressed)
Data Size: 2585838 Bytes = 2525 KiB
Load Address: 00000000
Entry Point: 00000000
Verifying Checksum … OK

Flattened Device Tree blob at 42000000

Booting using the fdt blob at 0x42000000
Loading Kernel Image … OK
OK

Loading init Ramdisk from Legacy Image at 41000000 …

Image Name: ramdisk
Image Type: ARM Linux RAMDisk Image (gzip compressed)
Data Size: 2585838 Bytes = 2525 KiB
Load Address: 00000000
Entry Point: 00000000
Verifying Checksum … OK
Loading Ramdisk to 43a84000, end 43cfb4ee … OK
Loading Device Tree to 413f2000, end 413ff539 … OK

Starting kernel …

atags: 0x413F2000
413F2000: EDFE0DD0 3AD50000 48000000 849E0000 28000000 11000000 10000000 00000000
413F2020: 22070000 3C9E0000 00000000 0040A843 00000000 EF742700 00000000 00000000
413F2040: 00000000 00000000 01000000 00000000 03000000 04000000 00000000 01000000
413F2060: 03000000 04000000 0F000000 01000000 03000000 04000000 1B000000 01000000
413F2080: 03000000 38000000 2C000000 65697266 796C646E 2C6D7261 796E6974 32313434
413F20A0: 6D617300 676E7573 7978652C 34736F6E 00323134 736D6173 2C676E75 6E797865
413F20C0: 0034736F 03000000 2F000000 37000000 65697246 796C646E 204D5241 594E4954
413F20E0: 32313434 616F6220 62206472 64657361 206E6F20 6E797845 3434736F 00003231

Uncompressing Linux… done, booting the kernel.

atags: 0x413F2000
413F2000: EDFE0DD0 3AD50000 48000000 849E0000 28000000 11000000 10000000 00000000
413F2020: 22070000 3C9E0000 00000000 0040A843 00000000 EF742700 00000000 00000000
413F2040: 00000000 00000000 01000000 00000000 03000000 04000000 00000000 01000000
413F2060: 03000000 04000000 0F000000 01000000 03000000 04000000 1B000000 01000000
413F2080: 03000000 38000000 2C000000 65697266 796C646E 2C6D7261 796E6974 32313434
413F20A0: 6D617300 676E7573 7978652C 34736F6E 00323134 736D6173 2C676E75 6E797865
413F20C0: 0034736F 03000000 2F000000 37000000 65697246 796C646E 204D5241 594E4954
413F20E0: 32313434 616F6220 62206472 64657361 206E6F20 6E797845 3434736F 00003231

[ 0.000000] Booting Linux on physical CPU 0xa00
[ 0.000000] Linux version 4.4.0-gbd49c0f-dirty ([email protected]) (gcc version 4.8.3 20140320 (prerelease) (Sourcery CodeBench Lite 2014.05-29) ) #25 SMP PREEMPT Tue Jan 19 05:50:47 PST 2016
[ 0.000000] CPU: ARMv7 Processor [413fc090] revision 0 (ARMv7), cr=10c5387d
[ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
[ 0.000000] Machine model: FriendlyARM TINY4412 board based on Exynos4412
[ 0.000000] bootconsole [earlycon0] enabled
[ 0.000000] cma: Reserved 64 MiB at 0x7bc00000
[ 0.000000] Memory policy: Data cache writealloc
[ 0.000000] Samsung CPU ID: 0xe4412011
[ 0.000000] PERCPU: Embedded 12 pages/cpu @ef79b000 s18816 r8192 d22144 u49152
[ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 260352
[ 0.000000] Kernel command line: root=/dev/ram0 rw rootfstype=ext4 console=ttySAC0,115200 init=/linuxrc earlyprintk
[ 0.000000] PID hash table entries: 4096 (order: 2, 16384 bytes)
[ 0.000000] Dentry cache hash table entries: 131072 (order: 7, 524288 bytes)
[ 0.000000] Inode-cache hash table entries: 65536 (order: 6, 262144 bytes)
[ 0.000000] Memory: 960824K/1047552K available (5867K kernel code, 293K rwdata, 2288K rodata, 440K init, 315K bss, 21192K reserved, 65536K cma-reserved, 195584K highmem)
[ 0.000000] Virtual kernel memory layout:
[ 0.000000] vector : 0xffff0000 - 0xffff1000 ( 4 kB)
[ 0.000000] fixmap : 0xffc00000 - 0xfff00000 (3072 kB)
[ 0.000000] vmalloc : 0xf0800000 - 0xff800000 ( 240 MB)
[ 0.000000] lowmem : 0xc0000000 - 0xf0000000 ( 768 MB)
[ 0.000000] pkmap : 0xbfe00000 - 0xc0000000 ( 2 MB)
[ 0.000000] modules : 0xbf000000 - 0xbfe00000 ( 14 MB)
[ 0.000000] .text : 0xc0008000 - 0xc07ff200 (8157 kB)
[ 0.000000] .init : 0xc0800000 - 0xc086e000 ( 440 kB)
[ 0.000000] .data : 0xc086e000 - 0xc08b7418 ( 294 kB)
[ 0.000000] .bss : 0xc08ba000 - 0xc0908d28 ( 316 kB)
可以看到 Uncompressing Linux… done, booting the kernel.前後就是dump出的裝置樹的內容(大小端 可能有些問題).

五、CONFIG_ARM_APPENDED_DTB
這個巨集是Linux核心中的,它的作用是支援zImage+dtb的啟動方式。為什麼要有種方式呢?因為很多廠家都有自己的bootloader,但是這些bootloader並不都一定支援裝置樹,為了實現支援裝置樹啟動,就引入了這種啟動方式,即將編譯出的zImage和編譯出的裝置樹映象檔案拼成一個新的映象,在核心的自解壓程式碼中會識別到,不會出現自解壓時導致裝置樹被覆蓋,具體實現如下(arch/arm/boot/compressed/head.S)

mov r5, #0 @ init dtb size to 0
#ifdef CONFIG_ARM_APPENDED_DTB
/*

  • r0 = delta
  • r2 = BSS start
  • r3 = BSS end
  • r4 = final kernel address (possibly with LSB set)
  • r5 = appended dtb size (still unknown)
  • r6 = _edata
  • r7 = architecture ID
  • r8 = atags/device tree pointer
  • r9 = size of decompressed image
  • r10 = end of this image, including bss/stack/malloc space if non XIP
  • r11 = GOT start
  • r12 = GOT end
  • sp = stack pointer
  • if there are device trees (dtb) appended to zImage, advance r10 so that the
  • dtb data will get relocated along with the kernel if necessary.
    */

ldr lr, [r6, #0]
#ifndef ARMEB
ldr r1, =0xedfe0dd0 @ sig is 0xd00dfeed big endian
#else
ldr r1, =0xd00dfeed
#endif
cmp lr, r1
bne dtb_check_done @ not found

#ifdef CONFIG_ARM_ATAG_DTB_COMPAT
/*

  • OK… Let’s do some funky business here.
  • If we do have a DTB appended to zImage, and we do have
  • an ATAG list around, we want the later to be translated
  • and folded into the former here. No GOT fixup has occurred
  • yet, but none of the code we’re about to call uses any
  • global variable.
    */

/* Get the initial DTB size /
ldr r5, [r6, #4]
#ifndef ARMEB
/
convert to little endian /
eor r1, r5, r5, ror #16
bic r1, r1, #0x00ff0000
mov r5, r5, ror #8
eor r5, r5, r1, lsr #8
#endif
/
50% DTB growth should be good enough /
add r5, r5, r5, lsr #1
/
preserve 64-bit alignment /
add r5, r5, #7
bic r5, r5, #7
/
clamp to 32KB min and 1MB max /
cmp r5, #(1 <;< 15)
movlo r5, #(1 <;< 15)
cmp r5, #(1 <;< 20)
movhi r5, #(1 <;< 20)
/
temporarily relocate the stack past the DTB work space */
add sp, sp, r5

stmfd sp!, {r0-r3, ip, lr}
mov r0, r8
mov r1, r6
mov r2, r5
bl atags_to_fdt

/*

  • If returned value is 1, there is no ATAG at the location
  • pointed by r8. Try the typical 0x100 offset from start
  • of RAM and hope for the best.
    */
    cmp r0, #1
    sub r0, r4, #TEXT_OFFSET
    bic r0, r0, #1
    add r0, r0, #0x100
    mov r1, r6
    mov r2, r5
    bleq atags_to_fdt

ldmfd sp!, {r0-r3, ip, lr}
sub sp, sp, r5
#endif

mov r8, r6 @ use the appended device tree

/*

  • Make sure that the DTB doesn’t end up in the final
  • kernel’s .bss area. To do so, we adjust the decompressed
  • kernel size to compensate if that .bss size is larger
  • than the relocated code.
    */
    ldr r5, =_kernel_bss_size
    adr r1, wont_overwrite
    sub r1, r6, r1
    subs r1, r5, r1
    addhi r9, r9, r1

/* Get the current DTB size /
ldr r5, [r6, #4]
#ifndef ARMEB
/
convert r5 (dtb size) to little endian */
eor r1, r5, r5, ror #16
bic r1, r1, #0x00ff0000
mov r5, r5, ror #8
eor r5, r5, r1, lsr #8
#endif

/* preserve 64-bit alignment */
add r5, r5, #7
bic r5, r5, #7

/* relocate some pointers past the appended dtb */
add r6, r6, r5
add r10, r10, r5
add sp, sp, r5
dtb_check_done:
#endif
拼接方法:

cat zImage dts/exynos4412-tiny4412.dtb > dtbImage
也可以修改核心編譯系統,在編譯完成後自動實現拼接,可以參考下面的博文實現:

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

下面是使用dtbImage啟動的方法:

1、修改裝置樹 arch/arm/boot/dts/exynos4412-tiny4412.dts

diff --git a/arch/arm/boot/dts/exynos4412-tiny4412.dts b/arch/arm/boot/dts/exynos4412-tiny4412.dts
index 4840bbd…1e33ede 100644
— a/arch/arm/boot/dts/exynos4412-tiny4412.dts
+++ b/arch/arm/boot/dts/exynos4412-tiny4412.dts
@@ -21,6 +21,7 @@

    chosen {
            stdout-path = &;serial_0;
  •           bootargs = "root=/dev/ram0 rw rootfstype=ext4 ramdisk=8192 initrd=0x41000000,8M console=ttySAC0,115200 init=/linuxrc mem=1024M"
      };
      memory {
    

@@ -78,7 +79,7 @@
bus-width = <;4>;
pinctrl-0 = <;&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>;
pinctrl-names = “default”;

  •   status = "okay";
    
  •   status = "disabled";
    

};

&;serial_0 {
2、編譯裝置樹 make dtbs,將生成的.dtb跟zImag拼接起來生成dtbImage

3、使用ramdisk啟動,目前不能使用ramdisk.img,還不知道為什麼。

4、啟動開發板,進入u-boot命令列模式,執行如下命令:

在u-boot裡執行下載dtbImage的命令: dnw 0x40008000

在開發機上執行: dnw dtbImage

在u-boot裡執行下載ramdisk的命令:dnw 0x41000000

在開發機上執行: dnw ramdisk

啟動核心: bootm 0x40008000 (u-boot不識別未壓縮的ramdisk,ramdisk的地址在bootargs中指定為0x41000000,而且上面我們已經把ramdisk下載到0x41000000了)

下面是完整的log:

U-Boot 2010.12-00000-gb391276-dirty (Jan 17 2016 - 06:03:22) for TINY4412

CPU: S5PC220 [Samsung SOC on SMP Platform Base on ARM CortexA9]
APLL = 1400MHz, MPLL = 800MHz

Board: TINY4412
DRAM: 1023 MiB

vdd_arm: 1.2
vdd_int: 1.0
vdd_mif: 1.1

BL1 version: N/A (TrustZone Enabled BSP)

Checking Boot Mode … SDMMC
REVISION: 1.1
MMC Device 0: 3803 MB
MMC Device 1: 3728 MB
MMC Device 2: N/A
*** Warning - using default environment

Net: No ethernet found.
Hit any key to stop autoboot: 0
TINY4412 # dnw 0x40008000
OTG cable Connected!
Now, Waiting for DNW to transmit data
Download Done!! Download Address: 0x40008000, Download Filesize:0x446302
Checksum is being calculated…
Checksum O.K.
TINY4412 # dnw 0x41000000
OTG cable Connected!
Now, Waiting for DNW to transmit data
Download Done!! Download Address: 0x41000000, Download Filesize:0x800000
Checksum is being calculated…
Checksum O.K.
TINY4412 # bootm 0x40008000
Boot with zImage

Starting kernel …

atags: 0x40CF68E8
40CF68E8: EDFE0DD0 72A50000 38000000 749E0000 28000000 11000000 10000000 00000000
40CF6908: FE060000 3C9E0000 00000000 00000000 00000000 00000000 01000000 00000000
40CF6928: 03000000 04000000 00000000 01000000 03000000 04000000 0F000000 01000000
40CF6948: 03000000 04000000 1B000000 01000000 03000000 38000000 2C000000 65697266
40CF6968: 796C646E 2C6D7261 796E6974 32313434 6D617300 676E7573 7978652C 34736F6E
40CF6988: 00323134 736D6173 2C676E75 6E797865 0034736F 03000000 2F000000 37000000
40CF69A8: 65697246 796C646E 204D5241 594E4954 32313434 616F6220 62206472 64657361
40CF69C8: 206E6F20 6E797845 3434736F 00003231 01000000 736F6863 00006E65 03000000

Uncompressing Linux… done, booting the kernel.

atags: 0x40CF68E8
40CF68E8: EDFE0DD0 72A50000 38000000 749E0000 28000000 11000000 10000000 00000000
40CF6908: FE060000 3C9E0000 00000000 00000000 00000000 00000000 01000000 00000000
40CF6928: 03000000 04000000 00000000 01000000 03000000 04000000 0F000000 01000000
40CF6948: 03000000 04000000 1B000000 01000000 03000000 38000000 2C000000 65697266
40CF6968: 796C646E 2C6D7261 796E6974 32313434 6D617300 676E7573 7978652C 34736F6E
40CF6988: 00323134 736D6173 2C676E75 6E797865 0034736F 03000000 2F000000 37000000
40CF69A8: 65697246 796C646E 204D5241 594E4954 32313434 616F6220 62206472 64657361
40CF69C8: 206E6F20 6E797845 3434736F 00003231 01000000 736F6863 00006E65 03000000

[ 0.000000] Booting Linux on physical CPU 0xa00
[ 0.000000] Linux version 4.4.0-gbd49c0f-dirty ([email protected]) (gcc version 4.8.3 20140320 (prerelease) (Sourcery CodeBench Lite 2014.05-29) ) #25 SMP PREEMPT Tue Jan 19 05:50:47 PST 2016
[ 0.000000] CPU: ARMv7 Processor [413fc090] revision 0 (ARMv7), cr=10c5387d
[ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
[ 0.000000] Machine model: FriendlyARM TINY4412 board based on Exynos4412
[ 0.000000] cma: Reserved 64 MiB at 0x7c000000
[ 0.000000] Memory policy: Data cache writealloc
[ 0.000000] Samsung CPU ID: 0xe4412011
[ 0.000000] PERCPU: Embedded 12 pages/cpu @ef79b000 s18816 r8192 d22144 u49152
[ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 260608
[ 0.000000] Kernel command line: root=/dev/ram0 rw rootfstype=ext4 ramdisk=8192 initrd=0x41000000,8M console=ttySAC0,115200 init=/linuxrc mem=1024M
[ 0.000000] PID hash table entries: 4096 (order: 2, 16384 bytes)
[ 0.000000] Dentry cache hash table entries: 131072 (order: 7, 524288 bytes)
[ 0.000000] Inode-cache hash table entries: 65536 (order: 6, 262144 bytes)
[ 0.000000] Memory: 956196K/1048576K available (5867K kernel code, 293K rwdata, 2288K rodata, 440K init, 315K bss, 26844K reserved, 65536K cma-reserved, 196608K highmem)
[ 0.000000] Virtual kernel memory layout:
[ 0.000000] vector : 0xffff0000 - 0xffff1000 ( 4 kB)
[ 0.000000] fixmap : 0xffc00000 - 0xfff00000 (3072 kB)
[ 0.000000] vmalloc : 0xf0800000 - 0xff800000 ( 240 MB)
[ 0.000000] lowmem : 0xc0000000 - 0xf0000000 ( 768 MB)
[ 0.000000] pkmap : 0xbfe00000 - 0xc0000000 ( 2 MB)
[ 0.000000] modules : 0xbf000000 - 0xbfe00000 ( 14 MB)
[ 0.000000] .text : 0xc0008000 - 0xc07ff200 (8157 kB)
[ 0.000000] .init : 0xc0800000 - 0xc086e000 ( 440 kB)
[ 0.000000] .data : 0xc086e000 - 0xc08b7418 ( 294 kB)
[ 0.000000] .bss : 0xc08ba000 - 0xc0908d28 ( 316 kB)
[ 0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1
[ 0.000000] Preemptible hierarchical RCU implementation.
[ 0.000000] Build-time adjustment of leaf fanout to 32.
[ 0.000000] RCU restricting CPUs from NR_CPUS=8 to nr_cpu_ids=4.
[ 0.000000] RCU: Adjusting geometry for rcu_fanout_leaf=32, nr_cpu_ids=4
[ 0.000000] NR_IRQS:16 nr_irqs:16 16
[ 0.000000] GIC physical location is 0x10490000
[ 0.000000] L2C: platform modifies aux control register: 0x02070000 ->; 0x3e470001
[ 0.000000] L2C: platform provided aux values permit register corruption.
[ 0.000000] L2C: DT/platform modifies aux control register: 0x02070000 ->; 0x3e470001
[ 0.000000] L2C-310 enabling early BRESP for Cortex-A9
[ 0.000000] L2C-310: enabling full line of zeros but not enabled in Cortex-A9
[ 0.000000] L2C-310 dynamic clock gating enabled, standby mode enabled
[ 0.000000] L2C-310 cache controller enabled, 16 ways, 1024 kB
[ 0.000000] L2C-310: CACHE_ID 0x4100c4c8, AUX_CTRL 0x4e470001
[ 0.000000] Exynos4x12 clocks: sclk_apll = 466666667, sclk_mpll = 800000000
[ 0.000000] sclk_epll = 96000000, sclk_vpll = 108000000, arm_clk = 1400000000
[ 0.000000] Switching to timer-based delay loop, resolution 41ns
[ 0.000000] clocksource: mct-frc: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 79635851949 ns
[ 0.000003] sched_clock: 32 bits at 24MHz, resolution 41ns, wraps every 89478484971ns
[ 0.000122] Console: colour dummy device 80x30
[ 0.000135] Calibrating delay loop (skipped), value calculated using timer frequency… 48.00 BogoMIPS (lpj=120000)
[ 0.000144] pid_max: default: 32768 minimum: 301
[ 0.000209] Mount-cache hash table entries: 2048 (order: 1, 8192 bytes)
[ 0.000217] Mountpoint-cache hash table entries: 2048 (order: 1, 8192 bytes)
[ 0.000586] CPU: Testing write buffer coherency: ok
[ 0.000772] CPU0: thread -1, cpu 0, socket 10, mpidr 80000a00
[ 0.000999] Setting up static identity map for 0x400082c0 - 0x40008318
[ 0.045048] CPU1: thread -1, cpu 1, socket 10, mpidr 80000a01
[ 0.060041] CPU2: thread -1, cpu 2, socket 10, mpidr 80000a02
[ 0.075042] CPU3: thread -1, cpu 3, socket 10, mpidr 80000a03
[ 0.075082] Brought up 4 CPUs
[ 0.075096] SMP: Total of 4 processors activated (192.00 BogoMIPS).
[ 0.075101] CPU: All CPU(s) started in SVC mode.
[ 0.075611] devtmpfs: initialized
[ 0.084566] VFP support v0.3: implementor 41 architecture 3 part 30 variant 9 rev 4
[ 0.084839] [email protected] has as child subdomain: [email protected]
[ 0.085225] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 9556302231375000 ns
[ 0.087164] pinctrl core: initialized pinctrl subsystem
[ 0.087929] NET: Registered protocol family 16
[ 0.089226] DMA: preallocated 256 KiB pool for atomic coherent allocations
[ 0.105005] cpuidle: using governor ladder
[ 0.120000] cpuidle: using governor menu
[ 0.120747] exynos-audss-clk 3810000.clock-controller: setup completed
[ 0.157138] SCSI subsystem initialized
[ 0.157506] usbcore: registered new interface driver usbfs
[ 0.157580] usbcore: registered new interface driver hub
[ 0.157660] usbcore: registered new device driver usb
[ 0.158780] Advanced Linux Sound Architecture Driver Initialized.
[ 0.159857] clocksource: Switched to clocksource mct-frc
[ 0.169153] missing cooling_device property
[ 0.169163] failed to build thermal zone cpu-thermal: -2
[ 0.169260] NET: Registered protocol family 2
[ 0.169627] TCP established hash table entries: 8192 (order: 3, 32768 bytes)
[ 0.169686] TCP bind hash table entries: 8192 (order: 5, 163840 bytes)
[ 0.169803] TCP: Hash tables configured (established 8192 bind 8192)
[ 0.169921] UDP hash table entries: 512 (order: 2, 24576 bytes)
[ 0.169950] UDP-Lite hash table entries: 512 (order: 2, 24576 bytes)
[ 0.170092] NET: Registered protocol family 1
[ 0.170297] RPC: Registered named UNIX socket transport module.
[ 0.170305] RPC: Registered udp transport module.
[ 0.170310] RPC: Registered tcp transport module.
[ 0.170315] RPC: Registered tcp NFSv4.1 backchannel transport module.
[ 0.170461] Trying to unpack rootfs image as initramfs…
[ 0.170628] rootfs image is not initramfs (junk in compressed archive); looks like an initrd
[ 0.193515] Freeing initrd memory: 8192K (c1000000 - c1800000)
[ 0.194996] futex hash table entries: 1024 (order: 4, 65536 bytes)
[ 0.204233] romfs: ROMFS MTD © 2007 Red Hat, Inc.
[ 0.204924] bounce: pool size: 64 pages
[ 0.204936] io scheduler noop registered
[ 0.204945] io scheduler deadline registered
[ 0.205116] io scheduler cfq registered (default)
[ 0.209955] dma-pl330 12680000.pdma: Loaded driver for PL330 DMAC-141330
[ 0.209967] dma-pl330 12680000.pdma: DBUFF-32x4bytes Num_Chans-8 Num_Peri-32 Num_Events-32
[ 0.213022] dma-pl330 12690000.pdma: Loaded driver for PL330 DMAC-141330
[ 0.213032] dma-pl330 12690000.pdma: DBUFF-32x4bytes Num_Chans-8 Num_Peri-32 Num_Events-32
[ 0.213909] dma-pl330 12850000.mdma: Loaded driver for PL330 DMAC-141330
[ 0.213919] dma-pl330 12850000.mdma: DBUFF-64x8bytes Num_Chans-8 Num_Peri-1 Num_Events-32
[ 0.271176] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
[ 0.272413] 13800000.serial: ttySAC0 at MMIO 0x13800000 (irq = 44, base_baud = 0) is a S3C6400/10
[ 0.908554] console [ttySAC0] enabled
[ 0.912530] 13810000.serial: ttySAC1 at MMIO 0x13810000 (irq = 45, base_baud = 0) is a S3C6400/10
[ 0.921327] 13820000.serial: ttySAC2 at MMIO 0x13820000 (irq = 46, base_baud = 0) is a S3C6400/10
[ 0.930171] 13830000.serial: ttySAC3 at MMIO 0x13830000 (irq = 47, base_baud = 0) is a S3C6400/10
[ 0.939720] [drm] Initialized drm 1.1.0 20060810
[ 0.953371] brd: module loaded
[ 0.958359] loop: module loaded
[ 0.959171] usbcore: registered new interface driver r8152
[ 0.959302] usbcore: registered new interface driver asix
[ 0.960434] usbcore: registered new interface driver ax88179_178a
[ 0.966498] usbcore: registered new interface driver cdc_ether
[ 0.972325] usbcore: registered new interface driver dm9601
[ 0.977884] usbcore: registered new interface driver smsc75xx
[ 0.983611] usbcore: registered new interface driver smsc95xx
[ 0.989325] usbcore: registered new interface driver net1080
[ 0.994965] usbcore: registered new interface driver cdc_subset
[ 1.000873] usbcore: registered new interface driver zaurus
[ 1.006454] usbcore: registered new interface driver cdc_ncm
[ 1.012397] ehci_hcd: USB 2.0 ‘Enhanced’ Host Controller (EHCI) Driver
[ 1.018528] ehci-exynos: EHCI EXYNOS driver
[ 1.022808] ohci_hcd: USB 1.1 ‘Open’ Host Controller (OHCI) Driver
[ 1.028850] ohci-exynos: OHCI EXYNOS driver
[ 1.033363] usbcore: registered new interface driver usb-storage
[ 1.039544] mousedev: PS/2 mouse device common for all mice
[ 1.045326] s3c-rtc 10070000.rtc: failed to find rtc source clock
[ 1.050645] s3c-rtc: probe of 10070000.rtc failed with error -2
[ 1.056739] i2c /dev entries driver
[ 1.062046] device-mapper: ioctl: 4.34.0-ioctl (2015-10-28) initialised: [email protected]
[ 1.069226] sdhci: Secure Digital Host Controller Interface driver
[ 1.074585] sdhci: Copyright© Pierre Ossman
[ 1.079056] Synopsys Designware Multimedia Card Interface Driver
[ 1.086865] usbcore: registered new interface driver usbhid
[ 1.090471] usbhid: USB HID core driver
[ 1.097222] NET: Registered protocol family 10
[ 1.099233] sit: IPv6 over IPv4 tunneling driver
[ 1.103848] NET: Registered protocol family 17
[ 1.107765] NET: Registered protocol family 15
[ 1.112340] Registering SWP/SWPB emulation handler
[ 1.118177] hctosys: unable to open rtc device (rtc0)
[ 1.134172] ALSA device list:
[ 1.134208] No soundcards found.
[ 1.134917] RAMDISK: ext2 filesystem found at block 0
[ 1.134972] RAMDISK: Loading 8192KiB [1 disk] into ram disk… done.
[ 1.262918] EXT4-fs (ram0): mounted filesystem with red data mode. Opts: (null)
[ 1.263014] VFS: Mounted root (ext4 filesystem) on device 1:0.
[ 1.263132] devtmpfs: mounted
[ 1.263411] Freeing unused kernel memory: 440K (c0800000 - c086e000)

Please press Enter to activate this console.
[[email protected] ]#
[[email protected] ]#