Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT




Loading

Unable to use BinarySemaphore on Cortex-M3

Posted by Rohit Grover on 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[0], 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[0], &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.

RE: Unable to use BinarySemaphore on Cortex-M3

Posted by Dave on May 21, 2010
What priority is the UART interrupt running at? Is it at or below whatever you have configMAX_SYSCALL_INTERRUPT_PRIORITY. And remember that a lower interrupt priority means a higher number (priority 5 is lower than priority 4). Are you sure that you have passed the priority into the function used to set the interrupt priority correctly as some want the number shifted and others don't.

One other thing, you don't mention that you installed the SysTick interrupt, which is another one FreeRTOS uses.

RE: Unable to use BinarySemaphore on Cortex-M3

Posted by Rohit Grover on May 21, 2010
I have not set the priority for the UART interrupt. According to the microcontroller's datasheet, the uart interrupt would be running priority 0. Oops. This means that it is running at a priority higher than configMAX_SYSCALL_INTERRUPT_PRIORITY while still attempting to use a FreeRTOS API. Perhaps that could explain why my program isn't working.

I fail to understand why an interrupt executing at a high priority would fail to Give() to a binary semaphore. All it would need to do is to set the semaphore as being available and setup a pending SV exception to be triggered upon return. Why would this run into trouble because of the priority especially since nothing else in the system is competing with this sequence?

By the way, I forgot to mention that I have also setup the SysTick interrupt handler to be the one provided by the port.

I will try to set a reasonable priority for the UART interrupt and report back. Thanks.

RE: Unable to use BinarySemaphore on Cortex-M3

Posted by Richard Damon on May 21, 2010
The issue with I high priority interrupt accessing FreeRTOS structures is that they may not be in a stable condition, and accessing them may corrupt their state. FreeRTOS may (depending on the port) only block interrupts below a given priority when modifying critical resources, in order to not impact the latency of those higher priority interrupts that don't need to interact with FreeRTOS.

RE: Unable to use BinarySemaphore on Cortex-M3

Posted by Rohit Grover on May 22, 2010
Hello again,

I tried setting the priority of the UART interrupt to configMAX_SYSCALL_INTERRUPT_PRIORITY--see the Configure() function included below,--but that still doesn't help. I have added code in my UART0 ISR to toggle an LED, but the LED gets set only once. The task waiting in GetChar doesn't make progress.

Please help.


#if defined(__FREERTOS__) && defined(UART_USES_INTERRUPTS)
/* The following pair of counting semaphores (one per UART) allow
* tasks to block waiting for interrupt events. */
static xSemaphoreHandle xBinarySemaphore[2];
#endif /* defined(__FREERTOS__) && defined(UART_USES_INTERRUPTS) */

/**
* \brief Configures an UART peripheral with the specified
* parameters. The UART is configured for 8-bit I/O (with no parity)
* using interrupts.
*
* \param uart The UART's configuration base memory address; as
* defined in board/at91sam3s4/AT91SAM3S4.h.
*
* \param baud Baudrate at which the UART should operate (in Hz).
*/
void
UART_Configure(Uart *pUart, uint32_t baud)
{
const Pin pins[] = {PINS_UART0, PINS_UART1};

/*
* For the AT91SAM3S4 micro-controller, there can only be two
* possile UARTs. Given the UART's base address as a parameter, it
* is possible to deduce some of the required initial state.
*/
if (pUart == UART0) {
#if defined(__FREERTOS__) && defined(UART_USES_INTERRUPTS)
/* IRQ must be enabled before configuring the UART registers */
NVIC_EnableIRQ(UART0_IRQn);
NVIC_SetPriority(UART0_IRQn, configMAX_SYSCALL_INTERRUPT_PRIORITY);

vSemaphoreCreateBinary(xBinarySemaphore[0]);
#endif /* defined(__FREERTOS__) && defined(UART_USES_INTERRUPTS) */

/* Configure the use of the UART pins */
PIO_Configure(&pins[0], 1);

/* Configure PMC to enable the UART0 peripheral */
PMC->PMC_PCER0 = 1 << ID_UART0;
} else if (pUart == UART1) {
#if defined(__FREERTOS__) && defined(UART_USES_INTERRUPTS)
/* IRQ must be enabled before configuring the UART registers */
NVIC_EnableIRQ(UART1_IRQn);
NVIC_SetPriority(UART1_IRQn, configMAX_SYSCALL_INTERRUPT_PRIORITY);

vSemaphoreCreateBinary(xBinarySemaphore[1]);
#endif /* defined(__FREERTOS__) && defined(UART_USES_INTERRUPTS) */

/* Configure the use of the UART pins */
PIO_Configure(&pins[1], 1);

/* Configure PMC to enable the UART1 peripheral */
PMC->PMC_PCER0 = 1 << ID_UART1;
} else {
/* NOTE: We should never be here!! */
/* XXX: add a LOG_ERR message here! */
return;
}

/* Reset and disable receiver & transmitter */
pUart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX
| UART_CR_RXDIS | UART_CR_TXDIS;

/* Configure mode */
pUart->UART_MR = UART_MR_PAR_NONE;

/* Configure baudrate */
/* Asynchronous, no oversampling */
pUart->UART_BRGR = (BOARD_MCK / 16) / baud;

/* Disable PDC channel */
pUart->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS;

/* Enable receiver and transmitter */
pUart->UART_CR = UART_CR_RXEN | UART_CR_TXEN;

#if defined(__FREERTOS__) && defined(UART_USES_INTERRUPTS)
pUart->UART_IER = UART_IER_RXRDY;
#endif /* defined(__FREERTOS__) && defined(UART_USES_INTERRUPTS) */
}

#if defined(__FREERTOS__) && defined(UART_USES_INTERRUPTS)
/*
* Interrupt Handlers for UART.
*/
void
UART0_IrqHandler(void)
{
portBASE_TYPE xHigherPriorityTaskWoken;

xHigherPriorityTaskWoken = pdFALSE;

LED_Toggle(0);

/* unblock a task waiting for data to arrive at UART0. */
xSemaphoreGiveFromISR(xBinarySemaphore[0], &xHigherPriorityTaskWoken);

/*
* 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.
*/
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
}

/**
* \brief Input a character from the UART line.
*
* \note This function is synchronous
* \return character received.
*/
uint8_t
UART_GetChar(volatile Uart *pUart)
{
/* wait indefinitely for data to arrive */
while ((pUart->UART_SR & UART_SR_RXRDY) == 0) {
xSemaphoreTake(xBinarySemaphore[0], portMAX_DELAY);
}

return (pUart->UART_RHR);
}



RE: Unable to use BinarySemaphore on Cortex-M3

Posted by Rohit Grover on May 22, 2010
I apologize for that confusing
...
block I included in the previous post. I hope you able to make sense of it if you begin reading from UART_Configure(). Thanks again.

RE: Unable to use BinarySemaphore on Cortex-M3

Posted by Rohit Grover on May 24, 2010
I have discovered that calling xQueueCreate (or vCreateBinarySemaphore) blows away my interrupt handler on the Cortex-CM3.

My initialization routine sets up the UART0 interrupt hander to go at configKERNEL_INTERRUPT_PRIORITY. Inside the ISR, I am toggling an LED plus reading UART0->UART_RHR to clear the status register. With this setup, every time I press a key in the console window, my LED toggles.

But when I add a xQueueCreate() to this mix, the LED doesn't toggle with key presses. I am not using the queue for anything and yet my ISR fails to go.

What am I missing? Please help.

RE: Unable to use BinarySemaphore on Cortex-M3

Posted by Rohit Grover on May 24, 2010
I hadn't paid attention to the following in the FAQ:

“Many API functions cannot be called prior to the scheduler being started. It is best to restrict such usage to the creation of the tasks, queues and semaphores that will be used once the scheduler activity has commenced.”


I have moved all my usage of Queues to after the scheduler is started; and now things appear to be working normally. I am able to use a queue to synchronize between an ISR and a task.

Thanks.


[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

FreeRTOS kernel V10 is available for immediate download. Now MIT licensed.


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS