一、IAP介绍
IAP(In applicating Programing)即应用编程。可以实现在使用过程中,通过串口等直接对程序进行更新,而不需要使用烧写器。
以下是找到的一个可以使用的IAP demo(Ymode传输模式)
https://github.com/dong930623/IAP
使用时注意以下几点
1.APP需要设置偏移,这里使用的是STMF103RBT6芯片,所以偏移设置10000 所以IROM为0x8010000
2.初始化中也要进行偏移的设置
SCB->VTOR = FLASH_BASE | 0x10000;
3.编写bin文件
使用IAP升级时,需要使用二进制文件,即.bin文件
有IAP时,程序运行的流程图
二、IAP的实现
//接收到IAP更新标志,进行更新
1 /**
2 * Íùij¸öµØÖ·ÇøÓòдÈëÊý¾Ý
3 * iAddress ÆðʼµØÖ· buf Êý×éÖ¸Õë iNbrToRead ÐèҪдÈëÊý×éµÄ³¤¶È´óС
4 */
5 uint16_t Flash_Write_Without_check(uint32_t iAddress, uint8_t *buf, uint16_t iNumByteToWrite) {
6 uint16_t i;
7 volatile FLASH_Status FLASHStatus = FLASH_COMPLETE;
8 i = 0;
9
10 // FLASH_UnlockBank1();
11 while((i < iNumByteToWrite) && (FLASHStatus == FLASH_COMPLETE))
12 {
13 FLASHStatus = FLASH_ProgramHalfWord(iAddress, *(uint16_t*)buf);
14 i = i+2;
15 iAddress = iAddress + 2;
16 buf = buf + 2;
17 }
18
19 return iNumByteToWrite;
20 }
21 /**
22 * Íùij¸öµØÖ·ÇøÓòдÈëÊý¾Ý
23 * iAddress ÆðʼµØÖ· buf Êý×éÖ¸Õë iNbrToRead ÐèҪдÈëÊý×éµÄ³¤¶È´óС
24 */
25 int Flash_Write(uint32_t iAddress, uint8_t *buf, uint32_t iNbrToWrite) {
26 /* Unlock the Flash Bank1 Program Erase controller */
27 volatile FLASH_Status FLASHStatus = FLASH_COMPLETE;
28 uint32_t secpos;
29 uint32_t iNumByteToWrite = iNbrToWrite;
30 uint16_t secoff;
31 uint16_t secremain;
32 uint16_t i = 0;
33 uint8_t tmp[PAGE_SIZE];
34
35 FLASH_UnlockBank1();
36 secpos=iAddress & (~(PAGE_SIZE -1 )) ;//ÉÈÇøµØÖ·
37 secoff=iAddress & (PAGE_SIZE -1); //ÔÚÉÈÇøÄÚµÄÆ«ÒÆ
38 secremain=PAGE_SIZE-secoff; //ÉÈÇøÊ£Óà¿Õ¼ä´óС
39
40
41 if(iNumByteToWrite<=secremain) secremain = iNumByteToWrite;//²»´óÓÚ4096¸ö×Ö½Ú
42
43 while( 1 ) {
44 Flash_Read(secpos, tmp, PAGE_SIZE); //¶Á³öÕû¸öÉÈÇø
45 for(i=0;i<secremain;i++) { //УÑéÊý¾Ý
46 if(tmp[secoff+i]!=0XFF)break; //ÐèÒª²Á³ý
47 }
48 if(i<secremain) { //ÐèÒª²Á³ý
49 FLASHStatus = FLASH_ErasePage(secpos); //²Á³ýÕâ¸öÉÈÇø
50 if(FLASHStatus != FLASH_COMPLETE)
51 return -1;
52 for(i=0;i<secremain;i++) { //¸´ÖÆ
53 tmp[i+secoff]=buf[i];
54 }
55 Flash_Write_Without_check(secpos ,tmp ,PAGE_SIZE);//дÈëÕû¸öÉÈÇø
56 } else {
57 Flash_Write_Without_check(iAddress,buf,secremain);//дÒѾ²Á³ýÁ˵Ä,Ö±½ÓдÈëÉÈÇøÊ£ÓàÇø¼ä.
58 }
59
60 if(iNumByteToWrite==secremain) //дÈë½áÊøÁË
61 break;
62 else {
63 secpos += PAGE_SIZE;
64 secoff = 0;//Æ«ÒÆλÖÃΪ0
65 buf += secremain; //Ö¸ÕëÆ«ÒÆ
66 iAddress += secremain;//дµØÖ·Æ«ÒÆ
67 iNumByteToWrite -= secremain; //×Ö½ÚÊýµÝ¼õ
68 if(iNumByteToWrite>PAGE_SIZE) secremain=PAGE_SIZE;//ÏÂÒ»¸öÉÈÇø»¹ÊÇд²»Íê
69 else secremain = iNumByteToWrite; //ÏÂÒ»¸öÉÈÇø¿ÉÒÔдÍêÁË
70 }
71 }
72 FLASH_LockBank1();
73 return iNbrToWrite;
74 }
75
76 /**
77 * ´Óij¸öµØÖ·ÇøÓò¶Á³öÊý¾Ý
78 * iAddress ÆðʼµØÖ· buf ´æ·ÅµÄÊý×éÖ¸Õë iNbrToRead ÐèÒª¶Á³öµÄ³¤¶È´óС
79 */
80 int Flash_Read(uint32_t iAddress, uint8_t *buf, int32_t iNbrToRead) {
81 int i = 0;
82 while(i < iNbrToRead ) {
83 *(buf + i) = *(__IO uint8_t*) iAddress++;
84 i++;
85 }
86 return i;
87 }
88
89 /******************************************************************************* *
90 Function Name : SystemReset
91 * Description : Configures the port pin connected to the push button. GPIO_D_4
92 * Input : None * Output : None
93 * Return : None ********************************************************
94 ***********************/
95 __asm void SystemReset(void)
96 { MOV R0, #1 //;
97 MSR FAULTMASK, R0 //; 清除FAULTMASK 禁止一切中断产生
98 LDR R0, =0xE000ED0C //;
99 LDR R1, =0x05FA0004 //;
100 STR R1, [R0] //; 系统软件复位
101 }
void downfile(){
uint8_t key = 1;
if((mGPSSend.GPSSendBuf[mGPSSend.TailPoint].Buf[0] == '$') &&
(mGPSSend.GPSSendBuf[mGPSSend.TailPoint].Buf[1] == '1') &&
(mGPSSend.GPSSendBuf[mGPSSend.TailPoint].Buf[2] == '2') &&
(mGPSSend.GPSSendBuf[mGPSSend.TailPoint].Buf[3] == '3') &&
(mGPSSend.GPSSendBuf[mGPSSend.TailPoint].Buf[4] == '4') ){
USART_ITConfig(USART3, USART_IT_RXNE, DISABLE);
Flash_Write(IsDownLoadFlagAddress, &key,1);
RTC_ITConfig(RTC_IT_SEC, DISABLE);
SystemReset();
while(1);
}
}
三、IAP具体更新流程
1.正常运行下
2.输入特定标识,进入IAP更新
3.在SecureCRT选择Transfer中Send Ymodem 选择生成的bin文件,Add然后点击OK
传输完成
更新后,重新启动的程序