void UART3_IRQHandler( void )
{
uint32_t ulInterruptSource, ulReceived;
const uint32_t ulRxInterrupts = ( UART_IIR_INTID_RDA | UART_IIR_INTID_CTI );
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
const unsigned portBASE_TYPE uxUARTNumber = 3UL;
Transfer_Control_t *pxTransferStruct;

	/* Determine the interrupt source. */
	ulInterruptSource = UART_GetIntId( LPC_UART3 );

	if( ( ulInterruptSource & ulRxInterrupts ) != 0UL )
	{
		pxTransferStruct = pxRxTransferControlStructs[ uxUARTNumber ];
		if( pxTransferStruct != NULL )
		{
			switch( diGET_TRANSFER_TYPE_FROM_CONTROL_STRUCT( pxTransferStruct ) )
			{
				case ioctlUSE_CIRCULAR_BUFFER_RX :

					#if ioconfigUSE_UART_CIRCULAR_BUFFER_RX == 1
					{
						ioutilsRX_CHARS_INTO_CIRCULAR_BUFFER_FROM_ISR(
																	pxTransferStruct, 	/* The structure that contains the reference to the circular buffer. */
																	( ( LPC_UART3->LSR & UART_LSR_RDR ) != 0 ), 	/* While loop condition. */
																	LPC_UART3->RBR,			/* Register holding the received character. */
																	ulReceived,
																	xHigherPriorityTaskWoken
																);
					}
					#endif /* ioconfigUSE_UART_CIRCULAR_BUFFER_RX */
					break;


				case ioctlUSE_CHARACTER_QUEUE_RX :

					#if ioconfigUSE_UART_RX_CHAR_QUEUE == 1
					{
						ioutilsRX_CHARS_INTO_QUEUE_FROM_ISR( pxTransferStruct, ( ( LPC_UART3->LSR & UART_LSR_RDR ) != 0 ), LPC_UART3->RBR, ulReceived, xHigherPriorityTaskWoken );
					}
					#endif /* ioconfigUSE_UART_RX_CHAR_QUEUE */
					break;


				default :

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

	if( ( ulInterruptSource & UART_IIR_INTID_THRE ) != 0UL )
	{
		/* The transmit holding register is empty.  Is there any more data
		to send? */
		pxTransferStruct = pxTxTransferControlStructs[ uxUARTNumber ];
		if( pxTransferStruct != NULL )
		{
			switch( diGET_TRANSFER_TYPE_FROM_CONTROL_STRUCT( pxTransferStruct ) )
			{
				case ioctlUSE_ZERO_COPY_TX:

					#if ioconfigUSE_UART_ZERO_COPY_TX == 1
					{
						iouitlsTX_CHARS_FROM_ZERO_COPY_BUFFER_FROM_ISR( pxTransferStruct, ( ( LPC_UART3->FIFOLVL & uartTX_FIFO_LEVEL_MASK ) != uartTX_FIFO_LEVEL_MASK ), ( LPC_UART3->THR = ucChar ), xHigherPriorityTaskWoken );
					}
					#endif /* ioconfigUSE_UART_ZERO_COPY_TX */
					break;


				case ioctlUSE_CHARACTER_QUEUE_TX:

					#if ioconfigUSE_UART_TX_CHAR_QUEUE == 1
					{
						ioutilsTX_CHARS_FROM_QUEUE_FROM_ISR( pxTransferStruct, ( UART_FIFOLVL_TXFIFOLVL( LPC_UART3->FIFOLVL ) != ( UART_TX_FIFO_SIZE - 1 ) ), ( LPC_UART3->THR = ucChar ), xHigherPriorityTaskWoken );
					}
					#endif /* ioconfigUSE_UART_TX_CHAR_QUEUE */
					break;


				default :

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

	/* The ulReceived parameter is not used by the UART ISR. */
	( void ) ulReceived;

	/* 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 );
}
コード例 #2
0
ファイル: FreeRTOS_lpc17xx_ssp.c プロジェクト: jabv/ZumoBot
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 );
}
コード例 #3
0
void uart1_irq_handler(void)
{
    uint32_t ulReceived = 0;
    portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
    const unsigned portBASE_TYPE uxUARTNumber = 1UL;
    Transfer_Control_t *pxTransferStruct;

    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
        pxTransferStruct = pxRxTransferControlStructs[uxUARTNumber];
        if (pxTransferStruct != NULL) {
            switch(diGET_TRANSFER_TYPE_FROM_CONTROL_STRUCT(pxTransferStruct)) {
            case ioctlUSE_CIRCULAR_BUFFER_RX:
            #if ioconfigUSE_UART_CIRCULAR_BUFFER_RX == 1
            {
                ioutilsRX_CHARS_INTO_CIRCULAR_BUFFER_FROM_ISR(
                        pxTransferStruct,   /* The structure that contains the reference to the circular buffer. */
                        (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != RESET),    /* While loop condition. */
                        USART_ReceiveData(USART1),         /* Register holding the received character. */
                        ulReceived,
                        xHigherPriorityTaskWoken);
            }
            #endif /* ioconfigUSE_UART_CIRCULAR_BUFFER_RX */
                break;

            case ioctlUSE_CHARACTER_QUEUE_RX:
            #if ioconfigUSE_UART_RX_CHAR_QUEUE == 1
            {
                size_t i = 1;
                ioutilsRX_CHARS_INTO_QUEUE_FROM_ISR(
                        pxTransferStruct,
                        i--,
                        USART_ReceiveData(USART1),
                        ulReceived,
                        xHigherPriorityTaskWoken);
            }
            #endif /* ioconfigUSE_UART_RX_CHAR_QUEUE */
                break;

            default:
                break;
            }
        }
        USART_ClearITPendingBit(USART1, USART_IT_RXNE);
    }

    if (USART_GetITStatus(USART1, USART_IT_TXE) != RESET) {
        pxTransferStruct = pxTxTransferControlStructs[uxUARTNumber];
        if (pxTransferStruct != NULL) {
            switch (diGET_TRANSFER_TYPE_FROM_CONTROL_STRUCT(pxTransferStruct)) {
            case ioctlUSE_ZERO_COPY_TX:
            #if ioconfigUSE_UART_ZERO_COPY_TX == 1
            {
                iouitlsTX_SINGLE_CHAR_FROM_ZERO_COPY_BUFFER_FROM_ISR(
                        pxTransferStruct,
                        USART_SendData(USART1, ucChar),
                        xHigherPriorityTaskWoken);
            }
            #endif /* ioconfigUSE_UART_ZERO_COPY_TX */
                if (xHigherPriorityTaskWoken != pdTRUE)
                    USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
                break;

            case ioctlUSE_CHARACTER_QUEUE_TX:
            #if ioconfigUSE_UART_TX_CHAR_QUEUE == 1
            {
                size_t i = 1;
                ioutilsTX_CHARS_FROM_QUEUE_FROM_ISR(
                        pxTransferStruct,
                        i--,
                        USART_SendData(USART1, ucChar),
                        xHigherPriorityTaskWoken);
            }
            #endif /* ioconfigUSE_UART_TX_CHAR_QUEUE */
            if (xHigherPriorityTaskWoken != pdTRUE)
                USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
                break;

            default:
                /* This must be an error.  Force an assert. */
                configASSERT( xHigherPriorityTaskWoken );
                break;
            }
        }
        USART_ClearITPendingBit(USART1, USART_IT_TXE);
    }
    /* The ulReceived parameter is not used by the UART ISR. */
    (void) ulReceived;

    /* If xHigherPriorityTaskWoken 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);
}
コード例 #4
0
void I2C2_IRQHandler( void )
{
uint32_t ulI2CStatus, ulChar, ulReceived = 0UL;
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
const unsigned portBASE_TYPE uxI2CNumber = 2UL;
Transfer_Control_t *pxTransferStruct;

	/* Determine the event that caused the interrupt. */
	ulI2CStatus = ( LPC_I2C2->I2STAT & I2C_STAT_CODE_BITMASK );

	/* States that are valid for both Rx and Tx, or are not dependent on either
	of the Rx or Tx state transfer structures being populated. */
	switch( ulI2CStatus )
	{
		case I2C_I2STAT_NO_INF	:

			/* There is no I2C status information to act upon.  Clear the
			interrupt. */
			LPC_I2C2->I2CONCLR = I2C_I2CONCLR_SIC;
			break;


		case I2C_I2STAT_M_RX_START	:
		case I2C_I2STAT_M_RX_RESTART	:

			/* A start or restart.	Send the slave address and 'W'rite
			bits.  This could be during an Rx or a Tx, hence it is outside of
			the Rx and Tx state machines. */
			LPC_I2C2->I2DAT = ( ucSlaveAddresses[ uxI2CNumber ] << 1U ) | ( uint8_t ) xDataDirection[ uxI2CNumber ];

			/* Clear the interrupt and the start bit. */
			LPC_I2C2->I2CONCLR = I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC;
			break;

		case I2C_I2STAT_M_TX_SLAW_NACK: /* SLA+W has been transmitted, and a NACK was received. */
		case I2C_I2STAT_M_TX_DAT_NACK:  /* Data has been transmitted, and a NACK was received. */
		case I2C_I2STAT_M_TX_ARB_LOST:  /* Arbitration lost.  Could be Rx or Tx. */
		case I2C_I2STAT_M_RX_SLAR_NACK: /* SLA+W has been transmitted, and a NACK was received. */
			/* Clear the interrupt. */
			LPC_I2C2->I2CONCLR = I2C_I2CONCLR_SIC;

			/* force an assert. */
			configASSERT( xHigherPriorityTaskWoken );
			break;
	}

	/* Transmit state machine. */
	pxTransferStruct = pxTxTransferControlStructs[ uxI2CNumber ];
	if( pxTransferStruct != NULL )
	{
		switch( ulI2CStatus )
		{
			case I2C_I2STAT_M_TX_SLAW_ACK:
			case I2C_I2STAT_M_TX_DAT_ACK:

				/* An Ack has been received after either the slave address or
				data was transmitted.  Is there more data to send?  */
				iouitlsTX_SINGLE_CHAR_FROM_ZERO_COPY_BUFFER_FROM_ISR( pxTransferStruct, ( LPC_I2C2->I2DAT = ucChar ), ulChar );

				if( ulChar == pdFALSE )
				{
					/* There was no more data to send, so send the stop bit and
					disable interrupts. */
					I2C_IntCmd( LPC_I2C2, DISABLE );
					I2C_Stop( LPC_I2C2 );
					pxTxTransferControlStructs[ uxI2CNumber ] = NULL;
					xDataDirection[ uxI2CNumber ] = i2cIdle;
					ioutilsGIVE_ZERO_COPY_MUTEX( pxTransferStruct, xHigherPriorityTaskWoken );
				}
				else
				{
					/* Clear the interrupt. */
					LPC_I2C2->I2CONCLR = I2C_I2CONCLR_SIC;
				}
				break;


			default:
				/* Error and naks can be implemented by extending this switch
				statement. */
				break;
		}
	}

	/* Receive state machine. */
	pxTransferStruct = pxRxTransferControlStructs[ uxI2CNumber ];
	if( pxTransferStruct != NULL )
	{
		switch( ulI2CStatus )
		{
			case I2C_I2STAT_M_RX_SLAR_ACK:
				/* The slave address has been acknowledged. */
				if( xBytesOutstanding[ uxI2CNumber ] > 1U )
				{
					/* Expecting more than one more byte, keep ACKing. */
					LPC_I2C2->I2CONSET = I2C_I2CONSET_AA;
				}
				else
				{
					/* End the reception after the next byte. */
					LPC_I2C2->I2CONCLR = I2C_I2CONSET_AA;
				}
				LPC_I2C2->I2CONCLR = I2C_I2CONCLR_SIC;
				break;


			case I2C_I2STAT_M_RX_DAT_ACK:
			case I2C_I2STAT_M_RX_DAT_NACK:

				/* Data was received.  The strange ( ulChar++ == 0UL )
				parameter is used to ensure only a single character is
				received. */
				ulChar = 0UL;
				ioutilsRX_CHARS_INTO_CIRCULAR_BUFFER_FROM_ISR(
															pxTransferStruct, 		/* The structure that contains the reference to the circular buffer. */
															( ulChar++ == 0UL ), 	/* While loop condition. */
															LPC_I2C2->I2DAT,		/* Register holding the received character. */
															ulReceived,
															xHigherPriorityTaskWoken
														);

				configASSERT( xBytesOutstanding[ uxI2CNumber ] );
				( xBytesOutstanding[ uxI2CNumber ] )--;

				if( ulI2CStatus == I2C_I2STAT_M_RX_DAT_ACK )
				{
					if( xBytesOutstanding[ uxI2CNumber ] > 1U )
					{
						/* Expecting more than one more byte, keep ACKing. */
						LPC_I2C2->I2CONSET = I2C_I2CONSET_AA;
					}
					else
					{
						/* End the reception after the next byte. */
						LPC_I2C2->I2CONCLR = I2C_I2CONSET_AA;
					}
					LPC_I2C2->I2CONCLR = I2C_I2CONCLR_SIC;
				}
				else
				{
					/* This is the last data item. */
					configASSERT( xBytesOutstanding[ uxI2CNumber ] == 0U );
					I2C_IntCmd( LPC_I2C2, DISABLE );
					I2C_Stop( LPC_I2C2 );
					xDataDirection[ uxI2CNumber ] = i2cIdle;
				}
				break;


			default:
				/* Error and naks can be implemented by extending this switch
				statement.  */
				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 );
}