rgrover1 wrote on Friday, May 21, 2010:
I am working with FreeRTOS6.0.4 using GCC on a Cortex-M3.
I would like to implement a driver for the UART peripheral using interrupts.
I have created a binary semaphore to synchronize between the ISR and the task calling Uart_GetChar(). The interrupt handler gets called, but it is unable to wakeup the task waiting on the binary semaphore.
I started with the standard port for CORTEX_CM3 and simply linked the PendSV_Handler and SVC_Handler to the appropriate functions in the port. Everything else seemed to be working thus far.
The following is the code I’m using:
uint8_t
UART_GetChar(volatile Uart *pUart)
{
/* wait indefinitely for data to arrive */
while ((pUart->UART_SR & UART_SR_RXRDY) == 0) {
xSemaphoreTake(xBinarySemaphore, portMAX_DELAY);
}
return (pUart->UART_RHR);
}
void
UART0_IrqHandler(void)
{
portBASE_TYPE xHigherPriorityTaskWoken;
xHigherPriorityTaskWoken = pdFALSE;
/* unblock a task waiting for data to arrive at UART0. */
xSemaphoreGiveFromISR(xBinarySemaphore, &xHigherPriorityTaskWoken);
if (xHigherPriorityTaskWoken == pdTRUE) {
/*
* If the priority of the unblocked task is higher than the
* currently running task - force a context switch to ensure
* that the interrupt returns directly to the unblocked
* (higher priority) task-i.e. the task waiting for the data.
*/
portYIELD();
}
}
I have verified that my interrupt handler gets called (using an LED).
Through debugging printfs, I have discovered that the IRQ is called only once (even though I’m generating multiple events) and the task is blocked within the call to xTaskResumeAll() (at line 944 in queue.c):
vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
prvUnlockQueue( pxQueue );
if( !xTaskResumeAll() )
{
portYIELD_WITHIN_API();
}
Could someone please help?
Thanks.