關於uboot啟動核心停留在Starting Kernel問題的解決
阿新 • • 發佈:2019-02-12
當通過Kermit方式使用串列埠線上將核心uImage載入到記憶體0xC0008000地址處後,執行bootm c0008000命令去啟動核心,console控制檯資訊執行到Starting Kernel就卡住不動了,這句列印資訊是uboot的最後一條列印資訊,也就是我們確定不了核心到底有沒有被啟動
一般核心啟動失敗常見的原因大多是因為傳參不正確導致的,即r0-r2暫存器的值。將machid和tag傳參地址通過uboot打印出來,如下圖所示
排除核心傳參錯誤後,將問題鎖定到核心,TI的早期處理器大多預設使用Uart2作為console控制檯,因為我們使用的是Uart0,所以需要修改核心程式碼。
核心在執行之前需要自解壓,即如下程式碼
void decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, unsigned long free_mem_ptr_end_p, int arch_id) { int ret; __stack_chk_guard_setup(); output_data = (unsigned char *)output_start; free_mem_ptr = free_mem_ptr_p; free_mem_end_ptr = free_mem_ptr_end_p; __machine_arch_type = arch_id; arch_decomp_setup(); putstr("Uncompressing Linux..."); ret = do_decompress(input_data, input_data_end - input_data, output_data, error); if (ret) error("decompressor returned an error"); else putstr(" done, booting the kernel.\n"); }
這部分程式碼位於arch/arm/boot/compressd/misc.c檔案,不難看出,核心解壓前控制檯應輸出Uncompressing Linux...,核心解壓完成後若解壓成功,則應輸出done, booting the kernel.
如果上述資訊未在控制檯輸出,那麼就要為putstr函式做輸出重定向了.
static void putstr(const char *ptr) { char c; while ((c = *ptr++) != '\0') { if (c == '\n') putc('\r'); putc(c); } flush(); } static inline void putc(char c) { if (!uart) return; while (!(uart[UART_LSR] & UART_LSR_THRE)) barrier(); uart[UART_TX] = c; }
putstr函式通過呼叫putc函式實現除錯資訊輸出,putc直接控制暫存器地址實現資料列印,找到設定uart全域性變數的地方,將串列埠2修改為串列埠0