细读DSP延时函数DSP28x_usDelay()及解决烧录至FLASH出错的方法

TI公司的DSP处理器(本文以C2000的F28377D为例,其他处理器同样原理)的程序为了实现精确的定时,使用了一个用汇编编写的延时函数DSP28x_usDelay(),该函数在文件F2837xD_usDelay.asm中,程序的细节请阅读该文件。为了调用该函数,在F2837xD_Examples.h中做了如下声明:

extern void F28x_usDelay(long LoopCount);// DO NOT MODIFY THIS LINE.
#define DELAY_US(A)  F28x_usDelay(((((long double) A * 1000.0L) / (long double)CPU_RATE) - 9.0L) / 5.0L)

利用宏定义的方式做了宏定义修正,来确保定时更加精确。

值得特别注意的是:
函数F28x_usDelay(long LoopCount)要想非常精确,必须在SARAM中运行,因此需要在运行时将其调入SARAM中。

下面谈谈如何实现将其调入SARAM中,需要做以下几个工作:

首先,在F2837xD_usDelay.asm中使用

.sect "ramfuncs"

上面代码意思是将该段代码定义到段“ramfuncs”中,段ramfuncs的位置在编译时指定,实际上是在CMD文件中的如下语句来指定:

ramfuncs LOAD = FLASHD, PAGE = 0,

RUN = RAML0, PAGE = 1,

LOAD_START(_RamfuncsLoadStart),

LOAD_END(_RamfuncsLoadEnd),

RUN_START(_RamfuncsRunStart)

第1行是将该段的装载在PAGA0的FLASHD中(PAGA0和FLASHD的分段请见CMD文件)

第2行表示该段的运行地址在PAGE1的RAML0中(PAGA1和RAML0的分段请见CMD文件);

LOAD_ START(_RamfuncsLoadStart)令编译器创建了一个变量RamfuncsLoadStart,该变量指向段ramfuncs的装载地址的首地址(其中,LOAD_ START为编译伪指令,详见CCS的帮助文档);

LOAD_ START(_RamfuncsLoadEnd)令编译器创建了一个变量RamfuncsLoadEnd,该变量指向段ramfuncs的装载地址的末地址(LOAD_ END为编译伪指令,详见CCS的帮助文档);

LOAD_ START(_RamfuncsRunStart)令编译器创建了一个变量RamfuncsRunStart,该变量指向段ramfuncs的运行地址的首地址(LOAD_ START为编译伪指令,详见CCS的帮助文档);

从第1和2行可以看出,段ramfuncs中的函数DSP28x_usDelay()的装载地址和运行地址是不同的,本程序中装载在Flash的块FLASHD中,而在SARAM L0中运行,但这只是需求目标,在实际运行时,DSP并不会自动将Flash中的代码拷贝到SARAM中,因此我们需要手动添加代码来完成。

在C函数中,为了使用变量RamfuncsLoadStartRamfuncsLoadEndRamfuncsRunStart,必须先声明,在工程文件DSP2837xD_GlobalPrototypes.h中已经有做了如下声明:

extern Uint16 RamfuncsLoadStart;
extern Uint16 RamfuncsLoadEnd;
extern Uint16 RamfuncsLoadSize;
extern Uint16 RamfuncsRunStart;
extern Uint16 RamfuncsRunEnd;
extern Uint16 RamfuncsRunSize;

但更常用的做法是直接在main程序前做如下定义:

extern Uint16 RamfuncsLoadStart;
extern Uint16 RamfuncsLoadSize;
extern Uint16 RamfuncsRunStart;

在main函数中调用如下函数,然后就可以使用了。

memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);// 把分配到 ramfuncs 段中的实时性要求高的关键代码从Flash中拷贝到RAM里执行

在上面main.c中,使用memCopy()函数将段ramfuncs中的函数DSP28x_usDelay()的代码从装载地址RamfuncsLoadStart—RamfuncsLoadEnd拷贝到RamfuncsRunStart开始的SARAM空间中。
在此之后我们便可以在主程序中调用延时函数DELAY_US(A)了,在程序运行时,只要调用DSP28x_usDelay()函数,都会自动地指向SARAM中相应的函数入口地址,这一点是自动完成的。memCopy()函数原型在memCopy.c中,在DSP2837xD_GlobalPrototypes.h声明。

最后但值得注意的是:即使这样做了上面的一系列校准工作,定时仍然有可能不完全精确,因为可能有中断可能会打断DSP28x_usDelay()的运行,所以在需求延时函数精准无误的情况下,在调用之前务必要关中断。

  • 6
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值