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

news/2024/12/1 0:29:59/

 复位向量

复位向量的地址统一在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,#311RPT     @T
||  NOP;
; Initialize the stack pointer
;MOV     SP, #__stack;
; Initialize the device for running in C28x mode.
;C28OBJ                                       ;Select C28x object modeC28ADDR                                      ;Select C27x/C28x addressingC28MAP                                       ;Set blocks M0/M1 for C28x modeCLRC    PAGE0                                ;Always use stack addressing modeMOVW    DP, #0                               ;Initialize DP to point to the low 64 KCLRC    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.RESCAND     AL, @0x0, #0x20                      ;Load ACC with (CpuSysRegs.RESC & 0x20) which is HWBIST RESC bitLSR     AL, 5                                ;Right shift ACC (HWBIST RESC bit) value by 5TBIT    @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 modeC28ADDR                                      ;Select C27x/C28x addressingC28MAP                                       ;Set blocks M0/M1 for C28x modeCLRC    PAGE0                                ;Always use stack addressing modeMOVW    DP, #0                               ;Initialize DP to point to the low 64 KCLRC    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.RESCAND     AL, @0x0, #0x20                      ;Load ACC with (CpuSysRegs.RESC & 0x20) which is HWBIST RESC bitLSR     AL, 5                                ;Right shift ACC (HWBIST RESC bit) value by 5TBIT    @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 RegisterMOVL    ACC, @0x34                           ;Load DevConfig.FUSEERR.allSBF     cpu1brom_fuseerr_none, EQ            ;Branch if FUSEERR is ZEROMOVB    ACC, #21                             ;Load error code value (for single bit check) to ACCCMPL    ACC, @0x34                           ;Compare ACC value and DevConfig.FUSEERR.all valueSBF     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:EALLOWMOVW    DP, #0x1c0                           ;Set DP to Watchdog RegisterMOVB    @0x29, #0x68, UNC                    ;Disable WatchdogEDIS

往寄存器中写入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.RESCMOVL    ACC, @0x0                            ;Load ACC with CpuSysRegs.RESCMOV     AH, #0x0                             ;Clear upper 16-bit of ACCANDB    AL, #0x3                             ;Mask to only include POR and XRS RESC bitsTEST    ACCSBF     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 stackMOV     AH, #0
stack_ram_zero_loop:MOV     *SP++, #0                            ;Zero out RAM for stackSUBB    ACC, #1BF      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 KCLRC    OVM                                  ;Clear overflow mode bitSPM     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的代码区间。


http://www.ppmy.cn/news/470435.html

相关文章

关于占位符%m.nd/f/e的使用区分

整型-%d 浮点型-%f 浮点型-%e 整型-%d int a 123;float b 3.14, c -3.14;long d 65535;printf("a1 is %d\n",a);printf("a2 is %2d\n",a);printf("a3 is %3d\n",a);printf("a4 is %4d\n",a);输出结果&#xff1a; 浮点型-%f pri…

基于stm32f303cbt6的点灯实验(硬件+软件)

一、硬件原理图及PCB 项目完整的原理图 理论上只要给高电平&#xff0c;灯就亮。 二、软件&#xff08;keil程序&#xff09; main.c //stm32f303cbt6 //32kb ram //128kb flash //本实验,LED常亮 /* Includes --------------------------------------------------------…

STM32F030开发日志之I2C

最近调试 一款 IQS333 电容触摸按键芯片IC,调了好几天发现I2C端口上没数据。最后追STM Clock tree 和STM 提供的I2C_Timing_Configuration工具解决了这个问题。现在分享给大家。 1. 首先我们观察Clock tree 查看 I2C clock source的缘由。 由 Clock tree可以得出I2C clock sou…

signature=694cde3d7f2450116894167453553a22,FIDO-U2F-Ledger 注册和登录过程中chrome和后台交互log分析...

注册流程 LOG Successfully registered device: No vendor metadata present! No device metadata present! Device transports: USB Registration Request javascript demo var request = {"appId":"https://localhost:8443","registeredKeys":…

使用命令行,一键修改文件夹所有文件修改日期改为最新

可以使用操作系统自带的命令行工具或者脚本来批量修改文件夹里面所有文件的修改日期。以下是两种常用的方法&#xff1a; 在 Windows 系统中使用 PowerShell 在 Windows 系统中&#xff0c;可以使用 PowerShell 来批量修改文件夹里面所有文件的修改日期。具体步骤如下&#xff…

Qt调试详细日志文件输出

qInstallMessageHandle安装消息&#xff0c;注册回调函数&#xff0c;对qDebug()、qWarning()、qCritial()、qInfo()、qFatal() 等函数输出信息重定向处理。 注明&#xff1a;以下方法仅适用于 Qt5 及以上版本。 目的&#xff1a;生成log.txt日志文件&#xff0c;记录详细日志…

Unity核心4——SpriteShape

Sprite Shape 是精灵形状的意思&#xff0c;它主要是方便我们以节约美术资源为前提&#xff0c;制作 2D 游戏场景地形或者背景的 ​ 在 Window --> Package Manager 中搜索 2D&#xff0c;选择 2D Sprite Shape&#xff0c;导入项目 一、Sprite Shape Profile 精灵形状概述文…

C51/C52--led流水灯、静态数码管

目录 一、led流水灯&#xff08;flowing water lamp&#xff09; 二、静态数码管 一、led流水灯&#xff08;flowing water lamp&#xff09; 我们在点亮一个led灯的基础上&#xff0c;对8个led灯按照某种特定的点亮规律进行操作&#xff0c;从而形成像水按顺序流动的效果。 …