搜索
bottom↓
回复: 49

ST官方代码——YModem协议部分代码分析

  [复制链接]

出0入0汤圆

发表于 2019-1-13 00:08:34 | 显示全部楼层 |阅读模式
本帖最后由 zirong0804 于 2019-1-13 10:30 编辑

感谢前人的分享资料,网上关于STM32 bootloader资料很多,传输协议可以自定义或使用标准YModem
但细细品味ST官方IAP中YModem协议文章没有,在此跑了一遍ST官方IAP代码,分享给大家!关于实验结论,欢迎交流!

1-实验结论:
对比标准Ymodem协议,ST官方IAP代码中YModem协议少了以下部分:(ST官方代码中YModem协议怎么会少内容呢?

发送端(secureCRT 8.5)                      接收端(开发板)
EOT---->
                                                   NAK----<

2-YModem
YModem协议是由XModem协议演变而来的,每包数据可以达到1024字节,是一个非常高效的文件传输协议。参考资料如下
https://www.amobbs.com/thread-5559677-1-1.html
https://baike.baidu.com/item/Ymodem?fr=aladdin
https://blog.csdn.net/qingzhuyuxian/article/details/80769163

3-ST官方IAP工程代码 (请见附件)

4-修改后的STM32f103ZET6工程代码,对ymodem.c添加注释和调试代码(请见附件)
串口1用于与secureCRT 8.5通信,串口2用于打印调试代码

5-ymodem.c文件代码分析,请见工程中
Ymodem_Receive(), Receive_Packet()

 7-分享不错的STM32 IAP文章
http://www.openedv.com/thread-78079-1-1.html

6-实验结果:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

阿莫论坛才是最爱国的,关心国家的经济、社会的发展、担心国家被别国牵连卷入战争、知道珍惜来之不易的和平发展,知道师夷之长,关注世界的先进文化与技术,也探讨中国文化的博大精深,也懂得警惕民粹主义的祸国殃民等等等等,无不是爱国忧民的表现。(坛友:tianxian)

出130入0汤圆

发表于 2019-1-13 01:20:05 | 显示全部楼层
这个资料可以,先拜读下

出0入13汤圆

发表于 2019-1-13 08:04:11 来自手机 | 显示全部楼层
谢谢分享,学习了,还没用过

出0入0汤圆

 楼主| 发表于 2019-1-13 09:35:39 | 显示全部楼层
对比标准Ymodem协议,ST官方代码中YModem协议怎么会少内容呢?

出0入0汤圆

发表于 2019-1-13 09:48:54 | 显示全部楼层
谢谢分享,学习了,记号

出0入0汤圆

发表于 2019-1-13 11:15:40 | 显示全部楼层
记号一下,礼拜一试试,谢谢分享

出0入4汤圆

发表于 2019-1-13 11:21:04 | 显示全部楼层
调试工具是哪个  

出870入263汤圆

发表于 2019-1-13 12:42:03 | 显示全部楼层
STcubeMX里的ymodem问题不少的,除了楼主说出的EOT只应答ACK的错误,还有个错误就是数据块编号从FF到00时(也就是传输数据块超过255时),代码会把00块当作新的文件名信息块。

出0入0汤圆

发表于 2019-1-13 12:42:43 来自手机 | 显示全部楼层
不错,感谢分享

出870入263汤圆

发表于 2019-1-13 12:46:46 | 显示全部楼层
还有更多错误

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出870入263汤圆

发表于 2019-1-13 12:55:37 | 显示全部楼层
还有错误

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出870入263汤圆

发表于 2019-1-13 12:56:51 | 显示全部楼层
还有更多错误,呵呵

出870入263汤圆

发表于 2019-1-13 13:04:24 | 显示全部楼层
看了ST的ymodem代码,会让人担心ST工程师队伍里有混饭吃的。

出0入0汤圆

发表于 2019-1-13 17:10:21 | 显示全部楼层
MARK,用到时在看

出0入0汤圆

发表于 2019-1-13 17:54:22 | 显示全部楼层
有些东西还得自己写,靠谱些!

出0入0汤圆

 楼主| 发表于 2019-1-13 17:56:09 | 显示全部楼层
ztrx 发表于 2019-1-13 11:21
调试工具是哪个

secureCRT 8.5

出0入0汤圆

 楼主| 发表于 2019-1-13 18:18:22 | 显示全部楼层
armstrong 发表于 2019-1-13 12:42
STcubeMX里的ymodem问题不少的,除了楼主说出的EOT只应答ACK的错误,还有个错误就是数据块编号从FF到00时( ...

谢谢提醒,从我目前的ymodem.c文件来看,这种情况不会发生,理由如下
1-packets_received 被定义为 int32_t
2- 假设packets_received 为256,if (packets_received == 0) 这个条件不满足,所以它还会被当做 Data packet  处理

出0入0汤圆

 楼主| 发表于 2019-1-13 18:22:52 | 显示全部楼层

谢谢分享,目前代码中使用的ymodem.c 没有这问题

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2019-1-13 18:27:13 | 显示全部楼层

的确,目前代码中定义,一般够用
#define FILE_NAME_LENGTH        (256)
#define FILE_SIZE_LENGTH        (16)

出870入263汤圆

发表于 2019-1-13 18:34:09 | 显示全部楼层
zirong0804 发表于 2019-1-13 18:27
的确,目前代码中定义,一般够用
#define FILE_NAME_LENGTH        (256)
#define FILE_SIZE_LENGTH      ...

楼主你用的ymodem是哪里来的?我的跟你不一样。我是这些目录里的:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出870入263汤圆

发表于 2019-1-13 18:35:31 | 显示全部楼层
本帖最后由 armstrong 于 2019-1-13 18:36 编辑
zirong0804 发表于 2019-1-13 18:18
谢谢提醒,从我目前的ymodem.c文件来看,这种情况不会发生,理由如下
1-packets_received 被定义为 int32 ...


问题不是本地定义的数据类型,是ymodem协议只有一个字节用于编号,这就注定0xff之后就会变成0x00。
如果代码本地无视这个规则,自增到256了,那就再也不会跟接收的数据包编号对应上了。

出870入263汤圆

发表于 2019-1-13 18:40:10 | 显示全部楼层
随便传一个STM32CubeMX\Repository\STM32Cube_FW_F1_V1.7.0\Projects\STM3210C_EVAL\Applications\IAP\IAP_Main\Src\ymodem.c
其它F4,F7的都一样错:
  1. /**
  2.   ******************************************************************************
  3.   * @file    IAP_Main/Src/ymodem.c
  4.   * @author  MCD Application Team
  5.   * @version V1.6.0
  6.   * @date    12-May-2017
  7.   * @brief   This file provides all the software functions related to the ymodem
  8.   *          protocol.
  9.   ******************************************************************************
  10.   * @attention
  11.   *
  12.   * <h2><center>&copy; Copyright ?2016 STMicroelectronics International N.V.
  13.   * All rights reserved.</center></h2>
  14.   *
  15.   * Redistribution and use in source and binary forms, with or without
  16.   * modification, are permitted, provided that the following conditions are met:
  17.   *
  18.   * 1. Redistribution of source code must retain the above copyright notice,
  19.   *    this list of conditions and the following disclaimer.
  20.   * 2. Redistributions in binary form must reproduce the above copyright notice,
  21.   *    this list of conditions and the following disclaimer in the documentation
  22.   *    and/or other materials provided with the distribution.
  23.   * 3. Neither the name of STMicroelectronics nor the names of other
  24.   *    contributors to this software may be used to endorse or promote products
  25.   *    derived from this software without specific written permission.
  26.   * 4. This software, including modifications and/or derivative works of this
  27.   *    software, must execute solely and exclusively on microcontroller or
  28.   *    microprocessor devices manufactured by or for STMicroelectronics.
  29.   * 5. Redistribution and use of this software other than as permitted under
  30.   *    this license is void and will automatically terminate your rights under
  31.   *    this license.
  32.   *
  33.   * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
  34.   * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
  35.   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  36.   * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
  37.   * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
  38.   * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  39.   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  40.   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
  41.   * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  42.   * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  43.   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  44.   * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  45.   *
  46.   ******************************************************************************
  47.   */

  48. /** @addtogroup STM32F1xx_IAP
  49.   * @{
  50.   */
  51.   
  52. /* Includes ------------------------------------------------------------------*/
  53. #include "flash_if.h"
  54. #include "common.h"
  55. #include "ymodem.h"
  56. #include "string.h"
  57. #include "main.h"
  58. #include "menu.h"

  59. /* Private typedef -----------------------------------------------------------*/
  60. /* Private define ------------------------------------------------------------*/
  61. #define CRC16_F       /* activate the CRC16 integrity */
  62. /* Private macro -------------------------------------------------------------*/
  63. /* Private variables ---------------------------------------------------------*/
  64. /* @note ATTENTION - please keep this variable 32bit alligned */
  65. uint8_t aPacketData[PACKET_1K_SIZE + PACKET_DATA_INDEX + PACKET_TRAILER_SIZE];

  66. /* Private function prototypes -----------------------------------------------*/
  67. static void PrepareIntialPacket(uint8_t *p_data, const uint8_t *p_file_name, uint32_t length);
  68. static void PreparePacket(uint8_t *p_source, uint8_t *p_packet, uint8_t pkt_nr, uint32_t size_blk);
  69. static HAL_StatusTypeDef ReceivePacket(uint8_t *p_data, uint32_t *p_length, uint32_t timeout);
  70. uint16_t UpdateCRC16(uint16_t crc_in, uint8_t byte);
  71. uint16_t Cal_CRC16(const uint8_t* p_data, uint32_t size);
  72. uint8_t CalcChecksum(const uint8_t *p_data, uint32_t size);

  73. /* Private functions ---------------------------------------------------------*/

  74. /**
  75.   * @brief  Receive a packet from sender
  76.   * @param  data
  77.   * @param  length
  78.   *     0: end of transmission
  79.   *     2: abort by sender
  80.   *    >0: packet length
  81.   * @param  timeout
  82.   * @retval HAL_OK: normally return
  83.   *         HAL_BUSY: abort by user
  84.   */
  85. static HAL_StatusTypeDef ReceivePacket(uint8_t *p_data, uint32_t *p_length, uint32_t timeout)
  86. {
  87.   uint32_t crc;
  88.   uint32_t packet_size = 0;
  89.   HAL_StatusTypeDef status;
  90.   uint8_t char1;

  91.   *p_length = 0;
  92.   status = HAL_UART_Receive(&UartHandle, &char1, 1, timeout);

  93.   if (status == HAL_OK)
  94.   {
  95.     switch (char1)
  96.     {
  97.       case SOH:
  98.         packet_size = PACKET_SIZE;
  99.         break;
  100.       case STX:
  101.         packet_size = PACKET_1K_SIZE;
  102.         break;
  103.       case EOT:
  104.         break;
  105.       case CA:
  106.         if ((HAL_UART_Receive(&UartHandle, &char1, 1, timeout) == HAL_OK) && (char1 == CA))
  107.         {
  108.           packet_size = 2;
  109.         }
  110.         else
  111.         {
  112.           status = HAL_ERROR;
  113.         }
  114.         break;
  115.       case ABORT1:
  116.       case ABORT2:
  117.         status = HAL_BUSY;
  118.         break;
  119.       default:
  120.         status = HAL_ERROR;
  121.         break;
  122.     }
  123.     *p_data = char1;

  124.     if (packet_size >= PACKET_SIZE )
  125.     {
  126.       status = HAL_UART_Receive(&UartHandle, &p_data[PACKET_NUMBER_INDEX], packet_size + PACKET_OVERHEAD_SIZE, timeout);

  127.       /* Simple packet sanity check */
  128.       if (status == HAL_OK )
  129.       {
  130.         if (p_data[PACKET_NUMBER_INDEX] != ((p_data[PACKET_CNUMBER_INDEX]) ^ NEGATIVE_BYTE))
  131.         {
  132.           packet_size = 0;
  133.           status = HAL_ERROR;
  134.         }
  135.         else
  136.         {
  137.           /* Check packet CRC */
  138.           crc = p_data[ packet_size + PACKET_DATA_INDEX ] << 8;
  139.           crc += p_data[ packet_size + PACKET_DATA_INDEX + 1 ];
  140.           if (Cal_CRC16(&p_data[PACKET_DATA_INDEX], packet_size) != crc )
  141.           {
  142.             packet_size = 0;
  143.             status = HAL_ERROR;
  144.           }
  145.         }
  146.       }
  147.       else
  148.       {
  149.         packet_size = 0;
  150.       }
  151.     }
  152.   }
  153.   *p_length = packet_size;
  154.   return status;
  155. }

  156. /**
  157.   * @brief  Prepare the first block
  158.   * @param  p_data:  output buffer
  159.   * @param  p_file_name: name of the file to be sent
  160.   * @param  length: length of the file to be sent in bytes
  161.   * @retval None
  162.   */
  163. static void PrepareIntialPacket(uint8_t *p_data, const uint8_t *p_file_name, uint32_t length)
  164. {
  165.   uint32_t i, j = 0;
  166.   uint8_t astring[10];

  167.   /* first 3 bytes are constant */
  168.   p_data[PACKET_START_INDEX] = SOH;
  169.   p_data[PACKET_NUMBER_INDEX] = 0x00;
  170.   p_data[PACKET_CNUMBER_INDEX] = 0xff;

  171.   /* Filename written */
  172.   for (i = 0; (p_file_name[i] != '\0') && (i < FILE_NAME_LENGTH); i++)
  173.   {
  174.     p_data[i + PACKET_DATA_INDEX] = p_file_name[i];
  175.   }

  176.   p_data[i + PACKET_DATA_INDEX] = 0x00;

  177.   /* file size written */
  178.   Int2Str (astring, length);
  179.   i = i + PACKET_DATA_INDEX + 1;
  180.   while (astring[j] != '\0')
  181.   {
  182.     p_data[i++] = astring[j++];
  183.   }

  184.   /* padding with zeros */
  185.   for (j = i; j < PACKET_SIZE + PACKET_DATA_INDEX; j++)
  186.   {
  187.     p_data[j] = 0;
  188.   }
  189. }

  190. /**
  191.   * @brief  Prepare the data packet
  192.   * @param  p_source: pointer to the data to be sent
  193.   * @param  p_packet: pointer to the output buffer
  194.   * @param  pkt_nr: number of the packet
  195.   * @param  size_blk: length of the block to be sent in bytes
  196.   * @retval None
  197.   */
  198. static void PreparePacket(uint8_t *p_source, uint8_t *p_packet, uint8_t pkt_nr, uint32_t size_blk)
  199. {
  200.   uint8_t *p_record;
  201.   uint32_t i, size, packet_size;

  202.   /* Make first three packet */
  203.   packet_size = size_blk >= PACKET_1K_SIZE ? PACKET_1K_SIZE : PACKET_SIZE;
  204.   size = size_blk < packet_size ? size_blk : packet_size;
  205.   if (packet_size == PACKET_1K_SIZE)
  206.   {
  207.     p_packet[PACKET_START_INDEX] = STX;
  208.   }
  209.   else
  210.   {
  211.     p_packet[PACKET_START_INDEX] = SOH;
  212.   }
  213.   p_packet[PACKET_NUMBER_INDEX] = pkt_nr;
  214.   p_packet[PACKET_CNUMBER_INDEX] = (~pkt_nr);
  215.   p_record = p_source;

  216.   /* Filename packet has valid data */
  217.   for (i = PACKET_DATA_INDEX; i < size + PACKET_DATA_INDEX;i++)
  218.   {
  219.     p_packet[i] = *p_record++;
  220.   }
  221.   if ( size  <= packet_size)
  222.   {
  223.     for (i = size + PACKET_DATA_INDEX; i < packet_size + PACKET_DATA_INDEX; i++)
  224.     {
  225.       p_packet[i] = 0x1A; /* EOF (0x1A) or 0x00 */
  226.     }
  227.   }
  228. }

  229. /**
  230.   * @brief  Update CRC16 for input byte
  231.   * @param  crc_in input value
  232.   * @param  input byte
  233.   * @retval None
  234.   */
  235. uint16_t UpdateCRC16(uint16_t crc_in, uint8_t byte)
  236. {
  237.   uint32_t crc = crc_in;
  238.   uint32_t in = byte | 0x100;

  239.   do
  240.   {
  241.     crc <<= 1;
  242.     in <<= 1;
  243.     if(in & 0x100)
  244.       ++crc;
  245.     if(crc & 0x10000)
  246.       crc ^= 0x1021;
  247.   }
  248.   
  249.   while(!(in & 0x10000));

  250.   return crc & 0xffffu;
  251. }

  252. /**
  253.   * @brief  Cal CRC16 for YModem Packet
  254.   * @param  data
  255.   * @param  length
  256.   * @retval None
  257.   */
  258. uint16_t Cal_CRC16(const uint8_t* p_data, uint32_t size)
  259. {
  260.   uint32_t crc = 0;
  261.   const uint8_t* dataEnd = p_data+size;

  262.   while(p_data < dataEnd)
  263.     crc = UpdateCRC16(crc, *p_data++);

  264.   crc = UpdateCRC16(crc, 0);
  265.   crc = UpdateCRC16(crc, 0);

  266.   return crc&0xffffu;
  267. }

  268. /**
  269.   * @brief  Calculate Check sum for YModem Packet
  270.   * @param  p_data Pointer to input data
  271.   * @param  size length of input data
  272.   * @retval uint8_t checksum value
  273.   */
  274. uint8_t CalcChecksum(const uint8_t *p_data, uint32_t size)
  275. {
  276.   uint32_t sum = 0;
  277.   const uint8_t *p_data_end = p_data + size;

  278.   while (p_data < p_data_end )
  279.   {
  280.     sum += *p_data++;
  281.   }

  282.   return (sum & 0xffu);
  283. }

  284. /* Public functions ---------------------------------------------------------*/
  285. /**
  286.   * @brief  Receive a file using the ymodem protocol with CRC16.
  287.   * @param  p_size The size of the file.
  288.   * @retval COM_StatusTypeDef result of reception/programming
  289.   */
  290. COM_StatusTypeDef Ymodem_Receive ( uint32_t *p_size )
  291. {
  292.   uint32_t i, packet_length, session_done = 0, file_done, errors = 0, session_begin = 0;
  293.   uint32_t flashdestination, ramsource, filesize;
  294.   uint8_t *file_ptr;
  295.   uint8_t file_size[FILE_SIZE_LENGTH], tmp, packets_received;
  296.   COM_StatusTypeDef result = COM_OK;

  297.   /* Initialize flashdestination variable */
  298.   flashdestination = APPLICATION_ADDRESS;

  299.   while ((session_done == 0) && (result == COM_OK))
  300.   {
  301.     packets_received = 0;
  302.     file_done = 0;
  303.     while ((file_done == 0) && (result == COM_OK))
  304.     {
  305.       switch (ReceivePacket(aPacketData, &packet_length, DOWNLOAD_TIMEOUT))
  306.       {
  307.         case HAL_OK:
  308.           errors = 0;
  309.           switch (packet_length)
  310.           {
  311.             case 2:
  312.               /* Abort by sender */
  313.               Serial_PutByte(ACK);
  314.               result = COM_ABORT;
  315.               break;
  316.             case 0:
  317.               /* End of transmission */
  318.               Serial_PutByte(ACK);
  319.               file_done = 1;
  320.               break;
  321.             default:
  322.               /* Normal packet */
  323.               if (aPacketData[PACKET_NUMBER_INDEX] != packets_received)
  324.               {
  325.                 Serial_PutByte(NAK);
  326.               }
  327.               else
  328.               {
  329.                 if (packets_received == 0)
  330.                 {
  331.                   /* File name packet */
  332.                   if (aPacketData[PACKET_DATA_INDEX] != 0)
  333.                   {
  334.                     /* File name extraction */
  335.                     i = 0;
  336.                     file_ptr = aPacketData + PACKET_DATA_INDEX;
  337.                     while ( (*file_ptr != 0) && (i < FILE_NAME_LENGTH))
  338.                     {
  339.                       aFileName[i++] = *file_ptr++;
  340.                     }

  341.                     /* File size extraction */
  342.                     aFileName[i++] = '\0';
  343.                     i = 0;
  344.                     file_ptr ++;
  345.                     while ( (*file_ptr != ' ') && (i < FILE_SIZE_LENGTH))
  346.                     {
  347.                       file_size[i++] = *file_ptr++;
  348.                     }
  349.                     file_size[i++] = '\0';
  350.                     Str2Int(file_size, &filesize);

  351.                     /* Test the size of the image to be sent */
  352.                     /* Image size is greater than Flash size */
  353.                     if (*p_size > (USER_FLASH_SIZE + 1))
  354.                     {
  355.                       /* End session */
  356.                       tmp = CA;
  357.                       HAL_UART_Transmit(&UartHandle, &tmp, 1, NAK_TIMEOUT);
  358.                       HAL_UART_Transmit(&UartHandle, &tmp, 1, NAK_TIMEOUT);
  359.                       result = COM_LIMIT;
  360.                     }
  361.                     /* erase user application area */
  362.                     FLASH_If_Erase(APPLICATION_ADDRESS);
  363.                     *p_size = filesize;

  364.                     Serial_PutByte(ACK);
  365.                     Serial_PutByte(CRC16);
  366.                   }
  367.                   /* File header packet is empty, end session */
  368.                   else
  369.                   {
  370.                     Serial_PutByte(ACK);
  371.                     file_done = 1;
  372.                     session_done = 1;
  373.                     break;
  374.                   }
  375.                 }
  376.                 else /* Data packet */
  377.                 {
  378.                   ramsource = (uint32_t) & aPacketData[PACKET_DATA_INDEX];

  379.                   /* Write received data in Flash */
  380.                   if (FLASH_If_Write(flashdestination, (uint32_t*) ramsource, packet_length/4) == FLASHIF_OK)                  
  381.                   {
  382.                     flashdestination += packet_length;
  383.                     Serial_PutByte(ACK);
  384.                   }
  385.                   else /* An error occurred while writing to Flash memory */
  386.                   {
  387.                     /* End session */
  388.                     Serial_PutByte(CA);
  389.                     Serial_PutByte(CA);
  390.                     result = COM_DATA;
  391.                   }
  392.                 }
  393.                 packets_received ++;
  394.                 session_begin = 1;
  395.               }
  396.               break;
  397.           }
  398.           break;
  399.         case HAL_BUSY: /* Abort actually */
  400.           Serial_PutByte(CA);
  401.           Serial_PutByte(CA);
  402.           result = COM_ABORT;
  403.           break;
  404.         default:
  405.           if (session_begin > 0)
  406.           {
  407.             errors ++;
  408.           }
  409.           if (errors > MAX_ERRORS)
  410.           {
  411.             /* Abort communication */
  412.             Serial_PutByte(CA);
  413.             Serial_PutByte(CA);
  414.           }
  415.           else
  416.           {
  417.             Serial_PutByte(CRC16); /* Ask for a packet */
  418.           }
  419.           break;
  420.       }
  421.     }
  422.   }
  423.   return result;
  424. }

  425. /**
  426.   * @brief  Transmit a file using the ymodem protocol
  427.   * @param  p_buf: Address of the first byte
  428.   * @param  p_file_name: Name of the file sent
  429.   * @param  file_size: Size of the transmission
  430.   * @retval COM_StatusTypeDef result of the communication
  431.   */
  432. COM_StatusTypeDef Ymodem_Transmit (uint8_t *p_buf, const uint8_t *p_file_name, uint32_t file_size)
  433. {
  434.   uint32_t errors = 0, ack_recpt = 0, size = 0, pkt_size;
  435.   uint8_t *p_buf_int;
  436.   COM_StatusTypeDef result = COM_OK;
  437.   uint32_t blk_number = 1;
  438.   uint8_t a_rx_ctrl[2];
  439.   uint8_t i;
  440. #ifdef CRC16_F   
  441.   uint32_t temp_crc;
  442. #else /* CRC16_F */   
  443.   uint8_t temp_chksum;
  444. #endif /* CRC16_F */  

  445.   /* Prepare first block - header */
  446.   PrepareIntialPacket(aPacketData, p_file_name, file_size);

  447.   while (( !ack_recpt ) && ( result == COM_OK ))
  448.   {
  449.     /* Send Packet */
  450.     HAL_UART_Transmit(&UartHandle, &aPacketData[PACKET_START_INDEX], PACKET_SIZE + PACKET_HEADER_SIZE, NAK_TIMEOUT);

  451.     /* Send CRC or Check Sum based on CRC16_F */
  452. #ifdef CRC16_F   
  453.     temp_crc = Cal_CRC16(&aPacketData[PACKET_DATA_INDEX], PACKET_SIZE);
  454.     Serial_PutByte(temp_crc >> 8);
  455.     Serial_PutByte(temp_crc & 0xFF);
  456. #else /* CRC16_F */   
  457.     temp_chksum = CalcChecksum (&aPacketData[PACKET_DATA_INDEX], PACKET_SIZE);
  458.     Serial_PutByte(temp_chksum);
  459. #endif /* CRC16_F */

  460.     /* Wait for Ack and 'C' */
  461.     if (HAL_UART_Receive(&UartHandle, &a_rx_ctrl[0], 1, NAK_TIMEOUT) == HAL_OK)
  462.     {
  463.       if (a_rx_ctrl[0] == ACK)
  464.       {
  465.         ack_recpt = 1;
  466.       }
  467.       else if (a_rx_ctrl[0] == CA)
  468.       {
  469.         if ((HAL_UART_Receive(&UartHandle, &a_rx_ctrl[0], 1, NAK_TIMEOUT) == HAL_OK) && (a_rx_ctrl[0] == CA))
  470.         {
  471.           HAL_Delay( 2 );
  472.           __HAL_UART_FLUSH_DRREGISTER(&UartHandle);
  473.           result = COM_ABORT;
  474.         }
  475.       }
  476.     }
  477.     else
  478.     {
  479.       errors++;
  480.     }
  481.     if (errors >= MAX_ERRORS)
  482.     {
  483.       result = COM_ERROR;
  484.     }
  485.   }

  486.   p_buf_int = p_buf;
  487.   size = file_size;

  488.   /* Here 1024 bytes length is used to send the packets */
  489.   while ((size) && (result == COM_OK ))
  490.   {
  491.     /* Prepare next packet */
  492.     PreparePacket(p_buf_int, aPacketData, blk_number, size);
  493.     ack_recpt = 0;
  494.     a_rx_ctrl[0] = 0;
  495.     errors = 0;

  496.     /* Resend packet if NAK for few times else end of communication */
  497.     while (( !ack_recpt ) && ( result == COM_OK ))
  498.     {
  499.       /* Send next packet */
  500.       if (size >= PACKET_1K_SIZE)
  501.       {
  502.         pkt_size = PACKET_1K_SIZE;
  503.       }
  504.       else
  505.       {
  506.         pkt_size = PACKET_SIZE;
  507.       }

  508.       HAL_UART_Transmit(&UartHandle, &aPacketData[PACKET_START_INDEX], pkt_size + PACKET_HEADER_SIZE, NAK_TIMEOUT);
  509.       
  510.       /* Send CRC or Check Sum based on CRC16_F */
  511. #ifdef CRC16_F   
  512.       temp_crc = Cal_CRC16(&aPacketData[PACKET_DATA_INDEX], pkt_size);
  513.       Serial_PutByte(temp_crc >> 8);
  514.       Serial_PutByte(temp_crc & 0xFF);
  515. #else /* CRC16_F */   
  516.       temp_chksum = CalcChecksum (&aPacketData[PACKET_DATA_INDEX], pkt_size);
  517.       Serial_PutByte(temp_chksum);
  518. #endif /* CRC16_F */
  519.       
  520.       /* Wait for Ack */
  521.       if ((HAL_UART_Receive(&UartHandle, &a_rx_ctrl[0], 1, NAK_TIMEOUT) == HAL_OK) && (a_rx_ctrl[0] == ACK))
  522.       {
  523.         ack_recpt = 1;
  524.         if (size > pkt_size)
  525.         {
  526.           p_buf_int += pkt_size;
  527.           size -= pkt_size;
  528.           if (blk_number == (USER_FLASH_SIZE / PACKET_1K_SIZE))
  529.           {
  530.             result = COM_LIMIT; /* boundary error */
  531.           }
  532.           else
  533.           {
  534.             blk_number++;
  535.           }
  536.         }
  537.         else
  538.         {
  539.           p_buf_int += pkt_size;
  540.           size = 0;
  541.         }
  542.       }
  543.       else
  544.       {
  545.         errors++;
  546.       }

  547.       /* Resend packet if NAK  for a count of 10 else end of communication */
  548.       if (errors >= MAX_ERRORS)
  549.       {
  550.         result = COM_ERROR;
  551.       }
  552.     }
  553.   }

  554.   /* Sending End Of Transmission char */
  555.   ack_recpt = 0;
  556.   a_rx_ctrl[0] = 0x00;
  557.   errors = 0;
  558.   while (( !ack_recpt ) && ( result == COM_OK ))
  559.   {
  560.     Serial_PutByte(EOT);

  561.     /* Wait for Ack */
  562.     if (HAL_UART_Receive(&UartHandle, &a_rx_ctrl[0], 1, NAK_TIMEOUT) == HAL_OK)
  563.     {
  564.       if (a_rx_ctrl[0] == ACK)
  565.       {
  566.         ack_recpt = 1;
  567.       }
  568.       else if (a_rx_ctrl[0] == CA)
  569.       {
  570.         if ((HAL_UART_Receive(&UartHandle, &a_rx_ctrl[0], 1, NAK_TIMEOUT) == HAL_OK) && (a_rx_ctrl[0] == CA))
  571.         {
  572.           HAL_Delay( 2 );
  573.           __HAL_UART_FLUSH_DRREGISTER(&UartHandle);
  574.           result = COM_ABORT;
  575.         }
  576.       }
  577.     }
  578.     else
  579.     {
  580.       errors++;
  581.     }

  582.     if (errors >=  MAX_ERRORS)
  583.     {
  584.       result = COM_ERROR;
  585.     }
  586.   }

  587.   /* Empty packet sent - some terminal emulators need this to close session */
  588.   if ( result == COM_OK )
  589.   {
  590.     /* Preparing an empty packet */
  591.     aPacketData[PACKET_START_INDEX] = SOH;
  592.     aPacketData[PACKET_NUMBER_INDEX] = 0;
  593.     aPacketData[PACKET_CNUMBER_INDEX] = 0xFF;
  594.     for (i = PACKET_DATA_INDEX; i < (PACKET_SIZE + PACKET_DATA_INDEX); i++)
  595.     {
  596.       aPacketData [i] = 0x00;
  597.     }

  598.     /* Send Packet */
  599.     HAL_UART_Transmit(&UartHandle, &aPacketData[PACKET_START_INDEX], PACKET_SIZE + PACKET_HEADER_SIZE, NAK_TIMEOUT);

  600.     /* Send CRC or Check Sum based on CRC16_F */
  601. #ifdef CRC16_F   
  602.     temp_crc = Cal_CRC16(&aPacketData[PACKET_DATA_INDEX], PACKET_SIZE);
  603.     Serial_PutByte(temp_crc >> 8);
  604.     Serial_PutByte(temp_crc & 0xFF);
  605. #else /* CRC16_F */   
  606.     temp_chksum = CalcChecksum (&aPacketData[PACKET_DATA_INDEX], PACKET_SIZE);
  607.     Serial_PutByte(temp_chksum);
  608. #endif /* CRC16_F */

  609.     /* Wait for Ack and 'C' */
  610.     if (HAL_UART_Receive(&UartHandle, &a_rx_ctrl[0], 1, NAK_TIMEOUT) == HAL_OK)
  611.     {
  612.       if (a_rx_ctrl[0] == CA)
  613.       {
  614.           HAL_Delay( 2 );
  615.           __HAL_UART_FLUSH_DRREGISTER(&UartHandle);
  616.           result = COM_ABORT;
  617.       }
  618.     }
  619.   }

  620.   return result; /* file transmitted successfully */
  621. }

  622. /**
  623.   * @}
  624.   */

  625. /*******************(C)COPYRIGHT 2016 STMicroelectronics *****END OF FILE****/
复制代码

出0入0汤圆

发表于 2019-1-13 18:44:02 | 显示全部楼层
学习了,感谢分享

出870入263汤圆

发表于 2019-1-13 18:48:41 | 显示全部楼层
经过每个文件查看过去,官方STM32CubeMX目录里的ymodem.c(注意我楼上的目录截图)都是错的。楼主使用的文件是经网友修改过的,所以问题并不一致。

出0入0汤圆

 楼主| 发表于 2019-1-13 18:49:49 | 显示全部楼层
本帖最后由 zirong0804 于 2019-1-13 18:51 编辑
armstrong 发表于 2019-1-13 18:34
楼主你用的ymodem是哪里来的?我的跟你不一样。我是这些目录里的:


你是新版本,我这是老版本了
STM32F0xx_AN4065_FW_V1.0.0\Project\STM32F0xx_IAP\src

  ******************************************************************************
  * @file    STM32F0xx_IAP/src/ymodem.c
  * @author  MCD Application Team
  * @version V1.0.0
  * @date    29-May-2012
  * @brief   Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2012 STMicroelectronics</center></h2>

出0入0汤圆

 楼主| 发表于 2019-1-13 18:53:06 | 显示全部楼层
本帖最后由 zirong0804 于 2019-1-13 18:55 编辑
armstrong 发表于 2019-1-13 18:48
经过每个文件查看过去,官方STM32CubeMX目录里的ymodem.c(注意我楼上的目录截图)都是错的。楼主使用的文 ...


是的,很高兴分享,讨论,学习
方便的话,提供下你文件的下载连接

出870入263汤圆

发表于 2019-1-13 18:54:27 | 显示全部楼层
zirong0804 发表于 2019-1-13 18:49
你是新版本,我这是老版本了
STM32F0xx_AN4065_FW_V1.0.0\Project\STM32F0xx_IAP\src

word天!这些ST工程师居然把原先还算正确代码改成错误百出的新代码了!
你的旧代码是2012年的,而新的文件是2017年的,全在STM32CubeMX目录里!

出0入0汤圆

 楼主| 发表于 2019-1-13 18:58:33 | 显示全部楼层
armstrong 发表于 2019-1-13 18:54
word天!这些ST工程师居然把原先还算正确代码改成错误百出的新代码了!
你的旧代码是2012年的,而新的文 ...

是的,还有个问题:使用secureCRT,怎么让它选择STX 1024字节传输,目前都是使用 SOH 128字节传输

出870入263汤圆

发表于 2019-1-13 19:00:55 | 显示全部楼层
zirong0804 发表于 2019-1-13 18:58
是的,还有个问题:使用secureCRT,怎么让它选择STX 1024字节传输,目前都是使用 SOH 128字节传输 ...

这个要在secureCRT选项中设定

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2019-1-13 20:54:15 | 显示全部楼层
MARK一下

出0入0汤圆

发表于 2019-1-13 23:18:43 | 显示全部楼层
armstrong 发表于 2019-1-13 19:00
这个要在secureCRT选项中设定

我去,YMODE都要去研究啊,我放弃了这个玩意,直接私有协议飞起。。。

出0入0汤圆

发表于 2019-1-14 15:25:23 | 显示全部楼层
谢谢分享,学习了,还没用过

出0入0汤圆

发表于 2019-1-14 16:00:26 | 显示全部楼层
谢谢分享

出870入263汤圆

发表于 2019-1-14 17:40:31 | 显示全部楼层
kinsno 发表于 2019-1-13 23:18
我去,YMODE都要去研究啊,我放弃了这个玩意,直接私有协议飞起。。。

...

主要是懒得写PC工具。私有协议速度应该能更快。
目前我用SecureCRT,2Mbps的波特率时,传输率才100kB/s;逻辑分析仪看起来,传输带宽利用率只有50%,太低了!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2019-1-15 21:05:07 | 显示全部楼层
本帖最后由 zirong0804 于 2019-1-15 21:06 编辑

修改代码,符合标准YModem协议,具体如下

1-接收端在第一次收到EOT时,发送NAK。那么发送端会再一次发送EOT,此时接收端发送ACK应答

发送端                                    接收端
                                               C---<
SOH-->
                                               ACK---<
                                                   C---<
SOH-->
                                              ACK---<
SOH-->
                                              ACK---<
...
SOH-->
                                              ACK---<
SOH-->
                                              ACK---<
EOT-->
                                              NAK---<

EOT-->
                                             ACK---<
                 (调试代码为ACK-end<)
                                                  C---<
SOH-->
                                              ACK---<

          (调试代码为ACK-empty<)

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入475汤圆

发表于 2019-4-29 10:43:53 | 显示全部楼层
正好遇到了新问题要请教一下楼主及各位

有没有谁使用超级终端的 winsock 方式传输 Ymodem 的呢?
目前还没有找到有人这么做,资料也没有多少研究的人,好像看了他的传输内容和串口的不一样啊

出0入0汤圆

 楼主| 发表于 2019-5-5 08:37:16 | 显示全部楼层
1a2b3c 发表于 2019-4-29 10:43
正好遇到了新问题要请教一下楼主及各位

有没有谁使用超级终端的 winsock 方式传输 Ymodem 的呢?

不好意思,没有学习过

出0入0汤圆

发表于 2019-5-5 09:22:44 | 显示全部楼层
感谢楼主分享

出0入0汤圆

发表于 2020-3-16 07:51:59 | 显示全部楼层
感谢楼主的分享

出0入0汤圆

发表于 2020-9-3 14:33:30 来自手机 | 显示全部楼层
正在学习这一部分,及时雨

出0入0汤圆

发表于 2020-9-3 15:01:45 | 显示全部楼层
多谢楼主分享

出0入0汤圆

发表于 2020-10-18 19:27:45 | 显示全部楼层
多谢分享,正在学习。

出0入4汤圆

发表于 2021-1-5 08:19:22 | 显示全部楼层
多谢分享!最近也在研究YMODEM,用C#写了YMODEM文件发送,文件接收还没写好。

出0入0汤圆

发表于 2021-1-5 13:31:29 | 显示全部楼层
YMODEM感觉升级的话用的很多啊

出0入0汤圆

发表于 2021-10-8 09:03:04 | 显示全部楼层
感谢分享

出0入0汤圆

发表于 2021-10-9 09:41:52 | 显示全部楼层
armstrong 发表于 2019-1-14 17:40
主要是懒得写PC工具。私有协议速度应该能更快。
目前我用SecureCRT,2Mbps的波特率时,传输率才100kB/s; ...

是不是传输太快,flash写入速度跟不上,所以是发送端在等待接收端

出0入0汤圆

发表于 2021-12-1 13:39:16 | 显示全部楼层
程序在烧写大一点的bin文件时,会卡死

出105入79汤圆

发表于 2021-12-1 22:42:10 | 显示全部楼层
XModem 方便很多

出0入0汤圆

发表于 2021-12-23 11:14:41 | 显示全部楼层

多谢分享,正在学习。

出0入0汤圆

发表于 2021-12-27 10:38:39 | 显示全部楼层
zirong0804 发表于 2019-1-13 18:27
的确,目前代码中定义,一般够用
#define FILE_NAME_LENGTH        (256)
#define FILE_SIZE_LENGTH      ...

请教下楼主为何文件名长度定义256字节,文件大小定义16字节,看协议这两个加起来最长就128字节吧。
#define FILE_NAME_LENGTH        (256)
#define FILE_SIZE_LENGTH        (16)
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-16 17:27

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表