0、前言
关于IAP程序升级的要点和YMODEM协议,可以查看串口YMODEM实现IAP程序升级(附完整工程);本文在GD32L233CCT6上实现串口YMODEM升级。
1、核心代码
(1)操作菜单,通过输入代码,选择执行的操作
代码语言:javascript复制void Main_Menu(void)
{
uint8_t key = 0;
while (1)
{
SerialPutString("rn================== Main Menu ===============================rnn");
SerialPutString(" Download Image To the GD32L233CCT6 Internal Flash ------- 1rnn");
SerialPutString(" Upload Image From the GD32L233CCT6 Internal Flash ------- 2rnn");
SerialPutString(" Execute The New Program --------------------------------- 3rnn");
SerialPutString("=============================================================rnn");
key = GetKey();
if (key == 0x31)
{
/* Download user application in the Flash */
SerialDownload();
}
else if (key == 0x32)
{
/* Upload user application from the Flash */
SerialUpload();
}
else if (key == 0x33)
{
if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000) //判断栈顶地址是否在合法范围内
{
JumpAddress = *(__IO uint32_t*) (ApplicationAddress 4);
/* Jump to user application */
Jump_To_Application = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) ApplicationAddress);
Jump_To_Application();
}
}
else
{
SerialPutString("Invalid Number ! ==> The number should be either 1, 2 or 3r");
}
}
}
(2)ymodem发送
代码语言:javascript复制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, ackReceived, size = 0, pktSize;
errors = 0;
ackReceived = 0;
for (i = 0; i < (FILE_NAME_LENGTH - 1); i )
{
FileName = sendFileName;
}
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)
{
/* 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 */
if ((Receive_Byte(&receivedC[0], 0xffffff) == 0) && (receivedC[0] == ACK))
{
ackReceived = 1;
if (size > pktSize)
{
buf_ptr = pktSize;
size -= pktSize;
if (blkNumber == (APP_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], 0xffffff) == 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 = 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], 0xffffff) == 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 */ //0xffffff
if ((Receive_Byte(&receivedC[0], 0xfff) == 0) && receivedC[0] == ACK)
{
ackReceived = 1;
}
else
{
errors ;
}
}while (!ackReceived && (errors < 0x0A));
if (errors >= 0x0A)
{
return errors;
}
return 0; /* file trasmitted successfully */
}
(3)ymodem接收
代码语言:javascript复制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, packet_length, session_done, file_done, packets_received, errors, session_begin, size = 0;
/* Initialize FlashDestination variable */
FlashDestination = ApplicationAddress;
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 ] = '