28388D上电时从BOOT跳转到main过程分析

上一篇讲到,DSP的BOOT流程是:

上电 =》从0x3F FFC0开始取复位中断向量=》跳转到InitBoot =》启动系统boot (StartSystemBoot)。

在系统boot里面,如果配置选择的是waitBoot模式,就会停在一个死循环中。那么,如果不是waitBoot模式,而是FLASH_BOOT模式呢?接下来继续分析。

FLASH_BOOT模式

首先,看看CPU1BROM_startSystemBoot()函数的最后:

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

如果不是WAIT_BOOT(或者WAIT_BOOT_ALT1),则进入else分析,开启开门狗,返回程序入口地址。如果是FLASH_BOOT,则entryAddress = 0x 0008 0000。这个值作为函数的返回值,保存在ACC寄存器里。后面会用到的!

CPU1BROM_startSystemBoot函数被调用的地方在这里:

cpu1brom_init_boot.asm文件中:    LCR    CPU1BROM_startSystemBoot

;
; Branch to system initialization to run final initializations and execute boot mode
;
    LCR    CPU1BROM_startSystemBoot


;
; Function: ExitPBISTLoc
;
; Cleanup and exit after PBIST. At this point the EntryAddr
; is located in the ACC register
;
ExitPBISTLoc:
    BF      ExitBoot,UNC

因此,CPU1BROM_startSystemBoot函数返回后继续执行:    BF      ExitBoot,UNC

退出系统BOOT

ExitBoot函数如下:

;
; Function: ExitBoot
;
; This module cleans up after boot
;
; 1) Make sure the stack is re-initialized
; 2) Push 0 onto the stack so RPC will be
;    0 after using LRETR to jump to the
;    entry point
; 2) Load RPC with the entry point
; 3) Clear all XARn registers
; 4) Clear ACC, P and XT registers
; 5) LRETR - this will also clear the RPC
;    register since 0 was on the stack
;
ExitBoot:
;
;   Insure that the stack is re-initialized
;
    MOV     SP,#__stack

;
; Clear the bottom of the stack.  This will endup
; in RPC when we are finished
;
    MOV     *SP++,#0
    MOV     *SP++,#0

;
; Load RPC with the entry point as determined
; by the boot mode.  This address will be returned
; in the ACC register.
;
    PUSH    ACC
    POP     RPC

;
; Put registers back in their reset state.
;
; Clear all the XARn, ACC, XT, and P and DP
; registers
;
; NOTE: Leave the device in C28x operating mode
;       (OBJMODE = 1, AMODE = 0)
;
    ZAPA
    MOVL    XT,ACC
    MOVZ    AR0,AL
    MOVZ    AR1,AL
    MOVZ    AR2,AL
    MOVZ    AR3,AL
    MOVZ    AR4,AL
    MOVZ    AR5,AL
    MOVZ    AR6,AL
    MOVZ    AR7,AL
    MOVW    DP, #0

;
;   Restore ST0 and ST1.  Note OBJMODE is
;   the only bit not restored to its reset state.
;   OBJMODE is left set for C28x object operating
;   mode.
;
;  ST0 = 0x0000     ST1 = 0x0A0B
;  15:10 OVC = 0    15:13      ARP = 0
;   9: 7  PM = 0       12       XF = 0
;      6   V = 0       11  M0M1MAP = 1
;      5   N = 0       10  reserved
;      4   Z = 0        9  OBJMODE = 1
;      3   C = 0        8    AMODE = 0
;      2  TC = 0        7 IDLESTAT = 0
;      1 OVM = 0        6   EALLOW = 0
;      0 SXM = 0        5     LOOP = 0
;                       4      SPA = 0
;                       3     VMAP = 1
;                       2    PAGE0 = 0
;                       1     DBGM = 1
;                       0     INTM = 1
;
    MOV     *SP++,#0
    MOV     *SP++,#0x0A0B
    POP     ST1
    POP     ST0

;
;   Jump to the EntryAddr as defined by the
;   boot mode selected and continue execution
;
    LRETR

最关键的是下面几句:

    PUSH    ACC
    POP     RPC

    LRETR

前面提到了,CPU1BROM_startSystemBoot函数返回时,把下一段程序的入口地址保存在ACC寄存器里。这里先把ACC压栈,再出栈到RPC里!到这时,RPC就保存了下一段程序的地址,就是FLASH的入口地址0x0008 0000。

 

跳转到FLASH入口

当执行LRETR时,RPC的值就会加载到PC中,CPU跳转到FLASH的入口开始执行。

 现在,调试器也显示到f2838x_codestartbranch.asm文件中的code_start了:

 到这个时候,已经脱离了厂家内置在CPU中的boot了,运行到用户领空。后面的代码跟用户及编译器有关了。

跳转到_c_int00

再往下,就是关闭看门狗,跳转到_c_int00。

    .if WD_DISABLE == 1

    .text
wd_disable:
    SETC OBJMODE        ;Set OBJMODE for 28x object code
    EALLOW              ;Enable EALLOW protected register access
    MOVZ DP, #7029h>>6  ;Set data page for WDCR register
    MOV @7029h, #0068h  ;Set WDDIS bit in WDCR to disable WD
    EDIS                ;Disable EALLOW protected register access
    LB _c_int00         ;Branch to start of boot._asm in RTS library

    .endif

_c_int00也是有源代码的:boot28.asm。这个文件位置跟编译器的安装路径和编译器的版本有关。

比如,我使用的编译器版本是V16.9.1,对应的boot28.asm文件在:

D:\ti\ccs1040\ccs\tools\compiler\ti-cgt-c2000_16.9.1.LTS\lib\src\boot28.asm

主要功能是初始化全局变量:c_int, DO_BINIT, DO_PINT, _const_init

当所有的初始化完成之后,马上就要到main函数了。稍等一下,在进入main之前,还有最后一道关:args_main

调用__args_main

最后的关键时刻,先调用__args_main。如果函数返回了,则再调用_exit。

BYPASS_AUTO_INIT:
****************************************************************************
*  CALL USER'S PROGRAM                                                     *
****************************************************************************
	LCR     __args_main			; execute main()
	LCR  	_exit
	.endasmfunc

__args_main函数是C代码,在args_main.c文件中:

int _args_main()
{
#pragma diag_suppress 1107,173
    register ARGS *pargs = (ARGS*)_symval(&__c_args__);
#pragma diag_default 1107,173
   register int    argc = 0;
   register char **argv = 0;

   if (_symval(&__c_args__) != NO_C_ARGS) 
   { argc = pargs->argc; argv = pargs->argv; }
  
   return main(argc, argv);
}

至此,已经完整地走完了孕育过程,main函数即将降临!让我们一起期待main函数的精彩表现吧!

  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值