Example #1
0
static size_t prvFillFifoFromBuffer( LPC_SSP_TypeDef * const pxSSP, uint8_t **ppucBuffer, const size_t xTotalBytes )
{
size_t xBytesSent;

	/* This function is only used by zero copy transmissions, so mutual
	exclusion is already taken care of by the fact that a task must first
	obtain a semaphore before initiating a zero copy transfer.  The semaphore
	is part of the zero copy structure, not part of the application.

	The buffer is passed in by reference as the incremented pointer is in
	effect returned. */
	for( xBytesSent = 0U; ( xBytesSent < sspMAX_FIFO_DEPTH ) && ( xBytesSent < xTotalBytes ); xBytesSent++ )
	{
		/* While the Tx FIFO is not full, and the Rx FIFO is not full. */
		if( ( ( pxSSP->SR & SSP_SR_TNF ) != 0 ) && ( ( pxSSP->SR & SSP_SR_RFF ) == 0 ) )
		{
			if( *ppucBuffer == NULL )
			{
				/* There is no data to send.  This transmission is probably
				just to	generate a clock so data can be received, so send out
				0xff each time. */
				pxSSP->DR = SSP_DR_BITMASK( ( ( uint16_t ) 0xffffU ) );
			}
			else
			{
				pxSSP->DR = SSP_DR_BITMASK( ( uint16_t ) ( **ppucBuffer ) );
				( *ppucBuffer )++;
			}
		}
		else
		{
			break;
		}
	}

	return xBytesSent;
}
Example #2
0
/*********************************************************************//**
 * @brief		Receive a single data from SSPx peripheral
 * @param[in]	SSPx	SSP peripheral selected, should be
 * 						- LPC_SSP0: SSP0 peripheral
 * 						- LPC_SSP1: SSP1 peripheral
 * @return 		Data received (16-bit long)
 **********************************************************************/
uint16_t SSP_ReceiveData(LPC_SSP_TypeDef* SSPx)
{
	CHECK_PARAM(PARAM_SSPx(SSPx));

	return ((uint16_t) (SSP_DR_BITMASK(SSPx->DR)));
}
Example #3
0
/*********************************************************************//**
 * @brief		Transmit a single data through SSPx peripheral
 * @param[in]	SSPx	SSP peripheral selected, should be:
 * 						- LPC_SSP0: SSP0 peripheral
 * 						- LPC_SSP1: SSP1 peripheral
 * @param[in]	Data	Data to transmit (must be 16 or 8-bit long,
 * 						this depend on SSP data bit number configured)
 * @return 		none
 **********************************************************************/
void SSP_SendData(LPC_SSP_TypeDef* SSPx, uint16_t Data)
{
	CHECK_PARAM(PARAM_SSPx(SSPx));

	SSPx->DR = SSP_DR_BITMASK(Data);
}
Example #4
0
void SSP1_IRQHandler( void )
{
uint32_t ulInterruptSource;
volatile uint32_t usJunk, ulReceived = 0UL;
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
const unsigned portBASE_TYPE uxSSPNumber = 1UL;
Transfer_Control_t *pxTxTransferStruct, *pxRxTransferStruct;

	/* Determine the interrupt source. */
	ulInterruptSource = LPC_SSP1->MIS;

	/* Clear receive overruns, and optionally assert. */
	if( ( ulInterruptSource & SSP_INTSTAT_ROR ) != 0 )
	{
		configASSERT( ( ulInterruptSource & SSP_INTSTAT_ROR ) == 0 );
		LPC_SSP1->ICR = SSP_INTCLR_ROR;
	}

	/* Clear timeouts. */
	if( ( ulInterruptSource & SSP_INTSTAT_RT ) != 0 )
	{
		LPC_SSP1->ICR = SSP_INTCLR_RT;
	}

	/* Is this a receive FIFO half full or receive timeout? */
	if( ( ulInterruptSource & sspRX_DATA_AVAILABLE_INTERRUPTS ) != 0 )
	{
		pxTxTransferStruct = pxTxTransferControlStructs[ uxSSPNumber ];
		pxRxTransferStruct = pxRxTransferControlStructs[ uxSSPNumber ];
		configASSERT( pxRxTransferStruct );
		configASSERT( pxTxTransferStruct );

		if( pxRxTransferStruct != NULL )
		{
			if( ulReceiveActive[ uxSSPNumber ] == pdFALSE )
			{
				/* The data being received is just in response to data
				being sent,	not in response to data being read, just
				just junk it. */
				while( ( LPC_SSP1->SR & SSP_SR_RNE ) != 0 )
				{
					usJunk = LPC_SSP1->DR;
					ulReceived++;
				}
			}
			else
			{
				/* Data is being received because a read is being
				performed.  Store the data using whichever
				transfer mechanism is currently configured. */
				switch( diGET_TRANSFER_TYPE_FROM_CONTROL_STRUCT( pxRxTransferStruct ) )
				{
					case ioctlUSE_CIRCULAR_BUFFER_RX :

						#if ioconfigUSE_SSP_CIRCULAR_BUFFER_RX == 1
						{
							/* This call will empty the FIFO, and give the New
							Data semaphore so a task blocked on an SSP read
							will unblock.  Note that this does not mean that
							more data will not arrive after this interrupt,
							even if there is no more data to send. */
							ioutilsRX_CHARS_INTO_CIRCULAR_BUFFER_FROM_ISR(
																		pxRxTransferStruct, 	/* The structure that contains the reference to the circular buffer. */
																		( ( LPC_SSP1->SR & SSP_SR_RNE ) != 0 ), 		/* While loop condition. */
																		( LPC_SSP1->DR ),						/* The function that returns the chars. */
																		ulReceived,
																		xHigherPriorityTaskWoken
																	);
						}
						#endif /* ioconfigUSE_SSP_CIRCULAR_BUFFER_RX */
						break;


					case ioctlUSE_CHARACTER_QUEUE_RX :

						#if ioconfigUSE_SSP_RX_CHAR_QUEUE == 1
						{
							ioutilsRX_CHARS_INTO_QUEUE_FROM_ISR( pxRxTransferStruct, ( ( LPC_SSP1->SR & SSP_SR_RNE ) != 0 ), ( LPC_SSP1->DR ), ulReceived, xHigherPriorityTaskWoken );
						}
						#endif /* ioconfigUSE_SSP_RX_CHAR_QUEUE */
						break;


					default :

						/* This must be an error.  Force an assert. */
						configASSERT( xHigherPriorityTaskWoken );
						break;
				}
			}

			/* Space has been created in the Rx FIFO, see if there is any data
			to send to the Tx FIFO. */
			switch( diGET_TRANSFER_TYPE_FROM_CONTROL_STRUCT( pxTxTransferStruct ) )
			{
				case ioctlUSE_ZERO_COPY_TX:

					#if ioconfigUSE_SSP_ZERO_COPY_TX == 1
					{
						iouitlsTX_CHARS_FROM_ZERO_COPY_BUFFER_FROM_ISR( pxTxTransferStruct, ( ( ulReceived-- ) > 0 ), ( LPC_SSP1->DR = ucChar), xHigherPriorityTaskWoken );
					}
					#endif /* ioconfigUSE_SSP_ZERO_COPY_TX */
					break;


				case ioctlUSE_CHARACTER_QUEUE_TX:

					#if ioconfigUSE_SSP_TX_CHAR_QUEUE == 1
					{
						ioutilsTX_CHARS_FROM_QUEUE_FROM_ISR( pxTxTransferStruct, ( ( ulReceived-- ) > 0 ), ( LPC_SSP1->DR = SSP_DR_BITMASK( ( uint16_t ) ucChar ) ), xHigherPriorityTaskWoken );
					}
					#endif /* ioconfigUSE_SSP_TX_CHAR_QUEUE */
					break;


				default :

					/* Should not get here.  Set the saved transfer control
					structure to NULL so the Tx interrupt will get disabled
					before this ISR is exited. */
					pxTxTransferControlStructs[ uxSSPNumber ] = NULL;

					/* This must be an error.  Force an assert. */
					configASSERT( xHigherPriorityTaskWoken );
					break;
			}
		}
	}

	/* If lHigherPriorityTaskWoken is now equal to pdTRUE, then a context
	switch should be performed before the interrupt exists.  That ensures the
	unblocked (higher priority) task is returned to immediately. */
	portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
}
Example #5
0
size_t FreeRTOS_SSP_write( Peripheral_Descriptor_t const pxPeripheral, const void *pvBuffer, const size_t xBytes )
{
Peripheral_Control_t * const pxPeripheralControl = ( Peripheral_Control_t * const ) pxPeripheral;
size_t xReturn = 0U;
LPC_SSP_TypeDef * const pxSSP = ( LPC_SSP_TypeDef * const ) diGET_PERIPHERAL_BASE_ADDRESS( ( ( Peripheral_Control_t * const ) pxPeripheral ) );
SSP_DATA_SETUP_Type *pxSSPTransferDefinition;
const uint32_t ulPeripheralNumber = ( uint32_t ) diGET_PERIPHERAL_NUMBER( ( ( Peripheral_Control_t * const ) pxPeripheral ) );

	/* Remember which transfer control structure is being used, so if
	an interrupt is being used, it can continue the same transfer until
	all data has been transmitted. */
	pxTxTransferControlStructs[ ulPeripheralNumber ] = diGET_TX_TRANSFER_STRUCT( pxPeripheralControl );

	switch( diGET_TX_TRANSFER_TYPE( pxPeripheralControl ) )
	{
		case ioctlUSE_POLLED_TX :

			#if ioconfigUSE_SSP_POLLED_TX == 1
			{
				/* Configure the transfer data.  No semaphore or queue is used
				here, so the application must ensure only one task attempts to
				make a polling write at a time. */
				pxSSPTransferDefinition = ( SSP_DATA_SETUP_Type * ) diGET_TX_TRANSFER_STATE( pxPeripheralControl );
				configASSERT( pxSSPTransferDefinition );
				pxSSPTransferDefinition->tx_data = ( void * ) pvBuffer;
				pxSSPTransferDefinition->rx_data = NULL;
				pxSSPTransferDefinition->length  = ( uint32_t ) xBytes;
				xReturn = SSP_ReadWrite( pxSSP, pxSSPTransferDefinition, SSP_TRANSFER_POLLING );
			}
			#endif /* ioconfigUSE_SSP_POLLED_TX */

			/* The transfer struct is set back to NULL as the Tx is complete
			before the above call to SSP_ReadWrite() completes. */
			pxTxTransferControlStructs[ ulPeripheralNumber ] = NULL;
			break;


		case ioctlUSE_ZERO_COPY_TX :

			#if ioconfigUSE_SSP_ZERO_COPY_TX == 1
			{
				/* The implementation of the zero copy write uses a semaphore
				to indicate whether a write is complete (and so the buffer
				being written free again) or not.  The semantics of using a
				zero copy write dictate that a zero copy write can only be
				attempted by a task, once the semaphore has been successfully
				obtained by that task.  This ensure that only one task can
				perform a zero copy write at any one time.  Ensure the semaphore
				is not currently available, if this function has been called
				without it being obtained first then it is an error. */
				configASSERT( xIOUtilsGetZeroCopyWriteMutex( pxPeripheralControl, ioctlOBTAIN_WRITE_MUTEX, 0U ) == 0 );
				xReturn = xBytes;
				ioutilsINITIATE_ZERO_COPY_TX
					(
						pxPeripheralControl,
						SSP_IntConfig( pxSSP, sspRX_DATA_AVAILABLE_INTERRUPTS, DISABLE ),		/* Disable interrupt. */
						SSP_IntConfig( pxSSP, sspRX_DATA_AVAILABLE_INTERRUPTS, ENABLE ), 		/* Enable interrupt. */
						prvFillFifoFromBuffer( pxSSP, ( uint8_t ** ) &( pvBuffer ), xBytes ), 	/* Write to peripheral function.  The buffer is passed in by address as the pointer is incremented. */
						pvBuffer, 																/* Data source. */
						xReturn																	/* Number of bytes to be written.  This will get set to zero if the write mutex is not held. */
					);
			}
			#endif /* ioconfigUSE_SSP_ZERO_COPY_TX */

			/* Remove compiler warnings in case the above is #defined out. */
			( void ) prvFillFifoFromBuffer;
			break;


		case ioctlUSE_CHARACTER_QUEUE_TX :

			#if ioconfigUSE_SSP_TX_CHAR_QUEUE == 1
			{
				/* The queue allows multiple tasks to attempt to write bytes,
				but ensures only the highest priority of these tasks will
				actually succeed.  If two tasks of equal priority attempt to
				write simultaneously, then the application must ensure mutual
				exclusion, as time slicing could result in the strings being
				sent to the queue becoming interleaved. */
				xReturn = xIOUtilsSendCharsToTxQueue( pxPeripheralControl, ( ( uint8_t * ) pvBuffer ), xBytes );

				ioutilsFILL_FIFO_FROM_TX_QUEUE(
						pxPeripheralControl,
						SSP_IntConfig( pxSSP, sspRX_DATA_AVAILABLE_INTERRUPTS, DISABLE ),	/* Disable Rx interrupt. */
						SSP_IntConfig( pxSSP, sspRX_DATA_AVAILABLE_INTERRUPTS, ENABLE ), 	/* Enable Rx interrupt. */
						sspMAX_FIFO_DEPTH, 													/* Bytes to write to the FIFO. */
						( pxSSP->SR & SSP_STAT_TXFIFO_NOTFULL ) != 0UL,						/* FIFO not full. */
						pxSSP->DR = SSP_DR_BITMASK( ucChar ) );							  	/* Tx function. */
			}
			#endif /* ioconfigUSE_SSP_RX_CHAR_QUEUE */
			break;


		default :

			/* Other methods can be implemented here.  For now, set the stored
			Tx structure back to NULL as nothing is being sent. */
			pxTxTransferControlStructs[ ulPeripheralNumber ] = NULL;
			configASSERT( xReturn );

			/* Prevent compiler warnings when the configuration is set such
			that the following parameters are not used. */
			( void ) pvBuffer;
			( void ) xBytes;
			( void ) pxSSP;
			( void ) pxSSPTransferDefinition;
			break;
	}

	return xReturn;
}
/*********************************************************************//**
 * @brief		Receive a single data from SSPx peripheral
 * @param[in]	SSPx	SSP peripheral selected, should be
 * 						- LPC_SSP0: SSP0 peripheral
 * 						- LPC_SSP1: SSP1 peripheral
 * @return 		Data received (16-bit long)
 **********************************************************************/
uint16_t SSP_ReceiveData(LPC_SSP_TypeDef* SSPx)
{
	return ((uint16_t) (SSP_DR_BITMASK(SSPx->DR)));
}
/*********************************************************************//**
 * @brief		Transmit a single data through SSPx peripheral
 * @param[in]	SSPx	SSP peripheral selected, should be:
 * 						- LPC_SSP0: SSP0 peripheral
 * 						- LPC_SSP1: SSP1 peripheral
 * @param[in]	Data	Data to transmit (must be 16 or 8-bit long,
 * 						this depend on SSP data bit number configured)
 * @return 		none
 **********************************************************************/
void SSP_SendData(LPC_SSP_TypeDef* SSPx, uint16_t Data)
{
	SSPx->DR = SSP_DR_BITMASK(Data);
}
Example #8
0
/*********************************************************************//**
 * @brief        SSP Read write data function
 * @param[in]    dataCfg	Pointer to a SSP_DATA_SETUP_Type structure that
 * 				    contains specified information about transmit
 * 				    data configuration.
 * @return       Actual Data length has been transferred in polling mode.
 * 		    In interrupt mode, always return (0)
 * 		    Return (-1) if error.
 * Note: This function can be used in both master and slave mode.
 ***********************************************************************/
int32_t SSP_ReadWrite (SSP_DATA_SETUP_Type *dataCfg)
{
    uint8_t *rdata8;
    uint8_t *wdata8;
    uint16_t *rdata16;
    uint16_t *wdata16;
    uint32_t stat;
    uint32_t tmp;
//    int32_t sspnum;
    int32_t dataword;

    dataCfg->rx_cnt = 0;
    dataCfg->tx_cnt = 0;
    dataCfg->status = 0;


    /* Clear all remaining data in RX FIFO */
    while (LPC_SSP0->SR & SSP_SR_RNE){
        tmp = (SSP_DR_BITMASK(LPC_SSP0->DR));
    }

    // Clear status
    LPC_SSP0->ICR = SSP_ICR_BITMASK;

    dataword = SSP_DATA_WORD;

    // Polling mode ----------------------------------------------------------------------
    if (dataword == 0){
        rdata8 = (uint8_t *)dataCfg->rx_data;
        wdata8 = (uint8_t *)dataCfg->tx_data;
    } else {
        rdata16 = (uint16_t *)dataCfg->rx_data;
        wdata16 = (uint16_t *)dataCfg->tx_data;
    }
    while ((dataCfg->tx_cnt != dataCfg->length) || (dataCfg->rx_cnt != dataCfg->length)){
        if ((LPC_SSP0->SR & SSP_SR_TNF) && (dataCfg->tx_cnt != dataCfg->length)){
            // Write data to buffer
            if(dataCfg->tx_data == NULL){
                if (dataword == 0){
                    LPC_SSP0->DR = SSP_DR_BITMASK(0xFF);
                    dataCfg->tx_cnt++;
                } else {
                    LPC_SSP0->DR = SSP_DR_BITMASK(0xFFFF);
                    dataCfg->tx_cnt += 2;
                }
            } else {
                if (dataword == 0){
                    LPC_SSP0->DR = SSP_DR_BITMASK(*wdata8);
                    wdata8++;
                    dataCfg->tx_cnt++;
                } else {
                    LPC_SSP0->DR = SSP_DR_BITMASK(*wdata16);
                    wdata16++;
                    dataCfg->tx_cnt += 2;
                }
            }
        }

        // Check overrun error
        if ((stat = LPC_SSP0->RIS) & SSP_RIS_RORRIS){
            // save status and return
            dataCfg->status = stat | SSP_STAT_ERROR;
            return (-1);
        }

        // Check for any data available in RX FIFO
        while ((LPC_SSP0->SR & SSP_SR_RNE) && (dataCfg->rx_cnt != dataCfg->length)){
            // Read data from SSP data
            tmp = (SSP_DR_BITMASK(LPC_SSP0->DR));

            // Store data to destination
            if (dataCfg->rx_data != NULL)
            {
                if (dataword == 0){
                    *(rdata8) = (uint8_t) tmp;
                    rdata8++;
                } else {
                    *(rdata16) = (uint16_t) tmp;
                    rdata16++;
                }
            }
            // Increase counter
            if (dataword == 0){
                dataCfg->rx_cnt++;
            } else {
                dataCfg->rx_cnt += 2;
            }
        }
    }

    // save status
    dataCfg->status = SSP_STAT_DONE;

    if (dataCfg->tx_data != NULL){
        return dataCfg->tx_cnt;
    } else if (dataCfg->rx_data != NULL){
        return dataCfg->rx_cnt;
    } else {
        return (0);
    }
}