void prvvMBSerialIRQHandler( void ) { portENTER_SWITCHING_ISR( ); static BOOL xTaskWokenReceive = FALSE; static BOOL xTaskWokenTransmit = FALSE; static USHORT usStatus; usStatus = UART_FlagStatus( MB_UART_DEV ); if( prvMBPortTXIsEnabled( ) && ( usStatus & UART_TxHalfEmpty ) ) { xTaskWokenReceive = pxMBFrameCBTransmitterEmpty( ); } if( prvMBPortRXIsEnabled( ) && ( usStatus & UART_RxBufFull ) ) { xTaskWokenReceive = pxMBFrameCBByteReceived( ); } /* End the interrupt in the EIC. */ EIC->IPR |= 1 << EIC_CurrentIRQChannelValue( ); portEXIT_SWITCHING_ISR( ( xTaskWokenReceive || xTaskWokenTransmit ) ? pdTRUE : pdFALSE ); }
/* Serial port ISR. This can cause a context switch so is not defined as a standard ISR using the __irq keyword. Instead a wrapper function is defined within serialISR.s79 which in turn calls this function. See the port documentation on the FreeRTOS.org website for more information. */ __arm void vSerialISR( void ) { unsigned short usStatus; signed char cChar; portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; /* What caused the interrupt? */ usStatus = UART_FlagStatus( UART0 ); if( usStatus & UART_TxHalfEmpty ) { /* The interrupt was caused by the THR becoming empty. Are there any more characters to transmit? */ if( xQueueReceiveFromISR( xCharsForTx, &cChar, &xHigherPriorityTaskWoken ) == pdTRUE ) { /* A character was retrieved from the queue so can be sent to the THR now. */ UART0->TxBUFR = cChar; } else { /* Queue empty, nothing to send so turn off the Tx interrupt. */ serINTERRUPT_OFF(); } } if( usStatus & UART_RxBufFull ) { /* The interrupt was caused by a character being received. Grab the character from the RHR and place it in the queue of received characters. */ cChar = UART0->RxBUFR; xQueueSendFromISR( xRxedChars, &cChar, &xHigherPriorityTaskWoken ); } /* If a task was woken by either a character being received or a character being transmitted then we may need to switch to another task. */ portEND_SWITCHING_ISR( xHigherPriorityTaskWoken ); /* End the interrupt in the EIC. */ portCLEAR_EIC(); }
void sio_serial_isr( UART_TypeDef * UARTx, u8_t * need_ctx_switch ) { int i; u16 status; volatile serdev_t *dev = SIO_FD_NULL; portBASE_TYPE rx_woken = pdFALSE; portBASE_TYPE tx_woken = pdFALSE; for( i = 0; i < UART_DEVICES_MAX; i++ ) { if( devices[i].ready && ( devices[i].UARTx == UARTx ) ) { dev = &devices[i]; break; } } if( dev != SIO_FD_NULL ) { status = UART_FlagStatus( dev->UARTx ); /* If there are characters in the UART fifo place them into the * ring buffer. In case the buffer is filled half or the requested * number of bytes has been read wakeup the receiver. */ if( status & UART_RxBufFull ) { do { /* Store the character in the ring buffer and advance write * position. */ dev->rx_buf[dev->rx_buf_wrpos] = dev->UARTx->RxBUFR; dev->rx_buf_wrpos = ( dev->rx_buf_wrpos + 1 ) % DEFAULT_RX_BUFSIZE; /* Increment the receiver buffer counter. Check for a buffer * overrun. In that case we have overwritten a old character. * Therefore we have to advance the read position. Note that * in this error case we must not increment the read counter * because an old character was lost. */ if( dev->rx_buf_cnt >= DEFAULT_RX_BUFSIZE ) { /* LWIP_ASSERT( "sio_serial_isr: receiver buffer overflow", 0 ); */ dev->rx_buf_rdpos = ( dev->rx_buf_rdpos + 1 ) % DEFAULT_RX_BUFSIZE; } else { dev->rx_buf_cnt++; } /* Get the new status from the UART. */ status = UART_FlagStatus( dev->UARTx ); } while( status & UART_RxBufFull ); /* Wakeup receiver if buffer is starting to fill. */ if( dev->rx_buf_cnt > ( DEFAULT_RX_BUFSIZE / 2 ) ) { rx_woken = xSemaphoreGiveFromISR( dev->rx_sem, rx_woken ); } } /* Check if we must send characters. */ if( ( dev->tx_buf_cnt > 0 ) && ( status & UART_TxHalfEmpty ) ) { do { /* Fetch character from the ring buffer and place them into * the FIFO. */ dev->UARTx->TxBUFR = dev->tx_buf[dev->tx_buf_rdpos]; dev->tx_buf_rdpos = ( dev->tx_buf_rdpos + 1 ) % DEFAULT_TX_BUFSIZE; dev->tx_buf_cnt--; /* Get the new status from the UART. */ status = UART_FlagStatus( dev->UARTx ); } while( ( dev->tx_buf_cnt > 0 ) && ( status & UART_TxHalfEmpty ) ); if( dev->tx_buf_cnt == 0 ) { tx_woken = xSemaphoreGiveFromISR( dev->tx_sem, tx_woken ); UART_ItConfig( dev->UARTx, UART_TxHalfEmpty, DISABLE ); } } if( tx_woken || rx_woken ) { *need_ctx_switch = 1; } } }