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)\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:须要这样干:
在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选项如图:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvTWV0YWxTZWVk/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
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)\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\rFailed to receive the file!\n\r");
}
} /**
*@brief Upload a file via serial port.
*@param None
*@retval None
*/
void SerialUpload(void)
{
uint8_t status = 0 ; SerialPutString("\n\n\rSelect Receive File\n\r"); 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("\n\rError Occurred while TransmittingFile\n\r");
}
else
{
SerialPutString("\n\rFile uploaded successfully \n\r");
}
}
}
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++] = '\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****/
然后就没有然后了。假设你还要然后能够博客下载完整project看看。。。
还要再然后的话能够博客留言联系。
。