data_stack 0 16 февраля, 2016 Опубликовано 16 февраля, 2016 · Жалоба Мозг дымится, прям беда какая то, никак не приручить STOP режим Есть кнопка 1, на которую нужно однократно нажать и ввести мк в стоп. Будить планирую другой кнопкой. void EXTI2_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line2) != RESET) { NVIC_DisableIRQ(EXTI2_IRQn); stop_enable = 1; LED1_TOGGLE(); EXTI_ClearITPendingBit(EXTI_Line2); } } В основном цикле чекаю флаг кнопки. После его срабатывания ухожу в стоп. Но беда в том, что контроллер не засыпает. Детектирую это светодиодом 2. while(1) { if(stop_enable == 1) { PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI); stop_enable = 0; LED2_TOGGLE(); NVIC_EnableIRQ(EXTI2_IRQn); } } Если вводить в сон не по кнопке, то все ок, но нужно именно по кнопке. Создалось впечатление что NVIC_DisableIRQ(EXTI2_IRQn) не отрабатывает, проверил отдельно от этого куска кода - работает. По отдельности все работает, сама проблема в том что именно этот кусок не работает, как сделать по другому не понятно. ЗЫ видел аналогичные темы, выдергивание swd не помогло. Ввожу в стоп не в прерывании. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlanDrakes 1 16 февраля, 2016 Опубликовано 16 февраля, 2016 · Жалоба В прерывании нельзя засыпать. Но есть возможность заснуть по выходе из прерывания. Вам потребуется бит SLEEPONEXIT: SCB->SCR |= SCB_SCR_SLEEPONEXIT; Эта инструкция должна быть максимально последней перед завершением обработчика прерывания. Проверьте. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
data_stack 0 16 февраля, 2016 Опубликовано 16 февраля, 2016 · Жалоба Специально же написал: Ввожу в стоп не в прерывании. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlanDrakes 1 16 февраля, 2016 Опубликовано 16 февраля, 2016 (изменено) · Жалоба Тогда вариант более простой - на обработчике событий. Создаёте глобальную переменную. В прерывании кнопки устанавливаете её в, допустим, 1. В бесконечном цикле проверяете, равна ли переменная единице и если так - усыпляете кристалл. От прерывания отвязались. Переменная, кстати, volatile? Можете проверить в отладчике, меняется ли она вообще. И посмотреть дизассемблированный код, который был сгенерирован. Некоторые переменные порой... выбрасываются. Изменено 16 февраля, 2016 пользователем AlanDrakes Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
data_stack 0 16 февраля, 2016 Опубликовано 16 февраля, 2016 (изменено) · Жалоба Вы издеваетесь надо мной? Так и сделано stop_enable глобальная переменная, если 1 уходим в стоп, проблема в том, что не уходит он так в стоп. Переменная volatile. Изменено 16 февраля, 2016 пользователем data_stack Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlanDrakes 1 16 февраля, 2016 Опубликовано 16 февраля, 2016 (изменено) · Жалоба У меня работает отлично вот такой код: volatile char test = 0; void EXTI2_IRQHandler(void) { test = 1; EXTI->PR = 4; // Очищаем бит ожидающего прерывания }; (В main()) <...> EXTI->RTSR |= 4; // По фронту импульса EXTI->IMR |= 4; // Разрешить генерировать прерывание NVIC_EnableIRQ(EXTI2_IRQn); // Разрешить само прерывание while (1) { if (test == 1) { test = 0; PWR->CR |= PWR_CR_PDDS | PWR_CR_LPSDSR; // Маломощный сон SCB->SCR |= SCB_SCR_SLEEPDEEP; // Последний бит, позволяющий именно STOP __WFI(); }; }; <...> Буквально только что заставил работать код на реальном железе. Да, у меня есть плата с этим кристаллом. Останавливается именно после команды __WFI(); и ждёт ближайшего следующего прерывания. Изменено 16 февраля, 2016 пользователем AlanDrakes Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
data_stack 0 4 марта, 2016 Опубликовано 4 марта, 2016 · Жалоба Поднимаю тему, перетестил много раз - не работает. Упростил задачу, нужно включить контроллер и уйти сразу в standby, если wakeup нажат, то проснуться пересброситься и снова уйти в сон. int main() { RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); PWR_WakeUpPinCmd(PWR_WakeUpPin_3, ENABLE); delay_ms(5000); PWR_EnterSTANDBYMode(); } Что выходит на деле: в первый раз все по феньшую - контроллер уходит в сон, жмакаем wakeup и все ломается, контроллер просыпается, тут же засыпает, тут же снова пересбрасывается и так до бесконечности, пока не ресетнешь. Такое впечатление что после того как нажат wakeup нужно сбросить некий бит, что он отработал. Перерыл референс мануал но ничего не нашел похожего Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 10 4 марта, 2016 Опубликовано 4 марта, 2016 · Жалоба Упростил задачу Лихо упростили. while(1){} не забыли? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
data_stack 0 4 марта, 2016 Опубликовано 4 марта, 2016 · Жалоба Лихо упростили. while(1){} не забыли? не забыл, в любом случае после входа в стендбай контроллер перезагружается Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
veteq 0 6 марта, 2016 Опубликовано 6 марта, 2016 (изменено) · Жалоба не забыл, в любом случае после входа в стендбай контроллер перезагружается Насколько я помню выход из режима standby сопровождается запуском программы сначала... Сохраняются только регистры бэкапа И да, там есть какая-то еррата насчет режима standby... Изменено 6 марта, 2016 пользователем veteq Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
data_stack 0 9 марта, 2016 Опубликовано 9 марта, 2016 · Жалоба чутье не подвело, существует флаг, который нужно очищать, иначе каждый раз после входа в standby сразу же из него выходит. В SPL делаю так: PWR_ClearFlag(PWR_FLAG_WU); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться