芯片:stm8L151K6T6
开发环境:iar for stm8
stm8L151K6T6的flash大小为32kb,这里我打算把bootloader放在前面的0-12kb(0x8000-0xAFFF),应用程序放在12-32kb(0xAFFF-0xFFFF),这里我打算尽量不用汇编的方式解决问题
bootloader的中断函数入口只需要跳转1次,pc->(0x8000+pos)->我们写的中断处理函数,为什么是0x8000请查看数据手册中的54页的向量表
应用程序的中断函数入口需要跳转2次,pc->(0x8000+pos)->(0x8000+pos+APPstartaddr)->我们写的中断处理函数,这里的APPstartaddr就是0xB000
#define APP_CODE_ADDR (0xB000)//应用程序地址
typedef void (*FUN_point)(void);
void jump_app(void);
void jump_app(void)
{
FUN_point app_start=(FUN_point)(APP_CODE_ADDR);
disableInterrupts();//写向量表需要关闭中断
write_app_ventor_tab(APP_CODE_ADDR);//写入APP向量表
enableInterrupts();//执行应用程序之前需要开启中断
app_start();//开始执行应用程序
}
现在需要解决向量表的切换问题
我的思路是利用stm8L的eeprom保存bootloader的中断入口表,因为当运行app时,bootloader的向量表肯定已经被修改,上电时假如需要升级,那么从eeprom恢复bootloader向量表,等升级完成后,向量表再次切换到主程序,然后正式执行主程序
/*
写入app的中断向量表
*/
void write_app_ventor_tab(u32 offet)
{
u8 Index;
if(*(u32 *)(0X8004)<(0x82000000+APP_CODE_ADDR))
{
FLASH_Unlock(FLASH_MemType_Program);
while (FLASH_GetFlagStatus(FLASH_FLAG_PUL) == RESET);
for(Index = 1; Index < 0X20;Index++)
{
value=*(u32 *)(0X8000+4*Index);
value1=(0X82000000+offet+Index*4);
if(value!=value1)
{
FLASH_ProgramWord(0X8000+4*Index,value1);
}
}
FLASH_Lock(FLASH_MemType_Program);
}
}
/*
从eeprom里恢复bootloader的向量表
*/
void get_bootloader_ventor_tab(void)
{
u8 Index;
if(*(u32 *)(0X8004)<(0x82000000+APP_CODE_ADDR))
{
FLASH_Unlock(FLASH_MemType_Data);
for(Index = 1; Index < 0X20;Index++)
{
FLASH_ProgramWord(0x1020+Index*4,*(u32 *)(0X8000+4*Index));
}
FLASH_Lock(FLASH_MemType_Data);
}
else
{
FLASH_Unlock(FLASH_MemType_Program);
while (FLASH_GetFlagStatus(FLASH_FLAG_PUL) == RESET);
for(Index = 1; Index < 0X20;Index++)
{
FLASH_ProgramWord(0X8000+4*Index,*(u32 *)(0x1020+4*Index));
}
FLASH_Lock(FLASH_MemType_Program);
}
}
void save_bootloader_ventor_tab(void)
{
u8 Index;
if(*(u32 *)(0X8004)<(0x82000000+APP_CODE_ADDR))
{
//写eeprom
FLASH_Unlock(FLASH_MemType_Data);
for(Index = 1; Index < 0X20;Index++)//31*4=124字节
{
FLASH_ProgramWord(0x1020+Index*4,*(u32 *)(0X8000+4*Index)); //把bootloader的向量表保存起来到eeprom-0x1020
}
FLASH_Lock(FLASH_MemType_Data);
}
}
int main()
{
disableInterrupts();
init();
save_bootloader_ventor_tab();
if(key_update_check()!=0)//是否需要升级的判断
{
jump_app();//不需要升级直接进入主程序
}
get_bootloader_ventor_tab();//恢复bootloader向量表
enableInterrupts();
//这里开始就可以使用中断了
bootloader_init(); //bootloader的一些初始化
while(1)
{
//升级的一些操作,把app的bin文件写入到app代码区......
}