BOOTLOADER 案例
准备两程序
一个,bootloader程序 用来跳转到APP程序
一个,APP程序 用来功能的实现
bootloader程序
typedef void (*Iapfun)(void); //定义函数指针
static Iapfun jump2app; //定义函数
static void Interrupt_Disable(void)
{
__ASM volatile("cpsid i");
}
void Delay(__IO u32 nCount);
/**
* @brief 主函数
* @param 无
* @retval 无
*/
int main(void)
{
int i=5;
static uint32_t addr;
/* SysTick 初始化*/
SysTick_Init();
/* LED 端口初始化 */
LED_GPIO_Config();
/* 控制LED灯 */
while (i--)
{
/* 亮灭5下进入APP程序*/
LED1( ON ); // 亮
Delay_ms(500);
LED1(OFF);
Delay_ms(500);
}
/* 进入跳转程序 */
addr = (*(__IO uint32_t*)(APP_ADDRESS));
if (((*(__IO uint32_t*)(APP_ADDRESS)) & 0x2FFC0000 ) == 0x20000000)
{
// Interrupt_Disable(); //在APP程序中就重新进入不了中断
addr = (*(__IO uint32_t*)(APP_ADDRESS));
//APPLICATION_ADDRESS + 4对应的是app中断向量表的第二项,复位地址
jump2app =(Iapfun) *(__IO uint32_t*) (APP_ADDRESS + 4);
//把地址强转为函数指针
__set_MSP(*(__IO uint32_t*) APP_ADDRESS);
//调用函数,实际失去app复位地址去执行复位操作
jump2app();
}
}
主题程序如上。在MDK中设置一个地方,是一个很关键的位置,卡在这里很久。
空间的大小0x4000一定要小于APP程序的起始地址,不然会被APP程序覆盖
APP程序:
#define PROGRAM_ADDRESS 0x4000 /* 要跳转到的地址 */
/**
* @brief 主函数
* @param 无
* @retval 无
*/
int main(void)
{
static uint32_t addr;
NVIC_SetVectorTable(NVIC_VectTab_FLASH,PROGRAM_ADDRESS);
/* SysTick 初始化*/
SysTick_Init();
/* LED 端口初始化 */
LED_GPIO_Config();
addr = *(uint32_t*)(PROGRAM_ADDRESS);
/* 控制LED灯 */
while (1)
{
/* 亮灭5下进入APP程序*/
LED2( ON ); // 亮
Delay_ms(1000);
LED2(OFF);
Delay_ms(1000);
}
}
两个关键位置
这里是设置APP程序下载的起始地址,和分配空间的大小。
分配空间的大小,一定要按在实际使用的芯片扇区的整数倍,不然会跳转失败。
NVIC_SetVectorTable(NVIC_VectTab_FLASH,PROGRAM_ADDRESS);
设置中断向量表的偏移,不设置的画,程序进入不了中断,例程中APP程序就进入不了Systick中断服务函数