Page 1 of 1

Basic queue help please

Posted: Sat Jul 08, 2023 8:50 am
by Lancsrick
Hi all,

I'm missing something fundamental here and could do with some help please.

The aim is to get an interrupt writing the current elapsed time to a queue. To do that I'm using xQueueSendFromISR and esp_timer_get_time(). I've included the relevant lines of code below. Any help would be greatly appreciated, thanks.

Code: Select all

#include "freertos/queue.h"
#include "esp_timer.h"

QueueHandle_t red_line_queue;

void IRAM_ATTR isr_function( void *arg) 
{
    xQueueSendFromISR(red_line_queue,esp_timer_get_time(),(TickType_t(0));
}
I'm currently getting errors of:
src/main.c:125:2: error: unterminated argument list invoking macro "xQueueSendFromISR"
src/main.c:39:5: error: 'xQueueSendFromISR' undeclared (first use in this function); did you mean 'xQueueCRSendFromISR'? (This is the xQueueSendFromISR line)


I can't for the life of me see why the argument list is unterminated!

Re: Basic queue help please

Posted: Sat Jul 08, 2023 10:44 am
by MicroController
The first problem is the missing ")" after (TickType_t(0)).

Then, you need to pass in a pointer to the data to enqueue, and you should also use pxHigherPriorityTaskWoken (which also must be a pointer, but may be NULL).

like so

Code: Select all

void IRAM_ATTR isr_function( void *arg) 
{
   const int64_t time = esp_timer_get_time(); // store the "data" we want to enqueue into a local variable
   BaseType_t shouldYield = pdFALSE; // declare and initialize another local variable for the pxHigherPriorityTaskWoken argument
   
   xQueueSendFromISR(
       red_line_queue,
       &time, // pass a *pointer* to our data (local variable) to the function; the data pointed-to will be *copied* into the queue
       &shouldYield); // pass a *pointer* to the shouldYield local variable (= shouldYield is used as an output parameter)

   // If some task was waiting on our queue and should now be switched to,
   // xQueueSendFromISR will have set our shouldYield variable to pdTRUE       
   if(shouldYield != pdFALSE) {
       // let FreeRTOS know that we want it to switch tasks now
       portYIELD_FROM_ISR();
   }
}

Re: Basic queue help please

Posted: Sat Jul 08, 2023 1:09 pm
by Lancsrick
Great thank you :). I'll do some reading up to understand what those changes do. Appreciate the help :).

Re: Basic queue help please

Posted: Sat Jul 08, 2023 3:44 pm
by MicroController
Added some explanatory comments :)

The shouldYield and portYIELD_FROM_ISR() part is not strictly required, but without it the task reading from the queue may not "see" the data before the next OS tick, which can cause a delay in processing of up to one OS tick (default: 10ms).

Re: Basic queue help please

Posted: Sat Jul 08, 2023 3:57 pm
by Lancsrick
That's brilliant thanks. I'm used to using pointers as a way of updating data at a fixed address for a later task to read, why is this being used as an intermediary in the ISR?

Re: Basic queue help please

Posted: Sat Jul 08, 2023 11:04 pm
by MicroController
Arbitrary data types:
The FreeRTOS queues are generic and can be used with arbitrary data items, from e.g. simple int's to structs to arrays which may all have different sizes from one byte to maybe tens or hundreds of bytes.
In order for a single C function to accept arbitrary kinds/types/sizes of data, a (void) pointer is basically the only option the language provides. (In C++ you could use templates and references instead.)

"Output" parameter:
The pxHigherPriorityTaskWoken is meant to serve as an output of the function, i.e. a place where the function can store a value for the caller. Again, in C, the only way to achieve this is to pass a pointer to a variable into the function so that the function can write a value to the (caller's) variable.
Notice that xQueueSendFromISR actually already has a return value (for indicating success/failure) and uses the "output parameter" to give an additional, second output back to the caller.

Btw, here is the relevant FreeRTOS documentation.