STM32 IAP入门示例
一、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
传输完成
更新后,重新启动的程序