TMS320F2812将flash中内容搬到ram中

  • 格式:pdf
  • 大小:195.44 KB
  • 文档页数:3

TMS320F2812将flash中内容搬到ram中
目前正在做一个基金项目,涉及到视觉图像处理方面的东东,在采集图像时用到了2812的两个外部中断,场中断XINT1,行中断NMI,本来行中断可以用XINT2的,但通过测试,XINT2有问题,所以只好用NMI了。

之前所做的一些处理工作,如图像数据采集、二值化处理、电机控制均是在线调试,调试通过后想脱机运行,但是在烧写flash时遇到了问题。

烧写进flash后,程序没有执行相应的功能,我当时就很纳闷,为什么在RAM里执行的好好的,但到了flash里却不执行了呢?这个问题困扰了我好几天。

后来我做了实验,进行了一些时间测试,我的测试条件是:系统时钟设置为60MHz,高速外围时钟为6MHz。

a.采用load program,测试行中断里这段程序for(buf=0;buf<20;buf++)的执行时间为5us;
b.相同的程序,烧写到flash后测得它的执行时间却达到了68us;
我看到这种结果后感到很吃惊,在flash里运行速度也太慢了吧,我一个行中断的时间只有64us,单纯的一个小延时就到到了68us,那其它的功能肯定别想实现了,这下我才明白为什么之前把程序烧到flash里没有运行结果了,因为行中断里面的代码执行时间已经远远超出64us了。

接下来摆在我面前的问题是如何解决这种高低速之间的矛盾,因为我的中断程序要进行图像采集,速度很快,而flash速度比较慢,所以接下来的任务就是如何实现把中断服务程序搬到RAM里面来运行。

翻了翻书,仔细研究了一下书中讲的如何将代码从flash搬到RAM里运行,按照自己的理解尝试了一下,最后终于成功了,我把我的搬运步骤列出来,跟大家一起分享一下。

第一阶段:修改2812_nonBIOS_flash.cmd文件
a.将初始化段中的.text, .cinit, .pinit, .const, .econst, .switch 块均放在FLASH_AB中;
b.将RAML1: origin=0x009000, length=0x001000 放在Page0区,之前的cmd里RAML1是放在Page1区;
c.将RAMH0: origin=0x3F8002, length=0x001FFE 放在Page1区,之前的cmd里RAMH0是放在Page0区,主要的目的是想增大数据存储区,让所有的动态变量全部放在RAMH0中,而之前的cmd中动态变量是被分配到RAML1中的,RAML1只有4K大小,影响采集的分辨率。

d.在SECTION的Data Memory中将.cio, .bss, .ebss, .sysmem, .esysmem 配置到
RAMH0中;
e.在的下面再添加下面这段:
secureRamFuncs : LOAD = FLASH_AB, PAGE=0
RUN = RAML0, PAGE = 0
RUN_START(_secureRamFuncs_runstart),
LOAD_START(_secureRamFuncs_loadstart),
LOAD_END(_secureRamFuncs_loadend)
secureRamFuncs这段之前的cmd中也有,这里也暂且把它列出来。

关键是要添加下面这段:
interruptRamFuncs : LOAD = FLASH_AB, PAGE = 0
RUN = RAML1, PAGE = 0
RUN_START(_interruptRamFuncs_runstart),
LOAD_START(_interruptRamFuncs_loadstart),
LOAD_END(_interruptRamFuncs_loadend)
以上是对cmd部分的修改。

第二阶段:修改DSP28_GlobalPrototypes.h文件
a.在文件的开始增加如下代码: #ifndef USER_NONBIOS_FLASH
#define USER_NONBIOS_FLASH
#endif
这段代码是借鉴一个例程上的,也可以不加。

b. 在// Global symbols defined in the linker command file 下面区域中添加如下代码
#ifdef USER_NONBIOS_FLASH
extern Uint16 secureRamFuncs_loadstart; // Used in flash example only
extern Uint16 secureRamFuncs_loadend; // Used in flash example only
extern Uint16 secureRamFuncs_runstart; // Used in flash example only
extern Uint16 interruptRamFuncs_loadstart;
extern Uint16 interruptRamFuncs_loadend;
extern Uint16 interruptRamFuncs_runstart;
#endif
关于secureRamFuncs的三个声明是之前就有的,后面的interruptRamFuncs的三个声明是自己加进去的,此时我才发现在cmd里面要用到这几个变量。

第三阶段:在DSP28_DefaultIsr.c 中添加以下两句代码:
#pragma CODE_SECTION(XINT1_ISR, "interruptRamFuncs");
#pragma CODE_SECTION(NMI_ISR, "interruptRamFuncs");
表示在interruptRamFuncs 块中为行、场中断服务程序分配空间。

第四阶段:正确书写memcpy函数
a. 首先进行系统控制寄存器的初始化,然后进行PIE控制寄存器的初始化以及PIE矢量表的初始化;
b. 在上述初始化后再进行拷贝工作,拷贝代码如下:
#ifdef USER_NONBIOS_FLASH
memcpy( &secureRamFuncs_runstart,
&secureRamFuncs_loadstart,
&secureRamFuncs_loadend - &secureRamFuncs_loadstart);
memcpy( &interruptRamFuncs_runstart,
&interruptRamFuncs_loadstart,
&interruptRamFuncs_loadend - &interruptRamFuncs_loadstart);
InitFlash();
#endif
当然也可以不要ifdef USER_NONBIOS_FLASH 和endif 这段,如果不要的话,在DSP28_GlobalPrototypes.h 就应把相应的定义全部去掉,这里我也是参考了下例程,想保持一种良好的习惯。

以上是我搬运中断服务程序到RAM运行的完整步骤,如果没有第三阶段,直接编译,会出现下面的warning: load address of uninitialized section interruptRamFuncs ignored。

我现在想起来了为什会出现这个warning,因为在主程序的memcpy 里使用了 interruptRamFuncs,
而 interruptRamFuncs 还没进行定义就使用,这是不符合规则的,#pragma的用法里有一条:在声明、使用XINT1_ISR 和 NMI_ISR 前必须用#pragma 进行定义。

完全按照以上四个阶段的操作来进行,编译没有错误,然后烧写进flash,程序能够运行,而且两个PWM口的输出逻辑完全符合我的预期,跟在线调试的结果一样。

最后脱机运行,我们的机器人终于可以动起来了。

困扰了很久的flash烧写终于有了一点小小成果,但是我仍然有点疑问,对下面这段拷贝代码:
memcpy( &secureRamFuncs_runstart,
&secureRamFuncs_loadstart,
&secureRamFuncs_loadend - &secureRamFuncs_loadstart);
InitFlash();
我看书上讲,如果要将代码从flash拷贝到RAM里运行,上面这几句是必须的。

我有点不太明白,这里的memcpy 到底拷贝的是哪部分的内容呢?希望各位朋友能够指教,一起交流交流。