轉自:http://blog.chinaunix.net/space.php?uid=7214824&do=blog&id=160521
DM365是的啓動方式有兩種,通過BOOTSEL[2:0]引腳決定。當其爲001時,直接從AEMIF上啓 動,比如NOR和OneNAND。除此之外皆是從RBL啓動,順序爲RBL-UBL-UBOOT-KERNEL,比如NAND,串口,SD卡等。RBL會 搜尋block1到block24去找UBL,關於RBL啓動的詳細細節可以參考用戶指南關於ARM子系統的那篇文檔,很詳盡,下面只分析UBL的源碼。
UBL源碼在PSP包裏的board_utilities\flash_utils目錄下,主要是COMMON目錄和各子平臺的目錄如DM36x等,內中除了UBL的源碼外還有CCS下JTAG的擦除燒寫源碼,串口燒寫源碼等。下面只分析UBL的啓動代碼。
入門代碼是彙編文件start.S,主要是切換操作模式,建立堆棧等,然後跳轉到main函數,進入到Common\ubl\src目錄下的C文件ubl.c中。main函數如下:
// Main entry point
void main(void)
{
// Call to real boot function code
LOCAL_boot();
// Jump to entry point
DEBUG_printString("\r\nJumping to entry point at ");
DEBUG_printHexInt(gEntryPoint);
DEBUG_printString(".\r\n");
APPEntry = (void (*)(void)) gEntryPoint;
(*APPEntry)();
}
|
main函數主要調用了LOCAL_boot函數來進行實質的引導功能,下面是此函數的內容:
static Uint32 LOCAL_boot(void)
{
DEVICE_BootMode bootMode;
// Read boot mode
bootMode = DEVICE_bootMode();
if (bootMode == DEVICE_BOOTMODE_UART)
{
// Wait until the RBL is done using the UART.
while((UART0->LSR & 0x40) == 0 );
}
// Platform Initialization
if ( DEVICE_init() != E_PASS )
{
DEBUG_printString(devString);
DEBUG_printString(" initialization failed!\r\n");
asm(" MOV PC, #0");
}
else
{
DEBUG_printString(devString);
DEBUG_printString(" initialization passed!\r\n");
}
// Set RAM pointer to beginning of RAM space
UTIL_setCurrMemPtr(0);
// Send some information to host
DEBUG_printString("TI UBL Version: ");
DEBUG_printString(UBL_VERSION_STRING);
DEBUG_printString("\r\nBooting Catalog Boot Loader\r\nBootMode = ");
// Select Boot Mode
#if defined(UBL_NAND)
{
//Report Bootmode to host
DEBUG_printString("NAND\r\n");
// Copy binary image application from NAND to RAM
if (NANDBOOT_copy() != E_PASS)
{
DEBUG_printString("NAND Boot failed.\r\n");
LOCAL_bootAbort();
}
}
#elif defined(UBL_NOR)
{
//Report Bootmode to host
DEBUG_printString("NOR \r\n");
// Copy binary application image from NOR to RAM
if (NORBOOT_copy() != E_PASS)
{
DEBUG_printString("NOR Boot failed.\r\n");
LOCAL_bootAbort();
}
}
#elif defined(UBL_SD_MMC)
{
//Report Bootmode to host
DEBUG_printString("SD/MMC \r\n");
// Copy binary of application image from SD/MMC card to RAM
if (SDMMCBOOT_copy() != E_PASS)
{
DEBUG_printString("SD/MMC Boot failed.\r\n");
LOCAL_bootAbort();
}
}
#else
{
//Report Bootmode to host
DEBUG_printString("UART\r\n");
UARTBOOT_copy();
}
#endif
DEBUG_printString(" DONE");
UTIL_waitLoop(10000);
DEVICE_TIMER0Stop();
return E_PASS;
}
|
先通過調用DEVICE_bootMode函數來判斷啓動方式(通過讀取SYS寄存器實現),而後調用了DEVICE_init函數來進行平臺的最底層初始化,包括電源域,時鐘,DDR,EMIF,UART,I2C,TIMER等,另有專篇分析。
而後通過UTIL_setCurrMemPtr函數對全局變量currMemPtr賦值,以後用到。接着通過判斷不同的引導方式,採取不同的處理辦法,以 NAND啓動爲例,將調用NANDBOOT_copy函數,此函數另有專篇分析。此函數將NAND中的某些內容(就是UBOOT)搬移到RAM中,而後 UBL結束,控制權正式交給UBOOT。