1 基础知识讲解
1.1 在RAM中运行还是在flash中运行指的是什么?
1.1.1 背景:程序编译完之后生成的.bin文件,.bin文件中包含代码段,代码段中全是汇编指令,而汇编指令中包含多个函数,各函数头的地址不同,如存在A函数和B函数,假设RAM地址区间是0x0000-0x8000,flash的地址区间是0xA000-0xF000,A函数要调用B函数,则A函数调用B函数的那段汇编指令中包含的是B函数头的存储地址,A函数和B函数都在flash中有存储
1.1.2 情况1:B函数是配置为在RAM中运行,则B函数的代码段会通过一定手段(通过其他函数去完成)被copy到RAM区域中,故A函数调用B函数时,A函数的跳转指令中包含的地址数据可能是0x1000。
1.1.3 情况2:B函数是配置为在flash中运行,故A函数调用B函数时,A函数的跳转指令中包含的地址数据可能是0xB000。
1.1.4 结论:在代码不更改的情况下,将某函数或整个程序配置为在RAM运行和配置为在flash中运行这两种情况下,编译结束之后得到的.bin文件代码段是不同的。
1.2 28375S的RAM区和flash地址段
1.2.1 芯片手册截图
1.3 在芯片flash中,我们可以存储两份或多份程序代码的.bin文件,我们这可以假设在芯片中存储两个程序P1和P2,芯片复位后,首先运行P1,可由P1跳转到P2,再运行P2
1.3.1 从flash启动代码时,芯片复位后,会从0x80000地址开始执行
2 配置1:对于P2程序,绝大部分函数分配到flash(起始地址0x84000)中运行,小部分函数分配到RAM(起始地址0x2000)中运行
2.1 在.cmd文件中的PAGE0中定义:
BEGIN: origin = 0x80000 , length = 0x10
FLASH_Code : origin = 0x84000 + 0x10, length = 0xE000
RAMLS_Fun : origin = 0x2000, length = 0x1000
2.2 在.cmd文件中的SECTION中定义:
.TI.ramfunc : {} LOAD = FLASH_Code,
RUN = RAMLS_Fun,
LOAD_START(_RamfuncsLoadStart),
LOAD_SIZE(_RamfuncsLoadSize),
LOAD_END(_RamfuncsLoadEnd),
RUN_START(_RamfuncsRunStart),
RUN_SIZE(_RamfuncsRunSize),
RUN_END(_RamfuncsRunEnd),
PAGE = 0, ALIGN(4)
2.3 在xxx.h中声明外部变量
extern Uint16 RamfuncsLoadStart;
extern Uint16 RamfuncsLoadEnd;
extern Uint16 RamfuncsLoadSize;
extern Uint16 RamfuncsRunStart;
extern Uint16 RamfuncsRunEnd;
extern Uint16 RamfuncsRunSize;
2.4 在xxx.c文件中定义映射到.TI.ramfunc的函数A,代表A函数会在RAM中运行,其函数的函数头的地址将会是RAM段的地址:
#pragma CODE_SECTION(".TI.ramfunc");
void A(void)
{
}
2.5 在调用A函数前,将存放在flash中的A函数的代码搬迁到RAM中,通常在main函数中的最开始就进行此步骤
memcpy(&RamfuncsRunStart,&RamfuncsLoadStart,(size_t)&RamfuncsLoadSize);
2.6 步骤之后,就可以调用A函数了,A函数将会在RAM中运行
void B(void)
{
A();
}
3 配置2:所有函数都分配到RAM (起始地址0x5000)中运行
3.1 在.cmd文件中的PAGE0中定义:
BEGIN: origin = 0x80000 , length = 0x10
FLASH_Code : origin = 0x5000 + 0x10, length = 0xE000
3.2 在.cmd文件中的SECTION中定义:
.TI.ramfunc : > FLASH_Code PAGE = 0, ALIGN(4)
3.3 注意:通过1.1和1.2的配置之后,编译生成的.hex文件中的地址信息都是以0x5000为基地址进行的标识
解决方法:在编译过程的后处理中添加后处理程序,后处理程序负责将.hex文件的地址信息修改为以0x84000为基地址的XDS.hex文件,然后通过仿真器将XDS.hex文件烧写到falsh中。
3.4 在一级程序P1中将P2程序的.bin数据全部拷贝到RAM区域,然后再跳转到P2程序中
MemCpy((u08*)0x5000, (u08*)0x84000,0xE000);
((void (*) (void))0x84000)();