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); }
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 ); }