X-Modem 协议接收端的实现 For RVDS

  1. 前段时间搞ARM实验平台的开发,需要经常实时调试程序。但是烧写一次Flash又太麻烦,后来想到一个最经典的解决方法,就是通过串口下载到内存实时运行调试。本来不想写太多,所以选择了最最古老但又最最有效的一个传输协议:X-Modem。X-Modem协议是 1977 年 Ward Christensen 所发明的。这个协议使用最简单的“等待/重传”算法,对于ARM这一类嵌入式系统来说,由于通常外围IP都有UART模块,所以不仅易于实现,而且还节省硬件资源。相关X-Modem协议详细资料可以在网上找到。
  2. 这里给出我前段时间写的X-Modem接收端程序核心。本程序是针对Samsung的s3c2410系列编写的,使用了2410的内部UART模块,以及UART的FIFO机制。值得注意的是,由于Xmodem接收包的时候并不能保证CPU处于100%在本进程,或者不能保证CPU能马上响应UART事件,所以并不能使用POLL方法进行UART的操作,必须要打开UART模块的FIFO机制,才能保证数据的准确而且不掉包。
  3. 本模块接口为:
  4. int xmodem_receive(unsigned char* buf, int timeoutcount, int* receivedsize)
  5. 返回值:具体值在 xmodem.h 里定义,是接收的最后状态。
  6. 输入参数:buf为接收缓冲区地址。timeoutcount为超时计数。
  7. 输出参数:receivedsize为总接收数据量,以byte为单位。
  8. xmodem.h:
  9.  /*=============================================================================
  10. --------------------------------- Copy Left -----------------------------------
  11.                         Illidan Fly's Project
  12.                         Power by BigFly Network
  13.                         http://bigfly.happybobby.com
  14.                         
  15.                         Released under GPL2 License
  16. ----------------------------- File Description --------------------------------
  17.  Filename:  xmodem.h
  18.  Date:      2007.01.12
  19.  Version:   0.0.1
  20.  Description:
  21.             Xmodem protocol using polling and Uart FIFO.
  22. ----------------------------- Version History ---------------------------------
  23.  0.0.2: Size parameter added to xmodem_receive().
  24.  0.0.1: First release
  25. =============================================================================*/
  26. #ifndef __XMODEM_H__
  27. #define __XMODEM_H__
  28. #define XMODEM_DATA_SIZE    128
  29. #define XMODEM_SOH  0x01
  30. #define XMODEM_EOT  0x04
  31. #define XMODEM_ACK  0x06
  32. #define XMODEM_NAK  0x15
  33. #define XMODEM_CAN  0x18
  34. #define XMODEM_ERR_OK       0x00
  35. #define XMODEM_ERR_TIMEOUT  0x01
  36. #define XMODEM_ERR_CANCEL   0x02
  37. #define XMODEM_ERR_TRANSMIT 0x03
  38. #define XMODEM_ERR_RECEIVE  0x04
  39. int xmodem_receive(unsigned char* buf, int timeoutcount, int* receivedsize);
  40. #endif  //__XMODEM_H__
  41. xmodem.c:
  42. /*=============================================================================
  43. --------------------------------- Copy Left -----------------------------------
  44.                         Illidan Fly's Project
  45.                         Power by BigFly Network
  46.                         http://bigfly.happybobby.com
  47.                         
  48.                         Released under GPL2 License
  49. ----------------------------- File Description --------------------------------
  50.  Filename:  xmodem.c
  51.  Date:      2007.01.14
  52.  Version:   0.0.2
  53.  Description:
  54.             Xmodem protocol using polling and Uart FIFO.
  55. ----------------------------- Version History ---------------------------------
  56.  0.0.2: First package issue fixed. Size parameter added to xmodem_receive().
  57.  0.0.1: First release
  58. =============================================================================*/
  59. #include "xmodem.h"
  60. #include "2410addr.h"
  61. #include "2410lib.h"
  62. #include "def.h"
  63. #define UART_NOT_EMPTY (rUFSTAT0 & 0x000F)
  64. // Save for UART state
  65. int save_rufcon;
  66. typedef struct _xmodem_package
  67. {
  68.     unsigned char blknum;
  69.     unsigned char checkblknum;
  70.     unsigned char data[XMODEM_DATA_SIZE];
  71.     unsigned char checksum;
  72. }xmodem_package;
  73. unsigned char uart_getdata(void)
  74. {
  75.     // Wait for Rx FIFO not empty
  76.     while(!UART_NOT_EMPTY){;}
  77.     return RdURXH0();
  78. }
  79. void uart_senddata(unsigned char data)
  80. {
  81.     // Wait for Tx FIFO not full
  82.     while(rUFSTAT0 & 0x0200){;}
  83.     WrUTXH0(data);
  84. }
  85. void uart_initstate(void)
  86. {
  87.     Uart_TxEmpty(0);
  88.     save_rufcon = rUFCON0;
  89.     
  90.     // Note: Xmodem must work in FIFO mode or will encounter data loss.
  91.     // Set UART0 to FIFO mode
  92.     rUFCON0 = 0x7;
  93.     Delay(100);
  94. }
  95. void uart_restorestate(void)
  96. {
  97.     rUFCON0 = save_rufcon;
  98. }
  99. int xmodem_receive(unsigned char* buf, int timeoutcount, int* receivedsize)
  100. {
  101.     xmodem_package receivedpak;
  102.     unsigned char tmpchar;
  103.     unsigned char tmpsum;
  104.     unsigned char packnum;
  105.     int retrytime;
  106.     int fc1;
  107.     
  108.     // Init UART state
  109.     uart_initstate();
  110.     
  111.     // Xmodem first frame number = 0x01
  112.     packnum=0x01;
  113.     retrytime=0;
  114.     *receivedsize=0;
  115.     
  116.     // Send NAK and wait for sender signal, resend NAK in 10 seconds
  117.     do
  118.     {
  119.         if(retrytime++>timeoutcount)
  120.         {
  121.             uart_restorestate();
  122.             return XMODEM_ERR_TIMEOUT;
  123.         }
  124.         uart_senddata(XMODEM_NAK);
  125.         for(fc1=0;fc1<10000000;fc1++)
  126.         {
  127.             if(UART_NOT_EMPTY){break;}
  128.         }
  129.     }while(!UART_NOT_EMPTY);
  130.     
  131.     // Start receive
  132.     while(1)
  133.     {
  134.         tmpsum=0;
  135.         
  136.         // Get control signal
  137.         tmpchar=uart_getdata();
  138.         switch(tmpchar)
  139.         {
  140.             case XMODEM_SOH:
  141.             // New package
  142.             break;
  143.             
  144.             case XMODEM_EOT:
  145.             // End of transmit
  146.             uart_senddata(XMODEM_ACK);
  147.             uart_restorestate();
  148.             return XMODEM_ERR_OK;
  149.             
  150.             case XMODEM_CAN:
  151.             // Cancel transmit
  152.             tmpchar=uart_getdata();
  153.             if(tmpchar==XMODEM_CAN)
  154.             {
  155.                 uart_restorestate();
  156.                 return XMODEM_ERR_CANCEL;
  157.             }
  158.             
  159.             default:
  160.             // Invaild signal
  161.             uart_restorestate();
  162.             return XMODEM_ERR_RECEIVE;
  163.         }
  164.         
  165.         // Receive package
  166.         receivedpak.blknum=uart_getdata();
  167.         receivedpak.checkblknum=uart_getdata();
  168.         for(fc1=0;fc1<XMODEM_DATA_SIZE;fc1++)
  169.         {
  170.             tmpchar=uart_getdata();
  171.             receivedpak.data[fc1]=tmpchar;
  172.             tmpsum+=tmpchar;
  173.         }
  174.         receivedpak.checksum=uart_getdata();
  175.         
  176.         // Check blknum
  177.         if(receivedpak.blknum==(~receivedpak.checkblknum))
  178.         {
  179.             if(receivedpak.blknum==(packnum & 0xFF))
  180.             {
  181.                 // Check checksum
  182.                 if(tmpsum==receivedpak.checksum)  
  183.                 {
  184.                         // Package vaild
  185.                         packnum++;
  186.                         for(fc1=0;fc1<XMODEM_DATA_SIZE;fc1++)
  187.                         {
  188.                             *(buf++)=receivedpak.data[fc1];
  189.                         }
  190.                         *receivedsize+=XMODEM_DATA_SIZE;
  191.                         uart_senddata(XMODEM_ACK);
  192.                 }
  193.                 else
  194.                 {
  195.                     // Package checksum invaild, request for resend
  196.                     uart_senddata(XMODEM_NAK);
  197.                 }
  198.             }
  199.             else if(receivedpak.blknum==packnum-1)
  200.             {
  201.                 // Sender didn't received ACK, resend ACK
  202.                 uart_senddata(XMODEM_ACK);
  203.             }
  204.             else
  205.             {
  206.                 // Package blknum invaild, error occur. Try to resend
  207.                 uart_senddata(XMODEM_NAK);
  208.             }
  209.         }
  210.         else
  211.         {
  212.             // Package blknum check invaild, request for resend
  213.             uart_senddata(XMODEM_NAK);
  214.         }
  215.     }
  216. }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值