linux kernel 4.6 移植到imx280手札
阿新 • • 發佈:2019-01-29
資源簡介
周立功過節發招,49元買了imx280核心板:
ARM926EJ-S 架構 arm v5TE 指令集,cpu最高能跑450M
預設光碟資料是 比較老的uboot-2009加linux-2.6核心。
因為本人電腦是ubuntu環境,周立功提供的燒寫環境都不適用與我的電腦。
不過眾裡尋他千百度,終於在開源專案rockbox裡面找到一個linux下面的usb燒寫工具.
外加一根串列埠線。我就是移植的全部外部環境。
自己的程式碼環境在github上面放了個倉庫,方面回老家的時候也能夠寫程式碼。
https://github.com/QtForQT/imx280_zlg.git
心酸史(一) 串列埠輸出
通過下載了最新的kernel(我移植時2016年5月)發現裡面預設支援了imx28這顆晶片。當時高興呀,以為只要make一下就能運行了。 通過make ARCH=arm CROSS_COMPILE=**** mxs_defconfig && make zImage然後替換周立功bootloader/imx-bootlets-src-10.12.01/ 裡面的zImage 發現只有 “Uncompressing Linux... done, booting the kernel.__error_p: #ifdef CONFIG_DEBUG_LL adr r0, str_p1 bl printascii mov r0, r9 bl printhex8 adr r0, str_p2 bl printascii b __error str_p1: .asciz "\nError: unrecognized/unsupported processor variant (0x" str_p2: .asciz ").\n" .align #endif ENDPROC(__error_p)
注意兩點:一個是巨集:CONFIG_DEBUG_LL一個是printascii printascii的實現:
ENTRY(printascii) addruart_current r3, r1, r2 b 2f 1: waituart r2, r3 senduart r1, r3 busyuart r2, r3 teq r1, #'\n' moveq r1, #'\r' beq 1b 2: teq r0, #0 ldrneb r1, [r0], #1 teqne r1, #0 bne 1b ret lr ENDPROC(printascii)
然後打開了CONFIG_DEBUG_LL巨集,檢視.config 發現裡面會有CONFIG_DEBUG_LL_INCLUDE=“debug/pl01x.S” 然後在arch/arm/include/debug/pl01x.S裡面實現了 addruart,senduart,busyuart三個巨集。
當然這其中還有因為編譯的是mxs_defonfig它裡面及支援imx23和imx28需要把imx23 uart相關的去掉。 就這樣愉快的加列印直到有一天。。。。。。。。
__turn_mmu_on關了我的世界
當__turn_mmu_on過後串列埠就沒有輸出了。看這個貨,估計是開啟mmu了。更具常識猜測,可能: 1.uart相關的記憶體沒有對映上來 2.uart的虛擬地址不對。 瘋狂的看原始碼,找到了對映虛擬地址的地方:__create_page_tables:
pgtbl r4, r8 @ page table address
...................................
...................................
#ifdef CONFIG_DEBUG_LL
#if !defined(CONFIG_DEBUG_ICEDCC) && !defined(CONFIG_DEBUG_SEMIHOSTING)
/*
* Map in IO space for serial debugging.
* This allows debug messages to be output
* via a serial console before paging_init.
*/
addruart r7, r3, r0
mov r3, r3, lsr #SECTION_SHIFT
mov r3, r3, lsl #PMD_ORDER
add r0, r4, r3
mov r3, r7, lsr #SECTION_SHIFT
ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags
orr r3, r7, r3, lsl #SECTION_SHIFT
..............................................................
..............................................................
#ifdef CONFIG_DEBUG_LL
#if !defined(CONFIG_DEBUG_ICEDCC) && !defined(CONFIG_DEBUG_SEMIHOSTING)
/*
* Map in IO space for serial debugging.
* This allows debug messages to be output
* via a serial console before paging_init.
*/
addruart r7, r3, r0
mov r3, r3, lsr #SECTION_SHIFT
mov r3, r3, lsl #PMD_ORDER
add r0, r4, r3
mov r3, r7, lsr #SECTION_SHIFT
ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags
orr r3, r7, r3, lsl #SECTION_SHIFT
發現它是通過addruart來獲得uart的物理和虛擬地址,然後映射了的。也就是說,地址是映射了的,因為這個巨集我們第一步的時候打開了的。 在檢查虛擬地址:
#ifdef CONFIG_DEBUG_UART_PHYS
.macro addruart, rp, rv, tmp
ldr \rp, =CONFIG_DEBUG_UART_PHYS
ldr \rv, =CONFIG_DEBUG_UART_VIRT
.endm
#endif
在arch/arm/Kconfig.debug中找到了
default 0xfe100000 if DEBUG_IMX23_UART || DEBUG_IMX28_UART
但是怎樣得到虛擬地址呢?我google很久,但是還是沒有找到規則。最終取了個巧,從周立功的程式碼得到了正確的地址。
default 0xf0074000 if DEBUG_IMX23_UART || DEBUG_IMX28_UART
走到哪裡了?
然後安裝debug流程在lib/vsprintf.c裡面加上了printascii貼出來的程式碼是我後來註釋掉的:int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
{
int i;
i = vsnprintf(buf, size, fmt, args);
//#if defined(CONFIG_DEBUG_LL)
//extern void printascii(const char *);
// printascii(buf);
//#endif
if (likely(i < size))
return i;
if (size != 0)
return size - 1;
return 0;
}
EXPORT_SYMBOL(vscnprintf);
然後在init/main.c中把
bool initcall_debug = 1;
這樣可以看在載入那個模組時失敗了的。
最終確定了是載入application uart卡住了。為了儘快啟動我直接去掉了這個驅動
開啟串列埠
為了能夠進入控制檯,和列印輸出。有把debug uart串列埠開啟。也就是前面的pl011arm,primecell-periphid = <0x00041011>;