예제 #1
0
size_t FreeRTOS_SSP_read( Peripheral_Descriptor_t const pxPeripheral, void * const 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 int8_t cPeripheralNumber = diGET_PERIPHERAL_NUMBER( ( ( Peripheral_Control_t * const ) pxPeripheral ) );

	/* Sanity check the array index. */
	configASSERT( cPeripheralNumber < ( int8_t ) ( sizeof( xIRQ ) / sizeof( IRQn_Type ) ) );

	switch( diGET_RX_TRANSFER_TYPE( pxPeripheralControl ) )
	{
		case ioctlUSE_POLLED_RX :

			#if ioconfigUSE_SSP_POLLED_RX == 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 read at a time.  *NOTE* the Tx transfer state
				is used, as the SSP requires a Tx to occur for any data to be
				received. */
				pxSSPTransferDefinition = ( SSP_DATA_SETUP_Type * ) diGET_TX_TRANSFER_STATE( pxPeripheralControl );
				configASSERT( pxSSPTransferDefinition );
				pxSSPTransferDefinition->tx_data = NULL;
				pxSSPTransferDefinition->rx_data = ( void * ) pvBuffer;
				pxSSPTransferDefinition->length  = ( uint32_t ) xBytes;
				xReturn = SSP_ReadWrite( pxSSP, pxSSPTransferDefinition, SSP_TRANSFER_POLLING );
			}
			#endif /* ioconfigUSE_SSP_POLLED_RX */
			break;


		case ioctlUSE_CIRCULAR_BUFFER_RX :
			/* _RB_ This relies on Tx being configured to zero copy mode. */
			#if ioconfigUSE_SSP_CIRCULAR_BUFFER_RX == 1
			{
				/* There is nothing to prevent multiple tasks attempting to
				read the circular buffer at any one time.  The implementation
				of the circular buffer uses a semaphore to indicate when new
				data is available, and the semaphore will ensure that only the
				highest priority task that is attempting a read will actually
				receive bytes. */

				/* A write is performed first, to generate the clock required
				to clock the data in.  NULL is passed as the source buffer as
				there isn't actually any data to send, and NULL will just
				result in 0xff being sent.  When the data written to the FIFO
				has been transmitted an Rx interrupt will copy the received
				data into the circular buffer, and check to see if there is
				more data to be written. */

				/* Ensure the last Tx has completed. */
				xReturn = xIOUtilsGetZeroCopyWriteMutex( pxPeripheralControl, ioctlOBTAIN_WRITE_MUTEX, ioutilsDEFAULT_ZERO_COPY_TX_MUTEX_BLOCK_TIME );
				configASSERT( xReturn );

				if( xReturn == pdPASS )
				{
					/* Empty whatever is lingering in the Rx buffer (there
					shouldn't be any. */
					vIOUtilsClearRxCircularBuffer( pxPeripheralControl );

					/* Data should be received during the following write. */
					ulReceiveActive[ cPeripheralNumber ] = pdTRUE;

					/* Write to solicit received data. */
					FreeRTOS_SSP_write( pxPeripheralControl, NULL, xBytes );

					/* This macro will continuously wait on the new data mutex,
					reading bytes from the circular buffer each time it
					receives it, until the desired number of bytes have been
					read. */
					ioutilsRECEIVE_CHARS_FROM_CIRCULAR_BUFFER
						(
							pxPeripheralControl,
							SSP_IntConfig( pxSSP, sspRX_DATA_AVAILABLE_INTERRUPTS, DISABLE ), /* Disable interrupt. */
							SSP_IntConfig( pxSSP, sspRX_DATA_AVAILABLE_INTERRUPTS, ENABLE ), /* Enable interrupt. */
							( ( uint8_t * ) pvBuffer ),	/* Data destination. */
							xBytes,						/* Bytes to read. */
							xReturn						/* Number of bytes read. */
						);

					/* Not expecting any more Rx data now, so just junk anything
					that is received until the next explicit read is performed. */
					ulReceiveActive[ cPeripheralNumber ] = pdFALSE;
				}
			}
			#endif
			break;


		case ioctlUSE_CHARACTER_QUEUE_RX :

			/* The queue allows multiple tasks to attempt to read bytes,
			but ensures only the highest priority of these tasks will
			actually receive bytes.  If two tasks of equal priority attempt
			to read simultaneously, then the application must ensure mutual
			exclusion, as time slicing could result in the string being
			received being partially received by each task. */
			#if ioconfigUSE_SSP_RX_CHAR_QUEUE == 1
			{
				/* Ensure the last Tx has completed. */
				xIOUtilsWaitTxQueueEmpty( pxPeripheralControl, boardDEFAULT_READ_MUTEX_TIMEOUT );

				/* Clear any residual data - there shouldn't be any! */
				xIOUtilsClearRxCharQueue( pxPeripheralControl );

				/* Data should be received during the following write. */
				ulReceiveActive[ cPeripheralNumber ] = pdTRUE;

				/* Write to solicit received data. */
				FreeRTOS_SSP_write( pxPeripheralControl, NULL, xBytes );

				/* Read the received data placed in the Rx queue by the
				interrupt. */
				xReturn = xIOUtilsReceiveCharsFromRxQueue( pxPeripheralControl, ( uint8_t * ) pvBuffer, xBytes );

				/* Not expecting any more Rx data now, so just junk anything
				that is received until the next explicit read is performed. */
				ulReceiveActive[ cPeripheralNumber ] = pdFALSE;
			}
			#endif
			break;


		default :

			/* Other methods can be implemented here. */
			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;
			( void ) cPeripheralNumber;
			break;
	}

	return xReturn;
}
size_t FreeRTOS_UART_read( Peripheral_Descriptor_t const pxPeripheral, void * const pvBuffer, const size_t xBytes )
{
Peripheral_Control_t * const pxPeripheralControl = ( Peripheral_Control_t * const ) pxPeripheral;
size_t xReturn = 0U;
LPC_UART_TypeDef * const pxUART = ( LPC_UART_TypeDef * const ) diGET_PERIPHERAL_BASE_ADDRESS( ( ( Peripheral_Control_t * const ) pxPeripheral ) );
//
//lecture - UART - rx transfer structure is NULL for rx polling mode
//                 in the case of i2c, this is different - refer to i2c related code
//
	if( diGET_RX_TRANSFER_STRUCT( pxPeripheralControl ) == NULL )
	{
		#if ioconfigUSE_UART_POLLED_RX == 1
		{
			/* No FreeRTOS objects exist to allow reception without blocking
			the task, so just receive by polling.  No semaphore or queue is
			used here, so the application must ensure only one task attempts
			to make a polling read at a time. */
			xReturn = UART_Receive( pxUART, pvBuffer, xBytes, NONE_BLOCKING );
		}
		#endif /* ioconfigUSE_UART_POLLED_RX */
	}
	else
	{
		/* Sanity check the array index. */
		configASSERT( diGET_PERIPHERAL_NUMBER( pxPeripheralControl ) < ( int8_t ) ( sizeof( xIRQ ) / sizeof( IRQn_Type ) ) );

		switch( diGET_RX_TRANSFER_TYPE( pxPeripheralControl ) )
		{
			case ioctlUSE_CIRCULAR_BUFFER_RX :

				#if ioconfigUSE_UART_CIRCULAR_BUFFER_RX == 1
				{
					/* There is nothing to prevent multiple tasks attempting to
					read the circular buffer at any one time.  The implementation
					of the circular buffer uses a semaphore to indicate when new
					data is available, and the semaphore will ensure that only the
					highest priority task that is attempting a read will actually
					receive bytes. */
					ioutilsRECEIVE_CHARS_FROM_CIRCULAR_BUFFER
						(
							pxPeripheralControl,
							UART_IntConfig( pxUART, UART_INTCFG_RBR, DISABLE ),	/* Disable peripheral. */
							UART_IntConfig( pxUART, UART_INTCFG_RBR, ENABLE ), 	/* Enable peripheral. */
							( ( uint8_t * ) pvBuffer ),							/* Data destination. */
							xBytes,												/* Bytes to read. */
							xReturn												/* Number of bytes read. */
						);
				}
				#endif /* ioconfigUSE_UART_CIRCULAR_BUFFER_RX */
				break;


			case ioctlUSE_CHARACTER_QUEUE_RX :

				#if ioconfigUSE_UART_RX_CHAR_QUEUE == 1
				{
					/* The queue allows multiple tasks to attempt to read
					bytes, but ensures only the highest priority of these
					tasks will actually receive bytes.  If two tasks of equal
					priority attempt to read simultaneously, then the
					application must ensure mutual exclusion, as time slicing
					could result in the string being received being partially
					received by each task. */
					xReturn = xIOUtilsReceiveCharsFromRxQueue( pxPeripheralControl, ( uint8_t * ) pvBuffer, xBytes );
				}
				#endif /* ioconfigUSE_UART_RX_CHAR_QUEUE */
				break;


			default :

				/* Other methods can be implemented here. */
				configASSERT( xReturn );

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

	return xReturn;
}
size_t FreeRTOS_I2C_read( Peripheral_Descriptor_t const pxPeripheral, void * const pvBuffer, const size_t xBytes )
{
Peripheral_Control_t * const pxPeripheralControl = ( Peripheral_Control_t * const ) pxPeripheral;
size_t xReturn = 0U;
LPC_I2C_TypeDef * const pxI2C = ( LPC_I2C_TypeDef * const ) diGET_PERIPHERAL_BASE_ADDRESS( ( ( Peripheral_Control_t * const ) pxPeripheral ) );
I2C_M_SETUP_Type *pxI2CTransferDefinition;
const int8_t cPeripheralNumber = diGET_PERIPHERAL_NUMBER( ( ( Peripheral_Control_t * const ) pxPeripheral ) );

	/* Sanity check the array index. */
	configASSERT( cPeripheralNumber < ( int8_t ) ( sizeof( xIRQ ) / sizeof( IRQn_Type ) ) );
	configASSERT( xBytes > 0U );

	/* Remove compiler warnings when configASSERT() is not defined. */
	( void ) xBytes;

	switch( diGET_RX_TRANSFER_TYPE( pxPeripheralControl ) )
	{
		case ioctlUSE_POLLED_RX :

			#if ioconfigUSE_I2C_POLLED_RX == 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. */
				pxI2CTransferDefinition = ( I2C_M_SETUP_Type * ) diGET_RX_TRANSFER_STATE( pxPeripheralControl );
				configASSERT( pxI2CTransferDefinition );
				pxI2CTransferDefinition->sl_addr7bit = ucSlaveAddresses[ cPeripheralNumber ];
				pxI2CTransferDefinition->tx_data = NULL;
				pxI2CTransferDefinition->tx_length = 0;
				pxI2CTransferDefinition->rx_data = ( uint8_t * ) pvBuffer;;
				pxI2CTransferDefinition->rx_length = xBytes;
				pxI2CTransferDefinition->retransmissions_max = boardI2C_MAX_RETRANSMISSIONS;

				if( I2C_MasterTransferData( pxI2C, pxI2CTransferDefinition, I2C_TRANSFER_POLLING ) == SUCCESS )
				{
					xReturn = xBytes;
				}
			}
			#endif /* ioconfigUSE_I2C_POLLED_RX */

			break;


		case ioctlUSE_CIRCULAR_BUFFER_RX :

			#if ioconfigUSE_I2C_CIRCULAR_BUFFER_RX == 1
			{
				/* There is nothing to prevent multiple tasks attempting to
				read the circular buffer at any one time.  The implementation
				of the circular buffer uses a semaphore to indicate when new
				data is available, and the semaphore will ensure that only the
				highest priority task that is attempting a read will actually
				receive bytes. */

				if( xDataDirection[ cPeripheralNumber ] == i2cIdle )
				{
					/* This is the first time read() has been called for this
					transfer.  Start the transfer by setting the start
					bit, then mark the read transfer as in progress. */
					pxI2C->I2CONSET = I2C_I2CONSET_STA;
					xDataDirection[ cPeripheralNumber ] = i2cReading;
					xBytesOutstanding[ cPeripheralNumber ] = xBytes;
					I2C_IntCmd( pxI2C, ENABLE );
				}

				ioutilsRECEIVE_CHARS_FROM_CIRCULAR_BUFFER
					(
						pxPeripheralControl,
						I2C_IntCmd( pxI2C, DISABLE ),	/* Disable peripheral. */
						I2C_IntCmd( pxI2C, ENABLE ), 	/* Enable peripheral. */
						( ( uint8_t * ) pvBuffer ),		/* Data destination. */
						xBytes,							/* Bytes to read. */
						xReturn							/* Number of bytes read. */
					);
			}
			#endif /* ioconfigUSE_I2C_CIRCULAR_BUFFER_RX */
			break;


		case ioctlUSE_CHARACTER_QUEUE_RX :
			/* Not (yet?) implemented for I2C. */
			configASSERT( xReturn );
			break;


		default :

			/* Other methods can be implemented here. */
			configASSERT( xReturn );

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

	return xReturn;
}