Не могу вылечить ватчдог на "голой" атмеге328р с внутр тактированием 8 МГц (РЕШЕНО)

Тема в разделе "Микроконтроллеры AVR", создана пользователем b707, 27 янв 2018.

  1. b707

    b707 Гуру

    Прошу прощения за кросспост с другого форума, но может кто ответит из местных.

    Вроде и голый контроллер прошиваю не впервые, и загрузчик для "лечения" ватчдога приходилось менять - все было без проблем. Но ватчдог на "голом" МК запускаю первый раз. И ничего не выходит.

    Выставляю фьюзы (рассчитаны по калькулятору для 8MHz internal), беру оптибут загрузчик, прошиваю в Ардуино ИДЕ через Arduino ISP - все прошивается без проблем. По диагностике avrdude видно, что фьюзы шьются правильные, файл буллоадера берется тот, что нужно. Заливаю тестовый скетч - тоже без ошибок. Так как у контроллера нет обвязки USART, то подключил к МК OLED дисплей и смотрю вывод на нем. После включения ватчдога плата наглухо виснет. На РЕСЕТ не реагирует, только на отключение питания.

    Прошерстил гугль - конкретно моего случая нет, у всех после замены бутлоадера на оптибут ватчдог работает. Оптибутовских загрузчиков попробовал 3 шт разных -

    1) из гитхабовского релиза оптибута файл optiboot_atmega328_pro_8MHz.hex

    2) из проекта MiniCore = файл optiboot_flash_atmega328p_UART0_38400_8000000L.hex

    3) и даже в одном месте вычитал, что можно брать бутлоадер и под 16МГЦ - взял стандартный оптибут optiboot_atmega328.hex

    После прошивки любого из этих бутов никаких изменений в поведении контроллера не происходит - точно так же без проблем перешивается и так же виснет при запуске вотчдога.

    Честно говоря. я в тупике. Больше идей нет. Такое впечатление, что не вижу чего-то прямо перед носом. Может кто что подскажет?

    Для справки - Фьюзы и параметры бутлоадера можно посмотреть в файле boards.txt:
    Код (Text):
    ##############################################################

    atmega328bb.name=ATmega328 on BB (8 MHz internal optiboot)

    atmega328bb.upload.tool=avrdude
    atmega328bb.upload.protocol=arduino
    atmega328bb.upload.maximum_size=32256
    atmega328bb.upload.speed=57600

    atmega328bb.bootloader.tool=avrdude
    atmega328bb.bootloader.low_fuses=0xE2
    atmega328bb.bootloader.high_fuses=0xDE
    atmega328bb.bootloader.extended_fuses=0x05

    atmega328bb.bootloader.file=optiboot/optiboot_atmega328_pro_8MHz.hex
    atmega328bb.bootloader.unlock_bits=0x3F
    atmega328bb.bootloader.lock_bits=0x0F

    atmega328bb.build.board=ATMEGA328BB
    atmega328bb.build.mcu=atmega328p
    atmega328bb.build.f_cpu=8000000L
    atmega328bb.build.core=arduino:arduino
    atmega328bb.build.variant=arduino:standard
    тестовый скетч
    Код (C++):
    #include <avr/wdt.h>
    #include "oled.h"

    void setup()
    {
       wdt_disable();
       LEDPIN_Init();
       LED_Init();
       LED_P8x16Str(23,0,"wait");
       delay(16000);
       wdt_enable (WDTO_8S);
    }
    void loop()
    {
        //wdt_reset();
       
        LED_P8x16Str(23,0,"wdt on");
        delay(1000);
     
      }
     
  2. b707

    b707 Гуру

    новости

    Упростил тест до предела, чтобы эксперимент был максимально чистым:

    1. Взял новую (еще ни разу не шитую) атмегу328р

    2. Собрал на макетке классическую обвязку
    [​IMG]
    3. Прошил оптибутовский загрузчик с фьзами 0xE2 0xDE 0x05

    4. подключил к 7 пину светодиод

    5. 3алил мега-простой скетч
    Код (C++):
    #include <avr/wdt.h>
    int led =7;

    void setup()
    {
       wdt_disable();
       pinMode(led,OUTPUT);
       digitalWrite(led,HIGH);
       delay(16000);
       wdt_enable (WDTO_1S);
    }
    void loop()
    {
        //wdt_reset();
        digitalWrite(led, ! digitalRead(led));
     
        delay(1000);
     
     
    }
     
    Результат - после срабатывания ватчдога светодиод начинает часто мигать - классический случай бесконечного ресета.

    Этот же самый бутлоадер в Нано - работает!!! ватчдог ресетится как положено.

    Вывод - налицо несовместимость оптибута с ватчдогом на атмеге328 с внутренним клоком 8МГц. Если это так = давно бы куча других ардуинщиков столкнулась бы с этим. Вопрос - почему я не вижу в гугле десятков подобных жалоб?

    Варианты:

    А) - я идиот. Уже готов согласится, при условии, что кто0нибудь обьяснит, в чем именно.

    Б) - мне попалась бракованая партия контроллеров. Не исключено. Проверить просто - нужна другая папртия. Может кто-нибудь не пожалеет получаса, повторит перечисленные выше пп 1-5 и напишет свой результат?

    В) - предлагайте свои варианты
     
  3. ostrov

    ostrov Гуру

    Бутлоадер нужен точно?
     
  4. AlexU

    AlexU Гуру

    А при чём тут бутлоадер? Он может быть любым или вообще отсутствовать.
    "Собака" настраивается там, где используется. Если тот или иной бутлоадер использует "собаку" -- он её (собаку) настраивает так, как нужно ему. Если Вы хотите использовать "собаку" в основной прошивке, то её нужно настроить в 'setup()' прежде, чем активировать. А затем после настройки "собаки" с ней ещё нужно в самой программе (напримр, в цикле loop) правильно работать. Ведь "собака" она на то и "сторожевая", что бы при определённых обстоятельствах перегружать микроконтроллер.
     
  5. b707

    b707 Гуру

    AlexU, сорри, но по-моему. вы не вполне в теме.
    В некоторых контроллерах атмега, в том числе самом ходовом - атмега328р - есть такая особенность (фактически баг) - после срабатывания ватчдога при следующей перезагрузке ватчдог остается включенным, причем настроенным на минимальный интервал - 15мс. Этого времени недостаточно для полной загрузки контроллера, ватчдог срабатывает раньше, чем ваш скетч доберется даже до setup() - что вводит МК в бесконечный цикл перезагрузки. Решением является использование загрузчика, который сразу после стартка МК выключал бы ватчдог. Таким загрузчиком является оптибут. Это все широко известно и находится в первой же ссылке гугля по запросу "ватчдог ардуино".

    Моя проблема заключается в том, что для "голого МК" атмега328р даже загрузчик оптибут не спасает от boot-loop.

    Давайте не будем голословны. В сообщении #2 у меня приведен тестовый скетч, в котором буквально десяток строк. Я буду признателен, если вы укажете, что именно я неправильно настраиваю в setup() и неверно использую в loop()
     
  6. AlexU

    AlexU Гуру

    Это не баг и не "такая особенность" -- всё описано в документации к микроконтроллеру. Если бы Вы не поленились и внимательно изучили документацию, только официальную, а не фиг знает какое описание, скачанное с супер-мупер-дупер про-ардуиновского сайта или форума на русском языке, то Вы бы понимали почему так происходит.
    Это частное решение, для конкретного случая.
    Я больше скажу, что optiboot сам активирует WD для проверки того, что надо делать -- перепрошивать память контроллера или запускать зашитую пользовательскую прошивку. И соответственно после перезагрузки по WD бутлоадер optibut этот самый WD, который настраивал ранее, сам же и отключает. Не будет зашитого optibut в микроконтроллер, то не будет никакой перезагрузки по WD, пока Вы "собаку" не настроите и сами не запустите -- либо в основной прошивке, либо в собственном (или чужом) бутлоадере -- и тогда Вы же сами и должны будете следить за "собакой".
    Исключением является прошитый фьюз WDTON. Этот фьюз активирует WD при старте контроллера. При чём только в одном режиме -- System Reset. И режим этот изменить нельзя.
    Но, судя по Вашим фьзам, WDTON не прошит. Поэтому WD нужно активировать ручками (точнее кодом в прошивке).
    Конечно не спасёт -- по той простой причине, что загрузчик здесь не при чём.
    Сейчас под рукой нет исходников функции 'wdt_enable()' поэтому не могу точно сказать -- настраивает эта функция режим WD (и какой режим?) или просто активирует WD с определённым предделителем. Но что касается 'loop()':
    1. если WD настроен в режиме System Reset, при закомментированной функции 'wdt_reset()' контроллер уйдёт в перезагрузку через 1 секунду после вызова функции 'wdt_enable()'; если вызов 'wdt_reset()' раскомметировать, то контроллер уйдёт в перезагрузку во время работы функции 'delay(1000)' -- после сброса счётчика WD некоторое время потратится на 'digitalWrite()', соответственно секунда, после вызова 'wdt_reset()' закончится в момент вызова функции 'delay(1000)'.
    2. если WD настроен в режиме Interrupt или Interrupt + System Reset, то контроллер уйдёт в перезагрузку через секунду после 'wdt_enable()' или после 'wdt_reset()' (если раскомментировать), по той простой причине, что у Вас не определён обработчик прерывания 'WDT' -- будет использован дефолтный обработчик, который просто производит перезагрузку МК. Это если прерывания разрешены вообщем и в частности обработка прерывания WDT. Если прерывания запрещены, то в режиме Interrupt контроллер не будет уходить в перезагрузку. А в режиме Interrupt + System Reset будет уходить через две секунды после 'wdt_enable()' при закомментированной 'wdt_reset()'.
    Вот как-то так...
     
    Последнее редактирование: 29 янв 2018
  7. b707

    b707 Гуру

    если вы позволите, я не буду цитировать всего. что вы написали. Все это, в целом, правильно, однако не имеет отношения к теме. Чтобы больше не возвращаться к этому - признаю, что употребил не вполне корректные термины, в частности "баг". Данная ситуация не является "багом" контроллера атмега328.

    Теперь о моем коде.

    Задача скетча крайне проста - проверить. что произойдет ПОСЛЕ перезагрузки МК по срабатыванию WD. Поэтому в скетче есть 'wdt_enable()' и нет (закомментирован) wdt_reset(). Мигающий светодиод нужен ИСКЛЮЧИТЕЛЬНО для диагностики, в каком состоянии находится программа - в сетап он горит постоянно, а в луп - мигает.

    В чем проявляется проблема

    Этот простейший код работает по разному на контроллере атмега328р, установленном на Ардуино Уно и на контроллере атмега328р, купленном в виде отдельной микросхемы.
    Если запустить этот код на Ардуино УНО - он отработает правильно. ПРАВИЛЬНО - это означает, что через 16сек задержки включится wdt_enable(). еще через 1 сек МК перезагрузится - и выполнение программы начнется с начала.
    Если этот же код запустить на "голом" МК атмега328р - то после перезагрузки программа второй раз не стартует. светодиод начинает суматошно мигать и вывести МК из этого состояния можно только выключением питания.

    Я был бы признателен, чтобы мне кто-нибудь обьяснил, в чем разница между этими двумя вариантами и что нужно сделать. чтобы на отдельном МК атмега328р этот код работал так же, как на Ардуино Уно.
     
    Последнее редактирование: 29 янв 2018
  8. AlexU

    AlexU Гуру

    Первое -- картинка в сообщении #2 непонятная (разрешение не позволяет понять что и куда подключено). Но всё же на картинке видно, что нет подтяжки ноги RESET испытуемого к питанию. Что бы исключить кривотолки всякие это нужно сделать (хотя может на реальной макетке это у Вас сделано).
    Второе -- настоятельно рекомендую не гадать на "кофейной гуще", а читать документацию, в которой помимо прочего есть фраза:
    WDE Вы сбрасываете через 'wdt_disable()', а Watchdog System Reset Flag (WDRF) нет. Тот же optiboot в Arduino UNO этот флаг сбрасывает.
    Третье -- что за optiboot Вы прошили в испытуемый контроллер (второй пост третий пункт)? Смущает фраза:
    Нано и испытуемый у Вас работают на разных частотах - 16 МГц против 8 МГц. Один и тот же бутлоадер не могут корректно работать на разных частотах без перекомпиляции под правильную частоту. Или Вы делали пересборку бутлоадера, а под фразой "Этот же самый бутлоадер" нужно понимать, что использовались одни и те же исходники, но компилировались под определённый микроконтроллер.
    Хотя с другой стороны в рассматриваемом случае частота контроллера особой роли играть не должна.

    И последнее -- повторюсь -- Вы не в том месте ищите решение проблемы. Бутлоадер не при чём, проблема либо в том, что Вы не корректно инициализируете WD, либо некорректно подключили контроллер (та же нога RESET), либо и то и другое одноврменно.
     
    b707 нравится это.
  9. b707

    b707 Гуру

    Подключение - стандартное для прошивки атмеги по SPI, например указанное в скетче "Arduino as ISP" Бутлоадеры и скетчи в МК прошиваются без ошибок, так что, полагаю, ошибки подключения можно исключить. Подтяжки RESET к питанию не делал, так как в даташите указано. что у пина RESET имеется внутренняя подтяжка к VCC (например, схема 15.1) Но чтобы не спорить - могу добавить резистор 10к, хотя думаю, что на результат не повлияет.
    для того я и прошиваю в МК оптибут вместо стандартного бутлоадера. чтобы оптибут сбрасывал все флаги правильно.И в случае с Уно и Нано оптибут все сбрасывает, а в случае с голым МК - почему-то нет.
    Фразу "этот же самый бутлоадер" нужно понимать буквально - в Нано 16 Мгц и в атмегу8Мгц прошивался один и тот же HEX файл - optiboot_atmega328.hex из поставки Ардуино IDE.
    Вы ошибаетесь, один и тот же бутлоадер МОЖЕТ работать на разных частотах без перекомпиляции. Частота, указанная при сборке бутлоадера, влияет только на работу UART - например на загрузку скетчей по UART. Если UART не используется. то разница 8МГц и 16МГц не имеет значения.
    Конечно, использование бутлоадера 16МГц на МК с частотй 8 - это не есть "правильно". Однако это было сделано исключительно для того, чтобы в сравниваемых МК был загружен абсолютно идентичный код, про который точно известно, что он не имеет проблем ватчдогом.
    Кроме того, в самом первом сообщении темы я указал. что пробовал загружать в контроллер варианты оптибута, скомпилированные и под 8 и под 16 МГц - см. список в начале ветки. Результат со всеми одинаков.
    Ногу RESET подключу, не вопрос. Насчет "неправильной инициализации WD" - все ж таки отелось бы конкретики. Что именно не так? и почему эта неправильная инициализация работает в случае с Уно и Нано?
     
    Последнее редактирование: 29 янв 2018
  10. AlexU

    AlexU Гуру

    Здесь может иметь место неточность документации (к сожалению такое бывает). RESET по сути такой же пин как и остальные. И подтяжка реализована также как и у других -- её нужно включать, например, через INPUT_PULLUP. (здесь ошибся, подтяжка присутствует изначально)
    Если прошивается программатором -- это не означает, что контроллер правильно включен и будет работать, после отключения программатора.
    Я не утверждал, что он не будет работать совсем. Я утверждал, что в общем случае его работа будет не корректной. А так же сделал замечание:
    Если посмотрите на исходники optiboot, то увидите, что сначала сбрасывается регистр MCUSR (все флаги, включая WDRF), а потом настраивается WD на 1 секунду в режиме System Reset. Это если контроллер был включен или перезагружен по RESET. А если был перезагружен по любой другой причине, то сбрасывается регистр MCUSR и отключается WD, затем запускается пользовательская прошивка.

    А если при зашитом optiboot и правильных фьюзах, отдельная ATmega328p не работала так же как и в составе Arduino UNO, то причина в неправильном подключении микроконтроллера.
     
    Последнее редактирование: 30 янв 2018
    b707 нравится это.
  11. b707

    b707 Гуру

    Считаете, это единственное возможное обьяснение ? - не уверен. Кроме подключения между этими двумя вариантами есть еще несколько отличий. возможно, влияющих на процесс отработки ватчдога. И главное из них, как мне кажется - работа от внешнего или внутреннего тактового сигнала.
    Что касается подключения - я пока вижу единственную возможную ошибку только в отсутствии подтяжки RESET к питанию, и, конечно же, попробую ее исправить. В режиме прошивки программатором, как мы уже обсудили, МК работает правильно, а в режиме исполнения кода при работе от внутреннего осциллятора контроллеру вообще ничего не нужно, кроме питания.
    В любом случае спасибо за дискуссию.
     
  12. b707

    b707 Гуру

    Отчитываюсь, добавил подтяжку RESET к питанию - ничего не изменилось.

    Но постепенно, мне кажется. двигаюсь к разгадке.

    Вчера вытащил атмегу328 из Уно, предварительно перешив фьюзы на 8МГц внутренний такт - на ней ватчдог тоже не работает. Таким образом, вариант "бракованая партия МК" можно отбросить.

    Причина проблем явно где-то в моих кривых руках. Что-то я делаю не так.
     
  13. SergeiL

    SergeiL Гуру

    А какие фьюзы Вы прошиваете? Какие значения?
     
  14. b707

    b707 Гуру

    atmega328bb.bootloader.low_fuses=0xE2
    atmega328bb.bootloader.high_fuses=0xDE
    atmega328bb.bootloader.extended_fuses=0x05

    подробнее см в первом посте ветки:
     
  15. SergeiL

    SergeiL Гуру

    А почему extended_fuses=0x05 а не 0xFD? Черт его знает, на что 0 в старших разрядах влияют?
     
  16. b707

    b707 Гуру

    да и правда. черт его знает - вроде как эти биты вовсе не используются. Насколько я понял, раньше было принято выставлять их в ноль, а последнее время - в единицы. В общем, в одних руководствах так, в других иначе - я уже пробовал оба варианта, не канает :)
     
  17. AlexU

    AlexU Гуру

    А можете провести следующий эксперимент (если есть возможность, сам смогу провести только завтра и то под вопросом):
    1. Берём UNO с правильными фьюзами/бутлоадером и убеждаемся, что всё прошивается и работает. Т.е. штатными средствами зашиваем скетч из сообщения #2 и видим, что контроллер перегружается по WD и после перезагрузки работает так как надо.
    2. Не вытаскивая контроллер меняем фьюзы на внетренний генератор 8 МГц (только фьюзы, без перепрошивки) и смотрим что получилось -- должно увеличится только время delay'ев в два раза. Если перестало работать, то проблема в прошивке -- будем думать из-за чего.
    3. Если на втором этапе всё работало как надо, то вытаскиваем контроллер на макетку и смотрим там с соответствующими выводами.
    Других вариантов как локализовать причину ошибки пока не вижу.

    В догонку несколько мыслей:
    По поводу подтяжки RESET к питанию -- призводитель настоятельно рекомендует не надеяться на встроенную подтяжку и делать внешнюю. Вот аппноут AVR042 (см. раздел 3) -- http://ww1.microchip.com/downloads/...ign-considerations_applicationnote_avr042.pdf
    По поводу неиспользуемых фьюзов -- лучше оставлять не запрограммированными, т.е. "единичками".
    По поводу макетки -- не надёжная как сама штука так и проводки, на выходные ребёнок собирал схемку, долго мучался, причина оказалась в проводочке (не самодельный, покупной из набора), который с виду целый без надломов и повреждений, а не прозванивался.
     
    SergeiL нравится это.
  18. ostrov

    ostrov Гуру

    Могу посмотреть как на моей UNO фьюзы стоят. Но попозже.
     
  19. AlexU

    AlexU Гуру

    Да с фьюзами всё в порядке, проблема в другом. Честно говоря самому страсть как интересно разобраться в чём проблема.
     
  20. SergeiL

    SergeiL Гуру

    А для начала, можете в Вашем варианте просто low_fuses= c 0xE2 на 0xС2 поменять?
    Мне кажется проблема именно в этом.