/* ========================================================================= */
/* The information contained herein is the exclusive property of */
/* Sunplus Technology Co. And shall not be distributed, reproduced, */
/* or disclosed in whole in part without prior written permission. */
/* (C) COPYRIGHT 2004 SUNPLUS TECHNOLOGY CO. */
/* ALL RIGHTS RESERVED */
/* The entire notice above must be reproduced on all authorized copies. */
/* ========================================================================= */
/* */
/* ========================================================================= */
/* Project Name : AN_SPMC75_0109 */
/* File Name : Xmodem.c */
/* Description : Xmodem����������� */
/* */
/* Processor : SPMC75F2413A */
/* Tools : u'nSP IDE tools v1.18.1A or later version */
/* ========================================================================= */
/* Revision */
/* ========================================================================= */
/* Version : 1.00 */
/* Date : 2005.9.2 */
/* Modified by : ����������ļ�ͷ�����µ�ͷ�ļ� */
/* Description : */
/* ========================================================================= */
#include "AN_SPMC75_0109.H"
/* ----------------------------------------------------------------------------------------
Xmodem transmit in 16-Bit CRC mode ,receiving buffer define:
+--------------------------------------------------------------------------------------+
| Byte0 | Byte1 | Byte2 | Byte 3--130 | Byte 131--132 |
+--------------------------------------------------------------------------------------+
| Start of header | Packet Number | ~(Packet Number) | Packet Data | CRC Hi | CRC Lo |
+--------------------------------------------------------------------------------------+ */
/* ----------------------------------------------------------------------------------------
Xmodem transmit in Check Sum mode ,receiving buffer define:
+-------------------------------------------------------------------------------------------+
| Byte0 | Byte1 | Byte2 | Byte 3--130 | Byte 131 | Byte 132 |
+-------------------------------------------------------------------------------------------+
| Start of header | Packet Number | ~(Packet Number) | Packet Data | CheckSum | NOP |
+-------------------------------------------------------------------------------------------+ */
UInt8 rxdbuf[133] = {0};
// --------------------------------------------------------------- //
TYPESTATUS xmodemstatus;
static UInt8 *rxdptr = rxdbuf;
static UInt16 XmodemTimeOut;
//===========================================================================
extern UInt16 Calc_CRC16(UInt8 *cptr, Int16 count);
extern UInt16 Calc_Cksum(UInt8 *cptr, Int16 count);
/*
//=============================================================
// ----Function: Calc_CRC16A();
// ------Syntax: UInt16 Calc_CRC16A(UInt8 *cptr, Int16 count)
// -Description: CRC 16 calculate
// -------Notes:
// --parameters: cptr: data Cursor count: data length
// -----returns: CRC16
//=============================================================
static UInt16 Calc_CRC16A(UInt8 *cptr, Int16 count)
{
UInt16 crc = 0,i;
while(--count >= 0)
{
crc = crc ^ (UInt16)(*cptr++) << 8;
for(i=0;i<8;i++)
{
if(crc & 0x8000) crc = crc << 1 ^ 0x1021;
else crc = crc << 1;
}
}
return(crc);
}*/
/*
//=============================================================
// ----Function: Calc_Cksum();
// ------Syntax: UInt16 Calc_Cksum(UInt8 *cptr, Int16 count);
// -Description: Check sum calculate
// -------Notes:
// --parameters: cptr: data Cursor count: data length
// -----returns: Checksum
//=============================================================
static UInt16 Calc_Cksum(UInt8 *cptr, Int16 count)
{
UInt16 sum = 0,i;
for(i=0;i<count;i++,cptr++) sum += *cptr;
return(sum&0xff);
}*/
//=============================================================
// ----Function: Spmc75_XmodemPurge();
// ------Syntax: void Spmc75_XmodemPurge(void);
// -Description: Purge
// -------Notes: Wait 1 second
// --parameters: none
// -----returns: none
//=============================================================
static void Spmc75_XmodemPurge(void)
{
UInt8 flush;
xmodemstatus.B._timeout = FALSE;
XmodemTimeOut = TIMEOUT_1S; // 1 second timeout
P_CMT_Start->B.ST0 = 1;
P_UART_Ctrl->W = CW_UART_RXEN|CW_UART_TXEN;
while(!xmodemstatus.B._timeout) // read uart until done
{
flush = P_UART_Data->W;
}
P_UART_Ctrl->W = CW_UART_RXIE|CW_UART_RXEN|CW_UART_TXEN;
P_CMT_Start->B.ST0 = 0; // disable timer/counter
}
//=============================================================
// ----Function: Spmc75_XmodemRecvwait();
// ------Syntax: void Spmc75_XmodemRecvwait(void);
// -Description: Recv wait buffer full or time out
// -------Notes:
// --parameters: none
// -----returns: none
//=============================================================
static void Spmc75_XmodemRecvwait(void)
{
xmodemstatus.B._timeout = FALSE; // set in timer counter 0 overflow interrupt routine
XmodemTimeOut = TIMEOUT_1S; // 1 second timeout
P_CMT_Start->B.ST0 = 1;
while(!xmodemstatus.B._bufmark && !xmodemstatus.B._timeout);
// turn off timer - no more time outs needed
P_CMT_Start->B.ST0 = 0; // disable timer/counter 1 clock
}
//=============================================================
// ----Function: Spmc75_XmodemRespond();
// ------Syntax: void Spmc75_XmodemRespond(UInt8 packet)
// -Description: Respond
// -------Notes:
// --parameters: packet: packet status
// -----returns: none
//=============================================================
static void Spmc75_XmodemRespond(UInt8 packet)
{
// clear buffer flag here ... when acking or nacking sender may respond
// very quickly.
xmodemstatus.B._bufmark = EMPTY;
xmodemstatus.B._recverr = FALSE; // framing and over run detection
if((packet == GOOD) || (packet == DUP) || (packet == END))
{
while(P_UART_Status->B.BY); // wait till transmit register is empty
P_UART_Data->W = ACK; // now for the next packet
}
else
{
while(P_UART_Status->B.BY); // wait till transmit register is empty
Spmc75_XmodemPurge(); // let transmitter empty its buffer
P_UART_Data->W = NAK; // tell sender error
}
}
//=============================================================
// ----Function: Spmc75_XmodemSendc();
// ------Syntax: void Spmc75_XmodemSendc(void);
// -Description: Send 'C'/NAK for request host transmitter
// -------Notes: 'C'->(wait 3s)->NAK->(wait 3s)->'C'->.....
// --parameters: none
// -----returns: none
//=============================================================
static void Spmc75_XmodemSendc(void)
{
XmodemTimeOut = TIMEOUT_3S; // 3 second timeout
xmodemstatus.B._bufmark = EMPTY;
xmodemstatus.B._recverr = FALSE; // checked in Spmc75_ValidatePacket for framing or overruns
// send character 'C'/NAK until we get a packet from the sender
while(!xmodemstatus.B._bufmark)
{
xmodemstatus.B._timeout = FALSE;
xmodemstatus.B._recvmod = 1; // tell sender CRC mode
while(P_UART_Status->B.BY); // wait till Data register is empty
P_UART_Data->W = CRCCHR; // signal transmitter that I'm ready in CRC mode ... 128 byte packets
P_CMT_Start->B.ST0 = 1; // Allow CMT0 timer start timing
// wait for timeout or recv buffer to fill
while(!xmodemstatus.B._timeout && !xmodemstatus.B._bufmark);
P_CMT_Start->B.ST0 = 0; // disable timer/counter 1 clock
if(xmodemstatus.B._timeout) // start wait loop again
{
xmodemstatus.B._timeout = FALSE;
xmodemstatus.B._recvmod = 0;// tell sender Checksum mode
while(P_UART_Status->B.BY); // wait till Data register is empty
P_UART_Data->W = NAK; // signal transmitter that I'm ready in Checksum mode ... 128 byte packets
P_CMT_Start->B.ST0 = 1; // Allow CMT0 timer start timing
while(!xmodemstatus.B._timeout && !xmodemstatus.B._bufmark);
P_CMT_Start->B.ST0 = 0; // disable timer/counter clock
}
}
}
//=============================================================
// ----Function: Spmc75_ValidatePacket();
// ------Syntax: UInt8 Spmc75_ValidatePacket(UInt8 *bufptr);
// -Description: Validate Packet status.
// -------Notes: Validate Packet is OK will apply 'break' Interrupt
// --parameters: bufptr: should Validate Packet data Cursor
// -----returns: result
//=============================================================
static UInt8 Spmc75_ValidatePacket(UInt8 *bufptr)
{
UInt8 packet = BAD;
if(!xmodemstatus.B._timeout)
{
if(!xmodemstatus.B._recverr)
{
if(bufptr[0] == SOH)
{ // valid start
if(bufptr[1] == xmodemstatus.B._number+1)
{ // sequential block number ?
if((bufptr[1] + bufptr[2]) == 0xff)
{ // block number and block number checksum are ok
// compute CRC and validate it
if(xmodemstatus.B._recvmod)
{
if(Calc_CRC16(&bufptr[3],128) == ((bufptr[131]<<8) | bufptr[132]))
{
xmodemstatus.B._number = bufptr[1]; // good packet ... ok to increment
if(xmodemstatus.B._number == 0xFF) xmodemstatus.B._number = 0;
packet = GOOD;
BREAK();
}
}
else if(Calc_Cksum(&bufptr[3],128) == bufptr[131])
{
xmodemstatus.B._number = bufptr[1]; // good packet ... ok to increment
if(xmodemstatus.B._number == 0xFF) xmodemstatus.B._number = 0;
packet = GOOD;
BREAK();
}
} // block number checksum
} // bad block number or same block number
else if(bufptr[1] == xmodemstatus.B._number)
{ // same block number ... ack got glitched
packet = DUP; // packet is previous packet don't inc packet number
}
} // check for the end
else if(bufptr[0] == EOT)
{
packet = END;
xmodemstatus.B._recvrdy = 1;
}
}
else packet = ERR;
}
else packet = OUT;
return(packet);
}
//=============================================================
// ----Function: Xmodem_Rxd_ISR();
// ------Syntax: void Xmodem_Rxd_ISR(void);
// -Description: Xmodem receive interrupt service.
// -------Notes: Used in UART Rxd ISR.
// --parameters: none
// -----returns: none
//=============================================================
void Xmodem_Rxd_ISR(void)
{
UInt8 *localptr = rxdptr;
*localptr++ = P_UART_Data->W; // get char
// Framing or over run error check for errors
if(P_UART_RXStatus->W & (CW_UART_Clear_FE|CW_UART_Clear_PE|CW_UART_Clear_OE))
{
xmodemstatus.B._recverr = TRUE;
P_UART_RXStatus->W = CW_UART_Clear_FE|CW_UART_Clear_PE|CW_UART_Clear_OE;
} // read status register after reading data register
switch(rxdbuf[0]) // determine if buffer full
{
case(SOH):
if(xmodemstatus.B._recvmod) // receive CRC16 mode
{
if(localptr > &rxdbuf[132])
{
xmodemstatus.B._bufmark = FULL;
localptr = &rxdbuf[0];
}
}
else // receive Checksum mode
{
if(localptr > &rxdbuf[131])
{
xmodemstatus.B._bufmark = FULL;
localptr = &rxdbuf[0];
}
}
break;
default:
xmodemstatus.B._bufmark = FULL; // first char unknown
localptr = &rxdbuf[0];
break;
}
rxdptr = localptr; // restore global pointer
}
//=============================================================
// ----Function: Spmc75_XmodemReceive();
// ------Syntax: void Spmc75_XmodemReceive(void);
// -Description: Receive data from PC in Xmodem Protocol
// -------Notes: First send 'C'/NAK, then receive data and responsion
// --parameters: none
// -----returns: none
//=============================================================
void Spmc75_XmodemReceive(void)
{
UInt8 packet; // status flag
rxdptr = rxdbuf; // point to recv buffer
Spmc75_XmodemSendc(); // send a 'c' until the buffer gets full
packet = Spmc75_ValidatePacket(rxdbuf); // validate packet 1
rxdptr = rxdbuf; // re-initialize buffer pointer before acknowledging
Spmc75_XmodemRespond(packet); // ack or nak
while(packet != GOOD) // if we nak'ed above wait for packet 1 again
{
Spmc75_XmodemRecvwait();
packet = Spmc75_ValidatePacket(rxdbuf); // validate packet 1
rxdptr = rxdbuf; // re-initialize buffer pointer before acknowledging
Spmc75_XmodemRespond(packet); // ack or nak
}
while(packet != END) // get remainder of file
{
Spmc75_XmodemRecvwait(); // wait for error or buffer full
packet = Spmc75_ValidatePacket(rxdbuf); // validate the packet
rxdptr = rxdbuf; // re-initialize buffer pointer before acknowledging
Spmc75_XmodemRespond(packet); // ack or nak
}// end of file transmission
}
//=============================================================
// ----Function: Spmc75_XmodemInitial();
// ------Syntax: void Spmc75_XmodemInitial(void);
// -Description: Initialization
// -------Notes: Initial UART and CMT0, CMT0->8Hz
// --parameters: none
// -----returns: none
//=============================================================
void Spmc75_XmodemInitial(void)
{
Spmc75_UART_Init();
Spmc75_CMT0_Init();
xmodemstatus.W = 0;
}
//=============================================================
// ----Function: Spmc75_TimeOut_ISR();
// ------Syntax: void Spmc75_TimeOut_ISR(void);
// -Description: Time out service.
// -------Notes: Used in CMT0 ISR.
// --parameters: none.
// -----returns: none.
//=============================================================
void Spmc75_TimeOut_ISR(void)
{
static UInt16 clock = 0;
if(++clock > XmodemTimeOut)
{
clock = 0;
xmodemstatus.B._timeout = TRUE;
}
}
//=============================================================
// *END*
//=============================================================
|