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

📄 ser270.c

📁 dm270 source code
💻 C
字号:
/*
    DM270 ARM Evaluation Software

    (c)Texas Instruments 2003
*/

/**
	\file ser270.c
	\brief Serial Interface Related APIs
*/
#include <ser270.h>
#include <clkc270.h>
#include <intc270.h>

#define SER_BIT_RATE( ARM_CLK, bitrate )	( (ARM_CLK)/((bitrate)*2) - 1)

static STATUS SER0_sendData( char *dataAddress, Uint32 dataSize );
static STATUS SER1_sendData( char *dataAddress, Uint32 dataSize );
static STATUS SER0_recvData( char *dataAddress, Uint32 dataSize );
static STATUS SER1_recvData( char *dataAddress, Uint32 dataSize );

/**
	\brief Configure serial interface

	Configures serial interface 'serialID' with configuration data 'serialConfig' \n
	After serial configuration, \n
	Use SER_sendData() to send data from DM270 to peripheral. \n
	Use SER_recvData() to recieve data from peripheral  to DM270 \n

	\param serialID			serial interface ID, 0:SER_0, 1:SER_1
	\param serialConfig		configuration data 

	\return if success, E_PASS, else error code
	\see SER_ConfigData
*/
STATUS SER_setConfig( Uint16 serialID, SER_ConfigData *serialConfig ) {
	STATUS status=E_PASS;

	switch(serialID) {
		case SER_0:

			// disable serial port 0
			SP0_RSET( SIOEN0, 0);
			
			SP0_FSET( SIOMODE0, RATE, SER_BIT_RATE( CLKC_getClockValue(CLK_ARM), serialConfig->bitRate) );

			SP0_FSET( SIOMODE0, SCLKM, serialConfig->clockMode == SER_IDLE_CLK_HIGH ? 0 : 1 );

			SP0_FSET( SIOMODE0, MSB,   serialConfig->lsbFirst == TRUE ? 0 : 1 );

			SP0_FSET( SIOMODE0, MSSEL, serialConfig->slaveOperation == TRUE ? 1 : 0 );

			INTC_setIntAsIRQ(INT_SER0);
			break;
		case SER_1:

			// disable serial port 0
			SP1_RSET( SIOEN1, 0);
			
			SP1_FSET( SIOMODE1, RATE, SER_BIT_RATE( CLKC_getClockValue(CLK_ARM), serialConfig->bitRate) );

			SP1_FSET( SIOMODE1, SCLKM, serialConfig->clockMode == SER_IDLE_CLK_HIGH ? 0 : 1 );

			SP1_FSET( SIOMODE1, MSB,   serialConfig->lsbFirst == TRUE ? 0 : 1 );

			SP1_FSET( SIOMODE1, MSSEL, serialConfig->slaveOperation == TRUE ? 1 : 0 );
		
			INTC_setIntAsIRQ(INT_SER1);
			break;
		default:
			status=E_INVALID_INPUT;
			break;
	}
	return status;
}


/**
    \brief	Send data over serial interface

	Transmits data over serial interface 'serialID' to a externally connected peripheral \n
	Make sure serial interface 0 or 1 is configured using SER_setConfig(), before using this API

    \param serialID		Serial Interface ID, 0:SER_0, 1:SER_1
	\param dataAddress	Source data address
	\param dataSize		Size of data to be transmitted

    \return if success, E_PASS, else error code
*/
STATUS SER_sendData( Uint16 serialID, char *dataAddress, Uint32 dataSize) {
	STATUS status=E_PASS;
	
	if(dataSize==0)
		return E_PASS;

	if(dataAddress==NULL)
		return E_INVALID_INPUT;

	switch(serialID) {
		case SER_0:
			SER0_sendData(dataAddress, dataSize);
			break;
		case SER_1:
			SER1_sendData(dataAddress, dataSize);
			break;
		default:
			status=E_INVALID_INPUT;
			break;
	}
	return status;
}

/**
    \brief	Enable/Disable serial interface

    \param serialID		Serial Interface ID, 0:SER_0, 1:SER_1
	\param enable		TRUE: enable, FALSE: disable

    \return if success, \c E_PASS, else error code
*/
STATUS SER_enable( Uint16 serialID, BOOL enable ) {
	STATUS status=E_PASS;

	switch(serialID) {
		case SER_0:
			SP0_FSET( SIOEN0, SIOEN, enable == TRUE ? 1 : 0);
			break;
		case SER_1:
			SP1_FSET( SIOEN1, SIOEN, enable == TRUE ? 1 : 0);
			break;
		default:
			status=E_INVALID_INPUT;
			break;
	}
	return status;
}

/**
    \brief	Send one byte of data over serial interface

	Make sure serial interface is enabled by using SER_enable()	\n
	After data transmission is over, use SER_enable() to disable serial interface

    \param serialID		Serial Interface ID, 0:SER_0, 1:SER_1
	\param byte			data byte to be sent using serialID 

    \return if success, \c E_PASS, else error code
*/
STATUS SER_sendByte( Uint16 serialID, Uint8 byte ) {
	STATUS status=E_PASS;

	switch(serialID) {
		case SER_0:
			SP0_RSET( TXDATA0, byte );

			//  Wait for the Serial Tx done
			while( INTC_getIntIRQStatus(INT_SER0) )
				;
			INTC_clearIRQ(INT_SER0);

			break;
		case SER_1:
			SP1_RSET( TXDATA1, byte );

	        //  Wait for the Serial Tx done
			while( INTC_getIntIRQStatus(INT_SER1) )
				;
			INTC_clearIRQ(INT_SER1);

			break;
		default:
			status=E_INVALID_INPUT;
			break;
	}
	return status;
}

static STATUS SER0_sendData( char *dataAddress, Uint32 dataSize ) {
	
	SP0_FSET( SIOEN0, SIOEN, 1 );

    while (dataSize--) {
		SP0_RSET( TXDATA0, *dataAddress++ );	// R/W, Tx data

        //  Wait for the Serial Tx done
		while( INTC_getIntIRQStatus(INT_SER0) )
				;
		INTC_clearIRQ(INT_SER0);

    }

	SP0_FSET( SIOEN0, SIOEN, 0 );
	return E_PASS;
}

static STATUS SER1_sendData( char *dataAddress, Uint32 dataSize ) {
	
	SP1_FSET( SIOEN1, SIOEN, 1 );

    while (dataSize--) {
		SP1_RSET( TXDATA1, *dataAddress++ );	// R/W, Tx data

        //  Wait for the Serial Tx done
		while( INTC_getIntIRQStatus(INT_SER1) )
				;
		INTC_clearIRQ(INT_SER1);

    }
   
	SP1_FSET( SIOEN1, SIOEN, 0 );
	return E_PASS;
}


/**
    \brief Receive data over serial interface

	Receives data over serial interface 'serialID' from a externally connected peripheral \n
	Make sure serial interface 0 or 1 is configured using SER_setConfig(), before using this API

    \param serialID		Serial Interface ID, 0:SER_0, 1:SER_1
	\param dataAddress	Destination data address
	\param dataSize		Size of data to be received

    \return if success, E_PASS, else error code
*/
STATUS SER_recvData( Uint16 serialID, char *dataAddress, Uint32 dataSize) {
	STATUS status=E_PASS;
	
	if(dataSize==0)
		return E_PASS;

	if(dataAddress==NULL)
		return E_INVALID_INPUT;

	switch(serialID) {
		case SER_0:
			SER0_recvData(dataAddress, dataSize);
			break;
		case SER_1:
			SER1_recvData(dataAddress, dataSize);
			break;
		default:
			status=E_INVALID_INPUT;
			break;
	}
	return status;
}

static STATUS SER0_recvData( char *dataAddress, Uint32 dataSize ) {
	
	SP0_FSET( SIOEN0, SIOEN, 1 );

    while (dataSize--) {
        
		SP0_RSET( TXDATA0, 0xFF );

		//  Wait for the Serial Tx done
        while ( SP0_FGET( RXDATA0, XMIT ) )
            ;

		// read data
		*dataAddress++ = SP0_FGET( RXDATA0, RXD );	// R/W, Tx data
    }

	SP0_FSET( SIOEN0, SIOEN, 0 );
	return E_PASS;
}

static STATUS SER1_recvData( char *dataAddress, Uint32 dataSize ) {
	
	SP1_FSET( SIOEN1, SIOEN, 1 );

    while (dataSize--) {
        
		SP1_RSET( TXDATA1, 0xFF );

		//  Wait for the Serial Tx done
        while ( SP1_FGET( RXDATA1, XMIT ) )
            ;

		// read data
		*dataAddress++ = SP1_FGET( RXDATA1, RXD );	// R/W, Tx data
    }

	SP1_FSET( SIOEN1, SIOEN, 0 );
	return E_PASS;
}


/**
    \brief	Configure DMA for serial interface 0
	
    \param serialDmaConfig	Serial Interface 0, DMA configuration parameters

    \return if success, E_PASS, else error code

	\see SER_DmaConfig
*/
STATUS SER_dmaConfig( SER_DmaConfig *serialDmaConfig) {
	STATUS status=E_PASS;
	Uint32 addr;

	SP0_FSET( DMAMODE0, PRM, serialDmaConfig->byteOrder);
	SP0_FSET( DMAMODE0, DIR, serialDmaConfig->direction);

	if( serialDmaConfig->size & 0x1 )
		status = E_INVALID_INPUT;

	SP0_FSET( DMAMODE0, TRSZ, serialDmaConfig->size );

	addr = (Uint32)serialDmaConfig->address - SDRAM_MEMORY_BASE;
	
	if( addr & 0x1 )
		status = E_INVALID_INPUT;

	SP0_RSET( DMASTADL0, addr );
	SP0_RSET( DMASTADH0, addr >> 16);

	return status;	
}

/**
    \brief	Start DMA operation

	Starts serial interface 0 DMA operation \n
	DMA operation must be configured by using SER_dmaConfig(), before using this API \n
	Also SDRAM DMA channel must be selected by using SDRC_selectDmaChannel(), before using this API 

    \return if success, E_PASS, else error code
*/
static Uint8 dmaChannel0;

STATUS SER_dmaStart() {
	// enable serial interface
	SER_enable( SER_0, TRUE);

	// select DMA channel for serial interface
	dmaChannel0 = SDRC_FGET( REFCTL, SDMA1);
	SDRC_FSET( REFCTL, SDMA1, 1);

	SP0_RSET( DMATRG0, 1);
	return E_PASS;
}

/**
    \brief	Wait for DMA to complete

	Wait for serial interface 0 DMA operation to complete \n
	DMA operation is started using SER_dmaStart()

    \param timeout	DMA operation completion timeout

	\warning paramter 'timeout' is not used in current implemetation, hence always pass 0

    \return if success, E_PASS, else error code
*/
STATUS SER_dmaWait( Uint32 timeout ) {
	STATUS status=E_PASS;

	if(timeout!=0) {
		//  Wait for the Serial Rx/Tx done
		while( INTC_getIntIRQStatus(INT_SER0) && timeout)
				timeout--;
			
		if(timeout==0)
			status=E_TIMEOUT;
	} else {
		//  Wait for the Serial Rx/Tx done
		while( INTC_getIntIRQStatus(INT_SER0) )
				;
	}

	INTC_clearIRQ(INT_SER0);

	// disable serial interface
	SER_enable( SER_0, FALSE);

	// set DMA channel to old value
	SDRC_FSET( REFCTL, SDMA1, dmaChannel0 );

	return status;
}

/**
    \brief	Get DMA transfer remaning byte count

	Returns serial interface 0, DMA transfer remaining byte count

    \return count in units of bytes
*/
Uint16 SER_getDmaCount() {
	return SP0_FGET( DMASTAT0, REM );
}

⌨️ 快捷键说明

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