Перейти к содержанию
    

STM32WLE5 - WFI иногда не уводит в shutdown

Столкнулся с такой проблемой - устройство должно уйти в shutdown и по сигналу WKUP3 проснуться. Реализовано это так:

Спойлер
void sleep_manager::do_shutdown()
{
    __disable_irq();
    // enable RTC write access, select Shutdown as deep sleep mode
    PWR->CR1 = 0
        | 0 * PWR_CR1_LPR                                       // Supply mode, 0: main regulator, 1: low power regulator
        | 1 * (PWR_CR1_VOS & -PWR_CR1_VOS)                      // Voltage scaling, 1: Range 1 (fast), 2: Range 2 (slow), 0, 3: forbidden
        | 1 * PWR_CR1_DBP                                       // Enable write access to backup domain registers
        | 0 * PWR_CR1_FPDS                                      // Flash mode during LPSleep, 0: Idle, 1: Power-down
        | 0 * PWR_CR1_FPDR                                      // Flash mode during LPRun, 0: Idle, 1: Power-down
        | 0 * PWR_CR1_SUBGHZSPINSSSEL                           // Radio SPI NSS select, 0: PWR->SUBGHZSPICR.NSS, 1: LPTIM3_OUT
        | 4 * (PWR_CR1_LPMS & -PWR_CR1_LPMS)                    // Low-power selection: 0: Stop0, 1: Stop1, 2: Stop2, 3: Standby, 4..7: Shutdown
        ;

    PWR->PUCRB = 0
        | 1 * PIN_BITMASK(SM353_INPUT)                          // подтяжка к питанию на WKUP3
        ;

    PWR->CR4 = 0
        | 0 * PWR_CR4_WRFBUSYP                                  // Wakeup from radio BUSY polarity, 0: active high(rising), 1: active low (falling)
        | 0 * PWR_CR4_VBRS                                      // Vbat battery charging resistor, 0: 5 kOhm, 1: 1.5 kOhm
        | 0 * PWR_CR4_VBE                                       // Vbat battery charging enable
        | 1 * PWR_CR4_WP3                                       // WKUP3 polarity, 0: active high(rising), 1: active low (falling)
        | 0 * PWR_CR4_WP2                                       // WKUP3 polarity, 0: active high(rising), 1: active low (falling)
        | 0 * PWR_CR4_WP1                                       // WKUP3 polarity, 0: active high(rising), 1: active low (falling)
        ;

    // disable PVD if was enabled
    PWR->CR2 = 0
        | 0 * PWR_CR2_PVME3                                     // Vdda monitoring versus 1.62v threshold enable
        | 0 * (PWR_CR2_PLS & -PWR_CR2_PLS)                      // PVD threshold, 0: 2.0v, 1: 2.2v, 2: 2.4v, 3: 2.5v, 4: 2.6v, 5: 2.8v, 6: 2.9v, 7: PVD_IN < VREFINT
        | 0 * PWR_CR2_PVDE                                      // PVD enable
        ;

    // настройка подтяжек на всех выводах
    PWR->PDCRA = ...
    PWR->PDCRB = ...
    PWR->PDCRC = ...
    PWR->PDCRH = ...

    PWR->CR3 = 0
        | 0 * PWR_CR3_EIWUL                                     // Internal wakeup line interrupt enable
        | 0 * PWR_CR3_EWRFIRQ                                   // Radio IRQ wakeup from standby enable
        | 0 * PWR_CR3_EWRFBUSY                                  // Radio busy wakeup from standby enable
        | 1 * PWR_CR3_APC                                       // Apply pull-up/down configuration, 1: use PWR->PUCRx, PWR->PDCRx
        | 0 * PWR_CR3_RRS                                       // SRAM2 power in Standby mode, 0: off, 1: low-power regulator
        | 0 * PWR_CR3_EWPVD                                     // PVD enable by radio active state
        | 1 * PWR_CR3_ULPEN                                     // Supply voltage sampling in Stop & Standby modes, 0: continuously,  1: periodically (~12 ms)
        | 1 * PWR_CR3_EWUP3                                     // WKUPx enable
        | 0 * PWR_CR3_EWUP2                                     // WKUPx enable
        | 0 * PWR_CR3_EWUP1                                     // WKUPx enable
        ;

    SCB->SCR |= SCB_SCR_SLEEPDEEP;
    EXTI->IMR1 = 0;

    {
        // errata 2.2.11: Potential deadlock condition on wakeup from some low-power modes
        auto Attempts = 48/6 * 1000 * 1000;   // ~1 sec at MSI48
        for(;;)
        {
            if(PWR->SR2 & PWR_SR2_LDORDY)
                break;

            if(!--Attempts)
                wdt_reboot();
        }
    }

    for(;;)
    {
        EXTI->PR1 = ~0; // clear pending EXTI.
        PWR->SCR = ~0;  // clear wakeup status

        __WFI();
    }
}

 

Почти всегда это работает, но очень редко устройство может сбойнуть (захочешь конкретное устройство специально загнать в это состояние - хоть обусыпляйся, но если ~сотню устройств разбудить/усыпить - где-то на третьем проходе одно из устройств может сбойнуть). При этом программа постоянно крутится в бесконечном цикле вокруг WFI, PWR->EXTSCR в нулях, т.е. ядро даже не пытается уйти в сон. В PWR->SR1 все флаги в нулях, EXTI->PRx в нулях, NVIC->ISPRx в нулях. Контроллер тактируется от MSI, настроенного на 48 МГц. Что может мешать ему уснуть?

Если программу перезапустить ножкой сброса - все будет работать и засыпать/просыпаться как ни в чем не бывало.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 минуты назад, jcxz сказал:

А если заменить на WFE?

Перепрошить ~сотню устройств (пусть около 20 сек на устройство - это займет около получаса) и пройти несколько кругов побудки/усыпления (это еще часа два-три) чисто ради любопытства - сомнительное удовольствие.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как всегда - стоило написать на форум и решение нашлось. В SCB->ICSR стоял бит PENDSTSET (SysTick exception is pending). 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...