DSP2812 RAM不够用的解决方法
DSP2812的FLASH虽然很大,但是程序在这个FLASH区域运行的速度与在RAM中运行速度相比要慢很多,为此通常的做法是将需要快速运行的程序copy到ram中运行,通常将中断子程序以及中断中调用的其他子程序copy到RAM中运行,对于一些不需要太快速度处理的程序可以不管,让其在FLASH中运行。
将FLASH中程序copy到RAM中的运行的RAM需要连续地址区域,而最大的连续区域仅8k,对于一些大软件来说就不够用了;扩充可用RAM区间分两个阶段,通常例程中cmd文件中的分配并未将单个8k都用起来,所以第一个阶段是将可用最大的8k RAM连起来作为一个连续区间,如下:
RAML0 : origin = 0x008000, length = 0x002000 /* on-chip RAM block L0 */
同时将与其相邻的另外段RAML01屏蔽,如下:
// RAML1 : origin = 0x00A000, length = 0x000000 /* on-chip RAM block L1 */
通过以上修改可以将RAML0调整到最大的8k,这样对应着可copy子程序的ramfuncs就是8k:
ramfuncs : LOAD = FLASHD,
RUN = RAML0,
LOAD_START(_RamfuncsLoadStart),
LOAD_END(_RamfuncsLoadEnd),
RUN_START(_RamfuncsRunStart),
PAGE = 0
第二阶段,是将RAMH0的8k也作为可拷贝程序的区间,有一些采用了将.test拆分的方法(http://blog.sina.com.cn/s/blog_c82fc4020102wdms.html),个人觉得太麻烦,实际上可以再定义一个ramfuncs2,采用和 ramfuncs同样的定义方式,将RUN = RAML0改为RUN = RAMH0岂不是更简单?
ramfuncs : LOAD = FLASHD,
RUN = RAML0,
LOAD_START(_RamfuncsLoadStart),
LOAD_END(_RamfuncsLoadEnd),
RUN_START(_RamfuncsRunStart),
PAGE = 0
ramfuncs2 : LOAD = FLASHB, /* 与RAMH0同属PAGE1区 */
RUN = RAMH0,
LOAD_START(_RamfuncsLoadStart2),
LOAD_END(_RamfuncsLoadEnd2),
RUN_START(_RamfuncsRunStart2),
PAGE = 1
改成上面的代码后会首先报错,找不到RamfuncsLoadStart2、_RamfuncsLoadEnd2和_RamfuncsRunStart2,仍采用复制
的方法,首先找到_RamfuncsLoadStart定义的位置(DSP281x_GlobalPrototypes.h),改后如下:
extern Uint16 RamfuncsLoadStart;
extern Uint16 RamfuncsLoadEnd;
extern Uint16 RamfuncsRunStart;
//以下为新增加
extern Uint16 RamfuncsLoadStart2;
extern Uint16 RamfuncsLoadEnd2;
extern Uint16 RamfuncsRunStart2;
定义好之后,就是在主程序中将程序从FLASH中copy到RAM的部分再复制一次,如:
InitSysCtrl();
MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart);//将定义在ramfuncs段中的数据从FLASH拷贝到RAM中
MemCopy(&RamfuncsLoadStart2, &RamfuncsLoadEnd2, &RamfuncsRunStart2);//将定义在ramfuncs2段中的数据从FLASH 拷贝到RAM中(新增加)
InitFlash();
经过以上更改后,就可以将子程序放到ramfuncs2中了,如下:
#pragma CODE_SECTION(delay, "ramfuncs");
#pragma CODE_SECTION(delay3, "ramfuncs");
#pragma CODE_SECTION(SQRT_FPGA, "ramfuncs");
#pragma CODE_SECTION(CTR_PRAM_CAL, "ramfuncs2"); //ramfuncs2为新增加数据段
#pragma CODE_SECTION(CTR_PRAM_CAL3, "ramfuncs2");
#pragma CODE_SECTION(CTR_PRAM_CAL4, "ramfuncs2");
经过以上的两个步骤,可以充分利用DSP2812中总共18k RAM中的16k,剩下的2k可用于存储全局变量或者局部变量,完整的
cmd文件如下(可直接复制替换):
MEMORY
{
PAGE 0: /* Program Memory */
/* Memory (RAM/FLASH/OTP) blocks can be moved to PAGE1 for data allocation */
ZONE0 : origin = 0x002000, length = 0x002000 /* XINTF zone 0 */
ZONE1 : origin = 0x004000, length = 0x002000 /* XINTF zone 1 */
RAML0 : origin = 0x008000, length = 0x002000 /* on-chip RAM block L0 */ //0x001000
ZONE2 : origin = 0x080000, length = 0x080000 /* XINTF zone 2 */
ZONE6 : origin = 0x100000, length = 0x080000 /* XINTF zone 6 */
OTP : origin = 0x3D7800, length = 0x000800 /* on-chip OTP */
FLASHJ : origin = 0x3D8000, length = 0x002000 /* on-chip FLASH */
FLASHI : origin = 0x3DA000, length = 0x002000 /* on-chip FLASH */
FLASHH : origin = 0x3DC000, length = 0x004000 /* on-chip FLASH */
FLASHG : origin = 0x3E0000, length = 0x004000 /* on-chip FLASH */
FLASHF : origin = 0x3E4000, length = 0x004000 /* on-chip FLASH */
FLASHE : origin = 0x3E8000, length = 0x004000 /* on-chip FLASH */
FLASHD : origin = 0x3EC000, length = 0x004000 /* on-chip FLASH */
FLASHC : origin = 0x3F0000, length = 0x004000 /* on-chip FLASH */
FLASHA : origin = 0x3F6000, length = 0x001F80 /* on-chip FLASH */
CSM_RSVD : origin = 0x3F7F80, length = 0x000076 /* Part of FLASHA. Program with all 0x0000 when CSM is in use.
*/
BEGIN : origin = 0x3F7FF6, length = 0x000002 /* Part of FLASHA. Used for "boot to Flash" bootloader mode. */
CSM_PWL : origin = 0x3F7FF8, length = 0x000008 /* Part of FLASHA. CSM password locations in FLASHA */
/* ZONE7 : origin = 0x3FC000, length = 0x003FC0 /* XINTF zone 7 available if MP/MCn=1 */
ROM : origin = 0x3FF000, length = 0x000FC0 /* Boot ROM available if MP/MCn=0 */
RESET : origin = 0x3FFFC0, length = 0x000002 /* part of boot ROM (MP/MCn=0) or XINTF zone 7 (MP/MCn=1) */
VECTORS : origin = 0x3FFFC2, length = 0x00003E /* part of boot ROM (MP/MCn=0) or XINTF zone 7 (MP/MCn=1) */
PAGE 1 : /* Data Memory */
/* Memory (RAM/FLASH/OTP) blocks can be moved to PAGE0 for program allocation */
/* Registers remain on PAGE1 */
RAMM0 : origin = 0x000000, length = 0x000400 /* on-chip RAM block M0 */
RAMM1 : origin = 0x000400, length = 0x000400 /* on-chip RAM block M1 */
// RAML1 : origin = 0x00A000, length = 0x000000 /* on-chip RAM block L1 */
FLASHB : origin = 0x3F4000, length = 0x002000 /* on-chip FLASH */
RAMH0 : origin = 0x3F8000, length = 0x002000 /* on-chip RAM block H0 */
}
/* 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
{
/* Allocate program areas: */
.cinit : > FLASHC PAGE = 0//FLASHA
.pinit : > FLASHC, PAGE = 0//FLASHA
.text : > FLASHC PAGE = 0//FLASHA
codestart : > BEGIN PAGE = 0
ramfuncs : LOAD = FLASHD,
RUN = RAML0,
LOAD_START(_RamfuncsLoadStart),
LOAD_END(_RamfuncsLoadEnd),
RUN_START(_RamfuncsRunStart),
PAGE = 0
ramfuncs2 : LOAD = FLASHB,
RUN = RAMH0,
LOAD_START(_RamfuncsLoadStart2),
LOAD_END(_RamfuncsLoadEnd2),
RUN_START(_RamfuncsRunStart2),
PAGE = 1
csmpasswds : > CSM_PWL PAGE = 0
csm_rsvd : > CSM_RSVD PAGE = 0
/* Allocate uninitalized data sections: */
.stack : > RAMM0 PAGE = 1
.ebss : > RAMM1 PAGE = 1
.esysmem : > RAMM1 PAGE = 1
/* Initalized sections go in Flash */
/* For SDFlash to program these, they must be allocated to page 0 */
.econst : > FLASHC PAGE = 0 //FLASHA
.switch : > FLASHC PAGE = 0 //FLASHA
/* Allocate IQ math areas: */
IQmath : > FLASHA PAGE = 0 //FLASHC /* Math Code */
IQmathTables : > ROM PAGE = 0, TYPE = NOLOAD /* Math Tables In ROM */
/* .reset is a standard section used by the compiler. It contains the */
/* the address of the start of _c_int00 for C Code. /*
/* When using the boot ROM this section and the CPU vector */
/* table is not needed. Thus the default type is set here to */
/* DSECT */
.reset : > RESET, PAGE = 0, TYPE = DSECT
vectors : > VECTORS PAGE = 0, TYPE = DSECT
}
经过以上改动后,新扩展的RAM区实测可用!
一些理解:LOAD_START(_RamfuncsLoadStart)表示告诉编译器将这一段编译之后产生的起始地址存入RamfuncsLoadStart变量中,其他的变量也类似,这样在主程序运行时的MemCopy()才会找到相应的数值,也就是说LOAD_START(_RamfuncsLoadStart)这句是赋值功能。