can总线实现stm32的IAP

使用stm32f105rct6的can通信做IAP,实现固件的远程更新功能。IAP的实现包括两个程序:BootLoader和应用程序。启动过程先启动BootLoader,等待1s,若接收到烧写指令则开始更新程序,若无指令则启动应用程序。应用程序接收到更新指令后,切换到BootLoader。
实现IAP流程,需要的工作包括:
1、规划单片机存储区,设置中断向量位置,生成应用程序bin文件
2、编写BootLoader,实现应用程序切换
3、编写远程更新上位机,实现通信协议
1、规划单片机存储区,设置中断向量位置,生成应用程序bin文件
stm32f105rct6的flash共256KB,规划flash空间:  
0x08000000~0x08004000 共16KB空间,给BootLoader  
0x08004000~0x08010000 共48KB空间,给应用程序
0x08010000~0x08014000 共16KB空间,保留
0x08014000~0x08018000 共16KB空间,给配置
单片机应用程序在起始地址中的结构,首先是中断向量,然后是代码。
中断向量的结构:开头4字节堆栈指针,接下来是4字节reset函数地址,之后是其他中断函数的地址。
单片机开机后,从0x08000000处取得SP,然后从0x08000004处取得reset地址作为PC,在reset函数中调用main函数,进入C语言控制的程序中。
 
在keil中的options -> target -> IROM 填写应用程序的起始和长度,并在linker -> use memory layout from target dialog中打钩
在应用程序中,调用NVIC函数,设置中断向量位置为0x08004000
生成应用程序的bin文件:
keil中,在options -> user -> after build -> run   中输入指令 
    fromelf.exe --bin -o ..\w01sim\bin\mcubin\canext.bin .\obj\test.axf
2、编写BootLoader,实现应用程序切换
建立一个普通的stm32工程,实现can通信和数据协议、flash烧写等功能,当超时无指令,或烧写成功后,需要进行程序切换。
程序切换时,首先应关闭设备时钟、关闭中断,避免应用程序中未对设备进行初始化,导致boot方式启动与冷启动有功能差别。
切换原理:模拟单片机上电过程,人工设置堆栈指针,调用应用程序入口函数。
切换代码如下:
 1 void switch_2_addr(u32 *pc) //切换到指定的程序指针
 2 {
 3     u32 i = 0;
 4     RCC->APB1RSTR = 0x00000000;//复位结束
 5     RCC->APB2RSTR = 0x00000000;
 6 
 7     RCC->AHBENR = 0x00000014;  //睡眠模式闪存和SRAM时钟使能.其他关闭.      
 8     RCC->APB2ENR = 0x00000000; //外设时钟关闭.
 9     RCC->APB1ENR = 0x00000000;   
10     RCC->CR |= 0x00000001;     //使能内部高速时钟HSION
11     RCC->CFGR &= 0xF8FF0000;   //复位SW[1:0],HPRE[3:0],PPRE1[2:0],PPRE2[2:0],ADCPRE[1:0],MCO[2:0]
12     RCC->CR &= 0xFEF6FFFF;     //复位HSEON,CSSON,PLLON
13     RCC->CR &= 0xFFFBFFFF;     //复位HSEBYP
14     RCC->CFGR &= 0xFF80FFFF;   //复位PLLSRC, PLLXTPRE, PLLMUL[3:0] and USBPRE
15     RCC->CIR = 0x00000000;     //关闭所有中断
16 
17     NVIC->ICER[0] = 0xFFFFFFFF;
18     NVIC->ICER[1] = 0x000007FF;
19     NVIC->ICPR[0] = 0xFFFFFFFF;
20     NVIC->ICPR[1] = 0x000007FF;
21     for(i = 0; i < 0x0B; i++)
22     {
23         NVIC->IP[i] = 0x00000000;
24     }
25    __ASM volatile("cpsid i"); //关闭所有中断
26 
27     MSR_MSP(*pc); //堆栈指针是应用程序起始的第一个u32
28     ((void (*)(void))*(pc+1))();//入口函数是应用程序起始的第二个u32
29 }

其中MSR_MSP函数如下:

1 __asm void MSR_MSP(u32 addr)
2 {
3     MSR MSP, r0             //set Main Stack value
4     BX r14
5 }
3、编写远程更新上位机,实现通信协议
上位机实现通信协议:
每个程序具有自己的version,16bit,高1字节为程序代号,低1字节为程序发布版本  
通信的过程:  
1. 控制方发送查询指令,应用程序或BootLoader收到后发送自身version  
2. 控制方发送起始指令,指令中带有长度和crc,应用程序收到后,若不准许,则发不准更新包,若准许,则不响应,直接切入BootLoader  
3. 控制方持续发送起始指令,BootLoader收到后,回复相同canid的包,准许更新  
4. 控制方得到准许后,发送id递增的can包,将bin文件下载到MCU  
5. 发送完成后,控制方额外发送一个can id低16bit为0xffff的包,内容为0,表示结束。BootLoader收到后开始计算crc,若失败,则发失败包。若成功,则开始烧写flash,若烧写失败,发送烧写失败包。  
6. 烧写成功,BootLoader切换到应用程序,此时控制方一直发查询指令,直到应用程序回复版本号正确。  
 

猜你喜欢

转载自www.cnblogs.com/yangzifb/p/10578009.html