在DSP如TI C2000系列的开发过程中为了提高代码的执行速度或者在进行Flash擦写操作时避免冲突我们通常需要将部分关键代码如中断服务函数、核心算法等从Flash搬运到RAM中运行。本文将以一个简单的test()函数为例完整演示如何将代码分配、搬运并在RAM中执行。第一步检查CMD文件中的RAM段定义在进行代码搬运前首先需要确认芯片的Linker Command (CMD) 文件中是否已经定义了用于代码搬移的段。 打开工程的CMD文件可以发现其中通常有关于.TI.ramfunc的如下定义 .TI.ramfunc : {} LOAD FLASHD, RUN RAMLS0, LOAD_START(RamfuncsLoadStart), ...这表示该段代码在烧录时存放于FlashFLASHD但在实际运行时将被加载到RAMRAMLS0中第二步使用 #pragma 指令分配函数要在RAM中运行我们自己编写的函数需要在函数定义前加上#pragma CODE_SECTION指令将其分配到刚才看过的.TI.ramfunc段中 。 例如我们定义一个test()函数#pragma CODE_SECTION(test, .TI.ramfunc); void test(void) { count; }第三步编译并查看Map文件验证代码修改后编译工程打开生成的.map文件验证分配是否成功在Map文件的.TI.ramfunc段中多出了main.obj中的test函数信息 。同时在常规的代码段.text中已经找不到test函数了 。利用查找功能Find查询test的运行地址显示为00008004。对照CMD文件中的MEMORY定义00008000正是RAMLS0的起始区间 。第四步核心操作——执行Flash到RAM的复制注意此时如果直接把程序烧入开发板运行程序会直接跑飞原因是此时RAM重新上电后内部是空的我们仅仅是在配置文件中“计划”了要在RAM中运行但并没有编写将Flash中的代码真实“复制”到RAM中的指令 。为了完成实际的搬运动作我们需要在main()函数的最开始添加初始化代码 引入工程配置头文件#include F28x_Project.h并调用系统初始化函数InitSysCtrl();。#include F28x_Project.h int main(void) { InitSysCtrl(); // 核心包含代码搬运与系统初始化 test(); return 0; }我们可以通过跳转查看InitSysCtrl()的底层定义就能明白其工作原理 在该函数内部有一个受#ifdef _FLASH宏控制的代码块 #ifdef _FLASH // Copy time critical code and Flash setup code to RAM. memcpy(RamfuncsRunStart, RamfuncsLoadStart, (size_t)RamfuncsLoadSize); InitFlash(); #endif正是这个memcpy函数利用CMD文件中生成的符号把代码从Flash的Load地址实际拷贝到了RAM的Run地址 。第五步全局宏定义 _FLASH从上一步源码可以看出代码搬运的前提是进入#ifdef _FLASH条件编译分支。 因此必须在工程属性中全局宏定义_FLASH 右键工程 - Properties - Build - C2000 Compiler - Predefined Symbols - 在 Pre-define NAME 中添加_FLASH。第六步最终调试与验证完成上述所有配置后重新编译工程再次查询map文件由于添加了头文件和系统初始化代码test函数在RAM中的相对位置发生了偏移运行地址变为了0000803b。启动Debug模式在main函数中的test();处打断点单步跳入该函数 。在汇编视图Disassembly中查看可以看到此时test()函数内部指令所处的真实物理地址正是0x00803b所在的RAM区间 。至此证明代码已成功搬运到RAM中并完美运行总结实现代码转移的三个核心点CMD文件分配 (ramfunc) - #pragma 指令映射函数 - 开启 _FLASH 宏并调用 memcpy (InitSysCtrl) 执行物理搬运。缺少最后一步的物理搬运是新手常犯的导致程序跑飞的原因。