这是以前就想写的一个小专题关于IAP,以及IAP在STM32编程的应用,专题分三小节,主要介绍常见的单片机烧录方式,IAP的实际应用,以及Ymodem协议在IAP编程中应用,在笔记吃灰很久了,终于拿出来晒晒太阳了@-@。
第一章:浅析ICP与ISP、及IAP三种单片机烧录方式
第二章:STM32应用IAP进行程序更新详解及实例
第三章:Ymodem协议解析-基于STM32的IAP实现
简单认识一下常用的三种协议:XModem、YModem和ZModem协议。
- XModem协议:是一种异步文件传输协议,这种协议以128字节块的形式传输数据,并且每个块都使用一个校验和过程来进行错误检测。
- YModem协议:是由XModem协议演变而来的,每包数据可以达到1024字节,是一个非常高效的文件传输协议。
- ZModem协议:Zmodem协议是针对modem的一种错误校验协议。利用Zmodem协议,可以在modem上发送512字节的数据块。如果某个数据块发生错误,接受端会发送“否认”应答,因此,数据块就会被重传。它是Xmodem 文件传输协议的一种增强形式,不仅能传输更大的数据,而且错误率更小。包含一种名为检查点重启的特性,如果通信链接在数据传输过程中中断,能从断点处而不是从开始处恢复传输。
本文主要就STM32 IAP中使用来传输烧录文件的YModem协议进行介绍。
首先了解一下Ymodem协议的数据包的帧的格式
从ST提供的基于STM32的IAP实例demo中的ymodem.h文件中,我们或多或少可以稍稍窥探ymodem协议的一些内容:
#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 */
1、起始帧:数据的起始帧并不传输文件的数据,而是传输与文件基本信息相关的一些数据,如:文件名和文件大小,帧的格式如下:
数据包头 | 发送序号 | 发送序号补码 | 数据 | CRC校验码高字节 | CRC校验码低字节 |
---|---|---|---|---|---|
S0H | 00 | FF | filename+filesize+…(00 补齐128 Byte) | CRCH | CRCL |
起始帧由于不直接传输数据,所以通常使用以“S0H”开头的数据包,传输128 Byte的数据基本满足关于文件名和文件大小的传输。
2、数据帧:数据帧中数据包的大小为1K,基本格式相同
数据包头 | 发送序号 | 发送序号补码 | 数据 | CRC校验码高字节 | CRC校验码低字节 |
---|---|---|---|---|---|
STX | 01 | FE | (1024 Byte 数据,不足0x1A补齐) | CRCH | CRCL |
在数据帧传输过程中可能出现以下情况:
- 1)文件剩余的大小在128 ~ 1024 Byte之间:使用STX格式数据帧进行传输,但是数据区间剩余的空间用0X1A进行填充。
- 2)文件剩余的大小在小于等于128 Byte:使用SOH格式数据帧进行传输,同样数据区间的剩余空间使用0X1A进行填充。
3、结束帧
数据包头 | 发送序号 | 发送序号补码 | 数据 | CRC校验码高字节 | CRC校验码低字节 |
---|---|---|---|---|---|
SOH | 00 | FF | NULL[128 Byte] | CRCH | CRCL |
结束帧的数据包以“SOH”开头,且发送序号为00, 数据由0x00填充128 Byte。
下图摘录来自Ymodem协议官方WiKi【http://wiki.synchro.net/ref:ymodem】的介绍,可以很清晰、直观地了解到使用该协议传输的交互流程:
下面来看一下代码实现:
/* 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, 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 */
*p_size = filesize;
if (*p_size > (USER_FLASH_SIZE + 1))
{
/* End session */
tmp = CA;
HAL_UART_Transmit(&huart2, &tmp, 1, NAK_TIMEOUT);
HAL_UART_Transmit(&huart2, &tmp, 1, NAK_TIMEOUT);
result = COM_LIMIT;
}
/* erase user application area */
FLASH_If_Erase(APPLICATION_ADDRESS);
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;
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/116941.html