(一)前言
一般情况下,未明确赋初值的全局变量会被自动清零,而且ANSI C中也有这一规定,之前写程序都默认这是没有例外的规定了。然而,在调试28035程序的时候发现,未赋初值的全局变量并没有被清零,而是一个随机值,这说明在TI的DSP中,全局变量并不会自动清零。TI论坛中的这个讨论也证实了这一结论,由此可见,TI的编译器的确会有这个现象。这并不是TI编译器的设计缺陷,TI的编译器是专门这样设计的,这样设计的目的在于赋予程序员更大的灵活性。在某些情况下,是需要对全局变量进行选择性清零或其它操作的。
一个实际的例子是:假设使用了看门狗,在某些情况下系统看门狗复位了,对于某些控制系统而言,这时是要求系统在最短的时间内恢复之前的工作状态的。这种情况下,一般在程序开头加上一段检测代码,检测复位原因,如果是正常上电复位,则对全局变量进行清零操作;若判断出是看门狗复位,则自动执行之前的程序。系统软复位时并没有掉电,故RAM中的数据不会丢失。因为此时并没有对全局变量进行清零,之前的全局变量数据全部都在,此时就可以很快的恢复之前的工作状态,并且还可以使用一些全局变量辅助判断之前的错误复位的原因。
有两种初始化方式:
1-在声明全局变量显式的赋初值
2-自己写一个清零函数完成这一工作
(二)程序启动过程
在描述RAM初始化前需要先了解DSP的程序是怎样启动的。
2.1.DSP上电引导过程
当CPU上电时,会引起上电复位RESET,RESET向量位于固化在boot ROM中的CPU Vector Table。TMS320x2803x的CPU Vector Table位于地址0x3F E000 - 0x3F FFFF。
CPU Vector Table内容如下图,其中唯一可被正常响应的向量就是位于0x3F FFC0的RESET向量。RESET向量出厂固化为指向InitBoot函数,InitBoot函数位于上图中的Bootloader functions区域。
进入InitBoot函数后,开始执行Bootloader模式查询过程,并根据查询选择的模式根据需求判断是否调用接口函数(如CAN、SCI、I2C等)读取“固定大小”内的源程序并搬移到RAM中执行,或者直接进入入口地址(如FLASH启动,地址为FLASH用户可用区域的最后2字的位置),TMS320x2803x FLASH入口地址为0x3F 7FF6。至此,完成一次Bootloader过程。
当仅使用一次引导的程序跳转功能,不使用一次引导复制程序时,最终默认配置将进入FLASH区域的BEGIN区(地址0x3F 7FF6)。
对于BEGIN区,查看CMD文件中的MEMORY指令,如下图。BEGIN位于PAGE 0,起始地址为0x3F 7FF6,长度为0x00 0002。(注:该地址恰好位于FLSAH用户可用区的末尾,且长度刚好可以存放一条长跳转语句)。
对于BEGIN区内存放的程序段,查看CMD文件中的SECTION指令,如下图。可以看出程序段“codestart”将被存放于此。
查看工程中的“xxx_CodeStartBranch.asm”汇编源文件,如下图,BEGIN区将存放一条长跳转指令,该指令默认指向c_int00。
c_int00是C/C++程序的入口地址,用于完成C运行环境的初始化,最终跳转到main函数,开始运行应用程序。
1) 定义系统栈.stack,并初始化栈指针,配置相关寄存器
2) 初始化全局变量(.cinit)
3) 若使用C++,还会完成全局对象构造(.pinit)
4) 调用main函数运行C程序
5) 当main函数return时,调用exit函数
2.2.系统初始化
在TI官网找到了rts2800_ml.lib对应的boot28.asm源文件,<C:\ti\ccs1210\ccs\tools\compiler\ti-cgt-c2000_22.6.0.LTS\lib\src>,其中核心内容为c_int00函数,其中关于“定义系统栈.stack,并初始化栈指针,配置相关寄存器”等系统初始化。
全局变量初始化(.cinit)分为两种初始化方式:运行时自动初始化、加载时初始化。
1) 运行时自动初始化
.cinit段与其他段一并从目标文件加载入存储器,链接器定义了一个名为CINIT的符号,用来标识初始化表的首地址。程序开始运行时,C启动程序将表中的数据复制给.bss段中特定的变量,这便允许将初始化数据放入ROM/FLASH中,在每次程序开始时将其复制到RAM中,从而达到ROM/FLASH保存初值、RAM中运行变量的目的。
.cinit段初始化表的格式如下图所示。
2) 加载时初始化:
连接器将.cinit段头中的STYP_COPY置位为1,并告知加载器不要把.cinit中的表加载入存储器并将符号CINIT赋值-1,告诉启动器初始化表不在储存器中,因此启动时不执行初始化。而由加载器直接把目标文件的.cinit复制到RAM的.bss中。
下面说明表明未显示初始的全局变量和静态变量不会初始化。
更详细的内容参考《TMS320C28x Optimizing C/C++ Compilerv22.6.0.LTS》7.10节。
(三)RAM初始化
3.1.在main函数前的RAM初始化
内存映射如图所示:
BOOT的x_CodeStartBranch.asm中把_c_int00替换为RAM初始化程序替换为mian_init
APP初始化
APP初始化时与BOOT初始化稍有不同, 在BOOT中Bootver和BootFlag为BOOT的版本号和标志位,不进行初始化。
3.2.程序运行中的RAM初始化
在main函数运行后,调用RAM初始化函数。
void InitRAM(void)
{
volatile UINT16 *pmemaddr;
UINT16 j, memerr;
memerr=0;
//L0 SARAM(2K*16) Check
pmemaddr = (UINT16 *) 0x8000;
for (j = 0x0000; j < 0x1000; j++)
{
*(pmemaddr + j) = 0x5555;
if (*(pmemaddr + j) != 0x5555)
{
memerr=1;
}
*(pmemaddr + j) = 0xaaaa;
if (*(pmemaddr + j) != 0xaaaa)
{
memerr=1;
}
*(pmemaddr + j) = 0x0000;
}
//L1 SARAM(1K*16) Check
pmemaddr = (UINT16 *) 0x9000;
for (j = 0x0000; j < 0x1000; j++)
{
*(pmemaddr + j) = 0x5555;
if (*(pmemaddr + j) != 0x5555)
{
memerr=1;
}
*(pmemaddr + j) = 0xaaaa;
if (*(pmemaddr + j) != 0xaaaa)
{
memerr=1;
}
*(pmemaddr + j) = 0x0000;
}
//RAML2L3 SARAM(1K + 4K)*16 Check
/* pmemaddr = (UINT16 *) 0x3F8000;
for (j = 0x0000; j < 0x800; j++)
{
*(pmemaddr + j) = 0x5555;
if (*(pmemaddr + j) != 0x5555)
{
memerr=1;
}
*(pmemaddr + j) = 0xaaaa;
if (*(pmemaddr + j) != 0xaaaa)
{
memerr=1;
}
*(pmemaddr + j) = 0x0000;
} */
if(memerr == 1)
{
while(1) // ???????????1?7
{
asm(" RPT #7 || NOP");
}
}
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/75266c900eac4716bd6f5ac56922e76c.png)
这个方法有隐患,在申明全局变量时赋值非0值,在该阶段会被清零。因此只能在初始化RAM再对全局变量进行初始赋值。
# 参考
[TMS320F280025的BOOT流程](https://blog.csdn.net/booksyhay/article/details/120172063)
[TMS320F280049系列文章之第N章 Bootloader(TMS320F28004x Flash API Reference Guide)的学习](https://blog.csdn.net/weixin_52554132/article/details/128882818?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170536965016800182197893%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=170536965016800182197893&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-2-128882818-null-null.142%5Ev99%5Epc_search_result_base4&utm_term=TMS320F28034%E7%9A%84BOOT%E6%B5%81%E7%A8%8B&spm=1018.2226.3001.4187)