一般来说,把一个在RAM里正常运行的程序移植到FLASH里(运行时将FLASH中的程序拷贝到RAM中运行)的步骤如下:
1.需要将适合RAM运行环境的CMD文件移出工程,替换成FLASH专用的的F28335.cmd
2.将另一个文件DSP2833x_CodeStartBranch.asm添加到工程中,如果工程内本来就有这个文件,就不用再添加了
3.在DSP28_SysCtrl.c文件中添加如下代码,如果工程里已有InitFlash函数,则不用再添加,检查下函数内容即可
1 #pragma CODE_SECTION(InitFlash, "RamFuncs"); 2 3 void InitFlash(void) 4 5 { 6 7 EALLOW; 8 9 //Enable Flash Pipeline mode to improve performance 10 11 //of code executed from Flash. 12 13 FlashRegs.FOPT.bit.ENPIPE = 1; 14 15 // CAUTION 16 17 //Minimum waitstates required for the flash operating 18 19 //at a given CPU rate must be characterized by TI. 20 21 //Refer to the datasheet for the latest information. 22 23 24 25 //Set the Paged Waitstate for the Flash 26 27 FlashRegs.FBANKWAIT.bit.PAGEWAIT = 5; 28 29 30 31 //Set the Random Waitstate for the Flash 32 33 FlashRegs.FBANKWAIT.bit.RANDWAIT = 5; 34 35 36 37 //Set the Waitstate for the OTP 38 39 FlashRegs.FOTPWAIT.bit.OTPWAIT = 8; 40 41 42 43 // CAUTION 44 45 //ONLY THE DEFAULT VALUE FOR THESE 2 REGISTERS SHOULD BE USED 46 47 FlashRegs.FSTDBYWAIT.bit.STDBYWAIT = 0x01FF; 48 49 FlashRegs.FACTIVEWAIT.bit.ACTIVEWAIT = 0x01FF; 50 51 EDIS; 52 53 54 55 //Force a pipeline flush to ensure that the write to 56 57 //the last register configured occurs before returning. 58 59 60 61 asm(" RPT #7 || NOP"); 62 63 }
4.在main函数所在的源文件中,添加下面所示的代码,位置可以放在main函数之前
1 extern Uint16 RamFuncs_loadstart; 2 3 extern Uint16 RamFuncs_loadend; 4 5 extern Uint16 RamFuncs_runstart;
5.在main函数中添加如下以红色字体显示的代码
1 /*初始化系统*/ 2 3 InitSysCtrl(); 4 5 memcpy(&RamFuncs_runstart,&RamFuncs_loadstart,&RamFuncs_loadend - &RamFuncs_loadstart); 6 7 asm(" RPT #8 || NOP"); 8 9 10 11 /*FLASH 初始化 */ 12 13 InitFlash(); 14 15 16 17 /*关中断*/ 18 19 DINT; 20 21 IER = 0x0000; 22 23 IFR = 0x0000;
6.在头文件DSP2833x_GlobalPrototypes.h中添加FLASH初始化函数的声明,如果已经声明,就不用再添加
1 extern void InitFlash(void);
//7.验证Boot mode //通常已经正确选择
通常,上述步骤完成之后,在编译没有报错的情况下直接Debug即可将程序烧写进FLASH,之后断电,拔掉仿真器,再重新上电,程序即可自动运行。
但是我在实际调试的过程中却遇到了在将程序Debug之后,直接在线仿真调试程序可以正常运行,但是一旦断电,拔掉仿真器,再重新上电之后,程序无法自动运行的现象。
经过一步步把程序向例程迁移→调试→迁移的尝试,最后发现问题出在DSP2833x_usDelay.asm 文件的内容和新的CMD文件配置不符。
原版的DSP2833x_usDelay.asm 文件是这样写的:
1 .def _DSP28x_usDelay 2 .sect "ramfuncs" 3 4 .global __DSP28x_usDelay 5 _DSP28x_usDelay: 6 SUB ACC,#1 7 BF _DSP28x_usDelay,GEQ ;; Loop if ACC >= 0 8 LRETR
可以看到分配到了"ramfuncs"段,而新的CMD文件中并无对应的Section
1 SECTIONS 2 { 3 4 /* Allocate program areas: */ 5 .cinit : > FLASHB PAGE = 0 6 .pinit : > FLASHB PAGE = 0 7 .text : > FLASHB PAGE = 0 8 codestart : > BEGIN PAGE = 0 9 //RamFuncs : > FLASHC PAGE = 0 10 RamFuncs : LOAD = FLASHC, PAGE = 0 /* Should be Flash */ 11 RUN = RAML1, PAGE = 0 /* Must be CSM secured RAM */ 12 LOAD_START(_RamFuncs_loadstart), 13 LOAD_END(_RamFuncs_loadend), 14 RUN_START(_RamFuncs_runstart) 15 16 17 csmpasswds : > CSM_PWL PAGE = 0 18 csm_rsvd : > CSM_RSVD PAGE = 0 19 20 /* Allocate uninitalized data sectins: */ 21 .stack : > RAMM1 PAGE = 1 22 .ebss : > RAML5 PAGE = 1 23 .esysmem : > RAMM1 PAGE = 1 24 25 /* Initalized sections go in Flash */ 26 /* For SDFlash to program these, they must be allocated to page 0 */ 27 .econst : > FLASHB PAGE = 0 28 .switch : > FLASHB PAGE = 0 29 30 /* Allocate IQ math areas: */ 31 IQmathTables : > IQTABLES, PAGE = 0, TYPE = NOLOAD 32 IQmathTables2 : > IQTABLES2, PAGE = 0, TYPE = NOLOAD 33 FPUmathTables : > FPUTABLES, PAGE = 0, TYPE = NOLOAD 34 35 .reset : > RESET, PAGE = 0, TYPE = DSECT 36 vectors : > VECTORS PAGE = 0, TYPE = DSECT 37 38 /* Allocate ADC_cal function (pre-programmed by factory into TI reserved memory) */ 39 .adc_cal : load = ADC_CAL, PAGE = 0, TYPE = NOLOAD 40 41 }
那么既然找到了问题的所在,解决方法也就很简单了,只要把DSP2833x_usDelay.asm 文件中的"ramfuncs"段修改为新CMD文件中存在的Section中即可
1 .def _DSP28x_usDelay 2 .text //这只是一种修改方法 3 4 .global __DSP28x_usDelay 5 _DSP28x_usDelay: 6 SUB ACC,#1 7 BF _DSP28x_usDelay,GEQ ;; Loop if ACC >= 0 8 LRETR
重新编译,Debug之后,程序已经可以在脱离仿真器的状态下正常运行。
备注:问题的关键主要在于新CMD文件和DSP2833x_usDelay.asm 文件编写的不配套。
应该说不是所有人都会遇到这种错误现象,但是当我遇到这种错误时,在互联网上查阅多时,都没有找到相关讨论。
记录下来,一来是给自己提个醒,二来也希望给遇到同一种错误现象的同学提供一种可能的解决问题的思路。
欢迎指正。