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