每个文件仅修改flash擦写和传输的串口即可
//common.h文件
/* Includes ------------------------------------------------------------------*/
#include "flash.h"
#include "ymodem.h"
#include <stdio.h>
#include <string.h>
/* Constants used by Serial Command Line Mode */
#define CMD_STRING_SIZE 128
/* BootLoader macro and functions ------------------------------------------------------- */
//修改存放地址
#define BootLoaderAddress (0x0000) //占16K
#define ApplicationAddress (0x4000) //占54K APP地址
#define Save_Updata_Address (ApplicationAddress + 1024*54) //占54K 存储升级APP地址
#define Ota_flag_Address (Save_Updata_Address + 54*1024) // Ota标志位
#define Ota_Bin_Size_Address (Ota_flag_Address + 4)
typedef void (*pFunction)( void );
#define PAGE_SIZE (0x200) /* 512 byte */
/* Compute the FLASH upload image size */
#define FLASH_IMAGE_SIZE (uint32_t) (FLASH_SIZE - (ApplicationAddress - BootLoaderAddress) )
#define Read( x ) (*( (volatile unsigned long *) (x) ) )
/* Exported macro ------------------------------------------------------------*/
/* Common routines */
#define IS_AF( c ) ( (c >= 'A') && (c <= 'F') )
#define IS_af( c ) ( (c >= 'a') && (c <= 'f') )
#define IS_09( c ) ( (c >= '0') && (c <= '9') )
#define ISVALIDHEX( c ) IS_AF( c ) || IS_af( c ) || IS_09( c )
#define ISVALIDDEC( c ) IS_09( c )
#define CONVERTDEC( c ) (c - '0')
#define CONVERTHEX_alpha( c ) (IS_AF( c ) ? ( (c) - 'A' + 10) : ( (c) - 'a' + 10) )
#define CONVERTHEX( c ) (IS_09( c ) ? ( (c) - '0') : CONVERTHEX_alpha( c ) )
#define SerialPutString( x ) Serial_PutString( (uint8_t *) (x) )
typedef struct
{
uint32_t size;
char md5[35];
uint32_t ota_flag;
}ota;
extern ota ota_data;
extern uint8_t tab_1024[1024];
/** @defgroup GPIO_Exported_Functions
* @{
*/
void Int2Str( uint8_t* str, int32_t intnum );
uint32_t Str2Int( uint8_t *inputstr, int32_t *intnum );
uint32_t GetIntegerInput( int32_t * num );
uint32_t SerialKeyPressed( uint8_t *key );
uint8_t GetKey( void );
void SerialPutChar( uint8_t c );
void Serial_PutString( uint8_t *s );
void GetInputString( uint8_t * buffP );
uint32_t FLASH_PagesMask( __IO uint32_t Size );
void FLASH_DisableWriteProtectionPages( void );
void SerialDownload( void );
void SerialUpload( void );
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // __COMM_H__
/************************ (C) COPYRIGHT FudanMicroelectronics *****END OF FILE****/
```c
//common.c
/**
******************************************************************************
* @file IAP/src/common.c
* @author FMSH AS Embedded Software Team
* @version V1.0.0
* @date 7/14/20121
* @brief This file provides all the common functions.
#include "common.h"
#include "bsp.h"
/* Private variables ---------------------------------------------------------*/
pFunction Jump_To_Application;
//uint8_t recv_flag = 0;
//uint8_t recv_data = 0;
uint32_t JumpAddress;
uint32_t BlockNbr = 0, UserMemoryMask = 0;
__IO uint32_t FlashProtection = 0;
extern uint32_t FlashDestination;
/**
* @brief Convert an Integer to a string
* @param str: The string
* @param intnum: The intger to be converted
* @retval None
*/
void Int2Str( uint8_t* str, int32_t intnum )
{
uint32_t i, Div = 1000000000, j = 0, Status = 0;
for ( i = 0; i < 10; i++ )
{
str[j++] = (intnum / Div) + '0';
intnum = intnum % Div;
Div /= 10;
if ( (str[j - 1] == '0') & (Status == 0) )
{
j = 0;
}
else
{
Status++;
}
}
}
/**
* @brief Convert a string to an integer
* @param inputstr: The string to be converted
* @param intnum: The intger value
* @retval 1: Correct
* 0: Error
*/
uint32_t Str2Int( uint8_t *inputstr, int32_t *intnum )
{
uint32_t i = 0, res = 0;
uint32_t val = 0;
if ( inputstr[0] == '0' && (inputstr[1] == 'x' || inputstr[1] == 'X') )
{
if ( inputstr[2] == '\0' )
{
return (0);
}
for ( i = 2; i < 11; i++ )
{
if ( inputstr[i] == '\0' )
{
*intnum = val;
/* return 1; */
res = 1;
break;
}
if ( ISVALIDHEX( inputstr[i] ) )
{
val = (val << 4) + CONVERTHEX( inputstr[i] );
}
else
{
/* return 0, Invalid input */
res = 0;
break;
}
}
/* over 8 digit hex --invalid */
if ( i >= 11 )
{
res = 0;
}
}
else /* max 10-digit decimal input */
{
for ( i = 0; i < 11; i++ )
{
if ( inputstr[i] == '\0' )
{
*intnum = val;
/* return 1 */
res = 1;
break;
}
else if ( (inputstr[i] == 'k' || inputstr[i] == 'K') && (i > 0) )
{
val = val << 10;
*intnum = val;
res = 1;
break;
}
else if ( (inputstr[i] == 'm' || inputstr[i] == 'M') && (i > 0) )
{
val = val << 20;
*intnum = val;
res = 1;
break;
}
else if ( ISVALIDDEC( inputstr[i] ) )
{
val = val * 10 + CONVERTDEC( inputstr[i] );
}
else
{
/* return 0, Invalid input */
res = 0;
break;
}
}
/* Over 10 digit decimal --invalid */
if ( i >= 11 )
{
res = 0;
}
}
return (res);
}
/**
* @brief Get an integer from the HyperTerminal
* @param num: The inetger
* @retval 1: Correct
* 0: Error
*/
uint32_t GetIntegerInput( int32_t * num )
{
uint8_t inputstr[16];
while ( 1 )
{
GetInputString( inputstr );
if ( inputstr[0] == '\0' )
continue;
if ( (inputstr[0] == 'a' || inputstr[0] == 'A') && inputstr[1] == '\0' )
{
SerialPutString( "User Cancelled \r\n" );
return (0);
}
if ( Str2Int( inputstr, num ) == 0 )
{
SerialPutString( "Error, Input again: \r\n" );
}
else
{
return (1);
}
}
}
/**
* @brief Test to see if a key has been pressed on the HyperTerminal
* @param key: The key pressed
* @retval 1: Correct
* 0: Error
*/
uint32_t SerialKeyPressed( uint8_t *key )
{
if ( LL_UART_IsActiveFlag_RXBF( EVAL_COM0 ) ) //EVAL_COM0为串口0传输
{
*key = LL_UART_ReceiveData( EVAL_COM0 );
// printf("1\r\n");
return (1);
}
// else if ( LL_UART_IsActiveFlag_RXBF( Blu_uart ) ) //用蓝牙传输
// {
// *key = LL_UART_ReceiveData( Blu_uart );
// return (1);
// }
// else if ( LL_UART_IsActiveFlag_RXBF( wifi_uart ) ) //用wifi传输
// {
// *key = LL_UART_ReceiveData( wifi_uart );
// return (1);
// }
return (0);
}
/**
* @brief Get a key from the HyperTerminal
* @param None
* @retval The Key Pressed
*/
uint8_t GetKey( void )
{
uint8_t key = 0;
/* Waiting for user input */
while ( 1 )
{
if ( SerialKeyPressed( (uint8_t *) &key ) )
break;
}
return (key);
}
/**
* @brief Print a character on the HyperTerminal
* @param c: The character to be printed
* @retval None
*/
void SerialPutChar( uint8_t c )
{
while ( !LL_UART_IsActiveFlag_TXBE( EVAL_COM0 ) )
;
LL_UART_TransmitData( EVAL_COM0, (uint32_t) c );
}
/**
* @brief Print a string on the HyperTerminal
* @param s: The string to be printed
* @retval None
*/
void Serial_PutString( uint8_t *s )
{
while ( *s != '\0' )
{
SerialPutChar( *s );
s++;
}
}
/**
* @brief Get Input string from the HyperTerminal
* @param buffP: The input string
* @retval None
*/
void GetInputString( uint8_t * buffP )
{
uint32_t bytes_read = 0;
uint8_t c = 0;
do
{
c = GetKey();
if ( c == '\r' )
break;
if ( c == '\b' ) /* Backspace */
{
if ( bytes_read > 0 )
{
SerialPutString( "\b \b" );
bytes_read--;
}
continue;
}
if ( bytes_read >= CMD_STRING_SIZE )
{
SerialPutString( "Command string size overflow\r\n" );
bytes_read = 0;
continue;
}
if ( c >= 0x20 && c <= 0x7E )
{
buffP[bytes_read++] = c;
SerialPutChar( c );
}
}
while ( 1 );
SerialPutString( ("\n\r") );
buffP[bytes_read] = '\0';
}
/**
* @brief Calculate the number of pages
* @param Size: The image size
* @retval The number of pages
*/
uint32_t FLASH_PagesMask( __IO uint32_t Size )
{
uint32_t pagenumber = 0x0;
uint32_t size = Size;
if ( (size % PAGE_SIZE) != 0 )
{
pagenumber = (size / PAGE_SIZE) + 1;
}
else
{
pagenumber = size / PAGE_SIZE;
}
return (pagenumber);
}
/**
* @brief Disable the write protection of desired pages
* @note FM15L02x don't have write protection function,this function is null
* @retval None
*/
void FLASH_DisableWriteProtectionPages( void )
{
}
```c
//dowmload.c
#include "common.h"
#include "uart.h"
#include "md5.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
extern uint8_t file_name[FILE_NAME_LENGTH];
uint8_t tab_1024[1024] = {
0
};
ota ota_data;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
void set_ota_flag(int32_t Size)
{
flash_erase(LL_FLASH_ERTYPE_PAGE, Ota_flag_Address);
ota_data.ota_flag = 1;
flash_program(Ota_flag_Address, ota_data.ota_flag);
flash_program(Ota_Bin_Size_Address, Size);
}
/**
* @brief Download a file via serial port
* @param None
* @retval None
*/
void SerialDownload( void )
{
uint8_t Number[10] = " ";
int32_t Size = 0;
char *p = NULL;
char md5_buf[35] = {0};
/*
OTA升级要把串口中断都关掉
如果定时器频繁中断 可能会影响传输 也要关掉
*/
// NVIC_DisableIRQ( LPTIM_IRQn );
NVIC_DisableIRQ( UART0_IRQn );
printf( "Waiting for the file to be sent ... (press 'a' to abort)\n\r" );
Size = Ymodem_Receive( &tab_1024[0] ); //获得下载升级bin文件的内容
if ( Size > 0 )
{
printf( "\n\n\r Programming Completed Successfully!\n\r--------------------------------\r\n Name: " );
printf( (char *)file_name );
Int2Str( Number, Size );
printf( "\n\r Size: " );
printf( (char *)Number );
printf( " Bytes\r\n" );
printf( "-------------------\n" );
//对比文件名
if((p=strstr((char *)file_name,"_"))!=NULL && ((strstr((char *)file_name,"bin文件名*(根据实际修改)"))!=NULL))
{
ota_data.size=Size;
memcpy(ota_data.md5,p+1,32);
GetBinFileMd5(md5_buf);
if(strcasecmp(md5_buf,ota_data.md5) == 0)
{
}
else
{
//md5校验失败
printf("ota_md5 fail\r\n");
return ;
}
}
else
{
printf("file name fail\r\n");
return;
}
set_ota_flag(Size);
NVIC_SystemReset();
}
else if ( Size == -1 )
{
printf( "\n\n\rThe image size is higher than the allowed space memory!\n\r" );
}
else if ( Size == -2 )
{
printf( "\n\n\rVerification failed!\n\r" );
}
else if ( Size == -3 )
{
printf( "\r\n\nAborted by user.\n\r" );
}
else
{
printf( "\n\rFailed to receive the file!\n\r" );
}
}
/*******************(C)COPYRIGHT 2010 STMicroelectronics *****END OF FILE******/
//md5.h文件
#ifndef _MD5_h
#define _MD5_h
void GetBinFileMd5(char *pEsult);
#endif
//md5.c
#include "main.h"
//#include "common.h"
#if 1
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
#define RL(x, y) (((x) << (y)) | ((x) >> (32 - (y))))
#define FF(a, b, c, d, x, s, ac) a = b + (RL((a + F(b, c, d) + x + ac), s))
#define GG(a, b, c, d, x, s, ac) a = b + (RL((a + G(b, c, d) + x + ac), s))
#define HH(a, b, c, d, x, s, ac) a = b + (RL((a + H(b, c, d) + x + ac), s))
#define II(a, b, c, d, x, s, ac) a = b + (RL((a + I(b, c, d) + x + ac), s))
#define PP(x) (x << 24) | ((x << 8) & 0xff0000) | ((x >> 8) & 0xff00) | (x >> 24)
uint32_t ulFlashAdd = Save_Updata_Address, ulFlieLength = 0;
uint32_t A = 0x67452301, B = 0xefcdab89, C = 0x98badcfe, D = 0x10325476, a, b, c, d, x[16];
extern ota ota_data;
void MD5(void)
{
a = A, b = B, c = C, d = D;
FF(a, b, c, d, x[0], 7, 0xd76aa478);
FF(d, a, b, c, x[1], 12, 0xe8c7b756);
FF(c, d, a, b, x[2], 17, 0x242070db);
FF(b, c, d, a, x[3], 22, 0xc1bdceee);
FF(a, b, c, d, x[4], 7, 0xf57c0faf);
FF(d, a, b, c, x[5], 12, 0x4787c62a);
FF(c, d, a, b, x[6], 17, 0xa8304613);
FF(b, c, d, a, x[7], 22, 0xfd469501);
FF(a, b, c, d, x[8], 7, 0x698098d8);
FF(d, a, b, c, x[9], 12, 0x8b44f7af);
FF(c, d, a, b, x[10], 17, 0xffff5bb1);
FF(b, c, d, a, x[11], 22, 0x895cd7be);
FF(a, b, c, d, x[12], 7, 0x6b901122);
FF(d, a, b, c, x[13], 12, 0xfd987193);
FF(c, d, a, b, x[14], 17, 0xa679438e);
FF(b, c, d, a, x[15], 22, 0x49b40821);
GG(a, b, c, d, x[1], 5, 0xf61e2562);
GG(d, a, b, c, x[6], 9, 0xc040b340);
GG(c, d, a, b, x[11], 14, 0x265e5a51);
GG(b, c, d, a, x[0], 20, 0xe9b6c7aa);
GG(a, b, c, d, x[5], 5, 0xd62f105d);
GG(d, a, b, c, x[10], 9, 0x02441453);
GG(c, d, a, b, x[15], 14, 0xd8a1e681);
GG(b, c, d, a, x[4], 20, 0xe7d3fbc8);
GG(a, b, c, d, x[9], 5, 0x21e1cde6);
GG(d, a, b, c, x[14], 9, 0xc33707d6);
GG(c, d, a, b, x[3], 14, 0xf4d50d87);
GG(b, c, d, a, x[8], 20, 0x455a14ed);
GG(a, b, c, d, x[13], 5, 0xa9e3e905);
GG(d, a, b, c, x[2], 9, 0xfcefa3f8);
GG(c, d, a, b, x[7], 14, 0x676f02d9);
GG(b, c, d, a, x[12], 20, 0x8d2a4c8a);
HH(a, b, c, d, x[5], 4, 0xfffa3942);
HH(d, a, b, c, x[8], 11, 0x8771f681);
HH(c, d, a, b, x[11], 16, 0x6d9d6122);
HH(b, c, d, a, x[14], 23, 0xfde5380c);
HH(a, b, c, d, x[1], 4, 0xa4beea44);
HH(d, a, b, c, x[4], 11, 0x4bdecfa9);
HH(c, d, a, b, x[7], 16, 0xf6bb4b60);
HH(b, c, d, a, x[10], 23, 0xbebfbc70);
HH(a, b, c, d, x[13], 4, 0x289b7ec6);
HH(d, a, b, c, x[0], 11, 0xeaa127fa);
HH(c, d, a, b, x[3], 16, 0xd4ef3085);
HH(b, c, d, a, x[6], 23, 0x04881d05);
HH(a, b, c, d, x[9], 4, 0xd9d4d039);
HH(d, a, b, c, x[12], 11, 0xe6db99e5);
HH(c, d, a, b, x[15], 16, 0x1fa27cf8);
HH(b, c, d, a, x[2], 23, 0xc4ac5665);
II(a, b, c, d, x[0], 6, 0xf4292244);
II(d, a, b, c, x[7], 10, 0x432aff97);
II(c, d, a, b, x[14], 15, 0xab9423a7);
II(b, c, d, a, x[5], 21, 0xfc93a039);
II(a, b, c, d, x[12], 6, 0x655b59c3);
II(d, a, b, c, x[3], 10, 0x8f0ccc92);
II(c, d, a, b, x[10], 15, 0xffeff47d);
II(b, c, d, a, x[1], 21, 0x85845dd1);
II(a, b, c, d, x[8], 6, 0x6fa87e4f);
II(d, a, b, c, x[15], 10, 0xfe2ce6e0);
II(c, d, a, b, x[6], 15, 0xa3014314);
II(b, c, d, a, x[13], 21, 0x4e0811a1);
II(a, b, c, d, x[4], 6, 0xf7537e82);
II(d, a, b, c, x[11], 10, 0xbd3af235);
II(c, d, a, b, x[2], 15, 0x2ad7d2bb);
II(b, c, d, a, x[9], 21, 0xeb86d391);
A += a;
B += b;
C += c;
D += d;
}
uint32_t ulSampleIndex = 0;
uint32_t ulDataIndex = 0;
uint32_t ulReadCnt = 0;
void ReadGroupTempBuf(void)
{
uint8_t j, k;
memset(x, 0, 64);
ulSampleIndex = 0;
for (j = 0; j < 16; j++)
{
for (k = 0; k < 4; k++)
{
if ((ulReadCnt >= ota_data.size / 1024) && (ulDataIndex >= ota_data.size % 1024))
break;
((char *)x)[ulSampleIndex] = tab_1024[ulDataIndex];
ulDataIndex++;
ulSampleIndex++;
}
}
}
void GetBinFileMd5(char *pEsult)
{
uint16_t usCnt = 0;
uint32_t ulFileLen[2] = {0};
ulFlashAdd = Save_Updata_Address;
ulSampleIndex = 0;
ulDataIndex = 0;
ulReadCnt = 0;
A = 0x67452301;
B = 0xefcdab89;
C = 0x98badcfe;
D = 0x10325476;
/* 计算整数部分 */
for (ulReadCnt = 0; ulReadCnt < ota_data.size / 1024; ulReadCnt++)
{
memcpy(tab_1024,(char *)ulFlashAdd,1024);
ulFlashAdd += 1024;
for (usCnt = 0; usCnt < 16; usCnt++)
{
ReadGroupTempBuf();
MD5();
}
ulDataIndex = 0;
}
/* 计算余数部分 */
memset(tab_1024, 0, 1024);
memcpy(tab_1024,(char *)ulFlashAdd,ota_data.size % 1024);
ReadGroupTempBuf();
for (usCnt = 0; usCnt < (ota_data.size % 1024) / 64; usCnt++)
{
MD5();
ReadGroupTempBuf();
}
/* 文件结束补1,补0操作,128二进制即10000000 */
((char *)x)[ota_data.size % 64] = 128;
if (ota_data.size % 64 > 55)
{
MD5(), memset(x, 0, 64);
}
/* 文件末尾加入原文件的bit长度 */
ulFileLen[1] = ota_data.size / 0x20000000;
ulFileLen[0] = (ota_data.size % 0x20000000) * 8;
memcpy(x + 14, ulFileLen, 8);
MD5();
sprintf(pEsult, "%08x%08x%08x%08x", PP(A), PP(B), PP(C), PP(D));
}
#endif
ymodem.c
/**
******************************************************************************
* @file IAP/src/ymodem.c
* @author MCD Application Team
* @version V3.3.0
* @date 10/15/2010
* @brief This file provides all the software functions related to the ymodem
* protocol.
******************************************************************************
* @copy
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>© COPYRIGHT 2010 STMicroelectronics</center></h2>
*/
/** @addtogroup IAP
* @{
*/
/* Includes ------------------------------------------------------------------*/
#include "common.h"
#include "fm15l0xx_ll_flash.h"
#include "fm15l0xx_ll_iwdt.h"
#include "main.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
uint8_t file_name[FILE_NAME_LENGTH];
uint32_t FlashDestination = Save_Updata_Address; /* Flash user program offset */
uint16_t PageSize = PAGE_SIZE;
uint32_t EraseCounter = 0x0;
uint32_t NbrOfPage = 0;
//FLASH_Status FLASHStatus = FLASH_COMPLETE;
uint32_t RamSource;
extern uint8_t tab_1024[1024];
uint8_t ota_up=0; //OTA 更新中禁止进入休眠
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
void delay( uint32_t del )
{
uint32_t i = 0;
for ( i = 0; i < 5; i++ )
for (; del > 1; del-- )
;
}
/**
* @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 )
{
LL_IWDT_ReloadCounter(); // Feed IWDT
if ( SerialKeyPressed( c ) == 1 )
{
return (0);
}
delay( 5 );
}
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 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 packet error
* 1: abort by user
*/
static int32_t Receive_Packet( uint8_t *data, int32_t *length, uint32_t timeout )
{
uint16_t i, packet_size;
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);
}
*length = packet_size;
return (0);
}
/**
* @brief Receive a file using the ymodem protocol
* @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, j, packet_length, session_done, file_done, packets_received, errors, session_begin, size = 0;
/* Initialize FlashDestination variable */
FlashDestination = Save_Updata_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 has valid data */
for ( i = 0, file_ptr = packet_data + PACKET_HEADER; (*file_ptr != 0) && (i < FILE_NAME_LENGTH); )
{
file_name[i++] = *file_ptr++;
}
file_name[i++] = '\0';
for ( i = 0, file_ptr++; (*file_ptr != ' ') && (i < FILE_SIZE_LENGTH); )
{
file_size[i++] = *file_ptr++;
}
file_size[i++] = '\0';
Str2Int( file_size, &size );
/* Test the size of the image to be sent */
/* Image size is greater than Flash size */
if ( size > (FLASH_SIZE - 1) )
{
/* End session */
Send_Byte( CA );
Send_Byte( CA );
return (-1);
}
/* Erase the needed pages where the user application will be loaded */
/* Define the number of page to be erased */
NbrOfPage = FLASH_PagesMask( size );
/* Erase the FLASH pages */
for ( EraseCounter = 0; EraseCounter < NbrOfPage; EraseCounter++ )
{
flash_erase( LL_FLASH_ERTYPE_SECTOR, FlashDestination + (PageSize * EraseCounter) );
}
Send_Byte( ACK );
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;
for ( j = 0; (j < packet_length) && (FlashDestination < Save_Updata_Address + size); j += 4 )
{
/* Program the data received into FM15L02x Flash */
flash_program( FlashDestination, *(uint32_t *) RamSource );
//FLASH_ProgramWord(FlashDestination, *(uint32_t*)RamSource);
if ( *(uint32_t *) FlashDestination != *(uint32_t *) RamSource )
{
/* End session */
Send_Byte( CA );
Send_Byte( CA );
return (-2);
}
FlashDestination += 4;
RamSource += 4;
}
Send_Byte( ACK );
}
packets_received++;
session_begin = 1;
}
}
break;
case 1:
Send_Byte( CA );
Send_Byte( CA );
return (-3);
default:
if ( session_begin > 0 )
{
errors++;
}
if ( errors > MAX_ERRORS )
{
Send_Byte( CA );
Send_Byte( CA );
return (0);
}
Send_Byte( CRC16 );
break;
}
if ( file_done != 0 )
{
break;
}
}
if ( session_done != 0 )
{
break;
}
}
return ( (int32_t) size);
}
/**
* @brief check response using the ymodem protocol
* @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
* 0: end of transmission
*/
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
* 0: end of transmission
*/
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 Update CRC16 for input byte
* @param CRC input value
* @param input byte
* @retval None
*/
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 None
*/
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 Transmit a data packet using the ymodem 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 ymodem protocol
* @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 ret = 0;
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, ackReceived, size = 0, pktSize;
errors = 0;
ackReceived = 0;
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], 10000 ) == 0 )
{
if ( receivedC[0] == ACK )
{
if ( (Receive_Byte( &receivedC[0], 10000 ) == 0) && (receivedC[0] == CRC16) )
/* 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 */
/* Resend packet if NAK for a count of 10 else end of commuincation */
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 */
/* 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 */
ret = Receive_Byte( &receivedC[0], 100000 );
if ( (ret == 0) && (receivedC[0] == ACK) )
{
ackReceived = 1;
if ( size > pktSize )
{
buf_ptr += pktSize;
size -= pktSize;
if ( blkNumber == (FLASH_IMAGE_SIZE / 1024) )
{
return (0xFF); /* error */
}
else
{
blkNumber++;
}
}
else
{
buf_ptr += pktSize;
size = 0;
}
}
else
{
errors++;
}
}
while ( !ackReceived && (errors < 0x0A) );
/* Resend packet if NAK for a count of 10 else end of commuincation */
if ( errors >= 0x0A )
{
return (errors);
}
}
ackReceived = 0;
receivedC[0] = 0x00;
errors = 0;
do
{
Send_Byte( EOT );
/* Send (EOT); */
/* Wait for Ack */
if ( (Receive_Byte( &receivedC[0], 10000 ) == 0) && receivedC[0] == ACK )
{
ackReceived = 1;
}
else
{
errors++;
}
}
while ( !ackReceived && (errors < 0x0A) );
if ( errors >= 0x0A )
{
return (errors);
}
/* Last packet preparation */
ackReceived = 0;
receivedC[0] = 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[0], 10000 ) == 0 )
{
if ( receivedC[0] == ACK )
{
/* Packet transfered correctly */
ackReceived = 1;
}
}
else
{
errors++;
}
}
while ( !ackReceived && (errors < 0x0A) );
/* Resend packet if NAK for a count of 10 else end of commuincation */
if ( errors >= 0x0A )
{
return (errors);
}
do
{
Send_Byte( EOT );
/* Send (EOT); */
/* Wait for Ack */
if ( (Receive_Byte( &receivedC[0], 10000 ) == 0) && receivedC[0] == ACK )
{
ackReceived = 1;
}
else
{
errors++;
}
}
while ( !ackReceived && (errors < 0x0A) );
if ( errors >= 0x0A )
{
return (errors);
}
return (0); /* file trasmitted successfully */
}
/**
* @}
*/
/*******************(C)COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/
main.c
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "main.h"
#include "uart.h"
#include "common.h"
uint8_t uart_recv_flag = 0;
uint32_t uart_recv_length = 0;
char uart_recv_buf[UART_RECV_BUF_MAXSIZE] = { 0 };
uint8_t esp_recv_flag = 0;
volatile uint8_t ble_recv_flag = 0;
u8 delay_flag = 0;
u16 delay_cnt = 0;
Time timer = {0};
Flag flag = {0};
LED ledR = {0};
LED ledB = {0};
extern char Ble_send_buf[512];
void NVIC_init( void )
{
nvic_init( UARTx );
}
void bsp_init()
{
LL_CMU_EnablePeriphBusClock_GPIO();
//串口打印
gpio_init( UART0 );
uart_init( UART0 );
flash_init();
}
/*
* @brief Main program
* @param None
* @retval None
*/
int main( void )
{
SCB->VTOR = ApplicationAddress; //修改向量表位置
bsp_init(); //硬件初始化
NVIC_init(); //设置中断源
printf("version:1.0.2\r\n");//版本号 可以查看是否ota成功
while ( 1 )
{
if(uart_recv_flag)//串口接收指令
{
if(strstr(uart_recv_buf,"ota") != NULL) //识别到ota标志
{
SerialDownload();//开始ota
}
}
}
}
}
#endif
/************************ (C) COPYRIGHT FMSH Microelectronics *****END OF FILE****/