找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2010|回复: 2
打印 上一主题 下一主题
收起左侧

xmodem源码下载

[复制链接]
跳转到指定楼层
楼主
ID:275352 发表于 2018-1-12 20:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
xmodem源码

单片机源程序如下:
  1. /**************************************************************************
  2. *
  3. * Written by Cencong Su (cencong.su@gmail.com)
  4. *
  5. ***************************************************************************
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above author notice,
  10. *    this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above author notice,
  12. *    this list of conditions and the following disclaimer in the documentation
  13. *    and/or other materials provided with the distribution.
  14. * 3. The name of the author may not be used to endorse or promote products
  15. *    derived from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
  18. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  19. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
  20. * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  21. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
  22. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  23. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  24. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  25. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  26. * OF SUCH DAMAGE.
  27. *
  28. **********************************************************************//*!
  29. *
  30. * @file xmodem.c
  31. *
  32. * @author Cencong Su
  33. *
  34. * @brief Implement xmodem protocol
  35. *
  36. * @details This module needs the following libray functions:
  37. * 1> memcpy
  38. * 2> memset
  39. * 3> malloc and free
  40. * Target dependent code is marked with special comment "Target Dependent :"
  41. *
  42. *
  43. ***************************************************************************/

  44. #include <common.h>
  45. #include <stdlib.h>
  46. #include "xmodem.h"
  47. #include "crc16.h"

  48. /** Target dependent : header files  */
  49. #include "fnet_serial.h"

  50. /*-----------------------------------------------------------------------------------*/
  51. /* -----------------------------Target Dependent : code ---------------------------*/

  52. /**
  53. * Initiate the xmodem module, serial port etc.
  54. * Leave empty here
  55. *
  56. * @param NONE
  57. * @return NONE
  58. */
  59. void xmodem_init()
  60. {

  61. }

  62. /**
  63. * Get one byte from xmodem serial port
  64. *
  65. * @param[in] timeout        timeout value for getting one byte from
  66. * serial port unit:ms
  67. *
  68. * @retval >0 data from xmodem serial port, other receive wrong
  69. */
  70. int getbyte_timeout(uint16_t timeout)
  71. {
  72.         int c = 0, len;
  73.         uint32_t time_cnt = fnet_timer_ms();

  74.         while ((fnet_timer_ms() - time_cnt) < timeout)
  75.         {
  76.                 c = fnet_getchar();
  77.                 if (c >= 0)
  78.                 {
  79.                         return c;
  80.                 }
  81.         }

  82.         return -1;
  83. }

  84. /**
  85. * Send one byte to xmodem serial port
  86. *
  87. * @param[in] ch data sent out
  88. *
  89. * @return None
  90. */
  91. void sendbyte(int ch)
  92. {
  93.         fnet_putchar(ch);
  94. }


  95. /**
  96. * flush serial port buffer
  97. *
  98. * @param NONE
  99. * @return NONE
  100. */
  101. void flush_input()
  102. {
  103.         while(getbyte_timeout(DLY_1S/3) >= 0);
  104. }

  105. /**
  106. * Send out a group of data
  107. * Implement this function here is because some platform will provide
  108. * similar function to send continuous serial data
  109. *
  110. * @param data  data address
  111. * @param len        data length
  112. *
  113. * @return NONE
  114. */
  115. void xmodem_send_data(uint8_t * data, uint16_t len)
  116. {
  117.         uint16_t i;

  118.         for (i = 0; i < len; i++)
  119.         {
  120.                 sendbyte(data[i]);
  121.         }
  122. }
  123. /* -------------------Target dependent code END --------------------*/
  124. /*-----------------------------------------------------------------------------------*/


  125. /**
  126. * Cancel xmodem transmission
  127. *
  128. * @param  NONE
  129. * @return NONE
  130. */
  131. void xmodem_cancel()
  132. {
  133.         sendbyte(CAN);
  134.         sendbyte(CAN);
  135.         sendbyte(CAN);
  136. }

  137. /**
  138. * Receive one xmodem packet with timeout
  139. *
  140. * @param[out] dest      address of memory to place received data
  141. * @param[in]  timeout   keep trying to get data until timeout
  142. * @param[in]  crc_flag  mechanism to check data integrity, 1:CRC, 0:Check sum
  143. *
  144. * @return Received data length
  145. */
  146. uint16_t xmodem_recv_pkt(uint8_t *dest, uint32_t timeout, uint8_t crc_flag)
  147. {
  148.         int ch;
  149.         uint16_t cnt = 0;

  150.         ch = getbyte_timeout(timeout);
  151.        
  152.         if(ch >= 0)
  153.         {
  154.                 dest[cnt++] = ch;
  155.                
  156.                
  157.                 while(cnt < ((crc_flag) ? sizeof(XMODEM_PACKET) : (sizeof(XMODEM_PACKET) - 1)))
  158.                 {
  159.                         //Try to receive one byte
  160.                         ch = getbyte_timeout(DLY_1S);
  161.                        
  162.                         if (ch >= 0)
  163.                         {
  164.                                 dest[cnt++] = ch;
  165.                         }
  166.                         else
  167.                         {
  168.                                 /*If the no data receive then keep trying to get data until timeout,
  169.                                  If data already arrives, then received char<0 means end of packet,
  170.                                  return received number*/
  171.                                 return cnt;
  172.                         }
  173.                 }
  174.                
  175.                 return cnt;
  176.         }
  177.         else
  178.         {
  179.                 return 0;
  180.         }       
  181. }

  182. /**
  183. * Check xmodem packet integrity
  184. *
  185. * @param[in] crc_flag   Check mechanism, 1:CRC, 0:Check sum
  186. * @param[in] pkt        xmodem packet
  187. *
  188. * @return TRUE: data is OK, FALSE: data wrong
  189. */
  190. bool xmodem_check(uint8_t crc_flag, XMODEM_PACKET_PTR pkt)
  191. {
  192.         uint16 i, crc;
  193.         uint8_t cks = 0;

  194.         if (crc_flag)
  195.         {
  196.                 crc = crc16_ccitt(pkt->data, PACKET_LEN);
  197.                 hsb2lsb(crc);
  198.                 if (crc == pkt->chk_code.crc)
  199.                 {
  200.                         return TRUE;
  201.                 }
  202.         }
  203.         else
  204.         {
  205.                 for (i = 0; i < PACKET_LEN; ++i)
  206.                 {
  207.                         cks += pkt->data[i];
  208.                 }

  209.                 if (cks == pkt->chk_code.chksum)
  210.                 {
  211.                         return TRUE;
  212.                 }
  213.         }

  214.         return FALSE;
  215. }

  216. /**
  217. * Parse one xmodem packet
  218. *
  219. * @param[in] data       xmodem packet address
  220. * @param[in] len        packet length
  221. * @param[in] crc_flag   Data check mechanism, 1: CRC, 0: Check sum
  222. *
  223. * @ret PARS_OK    Data is ok
  224. * @ret PARS_NAK   Need to response with "NAK"
  225. * @ret PARS_EOT   Receive "EOT"
  226. * @ret PARS_CAN   Receive "CAN"
  227. *
  228. * @see xmodem_parse_pkt_ret
  229. */
  230. xmodem_parse_pkt_ret xmodem_parse_pkt(uint8_t * data, uint32_t len,
  231.                 uint8_t crc_flag, uint8_t recv_pkt_no)
  232. {
  233.         XMODEM_PACKET_PTR pkt = (XMODEM_PACKET_PTR) data;

  234.         switch (data[0])
  235.         {
  236.         case SOH:
  237.                 if ((pkt->packet_num == recv_pkt_no)
  238.                 && (pkt->pkt_num_cmplemt == (uint8_t) ~recv_pkt_no)
  239.                 && (len == ((crc_flag) ?sizeof(XMODEM_PACKET) : (sizeof(XMODEM_PACKET) - 1)))
  240.                 && (xmodem_check(crc_flag, pkt) == 1))
  241.                 {
  242.                         return PARS_OK;
  243.                 }
  244.                 else
  245.                 {
  246.                         return PARS_ERR;
  247.                 }
  248.                 break;

  249.         case EOT:
  250.                 return PARS_EOT;

  251.         case CAN:
  252.                 return PARS_CAN;

  253.         default:
  254.                 return PARS_ERR;
  255.         }
  256. }

  257. /**
  258. * xmodem receive entry
  259. *
  260. * @param[in] dest  destination address to store received data
  261. * @param[in] destsz    destination area size
  262. *
  263. * @return actual data size copied to destination
  264. */
  265. uint32_t xmodem_recv(uint8_t *dest, uint32_t destsz)
  266. {
  267.         XMODEM_PACKET_PTR xdm_pkt;
  268.         uint8_t crc_flag = 1, i, recv_pkt_no = 1;
  269.         uint32_t recv_len, dest_index = 0, destsz_left = 0;
  270.         xmodem_parse_pkt_ret xdmParsRet;

  271.         flush_input();

  272.         xdm_pkt = (XMODEM_PACKET_PTR) malloc(sizeof(XMODEM_PACKET));
  273.         if (xdm_pkt == NULL)
  274.         {
  275.                 printf("Can't allocate memory for new xmodem packet in %s!\n",
  276.                                 __FUNCTION__);
  277.                 goto RETURN;
  278.         }

  279.         //Send out first byte and try to receive the acknowledge packet
  280.         for (i = 0; i < MAX_RETRANS; i++)
  281.         {
  282.                 //Try to communicate with remote: send 'C' -> NAK -> 'C' -> NAK...
  283.                 sendbyte((crc_flag) ? USE_CRC : NAK);
  284.                 recv_len = xmodem_recv_pkt((uint8_t *) xdm_pkt, (2 * DLY_1S), crc_flag);
  285.                 if (recv_len > 0)
  286.                 {
  287.                         //Tera term first xmodem packet will contain wrong data
  288.                         //flush serial port buffer to be compatible with teara term
  289.                         flush_input();
  290.                         break;
  291.                 }
  292.                 else
  293.                 {
  294.                         if( i == (MAX_RETRANS/2))
  295.                         {
  296.                             crc_flag = !crc_flag;
  297.                         }

  298.                         //Already try the maximum times to communicate with remote, cancel link
  299.                         if (i == (MAX_RETRANS - 1))
  300.                         {
  301.                                 xmodem_cancel();
  302.                                 goto RETURN;
  303.                         }
  304.                 }
  305.         }
  306.        
  307.         while (1)
  308.         {
  309.                 xdmParsRet = xmodem_parse_pkt((uint8_t *) xdm_pkt, recv_len, crc_flag,
  310.                                 recv_pkt_no);

  311.                 switch (xdmParsRet)
  312.                 {
  313.                 case PARS_OK:
  314.                         recv_pkt_no++;
  315.                         destsz_left = destsz - dest_index;
  316.                         if (destsz_left < PACKET_LEN)
  317.                         {
  318.                                 memcpy(dest + dest_index, xdm_pkt->data, destsz_left);
  319.                                 dest_index += destsz_left;
  320.                                 xmodem_cancel();
  321.                                 goto RETURN;
  322.                         }
  323.                         else
  324.                         {
  325.                                 memcpy(dest + dest_index, xdm_pkt->data, PACKET_LEN);
  326.                                 dest_index += PACKET_LEN;
  327.                                 sendbyte(ACK);
  328.                         }
  329.                         break;

  330.                 case PARS_CAN:
  331.                         sendbyte(ACK);
  332.                         goto RETURN;

  333.                 case PARS_EOT:
  334.                         sendbyte(ACK);
  335.                         goto RETURN;

  336.                 case PARS_ERR:
  337.                 default:
  338.                         flush_input();
  339.                         sendbyte(NAK);
  340.                         break;
  341.                 }

  342.                 recv_len = xmodem_recv_pkt((uint8_t *) xdm_pkt, (10 * DLY_1S),
  343.                                 crc_flag);
  344.                
  345.                 if (recv_len <= 0)
  346.                 {
  347.                         xmodem_cancel();
  348.                         goto RETURN;
  349.                 }
  350.         }

  351.         RETURN:
  352.         free(xdm_pkt);
  353.         return dest_index;
  354. }

  355. /**
  356. * Start xmodem transmit
  357. *
  358. * @param[in] crc_flag    check data integrity method: 1 - crc, 0 - checksum
  359. * @param[in] data_src    address of data be sent
  360. * @param[in] data_sz     size of data be sent
  361. *
  362. * @ret >0   actual sent data length
  363. * @ret -1   remote cancel
  364. * @ret -2   communication timeout
  365. *
  366. * @see REMOTE_CANCEL,COM_TIMEOUT
  367. */
  368. int xmodem_start_trans(uint8_t crc_flag, uint8_t *dat_src, int data_sz)
  369. {
  370.         XMODEM_PACKET xmodem_pkt;
  371.         uint8_t packetno = 1, i;
  372.         int sent_len = 0, left_num;
  373.         int ch;

  374.         START_TRANS:
  375.         memset(&xmodem_pkt, 0, sizeof(xmodem_pkt));
  376.         left_num = data_sz - sent_len;
  377.         xmodem_pkt.soh = SOH;
  378.         xmodem_pkt.packet_num = packetno;
  379.         xmodem_pkt.pkt_num_cmplemt = ~packetno;

  380.         //Still have left bytes to send
  381.         if (left_num > 0)
  382.         {
  383.                 if (left_num >= PACKET_LEN)
  384.                 {
  385.                         memcpy(xmodem_pkt.data, &dat_src[sent_len], PACKET_LEN);
  386.                 }
  387.                 else if (left_num < PACKET_LEN)
  388.                 {
  389.                         //The remain data can't fill one packet, so fill it with "CTRL-Z(0x1a)"
  390.                         memcpy(xmodem_pkt.data, &dat_src[sent_len], left_num);
  391.                         memset(xmodem_pkt.data + left_num, CTRLZ, PACKET_LEN - left_num);
  392.                 }

  393.                 //Calculate check code, checksum/CRC
  394.                 if (crc_flag)
  395.                 {
  396.                         xmodem_pkt.chk_code.crc = crc16_ccitt(xmodem_pkt.data, PACKET_LEN);

  397.                         //Exchange the lsb and hsb byte, hsb output first
  398.                         hsb2lsb(xmodem_pkt.chk_code.crc);
  399.                 }
  400.                 else
  401.                 {
  402.                         for (i = 0; i < PACKET_LEN; i++)
  403.                         {
  404.                                 xmodem_pkt.chk_code.chksum += xmodem_pkt.data[i];
  405.                         }
  406.                 }

  407.                 //Transmit the packet
  408.                 for (i = 0; i < MAX_RETRANS; i++)
  409.                 {
  410.                         xmodem_send_data((uint8_t *) &xmodem_pkt,
  411.                                         sizeof(xmodem_pkt) - (crc_flag ? 0 : 1));

  412.                         //Read response byte from remote
  413.                         if ((ch = getbyte_timeout(DLY_1S * 10)) >= 0)
  414.                         {
  415.                                 switch (ch)
  416.                                 {
  417.                                 case ACK:
  418.                                         packetno++;
  419.                                         sent_len += PACKET_LEN;
  420.                                         goto START_TRANS;

  421.                                 case CAN:
  422.                                         if ((ch = getbyte_timeout(DLY_1S)) == CAN)
  423.                                         {
  424.                                                 sendbyte(ACK);
  425.                                                 return REMOTE_CANCEL; /* canceled by remote */
  426.                                         }
  427.                                         break;

  428.                                 case NAK:
  429.                                 default:
  430.                                         break;
  431.                                 }
  432.                         }
  433.                        
  434.                         if(i == MAX_RETRANS -1)
  435.                         {
  436.                                 //Has retransmit the maximum times without response from remote
  437.                                 xmodem_cancel();
  438.                                 return COM_TIMEOUT;
  439.                         }
  440.                 }
  441.         }
  442.         else
  443.         {
  444.                 for (i = 0; i < MAX_RETRANS; i++)
  445.                 {
  446.                         sendbyte(EOT);
  447.                         if ((ch = getbyte_timeout((DLY_1S) << 1)) == ACK)
  448.                                 break;
  449.                 }
  450.                 return (ch == ACK) ? sent_len : COM_TIMEOUT;
  451.         }
  452. }

  453. /**
  454. * Transmit entry
  455. *
  456. * @param[in] src    address of data be sent
  457. * @param[in] srcsz  size of data be sent
  458. *
  459. * @ret >0 actual sent data length
  460. * @ret -1 remote cancel
  461. * @ret -2 communication timeout
  462. *
  463. * @see REMOTE_CANCEL,COM_TIMEOUT
  464. */
  465. int xmodemTransmit(unsigned char *src, int srcsz)
  466. {       
  467.         int ch = 0;

  468.         flush_input();
  469.        
  470.         //Try to receive the first byte from remote
  471.         ch = getbyte_timeout(DLY_1S * 30);
  472.         if (ch >= 0)
  473.         {
  474.                 switch (ch)
  475.                 {
  476.                 case USE_CRC:
  477.                         return xmodem_start_trans(1, src, srcsz);

  478.                 case NAK:
  479.                         return xmodem_start_trans(0, src, srcsz);

  480.                 case CAN:
  481.                         if ((ch = getbyte_timeout(DLY_1S)) == CAN)
  482.                         {
  483.                                 //Canceled by remote
  484.                                 sendbyte(ACK);
  485.                                 return REMOTE_CANCEL;
  486.                         }
  487.                         break;
  488.                 default:
  489.                         printf("Unrecognized xmodem command byte: %d\n", ch);
  490.                         break;
  491.                 }
  492.         }

  493.         xmodem_cancel();
  494.         return COM_TIMEOUT; /* no sync */

  495. }

  496. /**
  497. * Xmodem module test sample
  498. *
  499. * @param NONE
  500. *
  501. * @return NONE
  502. */
  503. void xmodem_test()
  504. {
  505.         int st;
  506.         uint8_t buf[128];

  507.         st = xmodem_recv(buf, 128);
  508.         xmodemTransmit(buf, st);
  509. }
复制代码

所有资料51hei提供下载:
xmodem.zip (8.66 KB, 下载次数: 30)


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:393586 发表于 2018-11-30 14:40 | 只看该作者
正要学习这个 谢谢楼主
回复

使用道具 举报

板凳
ID:472126 发表于 2019-1-23 15:50 | 只看该作者
多谢分享。。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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