【DSP28035】TI28035的RAM初始化问题

1 篇文章 0 订阅
文章详细阐述了在TI的DSP处理器中,全局变量不会自动清零的现象,并解释了这一设计的灵活性。介绍了程序启动过程,包括DSP的上电引导、系统初始化,以及RAM的初始化。在RAM初始化部分,提供了检查和初始化RAM的代码示例,强调了在初始化后再对全局变量赋值的必要性。
摘要由CSDN通过智能技术生成

(一)前言

	一般情况下,未明确赋初值的全局变量会被自动清零,而且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。

图1 Reset vector内存映射地址
CPU Vector Table内容如下图,其中唯一可被正常响应的向量就是位于0x3F FFC0的RESET向量。RESET向量出厂固化为指向InitBoot函数,InitBoot函数位于上图中的Bootloader functions区域。
图2 Vector Locations
进入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用户可用区的末尾,且长度刚好可以存放一条长跳转语句)。
图3 Flash CMD
对于BEGIN区内存放的程序段,查看CMD文件中的SECTION指令,如下图。可以看出程序段“codestart”将被存放于此。
图4 codestart
查看工程中的“xxx_CodeStartBranch.asm”汇编源文件,如下图,BEGIN区将存放一条长跳转指令,该指令默认指向c_int00。
图5 _c_int00
c_int00是C/C++程序的入口地址,用于完成C运行环境的初始化,最终跳转到main函数,开始运行应用程序。

图6 System Initialization
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段初始化表的格式如下图所示。
图7 Initalization of Variables
2) 加载时初始化:
连接器将.cinit段头中的STYP_COPY置位为1,并告知加载器不要把.cinit中的表加载入存储器并将符号CINIT赋值-1,告诉启动器初始化表不在储存器中,因此启动时不执行初始化。而由加载器直接把目标文件的.cinit复制到RAM的.bss中。
下面说明表明未显示初始的全局变量和静态变量不会初始化。
图8 Automatic Initalization of  Variable for COFF
更详细的内容参考《TMS320C28x Optimizing C/C++ Compilerv22.6.0.LTS》7.10节。

(三)RAM初始化

3.1.在main函数前的RAM初始化

	内存映射如图所示:

图9 内存映射

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)







 
 
 






		









	







		


		

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值