因特殊需要,iap需要做成 可以更新iap代码的,想了想,也只有ram中运行代码了, 一般iap代码都很小,往往相应的 单片机的ram都要大于 iap代码大小, 所以可以简单点,把iap代码全部复制到ram中,然后来个强制跳转,更新IAP的FLASH,OK, 重启完事^_^。需要注意的是,代码使用位置无关码,这个概念汇编里面比较清楚,即访问资源使用相对地址,一般也都是,如果有疑问,可以在相应汇编窗口下查看是否是相对寻址的代码。下面是主要代码
#include "test.h"
u8 inRam; // 是否在 ram中
const u8 VER_IAP[4] __attribute__((at(REV_IAP_ADDR_CONTROL))) = {1, 0, 0, 0}; //版本
u8 ramRunIap[1024*32] __attribute__((at(RAM_CODE_ADDR))); //sram : 把iap 搬到 ram 运行...
/* 为了在ram中执行 所有 const char* 字符串数组, 去掉const,
* 这样就会复制到ram,引用也是ram中的, 用到的中断向量需转换地址 */
char* CPUID[2]; // = { "fh", "fdh", "fgh", "dfg"};
char* iapFile[2];// = { "dh.bin", "dgf.bin", "dfhg.bin", "gh.bin", "dfg", "dh" }; //常量指针, 指向flash, 擦除&之后, 不能再访问!!!
void* addrCov(void* addr) //访问flash时, 改至访问ram 对应的位置
{
return (void*)((u32)addr - FLASH_BASE + RAM_CODE_ADDR);
}
void RamVectorSet(void) /* 所以code 复制到ram后, 中断向量改到 ram */
{
u32* p = (u32*)(RAM_CODE_ADDR+4); //reset vect
u8 i;
p[1] = (u32)addrCov((void*)(p[1])); //复位向量
p[3] = (u32)addrCov((void*)(p[3])); //硬错误向量
for(i = 14; i < SECT_NUM; i++)
{
p[i] = (u32)addrCov((void*)(p[i]));
}
}
//复制整个code区至 ram, 再强制跳转至 ram 区 main 函数
int main(void)
{
iapfun jump2ram;
CPUID[0] = "try" ; //为了生成位置无关码
CPUID[1] = "e4t" ;
iapFile[0] = "rtry.bin" ;
iapFile[1] = "yer.bin" ;
if(!inRam) // inRam = 0, 说明第一此执行到这,在 flash执行的
{
inRam = 1;
memcpy((void *)ramRunIap, (const void *)(FLASH_BASE), 1024*32); //复制代码, 设置向量偏移, 计算ram 处的 main 函数 并跳转
SCB->VTOR = RAM_CODE_ADDR & 0xfffffe00;
jump2ram = (iapfun)(addrCov(main));
jump2ram(); // 跳到 ram中的 main函数了
}
while(1)
{
/ code //
}
}