0

I'm writing an auto display turn-off function with ESP32 on Arduino framework with PIO. I have a Screen class for handling all of the screen functions.

void Screen::turn_off_screen(){

  digitalWrite(SCREEN_ENABLE, LOW);

}

void turn_off_screen_wrapper()
{
  Serial.println("turn_off_screen_wrapper called");
    if (c_screen_Instance != nullptr)
    {
      c_screen_Instance->turn_off_screen();
    }
}

void Screen::auto_display_power_off(int timeout){
  Serial.println("auto_display_power_off called");
  c_screen_Instance = this;
  auto_off_timer = timerBegin(0, 80, true);
  Serial.println("auto_off_timer ran");
  timerAttachInterrupt(auto_off_timer, &turn_off_screen_wrapper, true);
  Serial.println("timerAttachInterrupt ran");
  //Converts given seconds from us to seconds
  timerAlarmWrite(auto_off_timer,timeout*1000000,false);
  timerAlarmEnable(auto_off_timer);

}

The code compiles however I get this when I run it on the board.

auto_display_power_off called
[E][esp32-hal-cpu.c:93] addApbChangeCallback(): duplicate func=400811F8 arg=3FFBDC54
auto_off_timer ran

The screen never gets turned off of course since the callback never runs. Any ideas why this is happening?

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
Sarge324
  • 31
  • 7
  • 2
    I would say the best place to look for answers would be in esp32-hal-cpu.c:93. or where you call `addApbChangeCallback`. Neither of which is included in the question. – Goswin von Brederlow Jun 25 '22 at 09:55

2 Answers2

0

is c_screen_Instance global? is auto_off_timer global?

Consider providing a bit more of your code.

But anyway.

bool addApbChangeCallback(void * arg, apb_change_cb_t cb){
    initApbChangeCallback();
    apb_change_t * c = (apb_change_t*)malloc(sizeof(apb_change_t));
    if(!c){
        log_e("Callback Object Malloc Failed");
        return false;
    }
    c->next = NULL;
    c->prev = NULL;
    c->arg = arg;
    c->cb = cb;
    xSemaphoreTake(apb_change_lock, portMAX_DELAY);
    if(apb_change_callbacks == NULL){
        apb_change_callbacks = c;
    } else {
        apb_change_t * r = apb_change_callbacks;
        // look for duplicate callbacks
        while( (r != NULL ) && !((r->cb == cb) && ( r->arg == arg))) r = r->next;
        if (r) {
            log_e("duplicate func=%8p arg=%8p",c->cb,c->arg);
            free(c);
            xSemaphoreGive(apb_change_lock);
            return false;
        }
        else {
            c->next = apb_change_callbacks;
            apb_change_callbacks-> prev = c;
            apb_change_callbacks = c;
        }
    }
    xSemaphoreGive(apb_change_lock);
    return true;
}

This is addApbChangeCallback's declaration.

Your error comes from this line :

while( (r != NULL ) && !((r->cb == cb) && ( r->arg == arg))) r = r->next;

Where r it's a struct to hold all the callbacks. This error indeed indicates this callback function was already assigned somewhere in your code. r is global, so your code is re-assigning the same callback twice.

Try to either only assign it once, or to unassign the function before assigning it again with removeApbChangeCallback(void * arg, apb_change_cb_t cb) or timerDetachInterrupt

I've also found a reported issue related to timerAttach on the current version here: https://github.com/espressif/arduino-esp32/issues/6730

Try to roll back the Platform PIO's version to a more stable one:

# instead of espressif32
platform = https://github.com/platformio/platform-espressif32.git#<tag-version>

Check on the git link for the available tags you can use.

Nathan Almeida
  • 179
  • 1
  • 14
0

Problem was that I was attaching the interrupt in the void loop(). Which would run way faster than the actual timer. After moving it to setup (Setup being a placeholder) I plan on having it on a Hardware interrupt it worked as expected.

Sarge324
  • 31
  • 7