Jump to content

    

slanted

Участник
  • Content Count

    157
  • Joined

  • Last visited

Community Reputation

0 Обычный

About slanted

  • Rank
    Частый гость

Recent Profile Visitors

2288 profile views
  1. Сергей, там изначальная версия (от 28 июня, см выше по треду) на которую я отмашку дал, так и написана. Просто это потом куда-то потерялось. Но даже и в таком виде, маловерятно что это причина глюков — после выхода из sleep процессор СНАЧАЛА выполнит прерывание, потом всё остальное, и учитывая что прерывание редкое, крайне вероятно что wdt_count считается одним куском. Да это грязно и по уму надо обкладывать это место cli/sei (как и было сделано), но то что гонка в данных обстоятельствах именно здесь я слабо верю.
  2. Откомментировал прямо в коде (SL). В любом случае это первое что я буду смотреть как соберу свою железку, т.к. то что есть мне как-то в целом не нравится. void setup() { noInterrupts(); info.service = MCUSR; // причина перезагрузки MCUSR = 0; // без этого не работает после перезагрузки по watchdog // SL: да, это требуется для выключения WDT (см 8.5.2/bit 3 wde в даташите) wdt_disable(); // а нужно ли тут, если у меня код быстро дойдёт до инициализации watchdog? // SL: по хорошему да, потому что мы не знаем сколько займёт инициализация. // Если там еще и бутлоадер будет, к примеру, то это надо прямо там выключать. // Надо это еще раз продумать. interrupts(); set_sleep_mode( SLEEP_MODE_PWR_DOWN ); // достаточно же 1 раз сделать? // SL: В теории да, но мне встречалась рекомендация перезаписывать // эти биты при каждом входе в sleep mode wakeup_period = WAKEUP_PERIOD_DEFAULT; ..... } void loop() { power_all_disable(); //NoInterrupts не нужно? т.к. в wdt_enable есть ассемблерная команда cli // SL: и interrupts() тоже не нужно, в wdt_enable есть сладкая парочка // in tmp, SREG / out SREG, tmp, т.е. флаг прерывания оно восстановит // как было wdt_enable(WDTO_250MS); interrupts(); wdt_count = 0; while ((wdt_count < wakeup_period) && !button.pressed()) { counting(); WDTCR |= _BV(WDIE); //пока не понял, обязательно ли здесь или можно после wdt_enable раз в WDT_vect есть. без этого не работает. //SL: WDIE нужно обновлять при каждом срабатывании таймера, потому что аппаратура его сбрасывает. // Возможно, она его сбрасывает _при_выходе_ из прерывания, поэтому установка флага там не имеет эффекта. sleep_mode(); } power_all_enable(); // Далее: я не отключаю watchdog, для надежности. wdt_reset() вызывается в button.wait_release() где я могу долго ждать пока пользователь отпустит кнопку. ... //взаимоотношения с ESP }
  3. @dontsov, так с последними изменениями прошивка все еще вешается или нет?
  4. Могут. С другой стороны, завесить avr таким способом весьма непросто. С третьей - гораздо чаще виноват софт :)
  5. Там другая беда (если я правильную версию посмотрел): земля к тиньке подключена ОЧЕНЬ длинным проводом, и блокировочный конденсатор в такой ситуации бесполезен. И радиочастотная схема рядом. Ну, э.... примитивный параллелизм несложно делается. Таймер же есть и не один.
  6. Отловить ВСЕ глюки не удастся никогда, это аксиома. Я предлагаю зайти с другой стороны: с обеспечения возможности перешивки по воздуху. А стенд... ну чо стенд. Вторая ардуина рядом и пара транзисторов для имитации сухого контакта.
  7. Да вроде всё правильно.
  8. А, и да, чтоб два раза не вставать. Не очень критично, но всё же. По поводу этого каунтера: переполнение signed int — это undefined behavior, поэтому очередной чрезмерно оптимизирующий компилятор может что-нибудь такое решить и, к примеру, вообще выкинуть этот счётчик. Поэтому я обычно делаю все подобные счётчики unsigned, считающими вверх, и не сбрасываю их никогда, только сравниваю при ожидании. Заодно это даёт глобальный счётчик тиков, который можно переиспользовать где-нибудь еще. Примерно так: volatile uint16_t wdt_count; ISR(WDT_vect) { ++wdt_count; } { // цикл ожидания uint16_t const now = wdt_count; while ( (wdt_count - now) < wakeup_period ) { // работаем // спим } }
  9. Я просто забыл что они в avr-libc тоже есть :) Счас посмотрел — вполне адекватно написано, можно и их. PS. Одно последнее замечание — если у нас схема которая должна работать годами, то вочдог все же будет не лишним. Поэтому я бы оставил в WDT_vect остаётся только wdt_count--, а прерывание взводить только перед засыпанием: while ( wdt_count > 0 ) { ... wdt_reset(); WDTCR |= (1<<WDIE); interrupts(); sleep_mode(); } Считать время он будет как и раньше, только теперь если вдруг случится что-то еще, то следующим будет настоящий сброс по вочдогу.
  10. Я бы делал немного не так. setup() { cli(); info.service = MCUSR; // отключаем WDT MCUSR = 0; WDTCR = (1<<WDCE) | (1<<WDE); WDTCR = 0; sei(); // вся остальная инициализация ... } loop() { cli(); wdt_reset(); WDTCR = (1<<WDCE) | (1<<WDE); WDTCR = (1<<WDCE) | (1<<WDE) | (1<<WDIF) | (1<<WDIE) | (1<<WDP2) | (0<<WDP1) | (0<<WDP0); sei(); } Вообще при любых действиях с флагом IE (это относится не только к WDT, а к любой периферии вообще) рекомендуется этим же оператором ставить соответствующий IF. Это гарантирует то что соответствующее прервыание будет подавлено на момент смены конфигурации.
  11. Да, работа с вочдогом выглядит странно. Если хочется его именно выключить, то надо не просто WDTCR=(1<<WDCE), а как в даташите написано: WDTCR = (1<<WDCE)|(1<<WDE); WDTCR = 0; Ну и как бы выключать его не обязательно каждый раз, и даже переинициализировать не обязательно, достаточно wdt_reset() вовремя подавать. То что воспроизводится случайно — ну, никто ж не тестирует что будет если с вочдогом работать нештатными методами. Может гонка какая-то внутри его собственной логики, может еще что-то.
  12. Ну для ВАШЕЙ платформы (тем более что вы её не указали) у меня заведомо нет исходников, и я не телепат.
  13. А вы откройте исходники и посмотрите. Там всё архитектурно-зависимо и собирается для каждой платформы из разных мест, для x86 из cpufreq например.
  14. Им еще кто-то пользуется? В любом случае, имейте в виду что там библиотеки реструктурированы сильно. Какие-то футпринты потерялись, куча новых добавлена, у общеупотребительных местами геометрия изменена...
  15. В том-то и дело что не на каждую! Опция называется "change footprint with identifier" и меняет все футпринты с данным наименованием.