⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 obj_svcxmodem.c

📁 at91rm9200的一级bootloader
💻 C
字号:
//*----------------------------------------------------------------------------

//*      ATMEL Microcontroller Software Support  -  ROUSSET  -

//*----------------------------------------------------------------------------

//* The software is delivered "AS IS" without warranty or condition of any

//* kind, either express, implied or statutory. This includes without

//* limitation any warranty or condition with respect to merchantability or

//* fitness for any particular purpose, or against the infringements of

//* intellectual property rights of others.

//*----------------------------------------------------------------------------

//* File Name           : obj_svcxmodem.c

//* Object              : Send and receive funtions for USB device peripheral

//*

//* 1.0 20/06/01 	    : ODi Creation

//*----------------------------------------------------------------------------

#include "services/obj_buffer.h"

#include "services/obj_svcxmodem.h"

#include "periph/usart2/lib_usart2.h"



#define CRC16POLY   0x1021              /* CRC 16  polynom */



//*----------------------------------------------------------------------------

//* Function Name       : XmCheckHeader

//* Object              : Compute the CRC

//* Input Parameters    : <ptr>  char pointer

//*                       <count> nb of char

//* Output Parameters   : crc value

//*----------------------------------------------------------------------------

char AT91F_SvcXmodemCheckHeader(unsigned char currentPacket, char *packet)

{



	// Check that bloc number and bloc checksum are OK

	if ( (packet[0] + packet[1]) != 0xff )

		return 0;



	// Check that this is a sequential block number

	if ( packet[0] != currentPacket )

		return 0;



	return 1;

}



//*----------------------------------------------------------------------------

//* Function Name       : AT91F_SvcXmodemCheckCrc

//* Object              : Compute the CRC

//* Input Parameters    : <ptr>  char pointer

//*                       <count> nb of char

//* Output Parameters   : crc value

//*----------------------------------------------------------------------------

unsigned short AT91F_SvcXmodemGetCrc(char *ptr, unsigned int count)

{



    unsigned short crc, cmpt;



    crc = 0;

    //* For  all char

    while (count--)

    {



        crc = crc ^ (int) *ptr++ << 8;

        //* For All bit

        for (cmpt = 0; cmpt < 8; cmpt++)

        {

            if (crc & 0x8000)

                crc = crc << 1 ^ CRC16POLY;

            else

                crc = crc << 1;

        }//* end bit

    }//* Frame end



    return (crc & 0xFFFF);

}







//*----------------------------------------------------------------------------

//* Function Name       : AT91F_SvcXmodemCheckData

//* Object              : check the data frame, increment the address if OK

//* Input Parameters    : pointer to XmData

//* Output Parameters   : 1 OK, 0 not OK

//*----------------------------------------------------------------------------

char AT91F_SvcXmodemCheckData(AT91PS_SvcXmodem pSvcXmodem)

{

	unsigned short crc;

	char         *pData   = pSvcXmodem->pData;

	unsigned int dataSize = pSvcXmodem->dataSize;



	crc = pSvcXmodem->GetCrc(pData, dataSize);



	if ( (pData[dataSize]   == (unsigned char)(crc >> 8)) &&

	     (pData[dataSize+1] == (unsigned char)(crc)) )

	{

		pSvcXmodem->pData += dataSize;

		return 1;

	}

	else

		return 0;

}





//*----------------------------------------------------------------------------

//* Function Name       : OpenUdpService()

//* Object              :

//* Input Parameters    :

//* Output Parameters   : none

//*----------------------------------------------------------------------------

AT91PS_SvcComm AT91F_OpenSvcXmodem(

	AT91PS_SvcXmodem pSvcXmodem,

	AT91PS_USART2    pUsart,

	AT91PS_CtlTempo  pCtlTempo)

{

	AT91PS_SvcComm pSvcComm = &(pSvcXmodem->parent);



	// Init AT91S_CommSvc base structure



	// Init AT91PS_SvcComm methods

	pSvcComm->Reset        = (AT91PF_SvcCommReset)   0;

	pSvcComm->StartTx      = AT91F_SvcXmodemStartTx;

	pSvcComm->StartRx      = AT91F_SvcXmodemStartRx;

	pSvcComm->StopTx       = AT91F_SvcXmodemStopTx;

	pSvcComm->StopRx       = AT91F_SvcXmodemStopRx;

	pSvcComm->TxReady      = AT91F_SvcXmodemTxReady;

	pSvcComm->RxReady      = AT91F_SvcXmodemRxReady;



	// Init AT91PS_SvcComm data

	pSvcComm->pChild       = (void *) pSvcXmodem;

	pSvcComm->pBuffer      = (AT91PS_Buffer) 0;



	// Init AT91PS_SvcXmodem methods

	pSvcXmodem->ReadHandler  = AT91F_SvcXmodemReadHandler;

	pSvcXmodem->WriteHandler = AT91F_SvcXmodemWriteHandler;

	pSvcXmodem->GetCrc       = AT91F_SvcXmodemGetCrc;

	pSvcXmodem->CheckHeader  = AT91F_SvcXmodemCheckHeader;

	pSvcXmodem->CheckData    = AT91F_SvcXmodemCheckData;



	// Init AT91PS_SvcXmodem data

	pSvcXmodem->pUsart = pUsart;



	// Attach the tempo to a tempo controler

	pCtlTempo->CtlTempoCreate(pCtlTempo, &(pSvcXmodem->tempo));



	return pSvcComm;

}



//*----------------------------------------------------------------------------

//* Function Name       : AT91F_SvcXmodemRead()

//* Object              : Receive an XMODEM file with the USART, update the

//*                       linked buffer structure

//* Input Parameters    : AT91PS_SvcXmodem, AT91PS_USART2->US_CSR

//* Output Parameters   : none

//*----------------------------------------------------------------------------

AT91S_SvcCommStatus AT91F_SvcXmodemReadHandler(AT91PS_SvcXmodem pSvcXmodem, unsigned int csr)

{

	AT91PS_USART2      pUsart  = pSvcXmodem->pUsart;

	AT91PS_Buffer      pBuffer = (AT91PS_Buffer) pSvcXmodem->parent.pBuffer;



	char *pData;

	unsigned int bufSize;

	char c;



	if ( (csr & US_RXRDY) ) {

		// Stop sending 'C'

		pSvcXmodem->tempo.Stop(&(pSvcXmodem->tempo));

		pSvcXmodem->isPacketDesc = 1;

		pBuffer->GetRdBuffer(pBuffer, &pData, &bufSize);

		pSvcXmodem->pData    = pData;



		c = at91_usart2_getChar(pUsart);

		switch (c) {

			case AT91C_XMODEM_STX:

				pSvcXmodem->dataSize = AT91C_XMODEM_DATA_SIZE_STX;

				at91_usart2_receive_frame (

					pUsart,

					pSvcXmodem->packetDesc, AT91C_XMODEM_PACKET_SIZE,

					pData, AT91C_XMODEM_DATA_SIZE_STX + AT91C_XMODEM_CRC_SIZE);

				break;

			case AT91C_XMODEM_SOH:

				pSvcXmodem->dataSize = AT91C_XMODEM_DATA_SIZE_SOH;

				at91_usart2_receive_frame (

					pUsart,

					pSvcXmodem->packetDesc, AT91C_XMODEM_PACKET_SIZE,

					pData, AT91C_XMODEM_DATA_SIZE_SOH + AT91C_XMODEM_CRC_SIZE);

				break;

			case AT91C_XMODEM_EOT:

				at91_usart2_sendChar(pUsart, AT91C_XMODEM_ACK);

				at91_usart2_usidr(pUsart, US_RXRDY | US_ENDRX | US_RXBUFF);								

				if ( (pSvcXmodem->packetId == 1) || bufSize)

					pBuffer->FillRdBuffer(pBuffer, bufSize);

				pSvcXmodem->eot = 1;

				return AT91C_COMMSVC_SUCCESS;

			default:

				at91_usart2_receive_frame (

					pUsart,

					pData, AT91C_XMODEM_PACKET_SIZE + AT91C_XMODEM_DATA_SIZE_SOH + AT91C_XMODEM_CRC_SIZE,

					0, 0);

				at91_usart2_sendChar(pUsart, AT91C_XMODEM_ACK);

				break;

		}



		at91_usart2_usidr(pUsart, US_RXRDY);

		at91_usart2_usier(pUsart, US_ENDRX);

	}



	else if ( (csr & US_ENDRX) || (csr & US_RXBUFF) ) {

		if (pSvcXmodem->isPacketDesc) {

			pSvcXmodem->packetStatus = pSvcXmodem->CheckHeader(pSvcXmodem->packetId, pSvcXmodem->packetDesc);

			pSvcXmodem->isPacketDesc = 0;

			at91_usart2_usidr(pUsart, US_ENDRX);

			at91_usart2_usier(pUsart, US_RXBUFF);



		}

		else {

			if (pSvcXmodem->packetStatus && pSvcXmodem->CheckData(pSvcXmodem)) {

				pBuffer->FillRdBuffer(pBuffer, pSvcXmodem->dataSize);

				at91_usart2_sendChar(pUsart, AT91C_XMODEM_ACK);

				++(pSvcXmodem->packetId);

			}

			else

				at91_usart2_sendChar(pUsart, AT91C_XMODEM_NAK);



			at91_usart2_usidr(pUsart, US_ENDRX | US_RXBUFF);

			at91_usart2_usier(pUsart, US_RXRDY);

		}

	}

	return AT91C_COMMSVC_SUCCESS;

}



//*----------------------------------------------------------------------------

//* Function Name       : AT91F_SvcXmodemWrite()

//* Object              : Receive an XMODEM file with the USART, update the

//*                       linked buffer structure

//* Input Parameters    : AT91PS_SvcXmodem, AT91PS_USART2->US_CSR

//* Output Parameters   : none

//*----------------------------------------------------------------------------

AT91S_SvcCommStatus AT91F_SvcXmodemWriteHandler(AT91PS_SvcXmodem pSvcXmodem, unsigned int csr)

{

	AT91PS_USART2      pUsart  = pSvcXmodem->pUsart;

	AT91PS_Buffer      pBuffer = (AT91PS_Buffer) pSvcXmodem->parent.pBuffer;



	char const *pData;

	unsigned int bufSize;

	unsigned short crc;



	if ( (csr & US_RXRDY) ) {

		pBuffer->GetWrBuffer(pBuffer, &pData, &bufSize);

		switch ( at91_usart2_getChar(pUsart) ) {

		case 'C':

			pSvcXmodem->packetId = 1; // Current packet

			if (bufSize == 0)

				pBuffer->EmptyWrBuffer(pBuffer, 0);

			break;

		case AT91C_XMODEM_ACK:

			// Previous block has been received correctly

			if ( !(pSvcXmodem->eot) ) {

				pBuffer->EmptyWrBuffer(pBuffer, AT91C_XMODEM_DATA_SIZE_SOH);

				bufSize = 0;

			}

			++(pSvcXmodem->packetId);

			break;

		case AT91C_XMODEM_NAK:

			// Previous block must be resent

			break;

		default:

			break;

		}

		if (bufSize == 0) {

			at91_usart2_usidr(pUsart, US_ENDRX | US_ENDTX | US_TXRDY);

			at91_usart2_sendChar(pUsart, AT91C_XMODEM_EOT);

			pSvcXmodem->eot = 1;

		}

		else {

			pSvcXmodem->pData = (char *) pData;

			pSvcXmodem->eot           = 0;



			at91_usart2_sendChar(pUsart, AT91C_XMODEM_SOH);

			at91_usart2_usier(pUsart, US_TXRDY);

		}

	}

	else if ( (csr & US_TXRDY) ) {

		pSvcXmodem->packetDesc[0] = pSvcXmodem->packetId;

		pSvcXmodem->packetDesc[1] = ~(pSvcXmodem->packetId);

		at91_usart2_send_frame (

			pUsart,

			pSvcXmodem->packetDesc, AT91C_XMODEM_PACKET_SIZE,

			pSvcXmodem->pData,      AT91C_XMODEM_DATA_SIZE_SOH);

		at91_usart2_usidr(pUsart, US_TXRDY);

		at91_usart2_usier(pUsart, US_ENDTX);

	}

	else if ( (csr & US_ENDTX) ) {

		crc = pSvcXmodem->GetCrc(pSvcXmodem->pData, AT91C_XMODEM_DATA_SIZE_SOH);

		crc = ((crc & 0xff00) >> 8) | ((crc & 0x00ff) << 8 );

		at91_usart2_send_frame (

			pUsart,

			(char *) &crc, AT91C_XMODEM_CRC_SIZE,

			(char *) 0,0);

		at91_usart2_usidr(pUsart, US_ENDTX);

	}

	return AT91C_COMMSVC_SUCCESS;

}



//*----------------------------------------------------------------------------

//* Function Name       : AT91F_SvcUdpStartTx()

//* Object              :

//* Input Parameters    : AT91PS_SvcComm

//* Output Parameters   : none

//*----------------------------------------------------------------------------

AT91S_SvcCommStatus AT91F_SvcXmodemStartTx(AT91PS_SvcComm pSvcComm)

{

	AT91PS_SvcXmodem   pSvcXmodem = (AT91PS_SvcXmodem) pSvcComm->pChild;

	AT91PS_USART2      pUsart     = pSvcXmodem->pUsart;



	pSvcXmodem->Handler = pSvcXmodem->WriteHandler;

	at91_usart2_usier(pUsart, US_RXRDY);



	return AT91C_COMMSVC_SUCCESS;

}



//*----------------------------------------------------------------------------

//* Function Name       : AT91F_SvcUdpStoptTx()

//* Object              :

//* Input Parameters    : AT91PS_SvcComm

//* Output Parameters   : none

//*----------------------------------------------------------------------------

AT91S_SvcCommStatus AT91F_SvcXmodemStopTx(AT91PS_SvcComm pSvcComm)

{



	return AT91C_COMMSVC_SUCCESS;

}



//*----------------------------------------------------------------------------

//* Function Name       : AT91F_SvcXmodemSendC()

//* Object              :

//* Input Parameters    : AT91PS_SvcComm

//* Output Parameters   : none

//*----------------------------------------------------------------------------

void AT91F_SvcXmodemSendC(AT91S_TempoStatus status, void *pVoid)

{

		AT91PS_USART2 pUsart = (AT91PS_USART2) pVoid;



		at91_usart2_sendChar(pUsart, 'C');

}



//*----------------------------------------------------------------------------

//* Function Name       : AT91F_SvcXmodemStartRx()

//* Object              :

//* Input Parameters    : AT91PS_SvcComm

//* Output Parameters   : none

//*----------------------------------------------------------------------------

AT91S_SvcCommStatus AT91F_SvcXmodemStartRx(AT91PS_SvcComm pSvcComm)

{

	AT91PS_SvcXmodem   pSvcXmodem = (AT91PS_SvcXmodem) pSvcComm->pChild;

	AT91PS_USART2      pUsart     = pSvcXmodem->pUsart;



	pSvcXmodem->Handler = pSvcXmodem->ReadHandler;

	pSvcXmodem->packetId     = 1; // Current packet

	pSvcXmodem->eot          = 0; // end of transmition

	pSvcXmodem->isPacketDesc = 0;

	at91_usart2_usier(pUsart, US_RXRDY);

	at91_usart2_usidr(pUsart, US_ENDRX | US_ENDTX | US_TXRDY);

	

	pSvcXmodem->tempo.Start(&(pSvcXmodem->tempo), 1000, 1000, AT91F_SvcXmodemSendC, pUsart);

//	pSvcXmodem->tempo.Start(&(pSvcXmodem->tempo), 5, 5, AT91F_SvcXmodemSendC, pUsart);



	return AT91C_COMMSVC_SUCCESS;

}



//*----------------------------------------------------------------------------

//* Function Name       : AT91F_SvcUdpStoptRx()

//* Object              :

//* Input Parameters    : AT91PS_SvcComm

//* Output Parameters   : none

//*----------------------------------------------------------------------------

AT91S_SvcCommStatus AT91F_SvcXmodemStopRx(AT91PS_SvcComm pSvcComm)

{



	return AT91C_COMMSVC_SUCCESS;

}



//*----------------------------------------------------------------------------

//* Function Name       : AT91F_UdpTxReady()

//* Object              : Return the status of the USB

//* Input Parameters    :

//* Output Parameters   : none

//*----------------------------------------------------------------------------

char AT91F_SvcXmodemTxReady(AT91PS_SvcComm pSvcComm)

{

	AT91PS_SvcXmodem   pSvcXmodem = (AT91PS_SvcXmodem) pSvcComm->pChild;

	AT91PS_USART2      pUsart     = pSvcXmodem->pUsart;



	return (AT91F_US_CSR(pUsart) & US_TXRDY);



}



//*----------------------------------------------------------------------------

//* Function Name       : AT91F_UdpRxReady()

//* Object              : Return the status of the USB

//* Input Parameters    :

//* Output Parameters   : none

//*----------------------------------------------------------------------------

char AT91F_SvcXmodemRxReady(AT91PS_SvcComm pSvcComm)

{

	AT91PS_SvcXmodem   pSvcXmodem = (AT91PS_SvcXmodem) pSvcComm->pChild;

	AT91PS_USART2      pUsart     = pSvcXmodem->pUsart;



	return (AT91F_US_CSR(pUsart) & US_RXRDY);



}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -