コード例 #1
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);
}
コード例 #2
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 );
}