1、STM32 IAP升级流程
1.1 书写程序,keil生成bin文件
1.2 上位机加载bin文件,生成校验码,通过串口,将bin文件和校验码发送到单片机
1.3 单片机接收bin文件,所有数据存在USART_RX_BUF中
1.4 单片机程序校验接收数据是否正确
1.5 程序判断中断向量入口是否正确 if(((*(vu32*)(0X20001000+4))&0xFF000000)==0x08000000)
1.6 将USART_RX_BUF的所有数据写入指定的flash地址(FLASH_APP1_ADDR),不包括接收的校验码。
1.7 将写入数据重新读出,对比是否全部正确写入,以判断升级无误。(可选)
1.7 读取刚写入数据的中断入口地址,即头4位数据,判断是否正确。
if(((*(vu32*)(FLASH_APP1_ADDR+4))&0xFF000000)==0x08000000)
1.8 入口正确则说明这是一个程序,可以执行。
1.9 再次判断栈顶(MSP)地址是否合法,if(((*(vu32*)FLASH_APP1_ADDR)&0x2FFE0000)==0x20000000),正确则进行跳转
2、if(((*(vu32*)(0X20001000+4))&0xFF000000)==0x08000000)
很多人会疑惑这个判断是什么意思,尤其是0x20001000这个地址怎么来?
原子例程中有提到:“串口接收过来的数据,是从:0X20001000开始存储的。”
即:0x20001000是串口数据缓存数组的起始地址,也就是USART_RX_BUF的起始地址。但实际情况下,USART_RX_BUF的起始地址不一定是0x20001000。所以书写的时候,需注意。
也可以这样写:
u32 Flash_InterruptAddr=0;
Flash_InterruptAddr = USART_RX_BUF[7]; //USART_RX_BUF[7]=0x08
Flash_InterruptAddr = (Flash_InterruptAddr<<8)|USART_RX_BUF[6];//USART_RX_BUF[6]=0x00
Flash_InterruptAddr = (Flash_InterruptAddr<<8)|USART_RX_BUF[5];//USART_RX_BUF[5]=0x01
Flash_InterruptAddr = (Flash_InterruptAddr<<8)|USART_RX_BUF[4];//USART_RX_BUF[4]=0x01
if((Flash_InterruptAddr&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX.
{
//写入逻辑代码
}
(*(vu32*)(0X20001000+4),这个就是取中断向量的入口地址。如下图,bin文件中,0~3是MSP地址,4~7是中断向量入口地址。
(*(vu32*)(0X20001000+4) = [01 01 00 08] = 0x08000101
if(((*(vu32*)(0X20001000+4))&0xFF000000)==0x08000000) = if((0x08000101&0xFF000000)==0x08000000)
3、keil生成bin文件
指令:fromelf --bin -o ..\BIN\test.bin "#L"
4、bootloader程序与app程序关键配置(stm32f103c8t6为例,内存20k+64k)
bootloader:
开始地址为0x8000000,Size选择控制flash所有内存0x10000(64kb)。
IRAM1: 使用全部内存0x5000(20kb)
#define FLASH_APP1_ADDR 0x08002800 //第一个应用程序起始地址(存放在FLASH),留10kb flash给bootloader使用
app:
开始地址为0x8002800(10kb位置开始),Size = 0x10000-0x2800 = 0xD800,使用剩余全部内存
IRAM1:使用全部运行内存(20kb)
关键程序:SCB->VTOR = FLASH_BASE | 0x2800; /* Vector Table Relocation in Internal FLASH. */
/**
* @brief 主函数
* @param 无
* @retval 无
*/
int main(void)
{
SCB->VTOR = FLASH_BASE | 0x2800; /* Vector Table Relocation in Internal FLASH. */
BSP_Init();
printf("\r\n");
printf("LED APP Run Success\r\n");
printf("2019-10-10\r\n");
while(1)
{
/* add your code here ^_^. */
}
}