通过研究stm的ymodem协议,发现EOT之后直接就进行ACK回复确认了,没有进行NAK反复确认
所以具体需要修改:
主要是修改Ymodem_Receive函数
首先EOT 之后 直接默认结束传输,所以将ACK修改为NAK
最后在该函数的最后,模拟再次ACK C确认
然后接收一包结束帧,再回复ACK确认
注意:如果是xshell等终端需要再发送一个结束,提示ymodem协议结束
添加基础的注释,便于理解,目前代码还没整理完成,先暂时不上传了,只是上传官方的标准库
链接:https://pan.baidu.com/s/1Y4jVoSSPUTceuIA-O6X6Fg
提取码:n0kw
--来自百度网盘超级会员V4的分享
/**
* @brief 使用ymodem接受一个文件
* @param buf: 第一个字节的地址.
* @retval 文件的大小.
*/
LONG Ymodem_Receive (UCHAR *buf)
{
UCHAR packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD], file_size[FILE_SIZE_LENGTH], *file_ptr, *buf_ptr;
LONG i, packet_length, session_done, file_done, packets_received, errors, session_begin, size = 0;
ULONG flashdestination, ramsource;
ULONG t = 0;
UCHAR c = 0;
/* 初始化flash地址 */
flashdestination = APPLICATION_ADDRESS;
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)
{
/* 被发送者终止 */
case - 1:
{
Send_Byte(ACK);
return 0;
}
/* 结束传输 */
case 0:
{
/* 修改该地方 */
Send_Byte(NAK);
file_done = 1;
break;
}
default:
/* 正常包 */
if ((packet_data[PACKET_SEQNO_INDEX] & 0xff) != (packets_received & 0xff))
{
Send_Byte(NAK);
}
else
{
/* 如果是第一个起始帧 */
if (packets_received == 0)
{
/* 文件名字包 */
if (packet_data[PACKET_HEADER] != 0)
{
/* file_ptr+3 因为前三个字节是首部 再就是文件名字 */
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);)
{
file_size[i++] = *file_ptr++;
}
file_size[i++] = '\0';
/* 将文件大小转换为字符串 */
Str2Int(file_size, &size);
/* 检测被发送镜像bin文件的大小 */
/* 如果镜像bin文件比flash大 */
if (size > (USER_FLASH_SIZE + 1))
{
/* End session */
Send_Byte(CA);
Send_Byte(CA);
/*debug 文件太大 flash太小 没有合适的空间 */
return -1;
}
/* 擦除flash */
FLASH_If_Erase(APPLICATION_ADDRESS);
Send_Byte(ACK);
/* 收到第起始帧后立马回应 发送c */
Send_Byte(CRC16);
}
/* 文件名字包为空,结束传输 */
else
{
Send_Byte(ACK);
file_done = 1;
session_done = 1;
break;
}
}
/* 数据帧 */
else
{
/* 拷贝当前的数据 */
memcpy(buf_ptr, packet_data + PACKET_HEADER, packet_length);
ramsource = (ULONG)buf;
/* 往flash里边写数据 packet_length/4的原因是一个字占4个字节 */
if (FLASH_If_Write(&flashdestination, (ULONG *) ramsource, (USHORT) packet_length/4) == 0)
{
Send_Byte(ACK);
}
else /* 当往flash写的时候,出现错误 */
{
/* 结束传输 */
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;
}
}
Send_Byte(ACK);
Send_Byte(CRC16);
/* 最后接收结束帧 该帧其实不管对错 都已经传输完成 */
Receive_Packet(packet_data, &packet_length, NAK_TIMEOUT);
Send_Byte(ACK);
return (LONG)size;
}
版权声明:本文为CSDN博主「IT小生lkc」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_20017379/article/details/122768524
通过研究stm的ymodem协议,发现EOT之后直接就进行ACK回复确认了,没有进行NAK反复确认
所以具体需要修改:
主要是修改Ymodem_Receive函数
首先EOT 之后 直接默认结束传输,所以将ACK修改为NAK
最后在该函数的最后,模拟再次ACK C确认
然后接收一包结束帧,再回复ACK确认
注意:如果是xshell等终端需要再发送一个结束,提示ymodem协议结束
添加基础的注释,便于理解,目前代码还没整理完成,先暂时不上传了,只是上传官方的标准库
链接:https://pan.baidu.com/s/1Y4jVoSSPUTceuIA-O6X6Fg
提取码:n0kw
--来自百度网盘超级会员V4的分享
/**
* @brief 使用ymodem接受一个文件
* @param buf: 第一个字节的地址.
* @retval 文件的大小.
*/
LONG Ymodem_Receive (UCHAR *buf)
{
UCHAR packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD], file_size[FILE_SIZE_LENGTH], *file_ptr, *buf_ptr;
LONG i, packet_length, session_done, file_done, packets_received, errors, session_begin, size = 0;
ULONG flashdestination, ramsource;
ULONG t = 0;
UCHAR c = 0;
/* 初始化flash地址 */
flashdestination = APPLICATION_ADDRESS;
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)
{
/* 被发送者终止 */
case - 1:
{
Send_Byte(ACK);
return 0;
}
/* 结束传输 */
case 0:
{
/* 修改该地方 */
Send_Byte(NAK);
file_done = 1;
break;
}
default:
/* 正常包 */
if ((packet_data[PACKET_SEQNO_INDEX] & 0xff) != (packets_received & 0xff))
{
Send_Byte(NAK);
}
else
{
/* 如果是第一个起始帧 */
if (packets_received == 0)
{
/* 文件名字包 */
if (packet_data[PACKET_HEADER] != 0)
{
/* file_ptr+3 因为前三个字节是首部 再就是文件名字 */
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);)
{
file_size[i++] = *file_ptr++;
}
file_size[i++] = '\0';
/* 将文件大小转换为字符串 */
Str2Int(file_size, &size);
/* 检测被发送镜像bin文件的大小 */
/* 如果镜像bin文件比flash大 */
if (size > (USER_FLASH_SIZE + 1))
{
/* End session */
Send_Byte(CA);
Send_Byte(CA);
/*debug 文件太大 flash太小 没有合适的空间 */
return -1;
}
/* 擦除flash */
FLASH_If_Erase(APPLICATION_ADDRESS);
Send_Byte(ACK);
/* 收到第起始帧后立马回应 发送c */
Send_Byte(CRC16);
}
/* 文件名字包为空,结束传输 */
else
{
Send_Byte(ACK);
file_done = 1;
session_done = 1;
break;
}
}
/* 数据帧 */
else
{
/* 拷贝当前的数据 */
memcpy(buf_ptr, packet_data + PACKET_HEADER, packet_length);
ramsource = (ULONG)buf;
/* 往flash里边写数据 packet_length/4的原因是一个字占4个字节 */
if (FLASH_If_Write(&flashdestination, (ULONG *) ramsource, (USHORT) packet_length/4) == 0)
{
Send_Byte(ACK);
}
else /* 当往flash写的时候,出现错误 */
{
/* 结束传输 */
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;
}
}
Send_Byte(ACK);
Send_Byte(CRC16);
/* 最后接收结束帧 该帧其实不管对错 都已经传输完成 */
Receive_Packet(packet_data, &packet_length, NAK_TIMEOUT);
Send_Byte(ACK);
return (LONG)size;
}
版权声明:本文为CSDN博主「IT小生lkc」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_20017379/article/details/122768524
暂无评论