赞
踩
通过研究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;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。