Всем добрый день. Кто-то сталкивался с тем, что микроконтроллер stm32l051, от батарейного питания, в спящем режиме, перестаёт просыпаться и не реагирует даже на замыкание ножки РЕСЕТ ? Помогает только отключение питания. После этого работать может долго (месяц, два) и опять. Это не один контроллер, а уже много так себя повели.
Errata на stm32l051 для ревизии "A" прямо ПЕРВЫМ пунктом пишет: 2.1.1 - Выход из режима Stop по событию сбросу невозможен, когда в качестве основного источника тактирования выбран HSI16
Описание: В режим Stop можно войти независимо от источника тактирования. Системный тактовый генератор после выхода из режима Stop выбирается через бит STOPWUCK регистра RCC_CFGR: STOPWUCK = 0 - Внутренний тактовый генератор MSI (64kHz .. 4MHz) выбран STOPWUCK = 1 - Внутренний тактовый генератор HSI16 (16MHz) выбран
Микроконтроллер блокируется (не выбран источник тактирования) при следующих событиях: - Вход в режим Stop осуществляется когда источником системного тактирования выбран HSI16 и STOPWUCK = 1 - Выход из режима Stop происходит по сбросу (внешнему?) Только сброс-по-питанию может сбросить микроконтроллер.
Имеется возможность обхода: 1. Перейти на MSI 2. Войти в режим Stop 3. При событии сброса микроконтроллер сбрасывается (любители тафталогии) 4. Код выполняется штатным образом после сброса.
Похоже?
Там же есть про "Проблемы пробуждения Flash-памяти при выходе из режимов Stop и Sleep, когда Flash-контроллер в режиме экономии энергии. Уже для ревизий "A", "Z" И "Неожиданный сброс при выходе из режима Stop, когда регулятор напряжения в маломощном режиме".
Хотя эти два не должны приводить к полному зависанию.
Errata на stm32l051 для ревизии "A" прямо ПЕРВЫМ пунктом пишет: 2.1.1 - Выход из режима Stop по событию сбросу невозможен, когда в качестве основного источника тактирования выбран HSI16 ... Похоже?
Нисколько. Потому как у ТС это случается не всегда, а только иногда.
ну, это объясняет, почему сброс только через питание. вот почему зависает, не объясняет, да. Но это, да, либо баг, либо помехи мощные эпизодически ловит, либо ещё что... ТСу надо предоставлять всё, код, трассировку платы, внешние условия работы...
Питание батарейное = нестабильное, так что могут портится регистры и срабатывать еррата. Что с настройкой BOD?
_________________ Репозиторий STM32: https://cloud.mail.ru/public/2i19/Y4w8kKEiZ Актуальность репозитория: 1 сентября 2025 года Если чего-то не хватает с сайта st.com - пишите, докачаю.
Питание от литиевой батарейки, параллельно кондёры на 4400мкф - даже их хватает на 2 передачи, без них да, по низкому питанию срабатывало бы прерывание. Конструкция такая, если интересно. Повторюсь, некоторые работают по несколько месяцев без проблем, и может раз и пропал. Если батарейк норм, то переподключение её всё приводит в порядок. Неизвестно на сколько. Некоторые начинают во сне жрать несколько милливольт - тут уж контроллер под замену сразу.
Добавлено after 4 minutes 56 seconds: не пойму почему фото не добавляется
Добавлено after 8 minutes 18 seconds: Тактирование от внутреннего генератора MSI. В сон уходит на 5 минут + случайное число от 0 до 59 секунд.
ну как бы код не давал бы я думаю такой эффект. Так температуру измеряет и предаёт по лоре. Получается наверно или тактовый генератор спящего режима отваливается (ток потребляет же мало, не видно тестером). Или хз.
ну как бы код не давал бы я думаю такой эффект. Так температуру измеряет и предаёт по лоре. Получается наверно или тактовый генератор спящего режима отваливается (ток потребляет же мало, не видно тестером).
Ну да - проще ведь самые фантастические теории придумывать, чем в коде разбираться. С чего бы он "отваливался" если напряжение питания в норме? А оно ведь в норме? (ведь это несложно проверить мультиметром) С таким же успехом можно предполагать, что биты в каком-то регистре CPU самопроизвольно инвертируются под влиянием тёмной материи. Ну чем не теория?
Да и если есть подозрения на систему питания, то просто ставим десяток или несколько десятков девайсов на тех.прогон на долгое время от стабилизированного блока питания и проверяем.
Тактирование от внутреннего генератора MSI. В сон уходит на 5 минут + случайное число от 0 до 59 секунд.
В целях "ловли блох" генерим прошивку, которая будет уходить в сон в ~100 раз чаще (~3 секунды + случайное). И запускаем на техпрогон несколько десятков устройств (или больше) с такой прошивкой. Для ускорения поиска бага.
У меня лежит один на окне уже с зимы и работает, питание батарейки снизилось на 0.1В, передаёт без нареканий, прошивка одна и та же.
Добавлено after 4 minutes 59 seconds: вот фото
Добавлено after 12 minutes 29 seconds: AlanDrakes в самом верху же написал, что тактирование HSI отрубается. У меня только внутренний использован. Если бы в коде ошибка, он бы или не засыпал, или не работал бы вообще, а не так, что хз когда перестанет. Если бы случайно уходил на большое время в сон, то ресет срабатывал бы (из сна он выводит). Если бы не уходил в сон - батарейку бы жрал.
Добавлено after 4 minutes 42 seconds: там кода то всего int main(void) { uint16_t volt=0;
//BKP Registers enabled HAL_PWR_EnableBkUpAccess(); i_rtc = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR1); //чтение нового случайного числа из памяти и подстановка его в random m_rtc = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR2); if (m_rtc > 59) m_rtc = 59; if (i_rtc > 59) i_rtc = 59; //установка выводов в 1 редима работы ЛОРЫ (это спящий режим)
if (__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST)){ RTC_Delay(m_rtc, i_rtc); // Установка времени на энергосбережение __HAL_RCC_CLEAR_RESET_FLAGS(); HAL_PWR_EnterSTANDBYMode(); } else{ MX_IWDG_Init(); //чтение напряжения питания HAL_ADC_Start(&hadc); HAL_ADC_PollForConversion(&hadc,1000); volt=HAL_ADC_GetValue(&hadc)>>2; if (volt==0) volt=1; HAL_ADC_Stop(&hadc); __HAL_RCC_CLEAR_RESET_FLAGS(); }
HAL_IWDG_Refresh(&hiwdg);
while (1) { HAL_GPIO_WritePin(DS18_VCC_new_GPIO_Port, DS18_VCC_new_Pin, SET); HAL_Delay(25); status = ds18b20_init(SKIP_ROM); HAL_Delay(2); ds18b20_MeasureTemperCmd(SKIP_ROM, 0);
srand(volt+/*(uint16_t)i_rtc+*/(uint16_t)temper); //установка начального числа для рандома i_rtc=rand()%(59); //вычисление рандома в диапазоне от 0 до 59 //i_rtc=rand()%(59-5+1) + 5; HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR1, i_rtc); //Запись рандома для следующего захода после сна HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR2, 6); if (i_rtc >= 59) i_rtc = 59;
while (1) { ... HAL_IWDG_Refresh(&hiwdg); HAL_PWR_EnterSTANDBYMode(); }
(полагаю, на HAL тут можно не обращать внимания) Хотя, сомневаюсь, что это приведёт к такому поведению. Скорее, просто невозможно будет узнать событие, вызвавшее возврат в активный режим.
Оказывается нужен только один байт от temper... нафига тогда ранее аж с double-ом тягались? Я уж не говорю что double и float могут принимать и спец.значения типа NaN, +inf, -inf, etc.. Обработки коих тут совсем не наблюдается...
А где выключение тактирования всей периферии и всего остального, не нужного во сне? Или Хал это сам делает?
Вобщем - вы понадеялись на Хал. Что он сам всё сделает правильно в HAL_PWR_EnterSTANDBYMode(). А нужно было открывать мануал на МК и изучать регистры и биты для состояния сна. И самостоятельно ими управлять. Отсюда и проблемы.
PS: Код весьма отстойный: Задержки, "магические числа", неоптимальные операции, Хал, ... Не мудрено что он глючит...
void deep_sleep(void) { uint32_t tmp; SCB->SCR |= (SCB_SCR_SLEEPDEEP_Msk); // Deep sleep RCC->APB2ENR &= ~(RCC_APB2ENR_DBGEN); RCC->IOPSMENR &= ~(RCC_IOPSMENR_IOPBSMEN); RCC->APB1SMENR &= ~(RCC_APB1SMENR_PWRSMEN); PWR->CR |= PWR_CR_ULP | PWR_CR_FWU; // Ultra low power FLASH->ACR |= FLASH_ACR_SLEEP_PD; // <- Вот тут я теотерически мог поймать аппаратный баг. Но, видимо, ревизия более свежая. while (DMA_TTY0_TX); // Ждём окончания передачи текста. Если есть. while (!(USART1->ISR & USART_ISR_TC)); // Ждём полного окончания передачи (уже опрашиваем UART) RCC->APB1ENR |= RCC_APB1ENR_PWREN; PWR->CR |= PWR_CR_LPSDSR; // Регулятор напряжения в маломощный режим. SCB->SCR &= ~( SCB_SCR_SLEEPDEEP_Msk ); // Глубокий сон
__WFI(); // Проваливаемся в сон и останавливаемся тут.
RCC->APB2ENR |= (RCC_APB2ENR_DBGEN); // После пробуждения - возвращаем всё как было. RCC->IOPSMENR |= (RCC_IOPSMENR_IOPBSMEN); RCC->APB1SMENR |= (RCC_APB1SMENR_PWRSMEN); }
while(1) { deep_sleep(); while (tty_IsSymbolReady()) { microrl_insert_char(prl, tty_GetChar()); } if (ButtonPressed) { ButtonPressed = 0; console_timestamp(); console_put("Config button pressed.\r\n");
SleepTimeout_Minutes = 3; // Enable LED2 // PB5 -> Floating -> Alternative GPIOB->MODER &= ~(0x00000400); SystemCoreClockUpdate(); SysTick_Config(SystemCoreClock / 5); } if (TIM21_WAKE) { TIM21_WAKE = 0; if (SleepTimeout_Minutes) { if (--SleepTimeout_Minutes == 0) { // Disable LED2 // PB5 -> Alternative -> Floating GPIOB->MODER |= 0x00000400; SysTick->CTRL &= ~(SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk); console_timestamp(); console_put("Returning to idle mode.\r\n"); } } } if (TickWake) { TickWake = 0; UpdateValues(); FindRange(); } }
Примерно так. Из минусов - приходится при прошивке изменять OptionBytes, чтобы выставить BOR в 0xxx - "выключен". Иначе при низком напряжении пары С-батареек чип может не запуститься в случае сброса.
Кстати, да. Kost286, а какой диапазон напряжения у прибора? Может у Вас при падении напряжения до [примерного] уровня срабатывания BOR'а происходит защёлкивание? У него ведь некоторый гистерезис срабатывания и отпускания сброса.
Посмотрите биты FLASH->OTPR[19:16]
Цитата:
Bits 19:16 BOR_LEV: Brownout reset threshold level These bits reset the threshold level for a 1.45 V to 1.55 V voltage range (power-down only). In this particular case, VDD must have been above VBOR0 to start the device OBL sequence, in order to disable the BOR. The power-down is then monitored by the PDR. If the BOR is disabled, a “grey zone” exists between 1.65 V and the VPDR threshold (this means VDD can be below the minimum operating voltage (1.65 V) without any reset until the VPDR threshold). If there is a mismatch on this configuration during the Option bytes loading, it is loaded with 0x8. 0xxx: BOR OFF. This is the reset threshold level for the 1.45 V - 1.55 V voltage range (power-down only). In this particular case, VDD must have been above BOR LEVEL 1 to start the device OBL sequence in order to disable the BOR. The power-down is then monitored by the PDR. Note: If the BOR is disabled, a "grey zone" exists between 1.65 V and the VPDR threshold (this means that VDD may be below the minimum operating voltage (1.65 V) without causing a reset until it crosses the VPDR threshold) 1000: BOR LEVEL 1 is the reset threshold level for VBOR0 (around 1.8 V) 1001: BOR LEVEL 2 is the reset threshold level for VBOR1 (around 2.0 V) 1010: BOR LEVEL 3 is the reset threshold level for VBOR2 (around 2.5 V) 1011: BOR LEVEL 4 is the reset threshold level for VBOR3 (around 2.7 V). 1100: BOR LEVEL 5 is the reset threshold level for VBOR4 (around 3.0 V) Note: Refer to the device datasheets for the exact definition of BOR levels.
И в datasheet'е описаны типичные значения напряжений для срабатывания и отпускания сброса. Так-то он вроди бы настроен на 1.8В, но мало ли.
Скорее, просто невозможно будет узнать событие, вызвавшее возврат в активный режим.
Всё узнаётся.
Добавлено after 2 minutes 22 seconds: AlanDrakes, напряжение при передаче падает до 3,5 вольт всего. Даже без батарейки одних кондёров хватает на 2 передачи.
Добавлено after 4 minutes 31 second: jcxz, приёчем здесь доублы и прочее? Вопрос же не в том как лучше в коде сделать, а почему из сна не выходит и можно ли узнать почему и можно ли исправить.
Сейчас этот форум просматривают: Cliff и гости: 16
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения