📄 xmodem.c
字号:
//=====================
//file name: xmodem.c
//Discription: provide some xmodem-relative method used by the monitor program
//Author: Decell.Zhou
//Version:
// 0.1|071107
// 0.2|071108
//=====================
#include "xmodem.h"
//define a array to store the data package
unsigned char dataBuffer[135];
//define a variable to store the the port number we are using to transmit the data
static unsigned char portNum;
//the pointer point to the physical start address of a new block
static unsigned char *pDestinationHead;
//the pointer point to the physical stop address of a new block
static unsigned char *pDestinationTail;
//==============[portSelect]================
//Discription:the method is used to select a uart port for transmission
//Author:Decell.Zhou
//Version:
//pram:argPortNum|char|the uart port number
//return:none
//==========================================
void portSelect(char argPortNum){
if(argPortNum == 0 || argPortNum == 1){//we only allow to used port 0 and port 1
portNum = argPortNum;
}
}
//==============[xmodemGetByte]=====
//Discription: get a Byte from the serial port, it's different from the 2410lib.c's Uart_Getch() because it
//turn on the RxD FIFO for xmodem transmission
//Author: Decell.Zhou
//Version:
//pram: none
//return:the content of the serial receive buffer|unsigned char
//==================================
unsigned char xmodemGetByte(void){
switch(portNum){
case 0:{
while((rUFSTAT0 & (0xF)) == 0);//wait while the Rx FIFO have no data
return RdURXH0();
break;
}
case 1:{
while((rUFSTAT1 & (0xF)) == 0);//wait while the Rx FIFO have no data
return RdURXH1();
break;
}
default:{
break;
}
}
}
//==============[xmodemGetKey]=====
//Discription: get a Byte from the serial port, it's different from the 2410lib.c's Uart_GetKey() because it
//turn on the RxD FIFO for xmodem transmission
//Author: Decell.Zhou
//Version:
//pram: none
//return: 0|when the receive FIFO is null
// context of the receive buffer|unsigned char
//==================================
unsigned char xmodemGetKey(void){
switch(portNum){
case 0:{
if((rUFSTAT0 & (0xF)) == 0){//if the Rx FIFO have no data
return 0;
}else{
return RdURXH0();
}
break;
}
case 1:{
if((rUFSTAT1 & (0xF)) == 0){//if the Rx FIFO have no data
return 0;
}else{
return RdURXH1();
}
break;
}
default:{
break;
}
}
}
//==============[xmodemSendByte]=====
//Discription: Send a Byte to the serial port, it's different from the 2410lib.c's Uart_Getch() because it
//turn on the TxD FIFO for xmodem transmission
//Author: Decell.Zhou
//Version:
//pram: data|unsigned char|the data you want to transmit
//return:none
//==================================
void xmodemSendByte(unsigned char data){
int i;
switch(portNum){
case 0:{
while((rUFSTAT0 & (0x1<<9)) == 1);//wait while the Tx FIFO have not been full
for(i = 0;i <= 1000;i++);
WrUTXH0(data);
break;
}
case 1:{
while((rUFSTAT1 & (0x1<<9)) == 1);//wait while the Tx FIFO have not been full
for(i = 0;i <= 1000;i++);
WrUTXH1(data);
break;
}
default:{
break;
}
}
}
//==============[xmodemFIFOReset]==========
//Discription:Reset the uartFIFO
//Author:Decell.Zhou
//Version:
//pram:none
//return:
//=========================================
void xmodemFIFOReset(void ){}
//==============[xmodemLEDON]=============
//Discription:turn on the LED,that is GPF7 and GPF4
//Author:Decell.Zhou
//Version:
//pram:none
//return: none
//=========================================
void xmodemLEDON(void){
rGPFCON |= ((0x1 << 14)|(0x1 <<8));//set GPF7 and GPF4 as output
rGPFDAT &= ~((0x1 << 7)|(0x1 << 4));//set the out put the low, turn on the LED
}
//==============[xmodemLEDOFF]=============
//Discription:turn off the LED
//Author:Decell.Zhou
//Version:
//pram:none
//return:none
//=========================================
void xmodemLEDOFF(void){
rGPFDAT |= ((0x1 << 7)|(0x1 << 4));//set the out put the high, turn off the LED
rGPFCON &= ~((0x2 << 14) | (0x2 << 8));//set GPF7 and GPF4 as input
}
//==============[xmodemInit]========
//Discription: make preparation for the xmodem transmit
//Author:Decell.Zhou
//Version:
//pram:destination|unsigned int|the destination address to store the data
//return:none
//==================================
void xmodemInit(unsigned int destination){
int i;
pDestinationHead = (unsigned char *)destination;//set the destination head pointer to the target RAM address
pDestinationTail = (unsigned char *)destination;//set the destination tail pointer to the target RAM address
for(i = 0;i < 135;i++){//clear the data buffer
dataBuffer[i] = 0;
}
Uart_FIFOON();//turn on the FIFO for the UART
portSelect(0);//select port0 as our transmit port
}
//=============[xmodemTransmit]=====
//Discription: transmit data to a sepcified address under the xmodem protocal
// this method will store the data to the address PROGRAM_RO_BASE
//Author:Decell.Zhou
//Version:
//pram:destination|unsigned int|the destination address to store the data
//return:
// 0|char|transmit successful
// 1|char|transmit fault
//==================================
char xmodemTransmit(unsigned int destination){
char receiveReady ;//this variable indicate the
unsigned char nextBlockNum;//this variable indicate the number of the block me are going to receive
unsigned char curBlockNum;//this variable indicate the number of the block me received in the last time
unsigned char checkSum;//the checksum for each block
unsigned char byteCount;
unsigned int i;
unsigned char nakCount;//store how many times that the receiver has been send
unsigned char transResp;//the respond from the transmitter
//the varivable indicatting the receiver's state
unsigned char receiverStat; //1: send ACK
//2: send NAK
//3: send CAN
//4: reserve
//5: reserve
//6: reserve
//7: reserve
//8: reserve
xmodemInit(destination);//make preparation for xmodem transmition
receiveReady = 1;//now we are ready to receive the data
curBlockNum = 0;//initial blockNum
nextBlockNum = 1;//initial blockNum
receiverStat = 0;
transResp = 0;
//waiting for the SOHsignal
xmodemSendByte(NAK);//send NAK signal, waiting for the sender's SOH signal
setTimer(2);//set ten second to expire
for(;xmodemGetKey() != SOH ;){//if we don't get the SOH signal
if(timerExpire() == 1){//if the receiver has been time out,send another NAK
xmodemSendByte(NAK);
setTimer(2);
}
}
//receive the data block
for(;receiveReady == 1;){
xmodemLEDOFF();
//receive 131 bytes in total
setTimer(1);//set time to count down 1 second
for(byteCount = 0;(byteCount < 131) && (!timerExpire());){//received 131byte
dataBuffer[byteCount] = xmodemGetByte(); //include 2 numbyte, 128 data byte,
setTimer(1); //1 chechsum byte
byteCount ++;
}
//========================================
/*
//for package debuging
for(i = 0;i<=1000;i++){
xmodemSendByte(ACK);
}
for(i = 0; i < 135;i++){
Uart_Printf("%x ",dataBuffer[i]);
}
for(;;);
*/
//========================================
//analyizing the data block
if(dataBuffer[0] == (~dataBuffer[1] & 0xff)){//the blockNum is avaiable //if(dataBuffer[0] == (~dataBuffer[1] & 0xff))
if(dataBuffer[0] == nextBlockNum){//if the blockNum is correct
if(byteCount == 131){//the count of the byte is correct
for(i = 2,checkSum = 0;i <= 129;i++){//calculate the ckecksum
checkSum += dataBuffer[i];
}
if(checkSum == dataBuffer[130]){//the ckeckSum is correct
receiverStat = 1;//every goes right, send ACK
//copy the data to ram
for(i = 2;i <= 129;i++){
*pDestinationTail = dataBuffer[i];
pDestinationTail ++;
}
pDestinationHead = pDestinationTail;
curBlockNum = nextBlockNum;//increase the block number
nextBlockNum ++;
}else{
receiverStat = 2;//the ckeck Sum isn't correct, send NAK
}
}else{
receiverStat = 2;//the count of the byte isn't have correct length, send NAK signal
}
}else if (dataBuffer[0] == curBlockNum){
receiverStat = 1;//data block repeated, resend ACK again
}else{
receiverStat = 3;//fatal eorro occur,send CAN return and request resend
}
}else{
receiverStat = 2;//the blockNum is not avaiable,send NAK signal
}
xmodemLEDON();
//receiver makes action according to the receiver status
if(receiverStat == 1){//send ACK
xmodemSendByte(ACK);
nakCount = 0;//clear nak counter
//wating for the next time transmission
setTimer(2);//set timer for 10sec time out
transResp = xmodemGetKey();
for(;transResp != SOH && transResp != EOT && transResp != CAN ;){//if we don't get the SOH signal
if(timerExpire() == 1){//if the receiver has been time out,send NAK
xmodemSendByte(NAK);
nakCount++;
setTimer(2);
}
if(nakCount == 10){//fatal error, we may be losting the host,return,request for resend
xmodemSendByte(CAN);//send CAN for three times
xmodemSendByte(CAN);
xmodemSendByte(CAN);
return 1;
}
transResp = xmodemGetKey();//get responding from the host
}
if(transResp == SOH){
receiveReady = 1;
nakCount = 0;
}else if(transResp == EOT){//transmission complete!
xmodemSendByte(ACK);
//xmodemSendByte(ACK);
return 0;
}else{//get CAN singnal
return 1;//transmission cancel;
//=============================
//cleaning code add here
//=============================
}
}else if(receiverStat == 2){//send NAK
xmodemSendByte(NAK);
nakCount = 0;//clear nak counter
//wating for the next time transmission
setTimer(2);//set timer for 10sec time out
transResp = xmodemGetKey();
for(;transResp != SOH && transResp != EOT && transResp != CAN ;){//if we don't get the SOH signal
if(timerExpire() == 1){//if the receiver has been time out,send NAK
xmodemSendByte(NAK);
nakCount++;
setTimer(2);
}
if(nakCount == 10){//fatal error, we may be losting the host,return,request for resend
xmodemSendByte(CAN);//send CAN for three times
xmodemSendByte(CAN);
xmodemSendByte(CAN);
return 1;
}
transResp = xmodemGetKey();//get responding from the host
}
if(transResp == SOH){
receiveReady = 1;
nakCount = 0;
}else if(transResp == EOT){//transmission complete!
xmodemSendByte(ACK);
//xmodemSendByte(ACK);
return 0;
}else{//get CAN singnal
return 1;//transmission cancel;
//=============================
//cleaning code add here
//=============================
}
}else if(receiverStat == 3){//send CAN
xmodemSendByte(CAN);//send CAN for three times
xmodemSendByte(CAN);
xmodemSendByte(CAN);
return 1;
}else{
//reserve for futher improvment
}
}
}
//=============[xmodemJump]=========
//Discription: jump to the PROGRAM_RO_BASE,exeute the user prgram
//Author:Decell.Zhou
//Version:
//pram:none
//return:none
//==================================
void xmodemJump(void){
void (*pProgramEntrance)(void);
pProgramEntrance = (void (*)(void))PROGRAM_RO_BASE;//set up the entance
pProgramEntrance();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -