使用TI的F2811开发的过程中,发现程序刷到FLASH之后,掉电重启之后并不能正常运行,Debug的时候一旦进行CPU RESET之后也无法进入main()函数进行运行。但由于这个芯片过时已久,网上关于它的启动描述少之又少,遂从TI的手册上学习了281X系列芯片的启动过程,记录如下:

首先放出两个关于有启动过程描述的技术手册:

(1)281X Boot ROM参考手册:TMS320x281x Boot ROM Reference Guide (Rev. C)https://www.ti.com/lit/ug/spru095c/spru095c.pdf?ts=1749647921252

(2)281X数据手册:

TMS320F281x Digital Signal Processors datasheet (Rev. V)https://www.ti.com/lit/ds/symlink/tms320f2810-q1.pdf?ts=1749778682409&ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FTMS320F2810-Q1%253Fqgpn%253Dtms320f2810-q1

 接下来,关于它的启动过程,对照着三幅图来讲:

 

图1 Bootloader流程图,红框为图2的描述内容,绿框为图3的描述内容
图2 Boot 模式选择
图3 F281X程序流程图 红框为启动过程的内容

 以FLASH启动步骤为例,步骤描述如下,其他启动方式见上述参考文献1:

(1)CPU接收到RESET信号:这个信号可能是复位键被按下(XRS管脚低电平),也可能是CCS中调试时按下RESET

(2)判断XMPNMC信号:这是一个实际管脚的信号。当为高电平时DSP工作于微处理器模式,扩展XINTF有效,程序将从扩展XINTF的Zone7启动;当为低电平时工作于微计算机模式,扩展XINTF无效,将从内部Boot Rom启动。2812有这个管教,可以设置不同的启动模块。而2811、2810均无XINTF模块,默认该信号为低,将直接进入步骤3。

(3)PC指针来到0x3FFFC0地址:该地址保存着DSP的复位向量,所谓向量,通俗可以理解为指针,指针指向接下来要执行的函数地址。0x3FFFC0出厂存放固定地址:0x3FFC00。

(4)PC指针来到0x3FFC00地址:该地址出厂就被写入了InitBoot函数(不需要用户自定义),接下来DSP就执行InitBoot函数。见图2红框的内容。而InitBoot函数中,最重要的步骤是判断Boot模式,可以从FLASH、SCI、SPI 、H0 SARAM、OTP等选择。常用的是选择FLASH启动。怎么样判断是要选择哪个模式呢?是读取几个GPIO口的电平状态来决定,如图2所示。我们从FLASH中启动时,只需要GPIOF4(SCITXDA)的管脚是高电平即可,其余管脚信号不关心。这一点在设计电路的时候需要格外注意(根据启动方式的不同,几个管脚信号的上拉下拉选择);

(5)跳转到所选模式的入口地址:执行完InitBoot函数之后,会跳转到所选启动模式的入口地址,这个地址在模式为FLASH、H0 SARAM、OTP模式下都是固定的,见图2。而FLASH模式下会跳转到0x3F7FF6,这个地址存放着codestart段。实际上也是一个指针,指向接下来要执行的程序入口。而0x3F7FF6存放的codestart的定义,首先要在codestartbranch.asm中定义该段(这个库文件直接用就行,不用更改),其次要在.cmd文件中定义codestart段的分配内存,要有这么两句(这两句不是紧挨着的,一个是在MEMORY中,一个是在SECTION中,关于cmd文件的配置,请自行查找资料):

 BEGIN_FLASH : origin = 0x3F7FF6, length = 0x000002 
 codestart         : > BEGIN_FLASH,      PAGE = 3   

(6)跳转到0x3F7FF6内存所指的函数:也就是codestartbranch.asm中的几句代码,其中最主要的是执行_c_int00函数(LB _c_int00 ):

code_start:
    .if WD_DISABLE == 1
        LB wd_disable       ;Branch to watchdog disable code
    .else
        LB _c_int00         ;Branch to start of boot.asm in RTS library
    .endif

(7)执行_c_int00 函数,这个函数是在rts2800.lib的静态库文件中的boot28.asm中,所以在项目链接的库文件目录下一定要有这个库,当然也可能是另外一个名字(见图4),总之哪个编译能过用哪个

图4 几个不同的rts2800库,图来自顾卫钢老师《手把手教你学DSP》p61

(8) LCR     __args_main:这是_c_int00函数最后的语句,意思是跳转到__args_main函数执行,这个函数是编译器自带的,不用用户自己定义(不用任何操作,CCS自己会帮你配置好)。_args_main函数的最后一行为:

 return main(argc, argv);

返回main()函数。

(9)接下来就会到达用户项目中的main()函数中运行了。

注:关于(6)~(9)步骤,图3红框部分简要的做了解释。

最后,附上ROM的内存图示已供理解:

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐