初级会员

- 积分
- 102
- 金钱
- 102
- 注册时间
- 2019-2-16
- 在线时间
- 18 小时
|

楼主 |
发表于 2020-6-29 19:52:11
|
显示全部楼层
Stm32F777单片机下:
Ymodem.h
#define PACKET_HEADER_SIZE ((uint32_t)3)
#define PACKET_DATA_INDEX ((uint32_t)4)
#define PACKET_START_INDEX ((uint32_t)1)
#define PACKET_NUMBER_INDEX ((uint32_t)2)
#define PACKET_CNUMBER_INDEX ((uint32_t)3)
#define PACKET_TRAILER_SIZE ((uint32_t)2)
#define PACKET_OVERHEAD_SIZE (PACKET_HEADER_SIZE + PACKET_TRAILER_SIZE - 1)
#define PACKET_SIZE ((uint32_t)128)
#define PACKET_1K_SIZE ((uint32_t)1024)
#define FILE_NAME_LENGTH ((uint32_t)64)
#define FILE_SIZE_LENGTH ((uint32_t)16)
#define SOH ((uint8_t)0x01) /* start of 128-byte data packet */
#define STX ((uint8_t)0x02) /* start of 1024-byte data packet */
#define EOT ((uint8_t)0x04) /* end of transmission */
#define ACK ((uint8_t)0x06) /* acknowledge */
#define NAK ((uint8_t)0x15) /* negative acknowledge */
#define CA ((uint32_t)0x18) /* two of these in succession aborts transfer */
#define CRC16 ((uint8_t)0x43) /* 'C' == 0x43, request 16-bit CRC */
#define NEGATIVE_BYTE ((uint8_t)0xFF)
#define ABORT1 ((uint8_t)0x41) /* 'A' == 0x41, abort by user */
#define ABORT2 ((uint8_t)0x61) /* 'a' == 0x61, abort by user */
#define NAK_TIMEOUT ((uint32_t)0x100000)
#define DOWNLOAD_TIMEOUT ((uint32_t)1000) /* One second retry delay */
#define MAX_ERRORS ((uint32_t)5)
Ymodem.c
HAL_StatusTypeDef Serial_PutByte( uint8_t param )
{
return HAL_UART_Transmit(&huart1, ¶m, 1, TX_TIMEOUT);
}
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(&huart1, &char1, 1, timeout);
if (status == HAL_OK)//串口判忙
{
// printf("ReceivePacket中char1 = :%c\r\n",char1);
switch (char1)
{
case SOH://0x01
printf("SOH\r\n");
packet_size = PACKET_SIZE; //128byte
break;
case STX://0x02
printf("STX \r\n");
packet_size = PACKET_1K_SIZE; //1024byte
break;
case EOT://0x04 //结束发送标志位
printf("EOT\r\n");
if(EOTCN==0)
{
EOTCN=1;
}
else if(EOTCN==1)
{
EOTCN=2;
}
break;
case CA: //两个连续终止传输
printf("CA\r\n");
if ((HAL_UART_Receive(&huart1, &char1, 1, timeout) == HAL_OK) && (char1 == CA))
{
packet_size = 2;
}
else
{
status = HAL_ERROR;
}
break;
case ABORT1: //'A'
printf("ABORT1\r\n");
case ABORT2: //'a'
printf("ABORT2\r\n");
status = HAL_BUSY;
break;
default:
status = HAL_ERROR;
break;
}
*p_data = char1;
if (packet_size >= PACKET_SIZE )
{
printf("packet_size >= PACKET_SIZE\r\n");
status = HAL_UART_Receive(&huart1, &p_data[PACKET_NUMBER_INDEX], packet_size + PACKET_OVERHEAD_SIZE, timeout);
/* Simple packet sanity check */
if (status == HAL_OK )
{
printf("reeive %02x\n",p_data[PACKET_NUMBER_INDEX]);
if (p_data[PACKET_NUMBER_INDEX] != ((p_data[PACKET_CNUMBER_INDEX]) ^ NEGATIVE_BYTE))
{
packet_size = 0;
status = HAL_ERROR;
}
else
{
printf("check crc\r\n");
/* 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 )
{
printf("Error\r\n");
packet_size = 0;
status = HAL_ERROR;
}
}
}
else
{
printf("size = 0\r\n");
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; //起始帧的首位0x01
p_data[PACKET_NUMBER_INDEX] = 0x00; //起始帧的第二位,即帧序号,依次向下
p_data[PACKET_CNUMBER_INDEX] = 0xff; //起始帧的第三位,帧序号取反
/* Filename written */
for (i = 0; (p_file_name != '\0') && (i < FILE_NAME_LENGTH); i++)
{
p_data[i + PACKET_DATA_INDEX] = p_file_name;//从第四位开始是文件名字
}
p_data[i + PACKET_DATA_INDEX] = 0x00; //在文件末名尾加0x00,表示文件名的结束
/* file size written */
Int2Str (astring, length); //转换成字符
i = i + PACKET_DATA_INDEX + 1;
while (astring[j] != '\0') //加上0表示结束
{
p_data[i++] = astring[j++];
}
/* padding with zeros */
/* 用0填充 */
for (j = i; j < PACKET_SIZE + PACKET_DATA_INDEX; j++)//除去文件名与文件大小占用的空间,其余的都用0填充
{
p_data[j] = 0;
}
}
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) //判断数据包是否为1024字节
{
p_packet[PACKET_START_INDEX] = STX;
//数据帧的起始0x02
}
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 = *p_record++;
}
if ( size <= packet_size)
{
for (i = size + PACKET_DATA_INDEX; i < packet_size + PACKET_DATA_INDEX; i++)
{
p_packet = 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 flashdestination, 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:
printf("HAL_OK\r\n");
errors = 0;
switch (packet_length)
{
case 2:
/* Abort by sender */
printf("send ACK2\n");
Serial_PutByte(ACK);
result = COM_ABORT;
break;
case 0:
/* End of transmission */
if(EOTCN==1)
{
printf("EOTsend NAK\n");
Serial_PutByte(NAK);
}
else
{
printf("send ACK0\n");
Serial_PutByte(ACK);
file_done = 1;
}
break;
default:
/* Normal packet */
// printf("num%d\n",aPacketData[PACKET_NUMBER_INDEX]);
// printf("packets_received%d\n",packets_received);
if (aPacketData[PACKET_NUMBER_INDEX] != packets_received)
{
printf("NAK\n");
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(&huart1, &tmp, 1, NAK_TIMEOUT);
HAL_UART_Transmit(&huart1, &tmp, 1, NAK_TIMEOUT);
result = COM_LIMIT;
}
/* erase user application area */
if(SocFlashErase(APPLICATION_ADDRESS)==FLASHIF_OK)
{
printf("erase ok\n");
}
*p_size = filesize;
//printf("send ACK+C\n");
Serial_PutByte(ACK);
Serial_PutByte(CRC16);
}
/* File header packet is empty, end session */
else
{
EOTCN=0;
printf("send ACK3\n");
Serial_PutByte(ACK);
file_done = 1;
session_done = 1;
break;
}
}
else /* Data packet */
{
/* Write received data in Flash */
if (SocFlashWrite(flashdestination, & aPacketData[PACKET_DATA_INDEX], packet_length/4) == FLASHIF_OK)
{
flashdestination += packet_length;
printf("send ACK4\n");
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;
}
|
|