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

stm32l100 + standby + rtc wakeup timer

Всем привет.

 

Настраиваю stm32l100 для режима STANDBY. Пробуждение 2 раза в секунду, для этого запускаю RTC wakeup-timer.

После включения питания, первый уход и выход из STANDBY проходит штатно, а затем начинается ерунда - контроллер сразу выходит из STANDBY. Флаг что был в режиме STANDBY выставлен, а флаг что сработал wakeup-timer сброшен.

 

Если вместо режима STANDBY использовать обычный сон, то все работает штатно.

 

Словами и кодом опишу основные моменты

 

1) При старте

- анализирую и сохраняю флаги событий CSR_SBF и CSR_WUF. После этого сбрасываю их

    if (PWR->CSR & PWR_CSR_SBF_BIT) {
        // ...
    }

    if (PWR->CSR & PWR_CSR_WUF_BIT) {
        // ...
    }

    PWR->CR |= PWR_CR_CSBF_BIT|PWR_CR_CWUF_BIT;

    //while (PWR->CSR & PWR_CSR_SBF_BIT);
    while (PWR->CSR & PWR_CSR_WUF_BIT);

Заметил что флаг CSR_SBF никогда не сбрасывается, хотя в шите написано что должен. Если раскомментировать строчку с while, то там зависнет. Не понимаю почему так.

 

- анализирую и сохраняю причины сброса, потом эти флаги очищаю

    
    volatile uint32_t csr;
    csr = RCC->CSR;
    
    // .... анализ и сохранение
    
    // сброс флагов
    RCC->CSR |= RCC_CSR_RMVF_BIT;

 

При проблемном выходе из STANDBY все флаги сброшены, т.е. выглядит так что причины сброса нет или сброса не было. Но контроллер стартует с нуля.

 

2) Настройка RTC wakeup-timer

- все делаю по даташиту. Если не уходить в STANDBY, а просто засыпать через __WFI(), то все работает нормально - таймер генерирует прерывания с нужным периодом.

void rtc_set_wakeup_mode(const uint32_t wakeup_counter)
{
    RTC_WRITE_PROTECT_DISABLE();
    RTC->CR &= ~RTC_CR_WUTE_BIT;
    while (!(RTC->ISR & RTC_ISR_WUTWF_BIT));

    RTC->WUTR = wakeup_counter;
    RTC->CR &= 0xfffffff7;
    RTC->CR |= RTC_WAKEUPCLOCK_RTCCLK_DIV2;

    __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_IT();
    __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_RISING_EDGE();

    RTC->CR |= RTC_CR_WUTIE_BIT|RTC_CR_WUTE_BIT;
    RTC_WRITE_PROTECT_ENABLE();
}

Таймер настраиваю только один раз, когда причина сброса - питание/пин_ресет, т.е. явно не выход их STANDBY. Как понимаю из шита, дальше он должен постоянно перезагружать счетчик даже в режиме STANDBY.

 

3) Переход в режим STANDBY

void pwdm_enter_standby_mode(void)
{
    PWR->CR |= PWR_CR_PDDS_BIT;
    SCB->SCR |= SCB_SCR_SLEEPDEEP_BIT;

    __WFI();
}

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


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

Нашел проблему, все было просто. Работу по анализу флагов wakeup/standby поместил в самое начало main. Но тактирование на модуль PWR в этом коде не подается. Это происходит позже когда инициализируется кварц. В итоге регистр PWR->RCC в неопределенном состоянии, работать с ним нельзя и флаг wakeup не сбрасывался.

 

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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