串口OTA之主程序编写(笔记)

每个文件仅修改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>&copy; 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****/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值