in lib/cmsis/CMSIS/Pack/Example/CMSIS_Driver/USART_LPC18xx.c [1759:1896]
static void USART_IRQHandler (USART_RESOURCES *usart) {
uint32_t iir, event, val;
event = 0;
iir = usart->reg->IIR;
if ((iir & USART_IIR_INTSTATUS) == 0) {
// Transmit holding register empty
if ((iir & USART_IIR_INTID_MSK) == USART_IIR_INTID_THRE) {
val = 16;
while ((val --) && (usart->info->xfer.tx_num != usart->info->xfer.tx_cnt)) {
if (((usart->info->mode == ARM_USART_MODE_SYNCHRONOUS_MASTER) ||
(usart->info->mode == ARM_USART_MODE_SYNCHRONOUS_SLAVE )) &&
(usart->info->xfer.sync_mode == USART_SYNC_MODE_RX)) {
// Dummy write in synchronous receive only mode
usart->reg->THR = usart->info->xfer.tx_def_val;
} else {
// Write data to Tx FIFO
usart->reg->THR = usart->info->xfer.tx_buf[usart->info->xfer.tx_cnt];
}
usart->info->xfer.tx_cnt++;
}
// Check if all data is transmitted
if (usart->info->xfer.tx_num == usart->info->xfer.tx_cnt) {
// Disable THRE interrupt
usart->reg->IER &= ~USART_IER_THREIE;
// Clear TX busy flag
usart->info->flags &= ~USART_FLAG_SEND_ACTIVE;
// Set send complete event
if ((usart->info->mode == ARM_USART_MODE_SYNCHRONOUS_MASTER) ||
(usart->info->mode == ARM_USART_MODE_SYNCHRONOUS_SLAVE )) {
if ((usart->info->xfer.sync_mode == USART_SYNC_MODE_TX) &&
((usart->info->flags & USART_FLAG_RX_ENABLED) == 0)) {
event |= ARM_USART_EVENT_SEND_COMPLETE;
}
} else {
event |= ARM_USART_EVENT_SEND_COMPLETE;
}
}
}
// Receive line status
if ((iir & USART_IIR_INTID_MSK) == USART_IIR_INTID_RLS) {
event |= USART_RxLineIntHandler(usart);
}
// Receive data available and Character time-out indicator interrupt
if (((iir & USART_IIR_INTID_MSK) == USART_IIR_INTID_RDA) |
((iir & USART_IIR_INTID_MSK) == USART_IIR_INTID_CTI)) {
// Get all available data from RX FIFO
while (usart->reg->LSR & USART_LSR_RDR) {
// Check RX line interrupt for errors
event |= USART_RxLineIntHandler (usart);
if (((usart->info->mode == ARM_USART_MODE_SYNCHRONOUS_MASTER) ||
(usart->info->mode == ARM_USART_MODE_SYNCHRONOUS_SLAVE )) &&
(usart->info->xfer.sync_mode == USART_SYNC_MODE_TX)) {
// Dummy read in synchronous transmit only mode
usart->reg->RBR;
} else {
// Read data from RX FIFO into receive buffer
usart->info->xfer.rx_buf[usart->info->xfer.rx_cnt] = usart->reg->RBR;
}
usart->info->xfer.rx_cnt++;
// Check if requested amount of data is received
if (usart->info->xfer.rx_cnt == usart->info->xfer.rx_num) {
// Disable RDA interrupt
usart->reg->IER &= ~USART_IER_RBRIE;
// Clear RX busy flag and set receive transfer complete event
usart->info->status.rx_busy = 0;
if ((usart->info->mode == ARM_USART_MODE_SYNCHRONOUS_MASTER) ||
(usart->info->mode == ARM_USART_MODE_SYNCHRONOUS_SLAVE )) {
val = usart->info->xfer.sync_mode;
usart->info->xfer.sync_mode = 0;
switch (val) {
case USART_SYNC_MODE_TX:
event |= ARM_USART_EVENT_SEND_COMPLETE;
break;
case USART_SYNC_MODE_RX:
event |= ARM_USART_EVENT_RECEIVE_COMPLETE;
break;
case USART_SYNC_MODE_TX_RX:
event |= ARM_USART_EVENT_TRANSFER_COMPLETE;
break;
}
} else {
event |= ARM_USART_EVENT_RECEIVE_COMPLETE;
}
break;
}
}
}
// Character time-out indicator
if ((iir & USART_IIR_INTID_MSK) == USART_IIR_INTID_CTI) {
if ((usart->info->mode != ARM_USART_MODE_SYNCHRONOUS_MASTER) &&
(usart->info->mode != ARM_USART_MODE_SYNCHRONOUS_SLAVE )) {
// Signal RX Time-out event, if not all requested data received
if (usart->info->xfer.rx_cnt != usart->info->xfer.rx_num) {
event |= ARM_USART_EVENT_RX_TIMEOUT;
}
}
}
// Modem interrupt (UART1 only)
#if (RTE_UART1)
if (usart->uart_reg) {
if ((iir & USART_IIR_INTID_MSK) == UART_IIR_INTID_MS) {
// Save modem status register
val = usart->uart_reg->MSR;
// CTS state changed
if ((usart->capabilities.cts) && (val & UART_MSR_DCTS))
event |= ARM_USART_EVENT_CTS;
// DSR state changed
if ((usart->capabilities.dsr) && (val & UART_MSR_DDSR))
event |= ARM_USART_EVENT_DSR;
// Ring indicator
if ((usart->capabilities.ri) && (val & UART_MSR_TERI))
event |= ARM_USART_EVENT_RI;
// DCD state changed
if ((usart->capabilities.dcd) && (val & UART_MSR_DDCD))
event |= ARM_USART_EVENT_DCD;
}
}
#endif
}
if (usart->info->cb_event && event)
usart->info->cb_event (event);
}