- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
How do you write a UART receiver ISR in FreeRTOS when I send a command and sometimes get a response quickly. I'm trying to use a binary semaphore but I have a race condition where I get the response before I execute the xSemaphoreTake(). Here's what I'm doing:
SemaphoreHandle_t msg_rcvd_semaphore = NULL;
uint32 my_data;
void xbee_rx_isr(void)
{
volatile uint32_t read_data;
// Ignore all but received byte interrupts
if((XBEE_UART_HW->INTR_RX_MASKED & SCB_INTR_RX_MASKED_NOT_EMPTY_Msk ) == 0) {
return;
}
// Clear UART "RX fifo not empty interrupt"
XBEE_UART_HW->INTR_RX = XBEE_UART_HW->INTR_RX & SCB_INTR_RX_NOT_EMPTY_Msk;
// Get the byte
my_data = Cy_SCB_UART_Get(XBEE_UART_HW);
//
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(msg_rcvd_semaphore, &xHigherPriorityTaskWoken);
if (xHigherPriorityTaskWoken == pdTRUE) {
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}
void task (void)
{
msg_rcvd_semaphore = xSemaphoreCreateBinary();
// Initialize the receiver here
// Send commands and block for their responses
for (;;) {
// Transmit a command
xbee_uart_put_string("my_command");
// MY PROBLEM: Sometimes the response (and ISR) comes before I execute the following
// xSemaphoreTake(), in which case xSemaphoreTake() hangs forever.
// Wait for response (with 100 ms timeout)
if (xSemaphoreTake(msg_rcvd_semaphore, pdMS_TO_TICKS(100u)) == pdPASS) {
// Process my_data
} else {
// Process timeout
}
}
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
What is the problem with receiving the reply before executing xSemaphoreTake()? If that happens the fact the interrupt occurred is latched by the semaphore, so the call to take the semaphore will return immediately as the semaphore is already there. If interrupts occur quickly you may want to use a counting semaphore instead. Also, if it is always the same task that is signaled from the interrupt, consider using a task notification in place of a semaphore. There are some code examples here: FreeRTOS task notifications, fast Real Time Operating System (RTOS) event mechanism
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Mine doesn’t work that way for some reason. If the interrupt occurs before xSemaphoreTake(),it does not return immediately. It hangs. Do I need to initialize the semaphore before transmitting the command? I will look into your other suggestions. Thanks!!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
/Hi jihe_298791,
Are you generating an interrupt on every character received? If so, if you are receiving multiples character at a faster rate, there are chances that you might miss the interrupt event and hence the received character is lost when using Binary Semaphore. As suggested you can use a counting semaphore or task notifications. You can also try using level interrupts instead of RX FIFO NOT EMPTY interrupt so that your ISR is not triggered often.
Also, is the xSemaphoreTake() not returning even once?
What is the priority of the UART interrupt and what is the setting of configMAX_API_CALL_INTERRUPT_PRIORITY in your project?
Regards,
Bragadeesh
Bragadeesh