SAMD21 не просыпается после глубокого сна

Я работаю над сборкой личной доски с atsamd21e18a. Я на самом деле работаю над спящим режимом. Делаю функцию перевода самд21 в спящий режим вот так. Я использую библиотеку RTCZero.

Итак, в моей функции настройки у меня есть что-то вроде этого

RTCZero rtc;

void setup(){
    // Set the XOSC32K to run in standby
    SYSCTRL->XOSC32K.bit.RUNSTDBY = 1;

    rtc.begin();   
    .... other line code ....
    attachInterrupt(digitalPinToInterrupt(PIN_USER_BUTTON), wakeUpButtonUser, CHANGE);
    ...other line....
}

Итак, в моей настройке я инициализирую rtc и прикрепляю прерывание к своей пользовательской кнопке. Эта кнопка используется для включения или выключения платы.

Моя функция goTosleep():

SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
__DSB();
__WFI();

В моей функции wakeUpButtonUser у меня есть простой оператор if/else. Если пользователь нажимал кнопку более 3 секунд, samd21 переходит в спящий режим с функцией goToSleep(), иначе, если это менее 3 секунд, я хочу разбудить плату и зажечь светодиод, но это не работает.

Здесь моя функция wakeUpButtonUser, user_button — это объект, созданный из C++ для моей кнопки.

void wakeUpButtonUser(){
  if (userButton.isPressed())
  {
    userButton.setTimeStartPressed(millis());
    PRINT_DEBUG_LN("Pressed");
  }
  else
  {
    userButton.setTimeEndPressed(millis());
    PRINT_DEBUG_LN("Released");
    uint32_t time_pressed = userButton.getTimePressed();
    if (time_pressed >= temps_on && time_pressed < temps_off)
    {                  
        PRINT_DEBUG_LN("ON");
         //here I have code to light up a led
    }
    else
    {
        PRINT_DEBUG_LN("STOP");
        goSleepMode();
    }
  }
}

Эта функция работает, потому что, если я прокомментирую строку goToSleep(), я смогу прочитать мой серийный номер ON или OFF в зависимости от времени, когда я нажал кнопку, и светодиод работает также потому, что я могу зажечь светодиод перед сном. Но когда моя доска засыпает, она уже никогда не просыпается Я не понимаю почему, я что-то пропустил?


person simon    schedule 09.06.2021    source источник
comment
Я думаю, вам нужно использовать __WFE(); вместо _WFI();. См. stackoverflow.com/a/18828964/4902099.   -  person hcheung    schedule 10.06.2021
comment
Также этот embedded.com/   -  person hcheung    schedule 10.06.2021
comment
@hcheung Я думаю, что проблема была в том, что я перешел в спящий режим в своем функциональном прерывании, и если я поставлю goSleepMode() в loop, я смогу разбудить свою плату. Но спасибо за ваши ссылки, это тоже очень интересно   -  person simon    schedule 10.06.2021