- 前段时间搞ARM实验平台的开发,需要经常实时调试程序。但是烧写一次Flash又太麻烦,后来想到一个最经典的解决方法,就是通过串口下载到内存实时运行调试。本来不想写太多,所以选择了最最古老但又最最有效的一个传输协议:X-Modem。X-Modem协议是 1977 年 Ward Christensen 所发明的。这个协议使用最简单的“等待/重传”算法,对于ARM这一类嵌入式系统来说,由于通常外围IP都有UART模块,所以不仅易于实现,而且还节省硬件资源。相关X-Modem协议详细资料可以在网上找到。
- 这里给出我前段时间写的X-Modem接收端程序核心。本程序是针对Samsung的s3c2410系列编写的,使用了2410的内部UART模块,以及UART的FIFO机制。值得注意的是,由于Xmodem接收包的时候并不能保证CPU处于100%在本进程,或者不能保证CPU能马上响应UART事件,所以并不能使用POLL方法进行UART的操作,必须要打开UART模块的FIFO机制,才能保证数据的准确而且不掉包。
- 本模块接口为:
- int xmodem_receive(unsigned char* buf, int timeoutcount, int* receivedsize)
- 返回值:具体值在 xmodem.h 里定义,是接收的最后状态。
- 输入参数:buf为接收缓冲区地址。timeoutcount为超时计数。
- 输出参数:receivedsize为总接收数据量,以byte为单位。
- xmodem.h:
- /*=============================================================================
- --------------------------------- Copy Left -----------------------------------
- Illidan Fly's Project
- Power by BigFly Network
- http://bigfly.happybobby.com
- Released under GPL2 License
- ----------------------------- File Description --------------------------------
- Filename: xmodem.h
- Date: 2007.01.12
- Version: 0.0.1
- Description:
- Xmodem protocol using polling and Uart FIFO.
- ----------------------------- Version History ---------------------------------
- 0.0.2: Size parameter added to xmodem_receive().
- 0.0.1: First release
- =============================================================================*/
- #ifndef __XMODEM_H__
- #define __XMODEM_H__
- #define XMODEM_DATA_SIZE 128
- #define XMODEM_SOH 0x01
- #define XMODEM_EOT 0x04
- #define XMODEM_ACK 0x06
- #define XMODEM_NAK 0x15
- #define XMODEM_CAN 0x18
- #define XMODEM_ERR_OK 0x00
- #define XMODEM_ERR_TIMEOUT 0x01
- #define XMODEM_ERR_CANCEL 0x02
- #define XMODEM_ERR_TRANSMIT 0x03
- #define XMODEM_ERR_RECEIVE 0x04
- int xmodem_receive(unsigned char* buf, int timeoutcount, int* receivedsize);
- #endif //__XMODEM_H__
- xmodem.c:
- /*=============================================================================
- --------------------------------- Copy Left -----------------------------------
- Illidan Fly's Project
- Power by BigFly Network
- http://bigfly.happybobby.com
- Released under GPL2 License
- ----------------------------- File Description --------------------------------
- Filename: xmodem.c
- Date: 2007.01.14
- Version: 0.0.2
- Description:
- Xmodem protocol using polling and Uart FIFO.
- ----------------------------- Version History ---------------------------------
- 0.0.2: First package issue fixed. Size parameter added to xmodem_receive().
- 0.0.1: First release
- =============================================================================*/
- #include "xmodem.h"
- #include "2410addr.h"
- #include "2410lib.h"
- #include "def.h"
- #define UART_NOT_EMPTY (rUFSTAT0 & 0x000F)
- // Save for UART state
- int save_rufcon;
- typedef struct _xmodem_package
- {
- unsigned char blknum;
- unsigned char checkblknum;
- unsigned char data[XMODEM_DATA_SIZE];
- unsigned char checksum;
- }xmodem_package;
- unsigned char uart_getdata(void)
- {
- // Wait for Rx FIFO not empty
- while(!UART_NOT_EMPTY){;}
- return RdURXH0();
- }
- void uart_senddata(unsigned char data)
- {
- // Wait for Tx FIFO not full
- while(rUFSTAT0 & 0x0200){;}
- WrUTXH0(data);
- }
- void uart_initstate(void)
- {
- Uart_TxEmpty(0);
- save_rufcon = rUFCON0;
- // Note: Xmodem must work in FIFO mode or will encounter data loss.
- // Set UART0 to FIFO mode
- rUFCON0 = 0x7;
- Delay(100);
- }
- void uart_restorestate(void)
- {
- rUFCON0 = save_rufcon;
- }
- int xmodem_receive(unsigned char* buf, int timeoutcount, int* receivedsize)
- {
- xmodem_package receivedpak;
- unsigned char tmpchar;
- unsigned char tmpsum;
- unsigned char packnum;
- int retrytime;
- int fc1;
- // Init UART state
- uart_initstate();
- // Xmodem first frame number = 0x01
- packnum=0x01;
- retrytime=0;
- *receivedsize=0;
- // Send NAK and wait for sender signal, resend NAK in 10 seconds
- do
- {
- if(retrytime++>timeoutcount)
- {
- uart_restorestate();
- return XMODEM_ERR_TIMEOUT;
- }
- uart_senddata(XMODEM_NAK);
- for(fc1=0;fc1<10000000;fc1++)
- {
- if(UART_NOT_EMPTY){break;}
- }
- }while(!UART_NOT_EMPTY);
- // Start receive
- while(1)
- {
- tmpsum=0;
- // Get control signal
- tmpchar=uart_getdata();
- switch(tmpchar)
- {
- case XMODEM_SOH:
- // New package
- break;
- case XMODEM_EOT:
- // End of transmit
- uart_senddata(XMODEM_ACK);
- uart_restorestate();
- return XMODEM_ERR_OK;
- case XMODEM_CAN:
- // Cancel transmit
- tmpchar=uart_getdata();
- if(tmpchar==XMODEM_CAN)
- {
- uart_restorestate();
- return XMODEM_ERR_CANCEL;
- }
- default:
- // Invaild signal
- uart_restorestate();
- return XMODEM_ERR_RECEIVE;
- }
- // Receive package
- receivedpak.blknum=uart_getdata();
- receivedpak.checkblknum=uart_getdata();
- for(fc1=0;fc1<XMODEM_DATA_SIZE;fc1++)
- {
- tmpchar=uart_getdata();
- receivedpak.data[fc1]=tmpchar;
- tmpsum+=tmpchar;
- }
- receivedpak.checksum=uart_getdata();
- // Check blknum
- if(receivedpak.blknum==(~receivedpak.checkblknum))
- {
- if(receivedpak.blknum==(packnum & 0xFF))
- {
- // Check checksum
- if(tmpsum==receivedpak.checksum)
- {
- // Package vaild
- packnum++;
- for(fc1=0;fc1<XMODEM_DATA_SIZE;fc1++)
- {
- *(buf++)=receivedpak.data[fc1];
- }
- *receivedsize+=XMODEM_DATA_SIZE;
- uart_senddata(XMODEM_ACK);
- }
- else
- {
- // Package checksum invaild, request for resend
- uart_senddata(XMODEM_NAK);
- }
- }
- else if(receivedpak.blknum==packnum-1)
- {
- // Sender didn't received ACK, resend ACK
- uart_senddata(XMODEM_ACK);
- }
- else
- {
- // Package blknum invaild, error occur. Try to resend
- uart_senddata(XMODEM_NAK);
- }
- }
- else
- {
- // Package blknum check invaild, request for resend
- uart_senddata(XMODEM_NAK);
- }
- }
- }
X-Modem 协议接收端的实现 For RVDS
最新推荐文章于 2022-10-09 20:23:55 发布