void vSerialISR( void ) { unsigned long ulStatus; signed char cChar; portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; /* What caused the interrupt? */ ulStatus = BOARD_USART_BASE->US_CSR &= BOARD_USART_BASE->US_IMR; if( ulStatus & AT91C_US_TXRDY ) { /* 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. */ BOARD_USART_BASE->US_THR = cChar; } else { /* Queue empty, nothing to send so turn off the Tx interrupt. */ vInterruptOff(); } } if( ulStatus & AT91C_US_RXRDY ) { /* The interrupt was caused by a character being received. Grab the character from the RHR and place it in the queue or received characters. */ cChar = BOARD_USART_BASE->US_RHR; 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 ); }
static portBASE_TYPE xComPortISR( xComPort * const pxPort ) { unsigned short usStatusRegister; char cChar; portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE, xContinue = pdTRUE; /* NOTE: THIS IS NOT AN EFFICIENT ISR AS IT IS DESIGNED SOLELY TO TEST THE SCHEDULER FUNCTIONALITY. REAL APPLICATIONS SHOULD NOT USE THIS FUNCTION. */ while( xContinue == pdTRUE ) { xContinue = pdFALSE; usStatusRegister = portINPUT_WORD( pxPort->usStatusReg ); if( usStatusRegister & serRX_READY ) { cChar = ( char ) portINPUT_WORD( pxPort->usRxReg ); xQueueSendFromISR( pxPort->xRxedChars, &cChar, &xHigherPriorityTaskWoken ); /* Also release the semaphore - this does nothing interesting and is just a test. */ xSemaphoreGiveFromISR( pxPort->xTestSem, &xHigherPriorityTaskWoken ); /* We have performed an action this cycle - there may be other to perform. */ xContinue = pdTRUE; } if( pxPort->sTxInterruptOn && ( usStatusRegister & serTX_EMPTY ) ) { if( xQueueReceiveFromISR( pxPort->xCharsForTx, &cChar, &xHigherPriorityTaskWoken ) == pdTRUE ) { portOUTPUT_WORD( pxPort->usTxReg, ( unsigned short ) cChar ); /* We have performed an action this cycle - there may be others to perform. */ xContinue = pdTRUE; } else { /* Queue empty, nothing to send */ vInterruptOff( pxPort, serTX_HOLD_EMPTY_INT ); } } } serRESET_PIC( pxPort->usIRQVector ); /* If posting to the queue woke a task that was blocked on the queue we may want to switch to the woken task - depending on its priority relative to the task interrupted by this ISR. */ return xHigherPriorityTaskWoken; }
__interrupt void SIG_UART_DATA( void ) { signed char cChar, cTaskWoken = pdFALSE; if( xQueueReceiveFromISR( xCharsForTx, &cChar, &cTaskWoken ) == pdTRUE ) { /* Send the next character queued for Tx. */ outb( UDR, cChar ); } else { /* Queue empty, nothing to send. */ vInterruptOff(); } }
void vSerialClose( xComPortHandle xPort ) { unsigned char ucByte; /* Turn off the interrupts. We may also want to delete the queues and/or re-install the original ISR. */ portENTER_CRITICAL(); { vInterruptOff(); ucByte = UCSRB; ucByte &= ~serRX_INT_ENABLE; outb( UCSRB, ucByte ); } portEXIT_CRITICAL(); }
void vSerialClose( xComPortHandle xPort ) { uint8_t ucByte; /* The parameter is not used. */ ( void ) xPort; /* Turn off the interrupts. We may also want to delete the queues and/or re-install the original ISR. */ vPortFree (serialWorkBuffer); vQueueDelete(xRxedChars); vQueueDelete(xCharsForTx); portENTER_CRITICAL(); { vInterruptOff(); ucByte = UCSR0B; ucByte &= ~(_BV(RXCIE0)); UCSR0B = ucByte; } portEXIT_CRITICAL(); }