mirror of
https://github.com/STMicroelectronics/STM32CubeF7.git
synced 2025-05-05 19:30:14 +08:00
651 lines
18 KiB
C
651 lines
18 KiB
C
/**
|
|
******************************************************************************
|
|
* @file IAP/IAP_Main/Src/ymodem.c
|
|
* @author MCD Application Team
|
|
* @brief This file provides all the software functions related to the ymodem
|
|
* protocol.
|
|
******************************************************************************
|
|
* @attention
|
|
*
|
|
* Copyright (c) 2016 STMicroelectronics.
|
|
* All rights reserved.
|
|
*
|
|
* This software is licensed under terms that can be found in the LICENSE file
|
|
* in the root directory of this software component.
|
|
* If no LICENSE file comes with this software, it is provided AS-IS.
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
|
|
/** @addtogroup STM32F7xx_IAP
|
|
* @{
|
|
*/
|
|
|
|
/* Includes ------------------------------------------------------------------*/
|
|
#include "flash_if.h"
|
|
#include "common.h"
|
|
#include "ymodem.h"
|
|
#include "string.h"
|
|
#include "main.h"
|
|
#include "menu.h"
|
|
|
|
/* Private typedef -----------------------------------------------------------*/
|
|
/* Private define ------------------------------------------------------------*/
|
|
#define CRC16_F /* activate the CRC16 integrity */
|
|
/* Private macro -------------------------------------------------------------*/
|
|
/* Private variables ---------------------------------------------------------*/
|
|
__IO uint32_t flashdestination;
|
|
/* @note ATTENTION - please keep this variable 32bit alligned */
|
|
uint8_t aPacketData[PACKET_1K_SIZE + PACKET_DATA_INDEX + PACKET_TRAILER_SIZE];
|
|
|
|
/* Private function prototypes -----------------------------------------------*/
|
|
static void PrepareIntialPacket(uint8_t *p_data, const uint8_t *p_file_name, uint32_t length);
|
|
static void PreparePacket(uint8_t *p_source, uint8_t *p_packet, uint8_t pkt_nr, uint32_t size_blk);
|
|
static HAL_StatusTypeDef ReceivePacket(uint8_t *p_data, uint32_t *p_length, uint32_t timeout);
|
|
uint16_t UpdateCRC16(uint16_t crc_in, uint8_t byte);
|
|
uint16_t Cal_CRC16(const uint8_t* p_data, uint32_t size);
|
|
uint8_t CalcChecksum(const uint8_t *p_data, uint32_t size);
|
|
|
|
/* Private functions ---------------------------------------------------------*/
|
|
|
|
/**
|
|
* @brief Receive a packet from sender
|
|
* @param data
|
|
* @param length
|
|
* 0: end of transmission
|
|
* 2: abort by sender
|
|
* >0: packet length
|
|
* @param timeout
|
|
* @retval HAL_OK: normally return
|
|
* HAL_BUSY: abort by user
|
|
*/
|
|
static HAL_StatusTypeDef ReceivePacket(uint8_t *p_data, uint32_t *p_length, uint32_t timeout)
|
|
{
|
|
uint32_t crc;
|
|
uint32_t packet_size = 0;
|
|
HAL_StatusTypeDef status;
|
|
uint8_t char1;
|
|
|
|
*p_length = 0;
|
|
status = HAL_UART_Receive(&UartHandle, &char1, 1, timeout);
|
|
|
|
if (status == HAL_OK)
|
|
{
|
|
switch (char1)
|
|
{
|
|
case SOH:
|
|
packet_size = PACKET_SIZE;
|
|
break;
|
|
case STX:
|
|
packet_size = PACKET_1K_SIZE;
|
|
break;
|
|
case EOT:
|
|
break;
|
|
case CA:
|
|
if ((HAL_UART_Receive(&UartHandle, &char1, 1, timeout) == HAL_OK) && (char1 == CA))
|
|
{
|
|
packet_size = 2;
|
|
}
|
|
else
|
|
{
|
|
status = HAL_ERROR;
|
|
}
|
|
break;
|
|
case ABORT1:
|
|
case ABORT2:
|
|
status = HAL_BUSY;
|
|
break;
|
|
default:
|
|
status = HAL_ERROR;
|
|
break;
|
|
}
|
|
*p_data = char1;
|
|
|
|
if (packet_size >= PACKET_SIZE )
|
|
{
|
|
status = HAL_UART_Receive(&UartHandle, &p_data[PACKET_NUMBER_INDEX], packet_size + PACKET_OVERHEAD_SIZE, timeout);
|
|
|
|
/* Simple packet sanity check */
|
|
if (status == HAL_OK )
|
|
{
|
|
if (p_data[PACKET_NUMBER_INDEX] != ((p_data[PACKET_CNUMBER_INDEX]) ^ NEGATIVE_BYTE))
|
|
{
|
|
packet_size = 0;
|
|
status = HAL_ERROR;
|
|
}
|
|
else
|
|
{
|
|
/* Check packet CRC */
|
|
crc = p_data[ packet_size + PACKET_DATA_INDEX ] << 8;
|
|
crc += p_data[ packet_size + PACKET_DATA_INDEX + 1 ];
|
|
if (Cal_CRC16(&p_data[PACKET_DATA_INDEX], packet_size) != crc )
|
|
{
|
|
packet_size = 0;
|
|
status = HAL_ERROR;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
packet_size = 0;
|
|
}
|
|
}
|
|
}
|
|
*p_length = packet_size;
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* @brief Prepare the first block
|
|
* @param p_data: output buffer
|
|
* @param p_file_name: name of the file to be sent
|
|
* @param length: length of the file to be sent in bytes
|
|
* @retval None
|
|
*/
|
|
static void PrepareIntialPacket(uint8_t *p_data, const uint8_t *p_file_name, uint32_t length)
|
|
{
|
|
uint32_t i, j = 0;
|
|
uint8_t astring[10];
|
|
|
|
/* first 3 bytes are constant */
|
|
p_data[PACKET_START_INDEX] = SOH;
|
|
p_data[PACKET_NUMBER_INDEX] = 0x00;
|
|
p_data[PACKET_CNUMBER_INDEX] = 0xff;
|
|
|
|
/* Filename written */
|
|
for (i = 0; (p_file_name[i] != '\0') && (i < FILE_NAME_LENGTH); i++)
|
|
{
|
|
p_data[i + PACKET_DATA_INDEX] = p_file_name[i];
|
|
}
|
|
|
|
p_data[i + PACKET_DATA_INDEX] = 0x00;
|
|
|
|
/* file size written */
|
|
Int2Str (astring, length);
|
|
i = i + PACKET_DATA_INDEX + 1;
|
|
while (astring[j] != '\0')
|
|
{
|
|
p_data[i++] = astring[j++];
|
|
}
|
|
|
|
/* padding with zeros */
|
|
for (j = i; j < PACKET_SIZE + PACKET_DATA_INDEX; j++)
|
|
{
|
|
p_data[j] = 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Prepare the data packet
|
|
* @param p_source: pointer to the data to be sent
|
|
* @param p_packet: pointer to the output buffer
|
|
* @param pkt_nr: number of the packet
|
|
* @param size_blk: length of the block to be sent in bytes
|
|
* @retval None
|
|
*/
|
|
static void PreparePacket(uint8_t *p_source, uint8_t *p_packet, uint8_t pkt_nr, uint32_t size_blk)
|
|
{
|
|
uint8_t *p_record;
|
|
uint32_t i, size, packet_size;
|
|
|
|
/* Make first three packet */
|
|
packet_size = size_blk >= PACKET_1K_SIZE ? PACKET_1K_SIZE : PACKET_SIZE;
|
|
size = size_blk < packet_size ? size_blk : packet_size;
|
|
if (packet_size == PACKET_1K_SIZE)
|
|
{
|
|
p_packet[PACKET_START_INDEX] = STX;
|
|
}
|
|
else
|
|
{
|
|
p_packet[PACKET_START_INDEX] = SOH;
|
|
}
|
|
p_packet[PACKET_NUMBER_INDEX] = pkt_nr;
|
|
p_packet[PACKET_CNUMBER_INDEX] = (~pkt_nr);
|
|
p_record = p_source;
|
|
|
|
/* Filename packet has valid data */
|
|
for (i = PACKET_DATA_INDEX; i < size + PACKET_DATA_INDEX;i++)
|
|
{
|
|
p_packet[i] = *p_record++;
|
|
}
|
|
if ( size <= packet_size)
|
|
{
|
|
for (i = size + PACKET_DATA_INDEX; i < packet_size + PACKET_DATA_INDEX; i++)
|
|
{
|
|
p_packet[i] = 0x1A; /* EOF (0x1A) or 0x00 */
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Update CRC16 for input byte
|
|
* @param crc_in input value
|
|
* @param input byte
|
|
* @retval None
|
|
*/
|
|
uint16_t UpdateCRC16(uint16_t crc_in, uint8_t byte)
|
|
{
|
|
uint32_t crc = crc_in;
|
|
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* p_data, uint32_t size)
|
|
{
|
|
uint32_t crc = 0;
|
|
const uint8_t* dataEnd = p_data+size;
|
|
|
|
while(p_data < dataEnd)
|
|
crc = UpdateCRC16(crc, *p_data++);
|
|
|
|
crc = UpdateCRC16(crc, 0);
|
|
crc = UpdateCRC16(crc, 0);
|
|
|
|
return crc&0xffffu;
|
|
}
|
|
|
|
/**
|
|
* @brief Calculate Check sum for YModem Packet
|
|
* @param p_data Pointer to input data
|
|
* @param size length of input data
|
|
* @retval uint8_t checksum value
|
|
*/
|
|
uint8_t CalcChecksum(const uint8_t *p_data, uint32_t size)
|
|
{
|
|
uint32_t sum = 0;
|
|
const uint8_t *p_data_end = p_data + size;
|
|
|
|
while (p_data < p_data_end )
|
|
{
|
|
sum += *p_data++;
|
|
}
|
|
|
|
return (sum & 0xffu);
|
|
}
|
|
|
|
/* Public functions ---------------------------------------------------------*/
|
|
/**
|
|
* @brief Receive a file using the ymodem protocol with CRC16.
|
|
* @param p_size The size of the file.
|
|
* @retval COM_StatusTypeDef result of reception/programming
|
|
*/
|
|
COM_StatusTypeDef Ymodem_Receive ( uint32_t *p_size )
|
|
{
|
|
uint32_t i, packet_length, session_done = 0, file_done, errors = 0, session_begin = 0;
|
|
uint32_t ramsource, filesize;
|
|
uint8_t *file_ptr;
|
|
uint8_t file_size[FILE_SIZE_LENGTH], tmp, packets_received;
|
|
COM_StatusTypeDef result = COM_OK;
|
|
|
|
/* Initialize flashdestination variable */
|
|
flashdestination = APPLICATION_ADDRESS;
|
|
|
|
while ((session_done == 0) && (result == COM_OK))
|
|
{
|
|
packets_received = 0;
|
|
file_done = 0;
|
|
while ((file_done == 0) && (result == COM_OK))
|
|
{
|
|
switch (ReceivePacket(aPacketData, &packet_length, DOWNLOAD_TIMEOUT))
|
|
{
|
|
case HAL_OK:
|
|
errors = 0;
|
|
switch (packet_length)
|
|
{
|
|
case 2:
|
|
/* Abort by sender */
|
|
Serial_PutByte(ACK);
|
|
result = COM_ABORT;
|
|
break;
|
|
case 0:
|
|
/* End of transmission */
|
|
Serial_PutByte(ACK);
|
|
file_done = 1;
|
|
break;
|
|
default:
|
|
/* Normal packet */
|
|
if (aPacketData[PACKET_NUMBER_INDEX] != packets_received)
|
|
{
|
|
Serial_PutByte(NAK);
|
|
}
|
|
else
|
|
{
|
|
if (packets_received == 0)
|
|
{
|
|
/* File name packet */
|
|
if (aPacketData[PACKET_DATA_INDEX] != 0)
|
|
{
|
|
/* File name extraction */
|
|
i = 0;
|
|
file_ptr = aPacketData + PACKET_DATA_INDEX;
|
|
while ( (*file_ptr != 0) && (i < FILE_NAME_LENGTH))
|
|
{
|
|
aFileName[i++] = *file_ptr++;
|
|
}
|
|
|
|
/* File size extraction */
|
|
aFileName[i++] = '\0';
|
|
i = 0;
|
|
file_ptr ++;
|
|
while ( (*file_ptr != ' ') && (i < FILE_SIZE_LENGTH))
|
|
{
|
|
file_size[i++] = *file_ptr++;
|
|
}
|
|
file_size[i++] = '\0';
|
|
Str2Int(file_size, &filesize);
|
|
|
|
/* Test the size of the image to be sent */
|
|
/* Image size is greater than Flash size */
|
|
if (*p_size > (USER_FLASH_SIZE + 1))
|
|
{
|
|
/* End session */
|
|
tmp = CA;
|
|
HAL_UART_Transmit(&UartHandle, &tmp, 1, NAK_TIMEOUT);
|
|
HAL_UART_Transmit(&UartHandle, &tmp, 1, NAK_TIMEOUT);
|
|
result = COM_LIMIT;
|
|
}
|
|
/* erase user application area */
|
|
FLASH_If_Erase(APPLICATION_ADDRESS);
|
|
*p_size = filesize;
|
|
|
|
Serial_PutByte(ACK);
|
|
Serial_PutByte(CRC16);
|
|
}
|
|
/* File header packet is empty, end session */
|
|
else
|
|
{
|
|
Serial_PutByte(ACK);
|
|
file_done = 1;
|
|
session_done = 1;
|
|
break;
|
|
}
|
|
}
|
|
else /* Data packet */
|
|
{
|
|
ramsource = (uint32_t) & aPacketData[PACKET_DATA_INDEX];
|
|
/* Write received data in Flash */
|
|
if (FLASH_If_Write(flashdestination, (uint32_t*) ramsource, packet_length/4) == FLASHIF_OK)
|
|
{
|
|
flashdestination += packet_length;
|
|
Serial_PutByte(ACK);
|
|
}
|
|
else /* An error occurred while writing to Flash memory */
|
|
{
|
|
/* End session */
|
|
Serial_PutByte(CA);
|
|
Serial_PutByte(CA);
|
|
result = COM_DATA;
|
|
}
|
|
}
|
|
packets_received ++;
|
|
session_begin = 1;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
case HAL_BUSY: /* Abort actually */
|
|
Serial_PutByte(CA);
|
|
Serial_PutByte(CA);
|
|
result = COM_ABORT;
|
|
break;
|
|
default:
|
|
if (session_begin > 0)
|
|
{
|
|
errors ++;
|
|
}
|
|
if (errors > MAX_ERRORS)
|
|
{
|
|
/* Abort communication */
|
|
Serial_PutByte(CA);
|
|
Serial_PutByte(CA);
|
|
}
|
|
else
|
|
{
|
|
Serial_PutByte(CRC16); /* Ask for a packet */
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @brief Transmit a file using the ymodem protocol
|
|
* @param p_buf: Address of the first byte
|
|
* @param p_file_name: Name of the file sent
|
|
* @param file_size: Size of the transmission
|
|
* @retval COM_StatusTypeDef result of the communication
|
|
*/
|
|
COM_StatusTypeDef Ymodem_Transmit (uint8_t *p_buf, const uint8_t *p_file_name, uint32_t file_size)
|
|
{
|
|
uint32_t errors = 0, ack_recpt = 0, size = 0, pkt_size;
|
|
uint8_t *p_buf_int;
|
|
COM_StatusTypeDef result = COM_OK;
|
|
uint32_t blk_number = 1;
|
|
uint8_t a_rx_ctrl[2];
|
|
uint8_t i;
|
|
#ifdef CRC16_F
|
|
uint32_t temp_crc;
|
|
#else /* CRC16_F */
|
|
uint8_t temp_chksum;
|
|
#endif /* CRC16_F */
|
|
|
|
/* Prepare first block - header */
|
|
PrepareIntialPacket(aPacketData, p_file_name, file_size);
|
|
|
|
while (( !ack_recpt ) && ( result == COM_OK ))
|
|
{
|
|
/* Send Packet */
|
|
HAL_UART_Transmit(&UartHandle, &aPacketData[PACKET_START_INDEX], PACKET_SIZE + PACKET_HEADER_SIZE, NAK_TIMEOUT);
|
|
|
|
/* Send CRC or Check Sum based on CRC16_F */
|
|
#ifdef CRC16_F
|
|
temp_crc = Cal_CRC16(&aPacketData[PACKET_DATA_INDEX], PACKET_SIZE);
|
|
Serial_PutByte(temp_crc >> 8);
|
|
Serial_PutByte(temp_crc & 0xFF);
|
|
#else /* CRC16_F */
|
|
temp_chksum = CalcChecksum (&aPacketData[PACKET_DATA_INDEX], PACKET_SIZE);
|
|
Serial_PutByte(temp_chksum);
|
|
#endif /* CRC16_F */
|
|
|
|
/* Wait for Ack and 'C' */
|
|
if (HAL_UART_Receive(&UartHandle, &a_rx_ctrl[0], 1, NAK_TIMEOUT) == HAL_OK)
|
|
{
|
|
if (a_rx_ctrl[0] == ACK)
|
|
{
|
|
ack_recpt = 1;
|
|
}
|
|
else if (a_rx_ctrl[0] == CA)
|
|
{
|
|
if ((HAL_UART_Receive(&UartHandle, &a_rx_ctrl[0], 1, NAK_TIMEOUT) == HAL_OK) && (a_rx_ctrl[0] == CA))
|
|
{
|
|
HAL_Delay( 2 );
|
|
__HAL_UART_FLUSH_DRREGISTER(&UartHandle);
|
|
result = COM_ABORT;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
errors++;
|
|
}
|
|
if (errors >= MAX_ERRORS)
|
|
{
|
|
result = COM_ERROR;
|
|
}
|
|
}
|
|
|
|
p_buf_int = p_buf;
|
|
size = file_size;
|
|
|
|
/* Here 1024 bytes length is used to send the packets */
|
|
while ((size) && (result == COM_OK ))
|
|
{
|
|
/* Prepare next packet */
|
|
PreparePacket(p_buf_int, aPacketData, blk_number, size);
|
|
ack_recpt = 0;
|
|
a_rx_ctrl[0] = 0;
|
|
errors = 0;
|
|
|
|
/* Resend packet if NAK for few times else end of communication */
|
|
while (( !ack_recpt ) && ( result == COM_OK ))
|
|
{
|
|
/* Send next packet */
|
|
if (size >= PACKET_1K_SIZE)
|
|
{
|
|
pkt_size = PACKET_1K_SIZE;
|
|
}
|
|
else
|
|
{
|
|
pkt_size = PACKET_SIZE;
|
|
}
|
|
|
|
HAL_UART_Transmit(&UartHandle, &aPacketData[PACKET_START_INDEX], pkt_size + PACKET_HEADER_SIZE, NAK_TIMEOUT);
|
|
|
|
/* Send CRC or Check Sum based on CRC16_F */
|
|
#ifdef CRC16_F
|
|
temp_crc = Cal_CRC16(&aPacketData[PACKET_DATA_INDEX], pkt_size);
|
|
Serial_PutByte(temp_crc >> 8);
|
|
Serial_PutByte(temp_crc & 0xFF);
|
|
#else /* CRC16_F */
|
|
temp_chksum = CalcChecksum (&aPacketData[PACKET_DATA_INDEX], pkt_size);
|
|
Serial_PutByte(temp_chksum);
|
|
#endif /* CRC16_F */
|
|
|
|
/* Wait for Ack */
|
|
if ((HAL_UART_Receive(&UartHandle, &a_rx_ctrl[0], 1, NAK_TIMEOUT) == HAL_OK) && (a_rx_ctrl[0] == ACK))
|
|
{
|
|
ack_recpt = 1;
|
|
if (size > pkt_size)
|
|
{
|
|
p_buf_int += pkt_size;
|
|
size -= pkt_size;
|
|
if (blk_number == (USER_FLASH_SIZE / PACKET_1K_SIZE))
|
|
{
|
|
result = COM_LIMIT; /* boundary error */
|
|
}
|
|
else
|
|
{
|
|
blk_number++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
p_buf_int += pkt_size;
|
|
size = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
errors++;
|
|
}
|
|
|
|
/* Resend packet if NAK for a count of 10 else end of communication */
|
|
if (errors >= MAX_ERRORS)
|
|
{
|
|
result = COM_ERROR;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Sending End Of Transmission char */
|
|
ack_recpt = 0;
|
|
a_rx_ctrl[0] = 0x00;
|
|
errors = 0;
|
|
while (( !ack_recpt ) && ( result == COM_OK ))
|
|
{
|
|
Serial_PutByte(EOT);
|
|
|
|
/* Wait for Ack */
|
|
if (HAL_UART_Receive(&UartHandle, &a_rx_ctrl[0], 1, NAK_TIMEOUT) == HAL_OK)
|
|
{
|
|
if (a_rx_ctrl[0] == ACK)
|
|
{
|
|
ack_recpt = 1;
|
|
}
|
|
else if (a_rx_ctrl[0] == CA)
|
|
{
|
|
if ((HAL_UART_Receive(&UartHandle, &a_rx_ctrl[0], 1, NAK_TIMEOUT) == HAL_OK) && (a_rx_ctrl[0] == CA))
|
|
{
|
|
HAL_Delay( 2 );
|
|
__HAL_UART_FLUSH_DRREGISTER(&UartHandle);
|
|
result = COM_ABORT;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
errors++;
|
|
}
|
|
|
|
if (errors >= MAX_ERRORS)
|
|
{
|
|
result = COM_ERROR;
|
|
}
|
|
}
|
|
|
|
/* Empty packet sent - some terminal emulators need this to close session */
|
|
if ( result == COM_OK )
|
|
{
|
|
/* Preparing an empty packet */
|
|
aPacketData[PACKET_START_INDEX] = SOH;
|
|
aPacketData[PACKET_NUMBER_INDEX] = 0;
|
|
aPacketData[PACKET_CNUMBER_INDEX] = 0xFF;
|
|
for (i = PACKET_DATA_INDEX; i < (PACKET_SIZE + PACKET_DATA_INDEX); i++)
|
|
{
|
|
aPacketData [i] = 0x00;
|
|
}
|
|
|
|
/* Send Packet */
|
|
HAL_UART_Transmit(&UartHandle, &aPacketData[PACKET_START_INDEX], PACKET_SIZE + PACKET_HEADER_SIZE, NAK_TIMEOUT);
|
|
|
|
/* Send CRC or Check Sum based on CRC16_F */
|
|
#ifdef CRC16_F
|
|
temp_crc = Cal_CRC16(&aPacketData[PACKET_DATA_INDEX], PACKET_SIZE);
|
|
Serial_PutByte(temp_crc >> 8);
|
|
Serial_PutByte(temp_crc & 0xFF);
|
|
#else /* CRC16_F */
|
|
temp_chksum = CalcChecksum (&aPacketData[PACKET_DATA_INDEX], PACKET_SIZE);
|
|
Serial_PutByte(temp_chksum);
|
|
#endif /* CRC16_F */
|
|
|
|
/* Wait for Ack and 'C' */
|
|
if (HAL_UART_Receive(&UartHandle, &a_rx_ctrl[0], 1, NAK_TIMEOUT) == HAL_OK)
|
|
{
|
|
if (a_rx_ctrl[0] == CA)
|
|
{
|
|
HAL_Delay( 2 );
|
|
__HAL_UART_FLUSH_DRREGISTER(&UartHandle);
|
|
result = COM_ABORT;
|
|
}
|
|
}
|
|
}
|
|
|
|
return result; /* file transmitted successfully */
|
|
}
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|