转自: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 p_w_picpath 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 p_w_picpath 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 p_w_picpath 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。
转载于:https://blog.51cto.com/ttsky138/655399