- /* ========================================================================= */
- /* 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*
- //=============================================================
|