IAP需要有两个工程,第一个是Bootloader,第二个是Application 同时将这两份程序放在mcu的flash里的不同位置,启动时自动进入bootloader(可选择)进行iap,成功后跳转至application。
完整源码见最后内容,这里先瞎扯一点点:
那么IAP问题简化成三个步骤, Step1:做Bootloader工程 Step2:做Application工程 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)\n\r");
- Size = Ymodem_Receive(&tab_1024[0]);
- if(Size > 0)
- {
- SerialPutString("\n\n\r Programming CompletedSuccessfully!\n\r--------------------------------\r\n Name: ");
- SerialPutString(FileName);
- Int2Str(Number, Size);
- SerialPutString("\n\r Size: ");
- SerialPutString(Number);
- SerialPutString(" Bytes\r\n");
- SerialPutString("-------------------\n");
- }
- else if (Size == -1)
- {
- SerialPutString("\n\n\rThe image size is higher than the allowedspace memory!\n\r");
- }
- else if (Size == -2)
- {
- SerialPutString("\n\n\rVerification failed!\n\r");
- }
- else if (Size == -3)
- {
- SerialPutString("\r\n\nAborted by user.\n\r");
- }
- else
- {
- SerialPutString("\n\rFailedto receive the file!\n\r");
- }
- }
复制代码Step2:需要这样干: 在Application工程中程序运行的一开始加上如下中断拷贝即可 - 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:这就样 将两个工程分别烧在不同的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;
- }
复制代码
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++] = '\0';
- for (i = 0, file_ptr ++;(*file_ptr != ' ') && (i < (FILE_SIZE_LENGTH - 1));)
- {
- file_size[i++] =*file_ptr++;
- }
- file_size[i++] = '\0';
- Str2Int(file_size,&size);
-
- /* Test the size of theimage to be sent */
- /* Image size is greaterthan Flash size */
- if (size >(USER_FLASH_SIZE + 1))
- {
- /* End session */
- Send_Byte(CA);
- Send_Byte(CA);
- return -1;
- }
- /* erase user applicationarea */
- FLASH_If_Erase(APPLICATION_ADDRESS);
- Send_Byte(ACK); // ACK and 'C' ?
- Send_Byte(CRC16);
- }
- /* Filename packet is empty,end session */
- else
- {
- Send_Byte(ACK);
- file_done = 1;
- session_done = 1;
- break;
- }
- }
- /* Data packet */
- else //Õý³£Çé¿öϽøÈë
- {
- memcpy(buf_ptr, packet_data +PACKET_HEADER, packet_length);
- ramsource =(uint32_t)buf; //bufÊÇÒ»¸öÖ¸Õë
-
- /* Write received data inFlash */
- if(FLASH_If_Write(&flashdestination, (uint32_t*) ramsource, (uint16_t)packet_length/4) == 0) //½«Êý¾ÝдÈëflash
- {
- Send_Byte(ACK); //дÍêÒ»Ö¡Êý¾ÝÖ®ºó·¢ËÍÏìÓ¦
- }
- else /* An error occurredwhile writing to Flash memory */
- {
- /* End session */
- Send_Byte(CA);
- Send_Byte(CA);
- return -2;
- }
- }
- packets_received ++; //°üÊý+1
- session_begin = 1;
- }
- }
- break;
- case 1:
- Send_Byte(CA);
- Send_Byte(CA);
- return -3;
- default:
- if (session_begin > 0) //½ÓÊÕÒѾ¿ªÊ¼£¬µ«ÊÇReceive_Packet(packet_data, &packet_length,NAK_TIMEOUT)¸Ãº¯Êý·µ»Ø´íÎó¡£
- {
- errors ++;
- }
- if (errors > MAX_ERRORS)
- {
- Send_Byte(CA);
- Send_Byte(CA);
- return 0;
- }
- Send_Byte(CRC16); // the start C!!
- break;
- }
- if (file_done != 0)
- {
- break;
- }
- }
- if (session_done != 0)
- {
- break;
- }
- }
- return (int32_t)size;
- }
-
- /**
- *@brief check response using the ymodemprotocol
- *@param buf: Address of the first byte
- *@retval The size of the file
- */
- int32_t Ymodem_CheckResponse(uint8_t c)
- {
- return 0;
- }
-
- /**
- *@brief Prepare the first block
- *@param timeout
- *@retval None
- */
- void Ymodem_PrepareIntialPacket(uint8_t*data, const uint8_t* fileName, uint32_t *length)
- {
- uint16_t i, j;
- uint8_t file_ptr[10];
-
- /*Make first three packet */
- data[0] = SOH;
- data[1] = 0x00;
- data[2] = 0xff;
-
- /*Filename packet has valid data */
- for(i = 0; (fileName[i] != '\0') && (i < FILE_NAME_LENGTH);i++)
- {
- data[i + PACKET_HEADER] = fileName[i];
- }
-
- data[i + PACKET_HEADER] = 0x00;
-
- Int2Str (file_ptr, *length);
- for(j =0, i = i + PACKET_HEADER + 1; file_ptr[j] != '\0' ; )
- {
- data[i++] = file_ptr[j++];
- }
-
- for(j = i; j < PACKET_SIZE + PACKET_HEADER; j++)
- {
- data[j] = 0;
- }
- }
-
- /**
- *@brief Prepare the data packet
- *@param timeout
- *@retval None
- */
- void Ymodem_PreparePacket(uint8_t*SourceBuf, uint8_t *data, uint8_t pktNo, uint32_t sizeBlk)
- {
- uint16_t i, size, packetSize;
- uint8_t* file_ptr;
-
- /*Make first three packet */
- packetSize = sizeBlk >= PACKET_1K_SIZE ? PACKET_1K_SIZE :PACKET_SIZE;
- size = sizeBlk < packetSize ? sizeBlk :packetSize;
- if(packetSize == PACKET_1K_SIZE)
- {
- data[0] = STX;
- }
- else
- {
- data[0] = SOH;
- }
- data[1] = pktNo;
- data[2] = (~pktNo);
- file_ptr = SourceBuf;
-
- /*Filename packet has valid data */
- for(i = PACKET_HEADER; i < size + PACKET_HEADER;i++)
- {
- data[i] = *file_ptr++;
- }
- if( size <= packetSize)
- {
- for (i = size + PACKET_HEADER; i < packetSize + PACKET_HEADER; i++)
- {
- data[i] = 0x1A; /* EOF (0x1A) or 0x00 */
- }
- }
- }
-
- /**
- *@brief Transmit a data packet using theymodem protocol
- *@param data
- *@param length
- *@retval None
- */
- void Ymodem_SendPacket(uint8_t *data,uint16_t length)
- {
- uint16_t i;
- i =0;
- while (i < length)
- {
- Send_Byte(data[i]);
- i++;
- }
- }
-
- /**
- *@brief Transmit a file using the ymodemprotocol
- *@param buf: Address of the first byte
- *@retval The size of the file
- */
- uint8_t Ymodem_Transmit (uint8_t *buf,const uint8_t* sendFileName, uint32_t sizeFile)
- {
- uint8_t packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD];
- uint8_t FileName[FILE_NAME_LENGTH];
- uint8_t *buf_ptr, tempCheckSum ;
- uint16_t tempCRC, blkNumber;
- uint8_t receivedC[2], CRC16_F = 0, i;
- uint32_t errors = 0, ackReceived = 0, size = 0, pktSize;
-
- for(i = 0; i < (FILE_NAME_LENGTH - 1); i++)
- {
- FileName[i] = sendFileName[i];
- }
- CRC16_F = 1;
-
- /*Prepare first block */
- Ymodem_PrepareIntialPacket(&packet_data[0], FileName,&sizeFile);
-
- do
- {
- /* Send Packet */
- Ymodem_SendPacket(packet_data, PACKET_SIZE + PACKET_HEADER);
-
- /* Send CRC or Check Sum based on CRC16_F */
- if (CRC16_F)
- {
- tempCRC = Cal_CRC16(&packet_data[3], PACKET_SIZE);
- Send_Byte(tempCRC >> 8);
- Send_Byte(tempCRC & 0xFF);
- }
- else
- {
- tempCheckSum = CalChecksum (&packet_data[3], PACKET_SIZE);
- Send_Byte(tempCheckSum);
- }
-
- /*Wait for Ack and 'C' */
- if (Receive_Byte(&receivedC[0], 1000000) == 0)
- {
- if (receivedC[0] == ACK)
- {
- /* Packet transfered correctly */
- ackReceived = 1;
- }
- }
- else
- {
- errors++;
- }
- }while (!ackReceived && (errors < 0x0A));
-
- if(errors >= 0x0A)
- {
- return errors;
- }
- buf_ptr = buf;
- size = sizeFile;
- blkNumber = 0x01;
-
- /*Here 1024 bytes package is used to send the packets */
- while (size)
- {
- /* Prepare next packet */
- Ymodem_PreparePacket(buf_ptr, &packet_data[0], blkNumber, size);
- ackReceived = 0;
- receivedC[0]= 0;
- errors = 0;
- do
- {
- /* Send next packet */
- if (size >= PACKET_1K_SIZE)
- {
- pktSize = PACKET_1K_SIZE;
-
- }
- else
- {
- pktSize = PACKET_SIZE;
- }
- Ymodem_SendPacket(packet_data, pktSize + PACKET_HEADER);
- /* Send CRC or Check Sum based on CRC16_F */
- if (CRC16_F)
- {
- tempCRC = Cal_CRC16(&packet_data[3], pktSize);
- Send_Byte(tempCRC >> 8);
- Send_Byte(tempCRC & 0xFF);
- }
- else
- {
- tempCheckSum = CalChecksum (&packet_data[3], pktSize);
- Send_Byte(tempCheckSum);
- }
-
- /* Wait for Ack */
- if (Receive_Byte(&receivedC[0], 1000000) == 0)
- { if (receivedC[0] == ACK)
- {
- ackReceived = 1;
- if (size > pktSize)
- {
- buf_ptr += pktSize;
- size -= pktSize;
- if (blkNumber == (USER_FLASH_SIZE/1024))
- {
- return 0xFF; /* error */
- }
- else
- {
- blkNumber++;
- }
- }
- else
- {
- buf_ptr += pktSize;
- size = 0;
- }
- }
- }
- else
- {
- errors++;
- }
- }while(!ackReceived && (errors < 0x0A));
-
- /* Resend packet if NAK for acount of 10 else end of commuincation */
- if (errors >= 0x0A)
- {
- return errors;
- }
-
- }
- ackReceived = 0;
- receivedC[0] = 0x00;
- receivedC[1] = 0x00;
- errors = 0;
- do
- {
- Send_Byte(EOT);
- /* Send (EOT); */
- /* Wait for Ack */
- receivedC[0] = USART_ReceiveData(USART1);
- if (receivedC[0] == ACK)
- {
- ackReceived = 1;
- }
-
- else
- {
- errors++;
- }
- /* Clear Overrun flag of the USART2 */
- USART_ClearFlag(USART1, USART_FLAG_ORE);
- }while (!ackReceived && (errors < 0x0A));
-
- if(errors >= 0x0A)
- {
- return errors;
- }
-
- /*Last packet preparation */
- ackReceived = 0;
- receivedC[0] = 0x00;
- receivedC[1] = 0x00;
- errors = 0;
-
- packet_data[0] = SOH;
- packet_data[1] = 0;
- packet_data [2] = 0xFF;
-
- for(i = PACKET_HEADER; i < (PACKET_SIZE + PACKET_HEADER); i++)
- {
- packet_data [i] = 0x00;
- }
-
- do
- {
- /* Send Packet */
- Ymodem_SendPacket(packet_data, PACKET_SIZE + PACKET_HEADER);
-
- /* Send CRC or Check Sum based on CRC16_F */
- tempCRC = Cal_CRC16(&packet_data[3],PACKET_SIZE);
- Send_Byte(tempCRC >> 8);
- Send_Byte(tempCRC & 0xFF);
-
- /* Wait for Ack and 'C' */
- if (Receive_Byte(&receivedC[1], 1000000) == 0)
- {
- if (receivedC[1] == ACK)
- {
- /* Packet transfered correctly */
- ackReceived = 1;
- }
- }
- else
- {
- errors++;
- }
- }while (!ackReceived && (errors < 0x0A));
-
- /*Resend packet if NAK for a count of10 else end of commuincation */
- if(errors >= 0x0A)
- {
- return errors;
- }
- receivedC[0] = 0x00;
- do
- {
- Send_Byte(EOT);
- /* Send (EOT); */
- /* Wait for Ack */
- if ((Receive_Byte(&receivedC[0], 1000000) == 0) && receivedC[0] == ACK)
- {
- ackReceived = 1;
- }
-
- else
- {
- errors++;
- }
- /* Clear Overrun flag of the USART2 */
- USART_ClearFlag(USART1, USART_FLAG_ORE);
- }while (!ackReceived && (errors < 0x0A));
-
- if(errors >= 0x0A)
- {
- return errors;
- }
- return 0; /* file trasmitted successfully */
- }
-
- /**
- *@}
- */
-
- /************************ (C) COPYRIGHTSTMicroelectronics *****END OF FILE****/
复制代码然后就没有然后了,如果你还要然后可以博客下载完整工程看看。。(BY MetalSeed)
|
谢谢版主提供教程资料!