1. 程式人生 > >關於uboot啟動核心停留在Starting Kernel問題的解決

關於uboot啟動核心停留在Starting Kernel問題的解決

   當通過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