QueueHandle inside Class

Hi there,

I hope this is the right place for my question. I have an own class and I want to use the QueueHandle inside the class for Intertask-comunication. I started with the generic_gpio example from the ESP Examples found here: esp-idf/examples/peripherals/gpio/generic_gpio at 4523f2d67465373f0e732a3264273a8e84a1a6d1 · espressif/esp-idf · GitHub

So i have the problem if I define the QueueHandle_t gpio_evt_queue; inside the private section of my class, all my classfunctions do not work with this variable. A workaround was to define a variable outside the class as a global variable. The class can work with it but thats not a proper solution. Hopefully someon have a hint for me.

myApp.h

class App {
	public:
          static void IRAM_ATTR gpio_isr_handler(void* arg);
	private:
          // with the QueueHandle on this location my code is not working
          QueueHandle_t gpio_evt_queue;

myApp.cpp

//with the QueueHandle on this Location, my code is working
static QueueHandle_t gpio_evt_queue;

App::App()
{
    //compiler is throwing a error with QueueHandle in private section of myApp.h
    gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
};
void App::gpio_isr_handler(void* arg){
    uint32_t gpio_num = (uint32_t) arg;
    xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}

In the line xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL); The IDE says ‘a nonstatic reference must be relative to a specific object’.

Hopefully someon knows what is to do. Thank you for your time and effort!

Greetings

A static function has no access to member variables of an instance of a class because it lacks the this pointer to the instance.

Instead of just passing the address of the gpio_num variable, pass the address of the entire instance (this pointer).
This gives you access to all member variables of the instance in the static ISR routine:

class App {
  public:
    App();
    void begin(gpio_num_t gpio);

  protected:
    gpio_num_t            gpio_num;
    QueueHandle_t         gpio_evt_queue;
    static void IRAM_ATTR gpio_isr_handler(void* arg);
};

App::App()
    : gpio_num(GPIO_NUM_NC) {
    gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
}

void App::begin(gpio_num_t gpio) {
    gpio_num = gpio;

    // pass this pointer via arg to the isr handler
    gpio_isr_handler_add(gpio_num, &App::gpio_isr_handler, this);
}

void App::gpio_isr_handler(void* arg) {
    // get the instance ("this-pointer") form arg
    App* instance = static_cast<App*>(arg);
    
    xQueueSendFromISR(instance->gpio_evt_queue, &instance->gpio_num, NULL);
}

Via the instance pointer you have now access to all member variables:

image

Note: I freely invented the begin function because I don’t know where you call the gpio_isr_handler_add function. But I think the principle is clear.

Thank you very very much! I realy understand some things now, because this intermezzo drove me crazy. It’s actually quite simple once you understand the principle.

Thank you for your time sivar.

1 Like