在ti sprc097的example中,提供了一个us延时函数,其使用很简单,它的声明放在了DSP281x_Examples.h里面:
#define CPU_RATE 6.667L // for a 150MHz CPU clock speed (SYSCLKOUT)
// DO NOT MODIFY THIS LINE. #define DELAY_US(A) DSP28x_usDelay(((((long double) A * 1000.0L) / (long double)CPU_RATE) - 9.0L) / 5.0L)
ps:上面的CPU_RATE的值要与DSP281x_SysCtrl.c里面的InitPll(0xA);的参数相对应。
使用时候,调用即可,单位为us(microseconds)。但是为了确保延时准确,还要注意两个事情:
1、在 0 waitstate ram中执行此函数,我们知道读flash会有一个waitstate的延时,这个会影响此函数计时的准确性,F2812各个存储区的waitstate如下:
from:TMS320F281x Data Sheet (Rev. L).pdf
所以,如上表,我们可以放在M0,M1,L0&L1,H0来运行此函数。
2、为确保准确性,在运行此函数之前关中断。如果不能关中断,那么这个延时可能比预想的要长。
实际使用中,如何将此函数放在0 waitstate ram中运行呢?
情景一、Ram调试(即程序段(page0)和数据段(page1)都在ram中),那么不用过多的管,因为本来就载入(Load)在ram中,运行肯定也是。
情景二、写入到Flash,在Flash中运行。注意到在DSP281x_usDelay.asm中是将此函数定义到了段“ramfuncs”中:
.def _DSP28x_usDelay .sect "ramfuncs"
而“ramfuncs”在cmd中是这么定义的:
MEMORY { PAGE 0: /* Program Memory */ /* Memory (RAM/FLASH/OTP) blocks can be moved to PAGE1 for data allocation */ ... ...
RAML0 : origin = 0x008000, length = 0x001000 /* on-chip RAM block L0 */ FLASHD : origin = 0x3EC000, length = 0x004000 /* on-chip FLASH */ ... ... PAGE 1 : /* Data Memory */ /* Memory (RAM/FLASH/OTP) blocks can be moved to PAGE0 for program allocation */ /* Registers remain on PAGE1 */ ... ... RAML1 : origin = 0x009000, length = 0x001000 /* on-chip RAM block L1 */ ... ... } /* Allocate sections to memory blocks. Note: codestart user defined section in DSP28_CodeStartBranch.asm used to redirect code execution when booting to flash ramfuncs user defined section to store functions that will be copied from Flash into RAM */ SECTIONS { ... ... ramfuncs : LOAD = FLASHD, RUN = RAML0, LOAD_START(_RamfuncsLoadStart), LOAD_END(_RamfuncsLoadEnd), RUN_START(_RamfuncsRunStart), PAGE = 0 ... ... }
可以看到,这个段加载在FLASHD,运行在RAML0,完全ok,这样,只要再运行DSP28x_usDelay之前,手动copy一下就行了:
// Copy time critical code and Flash setup code to RAM // This includes the following ISR functions: EvaTimer1(), EvaTimer2() // EvbTimer3 and and InitFlash(); // The RamfuncsLoadStart, RamfuncsLoadEnd, and RamfuncsRunStart // symbols are created by the linker. Refer to the F2812.cmd file. MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart);
运行一下这个MemCopy函数即可,RamfuncsLoadStart, RamfuncsLoadEnd, 和RamfuncsRunStart是在上面的cmd文件中定义的,连接器在分配空间之后,把段ramfuncs 的几个地址幅值到这几个变量中了。LOAD_START等几个的定义可见
spru513b :TMS320C28x Assembly Language Tools User’s Guide
而当你决定在Flash中运行,其实上面MemCopy的工作本来就是必须做的,因为在Flash中运行的话,InitFlash(); 本来就必须在Ram中运行,而InitFlash()也刚好定义在ramfuncs里面,在运行InitFlash()之前就必须运行一次MemCopy了,所以,对于使用DSP28x_usDelay,相当于不用任何附加的操作,添加其源文件直接使用即可(当然,要自己考虑中断的影响)。