Exemplo n.º 1
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;
}
size_t FreeRTOS_UART_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_UART_TypeDef * const pxUART = ( LPC_UART_TypeDef * const ) diGET_PERIPHERAL_BASE_ADDRESS( ( ( Peripheral_Control_t * const ) pxPeripheral ) );
int8_t cPeripheralNumber;
//
//lecture - UART - tx transfer control structure is NULL for tx polling mode -
//                 in the case of i2c, this is not NULL - refer to i2c code more details !!!
//
//
	if( diGET_TX_TRANSFER_STRUCT( pxPeripheralControl ) == NULL )
	{
		#if ioconfigUSE_UART_POLLED_TX == 1
		{
			/* No FreeRTOS objects exist to allow transmission without blocking
			the	task, so just send out by polling.  No semaphore or queue is
			used here, so the application must ensure only one task attempts to
			make a polling write at a time. */
			xReturn = UART_Send( pxUART, ( uint8_t * ) pvBuffer, ( size_t ) xBytes, BLOCKING );

			/* The UART is set to polling mode, so may as well poll the busy bit
			too.  Change to interrupt driven mode to avoid wasting CPU time here. */
			while( UART_CheckBusy( pxUART ) != RESET );
		}
		#endif /* ioconfigUSE_UART_POLLED_TX */
	}
	else
	{
		/* Remember which transfer control structure is being used.
		The Tx interrupt will use this to continue to write data to the
		Tx FIFO/UART until the length member of the structure reaches
		zero. */
		cPeripheralNumber = diGET_PERIPHERAL_NUMBER( pxPeripheralControl );
		pxTxTransferControlStructs[ cPeripheralNumber  ] = diGET_TX_TRANSFER_STRUCT( pxPeripheralControl );

		switch( diGET_TX_TRANSFER_TYPE( pxPeripheralControl ) )
		{
			case ioctlUSE_ZERO_COPY_TX :

				#if ioconfigUSE_UART_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,
							UART_TxCmd( pxUART, DISABLE ),	/* Disable peripheral function. */
							UART_TxCmd( pxUART, ENABLE ), 	/* Enable peripheral function. */
							prvFillFifoFromBuffer( pxUART, ( uint8_t ** ) &( pvBuffer ), xBytes ), /* Write to peripheral function. */
							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_UART_ZERO_COPY_TX */
				break;


			case ioctlUSE_CHARACTER_QUEUE_TX :

				#if ioconfigUSE_UART_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 being interleaved. */
					ioutilsBLOCKING_SEND_CHARS_TO_TX_QUEUE
						(
							pxPeripheralControl,
							( pxUART->LSR & uartTX_BUSY_MASK ) == uartTX_BUSY_MASK,  /* Peripheral busy condition. */
							pxUART->THR = ucChar,				/* Peripheral write function. */
							( ( uint8_t * ) pvBuffer ),			/* Data source. */
							xBytes, 							/* Number of bytes to be written. */
							xReturn );
				}
				#endif /* ioconfigUSE_UART_TX_CHAR_QUEUE */
				break;


			default :

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

				/* 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_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_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 ) );

	/* 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[ cPeripheralNumber ] = diGET_TX_TRANSFER_STRUCT( pxPeripheralControl );
	xDataDirection[ cPeripheralNumber ] = i2cWriting;

	switch( diGET_TX_TRANSFER_TYPE( pxPeripheralControl ) )
	{
		case ioctlUSE_POLLED_TX :

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

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

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


		case ioctlUSE_ZERO_COPY_TX :

			#if ioconfigUSE_I2C_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,
						I2C_IntCmd( pxI2C, DISABLE ),	/* Disable interrupt.  Not really necessary in this case as it should not be enabled anyway. */
						( void ) 0, 					/* As the start condition has not been sent, the interrupt is not enabled yet. */
						0,  							/* In this case no write is attempted and all that should happen is the buffer gets set up ready. */
						pvBuffer, 						/* Data source. */
						xReturn							/* Number of bytes to be written.  This will get set to zero if the write mutex is not held. */
					);

				/* Ensure there are not already interrupt pending. */
				pxI2C->I2CONCLR = ( I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC | I2C_I2CONCLR_AAC | I2C_I2CONCLR_STAC );

				/* Set start flag. */
				pxI2C->I2CONSET = I2C_I2CONSET_STA;

				/* Now enable interrupts. */
				I2C_IntCmd( pxI2C, ENABLE );
			}
			#endif /* ioconfigUSE_I2C_ZERO_COPY_TX */
			break;


		case ioctlUSE_CHARACTER_QUEUE_TX :

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


		default :

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

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

	return xReturn;
}