STM32F051 IAP源代码分享
假设不懂IAP的请自己主动脑补或者怒戳这里
http://www.openedv.com/posts/list/11494.htm
然后STM32F051的IAP有一点差别也请自己主动脑补 ^_^
事实上我仅仅是来分享源代码的:
事情是介个样子滴:
IAP须要有两个project。第一个是Bootloader。第二个是Application
同一时候将这两份程序放在mcu的flash里的不同位置,启动时自己主动进入bootloader(可选择)进行iap,成功后跳转至application。
完整源代码见最后内容,这里先瞎扯一点点:
那么IAP问题简化成三个步骤,
Step1:做Bootloaderproject
Step2:做Applicationproject
Step3:烧进Flash的不同位置
Step1:须要做这些事情:
1:初始化IAP相关外设
2:下载文件(ymodem协议)
3: 写入Application程序存储空间
鸡:
IAP_Init();
SerialDownload();
详细实现:
/** *@brief Initialize the Iap module(leddelay usart and unlock flash) *@param None *@retval None */ void IAP_Init(void) { uint32_tt; LEDInit(); /*--Set up Led to Output signal --*/ SysTickInit(); /*-- Config System Tick for delay functions --*/ USART_Configuration(); /*-- Config usart to download .bin --*/ FLASH_If_Init(); /*-- Unlock Flash --*/ for(t = 2000; t > 10; t >>= 1 ) /*-- LED1 blink 3 second indeicate IAPbegin--*/ { LEDTogle(1); delayms(t); } } void SerialDownload(void) { uint8_t Number[10] = {0}; int32_t Size = 0; SerialPutString("Waitingfor the file to be sent ... (press 'a' to abort) "); Size = Ymodem_Receive(&tab_1024[0]); if(Size > 0) { SerialPutString(" Programming CompletedSuccessfully! -------------------------------- Name: "); SerialPutString(FileName); Int2Str(Number, Size); SerialPutString(" Size: "); SerialPutString(Number); SerialPutString(" Bytes "); SerialPutString("------------------- "); } else if (Size == -1) { SerialPutString(" The image size is higher than the allowedspace memory! "); } else if (Size == -2) { SerialPutString(" Verification failed! "); } else if (Size == -3) { SerialPutString(" Aborted by user. "); } else { SerialPutString(" Failedto receive the file! "); } }
Step2:须要这样干:
在Applicationproject中程序执行的一開始加上例如以下中断拷贝就可以
void InterruptRemap(void) { u8 i; u32 Data; u32 Address; for(i=1;i<48;i++) { Data = *(__IOu32*)(0x08003000+i*4); Address = 0x20000000 + (i*4); *(__IO u32*)Address= (u32)Data; } SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM); }
Step3:这就样
将两个project分别烧在不同的flash地址段中
A:bootloader
1:点Project选项卡,然后点Optionsfor Target选项如图:
2:Target选项卡下有on-chip地址设置,bootloader放在0x8000000开头的0x3000空间内
如图:
然后正常手段烧入flash就可以。
B:application
和上述设置手段一样。仅仅只是in-chip的IROM1设置起始地址为0x8003000。Size为mcu的Flash大小减去0x3000就可以(注意是16进制哦)
然后就祝你幸福了 0.0
完整源代码:
Main.c
/* Includes------------------------------------------------------------------*/ #include "stm32f0xx.h" #include "flash.h" #include "powerAPI.h" #include "IAP_Bootloader.h" /** *@brief Main program. *@param None *@retval None */ int main(void) { SystemPowerUp(); /*-- PowerUp && LoadSysMsg --*/ while (1) { if(FLASH_If_ReadWord((uint32_t)IAP_READY_FLAG_ADDRESS) == FLAG_READY) { IAP_Init(); SerialDownload(); IAP_End_Clear_Flag(); } else { JumpToApp(); } } return 0; }
/** ****************************************************************************** *@file bootloader.c *@brief IAP module function *@CPU STM32F051 *@compiler Keil uVision V4.74 *@author MetalSeed *@version V1.0.0 *@date 18-Sept-2014 *@modifydate20-Sept-2014 ****************************************************************************** *@attention */ #include "stm32f0xx.h" #include "IAP_Bootloader.h" #include "uart.h" #include "led.h" #include "delay.h" #include "flash.h" #include "ymodem.h" /*================================================================ APPLICATION_ADDRESS = (uint32_t)0x08003000 defined in flash ================================================================*/ extern uint32_t IapReady; uint8_t tab_1024[1024] ={ 0 }; uint8_t FileName[FILE_NAME_LENGTH]; /*================================================================ About Jump ================================================================*/ typedef void (*pFunction)(void); /*-- define a function type --*/ uint32_t JumpAddress; /*-- define the usrapp's address --*/ pFunction JumpToApplication; /*-- definethe function pointer which direct to usr app --*/ /** *@brief Jump to application *@retval None */ void JumpToApp(void) { if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) ==0x20000000)/*-- check whether stack pointer legal --*/ { JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4); JumpToApplication = (pFunction) JumpAddress; __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS); /*-- initialize theheap & stack pointer --*/ JumpToApplication(); } } /*================================================================ About IAP Download ================================================================*/ /** *@brief Initialize the Iap module(leddelay usart and unlock flash) *@param None *@retval None */ void IAP_Init(void) { uint32_t t; LEDInit(); /*--Set up Led to Output signal --*/ SysTickInit(); /*-- Config System Tick for delay functions --*/ USART_Configuration(); /*-- Config usart to download .bin --*/ FLASH_If_Init(); /*-- Unlock Flash --*/ for(t = 2000; t > 10; t >>= 1 ) /*-- LED1 blink 3 second indeicate IAPbegin--*/ { LEDTogle(1); delayms(t); } } /** *@brief IAP end, Clear Iap ready flag andoutput success signal *@retval None */ void IAP_End_Clear_Flag() { uint32_t i; if(FLASH_If_WriteWord(IAP_READY_FLAG_ADDRESS, FLAG_UNREADY) == 0)/*-- clear iap ready flag --*/ { for(i = 0; i < 50; ++i) /*-- IAP end, Led1 and Led2 blink in turnlast 2.5 second --*/ { LEDTogle(1); delayms(50); LEDTogle(2); } } LED1ON; /*-- IAPend, Led1 and Led2 turn ON last 3 second --*/ LED2ON; delayms(3000); } /** *@brief In App Program by Serial *@retval None */ void SerialDownload(void) { uint8_t Number[10] = {0}; int32_t Size = 0; SerialPutString("Waiting for the file to be sent ... (press 'a' toabort) "); Size = Ymodem_Receive(&tab_1024[0]); if(Size > 0) { SerialPutString(" Programming CompletedSuccessfully! -------------------------------- Name: "); SerialPutString(FileName); Int2Str(Number, Size); SerialPutString(" Size: "); SerialPutString(Number); SerialPutString(" Bytes "); SerialPutString("------------------- "); } else if (Size == -1) { SerialPutString(" The image size is higher than the allowedspace memory! "); } else if (Size == -2) { SerialPutString(" Verification failed! "); } else if (Size == -3) { SerialPutString(" Aborted by user. "); } else { SerialPutString(" Failed to receive the file! "); } } /** *@brief Upload a file via serial port. *@param None *@retval None */ void SerialUpload(void) { uint8_t status = 0 ; SerialPutString(" Select Receive File "); if(GetKey() == CRC16) { /* Transmit the flash image through ymodem protocol */ status = Ymodem_Transmit((uint8_t*)APPLICATION_ADDRESS, (constuint8_t*)"UploadedFlashImage.bin", USER_FLASH_SIZE); if (status != 0) { SerialPutString(" Error Occurred while TransmittingFile "); } else { SerialPutString(" File uploaded successfully "); } } }
FLASH.c /** ****************************************************************************** *@file flash.c *@brief XXX function *@CPU STM32F051 *@compiler Keil uVision V4.74 *@author MetalSeed *@version V1.0.0 *@date 18-Sept-2014 *@modifydate20-Sept-2014 ****************************************************************************** *@attention */ /* Includes ------------------------------------------------------------------*/ #include "stm32f0xx.h" #include "flash.h" #include "uart.h" /** @addtogroup STM32F0xx_IAP *@{ */ /** *@brief Unlocks Flash for write access *@param None *@retval None */ void FLASH_If_Init(void) { /*Unlock the Program memory */ FLASH_Unlock(); /*Clear all FLASH flags */ FLASH_ClearFlag(FLASH_FLAG_EOP|FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR |FLASH_FLAG_BSY); } /** *@brief This function does an erase of alluser flash area *@param StartSector: start of user flasharea *@retval 0: user flash area successfully erased * 1: error occurred */ uint32_t FLASH_If_Erase(uint32_tStartSector) { uint32_t flashaddress; flashaddress = StartSector; while (flashaddress <= (uint32_t) USER_FLASH_LAST_PAGE_ADDRESS) { if (FLASH_ErasePage(flashaddress) == FLASH_COMPLETE) { flashaddress += FLASH_PAGE_SIZE; } else { /* Error occurred while page erase */ return (1); } } return (0); } /** *@brief Read uint32_t int *@param FlashAddress: address to be read *@retval Read value */ uint32_t FLASH_If_ReadWord(__IO uint32_tFlashAddress) { return *(uint32_t*)FlashAddress; } /** *@brief Erase flash by one page *@param SectorNum: page number *@retval None */ uint32_t FLASH_If_ErasePage(uint32_tSectorNum) { uint32_t flashaddress; flashaddress = SectorNum; if(FLASH_ErasePage(flashaddress) == FLASH_COMPLETE) { return 0; } else { /* Error occurred while page erase */ return (1); } } /** *@brief Write uint32_t int *@param FlashAddress: address to write *@param Data: data to be write *@retval 0: Write success *@retval 1: Write error *@retval 2: read error */ uint32_t FLASH_If_WriteWord(uint32_tFlashAddress, uint32_t Data) { if(FLASH_ProgramWord(FlashAddress, Data) == FLASH_COMPLETE) { /*Check the written value */ if (*(uint32_t*)FlashAddress != Data) { /* Flash content doesn't match SRAM content */ return(2); } return 0; } else { /* Error occurred while writing data in Flash memory */ return (1); } } /** *@brief This function writes a databuffer in flash (data are 32-bit aligned). *@note After writing data buffer, theflash content is checked. *@param FlashAddress: start address forwriting data buffer *@param Data: pointer on data buffer *@param DataLength: length of data buffer(unit is 32-bit word) *@retval 0: Data successfully written to Flash memory * 1: Error occurred whilewriting data in Flash memory * 2: Written Data in flashmemory is different from expected one */ uint32_t FLASH_If_Write(__IO uint32_t*FlashAddress, uint32_t* Data ,uint16_t DataLength) //ÐèÒª½«Á½¸öµØÖ·¸³Öµ¹ýÀ´¡£°´Êý¾Ý³¤¶È½«Êý¾ÝдÈëflash { uint32_t i = 0; for(i = 0; (i < DataLength) && (*FlashAddress <=(USER_FLASH_END_ADDRESS-4)); i++) { /* the operation will be done by word */ if (FLASH_ProgramWord(*FlashAddress, *(uint32_t*)(Data+i)) ==FLASH_COMPLETE) { /* Check the written value */ if (*(uint32_t*)*FlashAddress != *(uint32_t*)(Data+i)) { /* Flash content doesn't match SRAM content */ return(2); } /* Increment FLASH destination address */ *FlashAddress += 4; } else { /* Error occurred while writing data in Flash memory */ return (1); } } return (0); } /** *@brief Disables the write protection ofuser desired pages *@param None *@retval 0: Write Protection successfully disabled * 1: Error: Flash writeunprotection failed * 2: Flash memory is not writeprotected */ uint32_tFLASH_If_DisableWriteProtection(void) { uint32_t UserMemoryMask = 0, WRPR = 0; FLASH_Status status = FLASH_BUSY; /*Clear all FLASH flags */ FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR |FLASH_FLAG_BSY); /*Get Write protection */ WRPR = FLASH_OB_GetWRP(); /*Test if user memory is write protected */ if(FLASH_If_GetWriteProtectionStatus() != 0x00) { /* Enable the FLASH option byte access */ FLASH_OB_Unlock(); /* Erase option bytes */ status = FLASH_OB_Erase(); /* Compute the User_Mask */ UserMemoryMask = FLASH_PROTECTED_PAGES | WRPR; if (UserMemoryMask != 0xFFFFFFFF) { /* Disable Write protection */ status = FLASH_OB_EnableWRP((uint32_t)~UserMemoryMask); } if (status == FLASH_COMPLETE) { /* Write Protection successfully disabled */ return (0); } else { /* Error: Flash write unprotection failed */ return (1); } } else { /* Flash memory is not write protected */ return(2); } } /** *@brief Returns the write protectionstatus of user flash area. *@param None *@retval If the sector is write-protected, the corresponding bit in returned * value is set. * If the sector isn'twrite-protected, the corresponding bit in returned * value is reset. */ uint32_t FLASH_If_GetWriteProtectionStatus(void) { return(~FLASH_OB_GetWRP() & FLASH_PROTECTED_PAGES); } /** *@} */ /************************ (C) COPYRIGHTSTMicroelectronics *****END OF FILE****/
Ymodem.c
/** ****************************************************************************** *@file STM32F0xx_IAP/src/ymodem.c *@author MCD Application Team *@version V1.0.0 *@date 29-May-2012 *@brief Main program body ****************************************************************************** *@attention * *<h2><center>© COPYRIGHT 2012STMicroelectronics</center></h2> * *Licensed under MCD-ST Liberty SW License Agreement V2, (the"License"); *You may not use this file except in compliance with the License. *You may obtain a copy of the License at: * * http://www.st.com/software_license_agreement_liberty_v2 * *Unless required by applicable law or agreed to in writing, software *distributed under the License is distributed on an "AS IS" BASIS, *WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *See the License for the specific language governing permissions and *limitations under the License. * ****************************************************************************** */ /* Includes------------------------------------------------------------------*/ #include "ymodem.h" #include "uart.h" #include "string.h" #include "flash.h" /** @addtogroup STM32F0xx_IAP *@{ */ /* Private typedef-----------------------------------------------------------*/ /* Private define------------------------------------------------------------*/ /* Private macro-------------------------------------------------------------*/ /* Private variables---------------------------------------------------------*/ extern uint8_t FileName[]; /* Private function prototypes-----------------------------------------------*/ /* Private functions---------------------------------------------------------*/ /** *@brief Receive byte from sender *@param c: Character *@param timeout: Timeout *@retval 0: Byte received * -1: Timeout */ static int32_t Receive_Byte (uint8_t *c, uint32_t timeout) { while (timeout-- > 0) { if (SerialKeyPressed(c) == 1) { return 0; } } return -1; } /** *@brief Send a byte *@param c: Character *@retval 0: Byte sent */ static uint32_t Send_Byte (uint8_t c) { SerialPutChar(c); return 0; } /** *@brief Update CRC16 for input byte *@param CRC input value *@param input byte *@retval Updated CRC value */ uint16_t UpdateCRC16(uint16_t crcIn,uint8_t byte) { uint32_t crc = crcIn; uint32_t in = byte|0x100; do { crc <<= 1; in <<= 1; if(in&0x100) { ++crc; } if(crc&0x10000) { crc ^= 0x1021; } }while(!(in&0x10000)); return (crc&0xffffu); } /** *@brief Cal CRC16 for YModem Packet *@param data *@param length *@retval CRC value */ uint16_t Cal_CRC16(const uint8_t* data,uint32_t size) { uint32_t crc = 0; const uint8_t* dataEnd = data+size; while(data<dataEnd) { crc = UpdateCRC16(crc,*data++); } crc= UpdateCRC16(crc,0); crc= UpdateCRC16(crc,0); return (crc&0xffffu); } /** *@brief Cal Check sum for YModem Packet *@param data *@param length *@retval None */ uint8_t CalChecksum(const uint8_t* data,uint32_t size) { uint32_t sum = 0; const uint8_t* dataEnd = data+size; while(data < dataEnd) { sum += *data++; } return (sum&0xffu); } /** *@brief Receive a packet from sender *@param data *@param length *@param timeout * 0: end of transmission * -1: abort by sender * >0: packet length *@retval 0: normally return * -1: timeout or packeterror * 1: abort by user */ static int32_t Receive_Packet (uint8_t*data, int32_t *length, uint32_t timeout) { uint16_t i, packet_size, computedcrc; uint8_t c; *length = 0; if(Receive_Byte(&c, timeout) != 0) { return -1; } switch (c) { case SOH: packet_size = PACKET_SIZE; break; case STX: packet_size = PACKET_1K_SIZE; break; case EOT: return 0; case CA: if ((Receive_Byte(&c, timeout) == 0) && (c == CA)) { *length = -1; return 0; } else { return -1; } case ABORT1: case ABORT2: return 1; default: return -1; } *data = c; for(i = 1; i < (packet_size + PACKET_OVERHEAD); i ++) { if (Receive_Byte(data + i, timeout) != 0) { return -1; } } if(data[PACKET_SEQNO_INDEX] != ((data[PACKET_SEQNO_COMP_INDEX] ^ 0xff) &0xff)) { return -1; } /*Compute the CRC */ computedcrc = Cal_CRC16(&data[PACKET_HEADER],(uint32_t)packet_size); /*Check that received CRC match the already computed CRC value data[packet_size+3]<<8) | data[packet_size+4] contains thereceived CRC computedcrc contains the computed CRC value */ if(computedcrc != (uint16_t)((data[packet_size+3]<<8) |data[packet_size+4])) { /* CRC error */ return -1; } *length = packet_size; return 0; } /** *@brief Receive a file using the ymodemprotocol *@param buf: Address of the first byte *@retval The size of the file */ int32_t Ymodem_Receive (uint8_t *buf) { uint8_t packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD],file_size[FILE_SIZE_LENGTH], *file_ptr, *buf_ptr; int32_t i, packet_length, session_done, file_done, packets_received,errors, session_begin, size = 0; uint32_t flashdestination, ramsource; /*Initialize flashdestination variable */ flashdestination = APPLICATION_ADDRESS; for(session_done = 0, errors = 0, session_begin = 0; ;) { for (packets_received = 0, file_done = 0, buf_ptr = buf; ;) { switch (Receive_Packet(packet_data, &packet_length, NAK_TIMEOUT)) { case 0: errors = 0; switch (packet_length) { /* Abort by sender */ case - 1: Send_Byte(ACK); return 0; /* End of transmission */ case 0: Send_Byte(ACK); file_done = 1; break; /* Normal packet Õý³£Çé¿öϵİü*/ default: if((packet_data[PACKET_SEQNO_INDEX] & 0xff) != (packets_received & 0xff)) { Send_Byte(NAK); } else { if (packets_received == 0) { /* Filename packet */ if(packet_data[PACKET_HEADER] != 0) { /* Filename packet hasvalid data */ for (i = 0, file_ptr =packet_data + PACKET_HEADER; (*file_ptr != 0) && (i <FILE_NAME_LENGTH);) { FileName[i++] =*file_ptr++; } FileName[i++] = '