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