/**
******************************************************************************
* @file STM32F0xx_IAP/src/ymodem.c
* @author MCD Application Team
* @version V1.0.0
* @date 29-May-2012
* @brief Main program body
******************************************************************************
* @attention
*
*
© COPYRIGHT 2012 STMicroelectronics
*
* 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 "string.h"
//#include "main.h"
#include "aes.h"
#include "mk_flash.h"
//#include "stm32f4xx_hal.h"
#include "AppConfig.h"
#include "mk_uart.h"
#include "mk_trace.h"
/** @addtogroup STM32F0xx_IAP
* @{
*/
#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))
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
extern uint8_t FileName[];
extern void Int2Str(uint8_t* str, int32_t intnum);
//extern UART_HandleTypeDef huart1;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
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 Receive byte from sender
* @param c: Character
* @param timeout: Timeout
* @retval 0: Byte received
* -1: Timeout
*/
int32_t Receive_Byte (uint8_t *c, uint32_t timeout)
{
while (timeout-- > 0)
{
if (SerialKeyPressed(c) == 1)//Èç¹ûÊÕµ½´®¿ÚÊý¾Ý
{
// Serial0_PutString("½ÓÊܳɹ¦");
return 0;
}
}
// Serial0_PutString("½ÓÊÜʧ°Ü");
return -1;
}
/**
* @brief Send a byte
* @param c: Character
* @retval 0: Byte sent
*/
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(data0: packet length
* @retval 0: normally return
* -1: timeout or packet error
* 1: abort by user
*/
uint16_t current_seqno,flash_seqno,i2;
uint8_t c;
static int32_t Receive_Packet (uint8_t *data, int32_t *length, uint32_t timeout)
{
uint16_t packet_size, computedcrc;
*length = 0;
if (Receive_Byte(&c, timeout) != 0)//·µ»Ø0³É¹¦ÊÕÈ¡Êý¾Ý,-1ΪûÊÕµ½Êý¾Ý
{
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;//·Åµ½1024+5×ֽڵİüÀïÃæ
for (i2 = 1; i2 < (packet_size + PACKET_OVERHEAD); i2 ++)
{
if (Receive_Byte(data + i2, timeout) != 0)//²»¶ÏµÄ½ÓÊÕ1024×Ö½Ú·ÅÈë
{
return -1;
}
}
//¼ì²âÐòºÅ²¹ÂëÊÇÊÇ·ñÕýÈ·
if (data[PACKET_SEQNO_INDEX] != ((data[PACKET_SEQNO_COMP_INDEX] ^ 0xff) & 0xff))
{
return 1;
}
if(current_seqno==data[PACKET_SEQNO_INDEX]||c==SOH)
{
current_seqno++;
}else{
return 1;
}
/* Compute the CRC */
computedcrc = Cal_CRC16(&data[PACKET_HEADER], (uint32_t)packet_size);//¼ÆËãCRC16Âë
/* Check that received CRC match the already computed CRC value
data[packet_size+3]<<8) | data[packet_size+4] contains the received CRC
computedcrc contains the computed CRC value */
if (computedcrc != (uint16_t)((data[packet_size+3]<<8) | data[packet_size+4]))//¼ì²âCRC16УÑéÂë
{
/* CRC error */
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
*/
extern volatile unsigned long time32_reset;
uint8_t packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD], file_size[FILE_SIZE_LENGTH], *file_ptr, *buf_ptr; //1024 + 5
uint8_t bufferOut[16]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t *BufferIn;
int32_t i, j, packet_length, session_done, file_done, packets_received, errors, session_begin, size = 0;
uint32_t flashdestination, ramsource,tempaddress;
int32_t Ymodem_Receive (uint8_t *buf)
{
aesDecInit();//AES½âÃܳõʼ»¯
/* Initialize flashdestination variable */
flashdestination = APP_CONFIG_APPLICATION_ADDRESS; //APP´úÂëµÄÆðʼµØÖ·,APP_CONFIG_APPLICATION_ADDRESS = 0x8005000,¿ÉÔÚtarget½çÃæ¸ù¾ÝÇé¿öÉèÖÃ
current_seqno=0; //ÕâЩ¶¼ÔÚymodem.hÀïÃæµÄºê½øÐÐÉèÖÃ
flash_seqno=2;
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://³É¹¦½ÓÊÕµ½1K
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))
{//ÐòºÅ00(ÎļþÃû)
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);)
{
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);//Convert a string to an integer
/* Test the size of the image to be sent */
/* Image size is greater than Flash size */
if (size > (APP_CONFIG_APPLICATION_SIZE + 1))
{
/* End session */
Send_Byte(CA);
Send_Byte(CA);
return -1;
}
/* erase user application area */
// Flash_Init();
// Flash_Erase(APP_CONFIG_APPLICATION_ADDRESS, APP_CONFIG_APPLICATION_SIZE);MK8000 ÐÞ¸Ä
flash_erase(FLASH_ID0, APP_CONFIG_APPLICATION_ADDRESS, APP_CONFIG_APPLICATION_SIZE);//²Á³ýAPP
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);
/*----------------------------------------------------------------------------------------------*/
BufferIn=buf;
for (j = 0; j < packet_length; j += 16) //ÿ´Î½âÃÜ16×Ö½Ú
{
//½âÃÜÊý¾Ý°ü
aesDecrypt(BufferIn,bufferOut); //ÓÉÓÚ²ÎÊýʹÓõÄÊÇÖ¸Õë,ËùÒÔ½âÃܺóÒÀ¾É´æÔÚbufÀïÃæ
BufferIn+=16;
}
/*----------------------------------------------------------------------------------------------*/
/* Write received data in Flash */ //Õâ¸ösize²ÎÊýÊÇ×Ô¼º¼Ó½øÈëµÄ,±ãÓÚÅжÏÎļþ´«ÊäÍê³É
// if (Flash_Write(flashdestination, buf, packet_length) == 0&&(flashdestination==tempaddress||tempaddress>size)) MK8000ÐÞ¸Ä
// {
// flashdestination += packet_length;
// //дÈëFLASH
// Send_Byte(ACK);
// flash_seqno++;
// time32_reset = 0;
// }
// else /* An error occurred while writing to Flash memory */
// {
// /* End session */
// Send_Byte(CA);
// Send_Byte(CA);
// return -2;
// }
ramsource = (uint32_t)buf;
tempaddress=APP_CONFIG_APPLICATION_ADDRESS+(current_seqno-1)*0x400;
if(flash_write_nbytes(FLASH_ID0,flashdestination, buf, packet_length)== 0&&(flashdestination==tempaddress||tempaddress>size))
{
flashdestination += packet_length;
//дÈëFLASH
Send_Byte(ACK);
flash_seqno++;
time32_reset = 0;
}
else
{
/* End session */
Send_Byte(CA);
Send_Byte(CA);
return -2;
}
}
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
* @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 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
*/
static struct UART_HANDLE_T uart_handle[UART_MAX_NUM] = {
{
.base = UART0,
.irq = UART0_IRQn,
.dma_rx_ch = DMA_CH4,
.dma_tx_ch = DMA_CH5,
},
{
.base = UART1,
.irq = UART1_IRQn,
.dma_rx_ch = DMA_CH6,
.dma_tx_ch = DMA_CH7,
},
};
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 == (APP_CONFIG_APPLICATION_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;
receivedC[1] = 0x00;
errors = 0;
do
{
Send_Byte(EOT);
/* Send (EOT); */
/* Wait for Ack */
//receivedC[0] = (uint16_t)(USART1->DR & (uint16_t)0x01FF); MK8000ÐÞ¸Ä
receivedC[0]= (uint16_t)(uart_handle[1].base->RX_DATA&(uint16_t)0x01FF);
if (receivedC[0] == ACK)
{
ackReceived = 1;
}
else
{
errors++;
}
/* Clear Overrun flag of the USART2 */
//__HAL_UART_CLEAR_OREFLAG(&huart1); MK8000ÐÞ¸Ä
// USART_ClearFlag(USART1, UART_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 of 10 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 */
// __HAL_UART_CLEAR_OREFLAG(&huart1); MK8000ÐÞ¸Ä
}while (!ackReceived && (errors < 0x0A));
if (errors >= 0x0A)
{
return errors;
}
return 0; /* file trasmitted successfully */
}
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/