转自: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。