28388D上电过程汇编代码分析

 复位向量

复位向量的地址统一在0x3F FFC0处。

 0x003FFFC0处保存的是复位向量的地址,其值为0x003FD2AE。

复位后CPU的状态

PC指针指向0x003FD2AE,栈指针SP指向0x0400,XAR0寄存器为0xFFFFFFFF,其他寄存器全为0.

进入InitBoot

0x003FD2AE地址处保存的是厂家固化的InitBoot。

汇编指令为:

InitBoot的汇编源码

可以找到其汇编源代码:

D:\ti\c2000\C2000Ware_3_04_00_00\libraries\boot_rom\f2838x\revA\rom_sources\cpu1\F2838x_ROM\bootROM\source\cpu1brom_init_boot.asm

节选部分代码如下:

;
; Function: InitBoot
;
; This function performs the initial boot routine
; for the CPU1 boot ROM.
;
; This module performs the following actions:
;
;     1) Initializes the stack pointer
;     2) Sets the device for C28x operating mode
;     3) Setup device systems
;     4) Run RAM initialization and call the main boot function
;
    .sect ".InitBoot"
InitBoot:

;
; Create stack section
;
__stack:    .usect ".stack",0

;
; EFUSE INTOSC and PMM Trim Blanking Window
;
; Calculate the Count for 75 uS at 15/4 MHz untrimmed clock, with buffer.
; This would result in 83uS blank window for count of 311
;
    MOV     @T,#311
    RPT     @T
||  NOP

;
; Initialize the stack pointer
;
    MOV     SP, #__stack

;
; Initialize the device for running in C28x mode.
;
    C28OBJ                                       ;Select C28x object mode
    C28ADDR                                      ;Select C27x/C28x addressing
    C28MAP                                       ;Set blocks M0/M1 for C28x mode
    CLRC    PAGE0                                ;Always use stack addressing mode
    MOVW    DP, #0                               ;Initialize DP to point to the low 64 K
    CLRC    OVM                                  ;Clear overflow mode bit
;
; Set Product Mode shift to 0
;
    SPM     0

;
; Check for HWBIST as reset cause and handle accordingly
;
cpu1brom_hwbist_reset_check:
;
; if((CpuSysRegs.RESC.bit.HWBIST & 0x1) == 1) then check CSTCRET
;
    MOVW    DP, #0x174e                          ;Set DP to CpuSysRegs.RESC
    AND     AL, @0x0, #0x20                      ;Load ACC with (CpuSysRegs.RESC & 0x20) which is HWBIST RESC bit
    LSR     AL, 5                                ;Right shift ACC (HWBIST RESC bit) value by 5
    TBIT    @AL, #0x0                            ;Check bit 0 of ACC value (HWBIST RESC)
    SBF     cpu1brom_hwbist_reset_done, NTC      ;Branch if reset bit not set

可以看到,二者是一一对应的:

 

代码版本

源代码的版本为v2.0,日期为19年8月。

与 CPU固件中的值是一致的。固件中boot版本号保存在0x003F FF7A的地方。

 查看该处内容,正是0x0200 和0x0819

InitBoot代码分析

初始化CPU环境

;
; Initialize the device for running in C28x mode.
;
    C28OBJ                                       ;Select C28x object mode
    C28ADDR                                      ;Select C27x/C28x addressing
    C28MAP                                       ;Set blocks M0/M1 for C28x mode
    CLRC    PAGE0                                ;Always use stack addressing mode
    MOVW    DP, #0                               ;Initialize DP to point to the low 64 K
    CLRC    OVM                                  ;Clear overflow mode bit
;
; Set Product Mode shift to 0
;
    SPM     0

检查硬件内置自检的结果

;
; Check for HWBIST as reset cause and handle accordingly
;
cpu1brom_hwbist_reset_check:
;
; if((CpuSysRegs.RESC.bit.HWBIST & 0x1) == 1) then check CSTCRET
;
    MOVW    DP, #0x174e                          ;Set DP to CpuSysRegs.RESC
    AND     AL, @0x0, #0x20                      ;Load ACC with (CpuSysRegs.RESC & 0x20) which is HWBIST RESC bit
    LSR     AL, 5                                ;Right shift ACC (HWBIST RESC bit) value by 5
    TBIT    @AL, #0x0                            ;Check bit 0 of ACC value (HWBIST RESC)
    SBF     cpu1brom_hwbist_reset_done, NTC      ;Branch if reset bit not set

上述代码的作用是,读取(0x174e << 6 + 0x00=0x5D380)处的内容,再与0x20作“与运算”(相当于是判断bit5)。测试结果如果为0,则跳转到cpu1brom_hwbist_reset_done处(地址为0x3fd2dc)。

外设地址0x5D380处正是CPU复位原因寄存器。

系统控制寄存器组中,CPU系统寄存器的起始地址为0x0005 D300:

 CPU系统寄存器中,复位原因寄存器的偏移量为0x80:

 该寄存器的定义:

 其中HWBISTn的说明:

 如果该位为1,说明CPU的HWBIST自检不通过。

 查看寄存器状态,该位为0.说明CPU自检结果正常。

 继续运行,则跳转到0x3F D2DC处。对应的是cpu1brom_hwbist_reset_done函数。

检查EFUSE错误

cpu1brom_hwbist_reset_done:

;
; Check for any eFUSE errors
;
    MOVW    DP, #0x1741                          ;Set DP to Device Config Register
    MOVL    ACC, @0x34                           ;Load DevConfig.FUSEERR.all
    SBF     cpu1brom_fuseerr_none, EQ            ;Branch if FUSEERR is ZERO
    MOVB    ACC, #21                             ;Load error code value (for single bit check) to ACC
    CMPL    ACC, @0x34                           ;Compare ACC value and DevConfig.FUSEERR.all value
    SBF     cpu1brom_fuseerr_reset, NEQ          ;Branch to trigger reset if not equal (multi-bit error)
    SB      cpu1brom_fuseerr_none, UNC           ;Branch to continue flow (only single bit error)

先读取(0x1741 << 6) + 0x34 = 0x5 D074处的值。

对应的是,系统控制寄存器组(SYSCTRL)中的DevCfgRegs的FUSEERR寄存器。

 

 如果寄存器的值为0,则跳转到cpu1brom_fuseerr_none。

没有错误,继续执行。

禁止看门狗


;
; Disable watchdog
;
cpu1brom_disable_wdog:
    EALLOW
    MOVW    DP, #0x1c0                           ;Set DP to Watchdog Register
    MOVB    @0x29, #0x68, UNC                    ;Disable Watchdog
    EDIS

往寄存器中写入0x68,写入的地址=(0x01C0 << 6 ) + 0x29 = 0x7029。对应的是看门狗控制寄存器WDCR: 

 写入的0x68对应的是WDDIS=1, WDCHK=101, WDPS=000:

 注意:WDDIS写入1为禁止看门狗,写入0则使能。

 禁止看门狗后,继续执行。

检查POR和XRS复位

;
; Check if reset cause is from POR or XRS
;
    MOVW    DP, #0x174e                          ;Set DP to CpuSysRegs.RESC
    MOVL    ACC, @0x0                            ;Load ACC with CpuSysRegs.RESC
    MOV     AH, #0x0                             ;Clear upper 16-bit of ACC
    ANDB    AL, #0x3                             ;Mask to only include POR and XRS RESC bits
    TEST    ACC
    SBF     stack_init, EQ                       ;Branch if ACC is zero (Not a POR or XRS reset) to stack init,
 

 再次读取RESC寄存器,判断低2位。如果都等于0(既不是POR,也不是XRS),则跳转到stack_init。

由于现在是带着仿真器调试的,不是上电或者外部复位:

 因此,会直接跳转到stack_init。

正常上电时的执行情况,后面再单独分析。

栈初始化

;
; Not POR - Initialize the stack used for boot to zero
;
stack_init:
    MOV     AL, #0x150                           ;Size of stack
    MOV     AH, #0
stack_ram_zero_loop:
    MOV     *SP++, #0                            ;Zero out RAM for stack
    SUBB    ACC, #1
    BF      stack_ram_zero_loop, GEQ
stack_ram_init_done:
    MOV     SP, #__stack                         ;Re-Initialize the stack pointer

相当于C代码:

stack_size = 0x150;
while(stack_size--)
{
	*sp++ = 0;
}

执行情况:当ACC自减后等于0时,    BF      stack_ram_zero_loop, GEQ这一句还是会跳转。因为GEQ的条件是“大于等于0”。再下一圈,ACC=-1=0xFFFFFFFF时,才不满足跳转条件,继续向下执行。

此时,ACC=-1:

调用CPU1BROM_startSystemBoot函数

stack_ram_init_done:
    MOV     SP, #__stack                         ;Re-Initialize the stack pointer

;
; RAM Init or Stack Init is complete, prepare to begin system initialization
;
cpu1brom_perform_ram_inits_complete:
    MOVW    DP,#0                                ;Initialize DP to point to the low 64 K
    CLRC    OVM                                  ;Clear overflow mode bit
    SPM     0                                    ;Set Product Mode shift to 0
;
; Branch to system initialization to run final initializations and execute boot mode
;
    LCR    CPU1BROM_startSystemBoot

接下来,将SP指针还原为__stack=0x0060。最后调用CPU1BROM_startSystemBoot函数。

 

 启动系统Boot

CPU1BROM_startSystemBoot函数为C代码。文件路径:

D:\ti\c2000\C2000Ware_3_04_00_00\libraries\boot_rom\f2838x\revA\rom_sources\cpu1\F2838x_ROM\bootROM\source\cpu1brom_system_boot.c

函数说明如下:

//*****************************************************************************
//
// Performs system initialization and boot mode execution
//
// Parameters: None
//
// This function performs the following actions:
//  - Enable NMI
//  - Initialization the DCSM
//  - Perform memory power on self test (MPOST) (if enabled in user OTP)
//  - Enable pullups on unbonded GPIOs
//  - Decode the requested boot mode
//  - Run the requested boot mode or bootloader
//
// Return: Returns the memory entry address that the device will branch to
//         upon exiting boot.
//
//*****************************************************************************
uint32_t CPU1BROM_startSystemBoot(void)
{
    // …………
}

关键代码段:CPU1BROM_selectBootMode

选择BOOT模式

CPU1BROM_selectBootMode函数在文件cpu1brom_select_bootmode.c中。

uint32_t CPU1BROM_selectBootMode(void)
{
    uint32_t bootMode;

    EALLOW;

    if(((uint32_t)HWREG(CPUSYS_BASE + SYSCTL_O_RESC) & 
        (uint32_t)SYSCTL_RESC_TRSTN_PIN_STATUS) == SYSCTL_RESC_TRSTN_PIN_STATUS)
    {
        //
        // Run emulation boot flow when debugger connected.
        //
        bootMode = CPU1BROM_getEmulationBootMode();
    }
    else
    {
        //
        // Run standalone/true boot flow when debugger isn't connected.
        //
        bootMode = CPU1BROM_getStandaloneBootMode();
    }

    EDIS;

    return(bootMode);
}

连接仿真器时,会判断EMU_BOOTPIN_CONFIG_KEY的值,如果是0xA5,则进入仿真standalone模式;如果是0x5A,则读取 BOOTPINCONFIG 的值,选择相应的模式。其他值,则进入WaitBoot模式。

EMUBOOTPINCONFIG寄存器的地址是0x0D00。

注意:此地址与中断向量表PieVectTable有重叠,但不影响。具体情况可参考:

TMS320F280025的BOOT流程_booksyhay的专栏-CSDN博客CPU启动流程根据启动时是否连接了仿真器,分为两种情况:Standalone BootEmulation Boot独立运行时的流程Standalone Boot先看整体流程图:BOOT管脚配置BOOTPINCONFIGBOOT开始时,首先读取管脚配置PINCONFIG。管脚配置有2组:Z1和Z2.Z2的优先级比Z1的高。当Z2有效时,会忽略Z1的配置 。由于这个配置是一次性写入的,写入之后不能更改。因此,通常情况下,先全能Z1配置,保留...https://blog.csdn.net/booksyhay/article/details/120172063

 一般情况下,0x0D00处的最高字节不是0x5A或者0xA5,比如,我仿真时就是0xA6。

 因此,会进入WaitBoot模式。

  

在WAIT_BOOT模式


    //
    // Get boot mode selected
    //
    CPU1BROM_bootMode = CPU1BROM_selectBootMode();


…………


    //
    // Enter specified wait boot or enable watchdog, then branch to address
    //
    if(CPU1BROM_bootMode == WAIT_BOOT)
    {
        SysCtl_enableWatchdog();
        for(;;)
        {
        }
    }

在WAIT_BOOT模式下,程序会进入死循环。不会跳转到用户的main函数。

 如果程序进入死循环,但又不是用户空间,而是BOOT空间,则可以查看手册,看是什么状况。

比如,WAIT_BOOT模式下,PC地址为0x3FB114,确实是处于wait boot mode的代码区间。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值