Не могу вылечить ватчдог на "голой" атмеге328р с внутр тактированием 8 МГц
- Войдите на сайт для отправки комментариев
Вроде и голый контроллер прошиваю не впервые, и загрузчик для "лечения" ватчдога приходилось менять - все было без проблем. Но ватчдог на "голом" МК запускаю первый раз. И ничего не выходит.
Выставляю фьюзы (рассчитаны по калькулятору для 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:
############################################################## 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
Тестовый скетч
#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);
}
Провел еще один тест - подключил к одному из пинов МК светодиод. Была мысль, что при ресете от ватчдога просто не стартует LED-экран, а все остальное - работает. Это уже просто от безисходности
Снова мимо. При первом старте платы светик загорается, гаснет при срабатывании ватчдога и больше не зажигается. То есть дело не в том, что просто не зажигается экран - плата реально зависает...
Попробуй поменять время собаке на меньшее.
Попробуй поменять время собаке на меньшее.
Попробовал 1сек - без разницы.
Упростил тест до предела, чтобы эксперимент был максимально чистым:
1. Взял новую (еще ни разу не шитую) атмегу328р
2. Собрал на макетке классическую обвязку
3. Прошил оптибутовский загрузчик с фьзами 0xE2 0xDE 0x05
4. подключил к 7 пину светодиод
5. 3алил мега-простой скетч
#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); }Итог - при включении светик горит 16сек, потом начинает мигать. После срабатывания ватчдога - мигает часто-часто - то есть типичный случай бесконечного ресета.
Этот же самый бутлоадер в Нано - работает!!! ватчдог ресетится как положено.
Вывод - налицо несовместимость оптибута с атмегой328 с внутренним клоком 8МГц. Если это так = давно бы куча других ардуинщиков столкнулась бы с этим. Вопрос - почему я не вижу в гугле десятков подобных жалоб?
Варианты:
А) - я идиот. Уже готов согласится, при условии, что кто0нибудь обьяснит, в чем именно.
Б) - мне попалась бракованая партия контроллеров. Не исключено. Проверить просто - нужна другая папртия. Может кто-нибудь не пожалеет получаса, повторит перечисленные выше пп 1-5 и напишет свой результат?
В) - предлагайте свои варианты
С субботы на воскресенье всегда так. Все нормальные спят.
А по делу-я сча попробую проверить( пивко псле копоратива эсли позволит). Как ты сказал- "это где-то под носом"У мну была ппрблм с ватчдогом с мегой32. Но насколько могу вспомнить- проблема в Мега32.(Ватч от 2 ух сек и ниже только работал)
Вывод - налицо несовместимость оптибута с атмегой328 с внутренним клоком 8МГц. Если это так = давно бы куча других ардуинщиков столкнулась бы с этим. Вопрос - почему я не вижу в гугле десятков подобных жалоб?
Однозначно работает, ректификатор на нем пару лет пашет. Сам оптибут есть, а вот секцию с фузами потерял когда комп переустанавливал. Т.к. шил первый раз брал все с сайта. Поищи, это у Жеки_ТМ было, он ссылку где то на ЯД давал.
#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); }В) - предлагайте свои варианты
[/quote]
Собака настроена на 1сек и delay 1сек + обрабока пина => времени срабоки собаки
Почему закоментирован сброс собаки.
Собака настроена на 1сек и delay 1сек + обрабока пина => времени срабоки собаки.
интервал собаки можно взять любой - ничего не меняется. Первоначально стояло 8сек, это я уже по совету Штирлица уменьшил.
потому что! :) это вы не проснулись еще...
Народ, вынужден поднять ветку, так как очень нужно решение
Прошу тех, у кого есть под рукой атмега328 в DIP-корпусе - попробовать залить мой скетч и написать о результате.
Попробуй отсюда, на 168 проминьку недавно делал, как раз для собаки, нормально пашет.
Попробуй отсюда, на 168 проминьку недавно делал, как раз для собаки, нормально пашет.
да. спасибо, уже сам нашел эту ветку и прочитал все страницы. Вечером попробую.
Попробуй отсюда, на 168 проминьку недавно делал, как раз для собаки, нормально пашет.
сгенерил бутлоадер по ссылке, прошил - результат тот же.
Все больше прихожу к выводу. что причина во мне - не замечаю чего-то очевидного.
Может все ж-таки кто-то потратит 20 минут времени и попробует повторить мои тесты ?
У меня где-то есть 168-я в DIP, но она уже стояла в ардуине...
сорри, что поздно заметил!!!! Это лечится ОЧЕНЬ просто и об этом написано в документации:
Functions
Detailed Description
This header file declares the interface to some inline macros handling the watchdog timer present in many AVR devices. In order to prevent the watchdog timer configuration from being accidentally altered by a crashing application, a special timed sequence is required in order to change it. The macros within this header file handle the required sequence automatically before changing any value. Interrupts will be disabled during the manipulation.
Note that for newer devices (ATmega88 and newer, effectively any AVR that has the option to also generate interrupts), the watchdog timer remains active even after a system reset (except a power-on condition), using the fastest prescaler value (approximately 15 ms). It is therefore required to turn off the watchdog early during program startup, the datasheet recommends a sequence like the following:
Saving the value of MCUSR in
mcusr_mirroris only needed if the application later wants to examine the reset source, but in particular, clearing the watchdog reset flag before disabling the watchdog is required, according to the datasheet.==========================
вот пример кода, который я ТОЬКО ЧТО проверил на голом 328 в ДИП корпусе.
Вот видео, снял и кинул на Ютуб
Вот код:
#include <stdint.h> #include <avr/wdt.h> uint8_t mcusr_mirror __attribute__ ((section (".noinit"))); void get_mcusr(void) \ __attribute__((naked)) \ __attribute__((section(".init3"))); void get_mcusr(void) { mcusr_mirror = MCUSR; MCUSR = 0; wdt_disable(); } #include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27,16,2); void setup() { pinMode(8,OUTPUT); lcd.init(); lcd.backlight(); lcd.setCursor(0,0); lcd.print("Setup..."); wdt_enable (WDTO_8S); lcd.print(" WDT on"); } void loop(){ static int timer = 0; if(!(millis()%1000)){ timer++; lcd.setCursor(0,1); lcd.print("Count: "); lcd.print(timer); digitalWrite(8, !digitalRead(8)); } }wdrakula, спасибо огромное, вечером проверю. Думаю, что заработает :)
О необходимости этого кода я уже читал во многих местах. Но он, в принципе, должен быть встроен в оптибут - собственно, потому замена штатного бута на оптибут и "лечит" ватчдог. Поэтому я не добавлял этот код в скетч, рассчитывая. что оптибут справится сам.
wdrakula, спасибо огромное, вечером проверю. Думаю, что заработает :)
О необходимости этого кода я уже читал во многих местах. Но он, в принципе, должен быть встроен в оптибут - собственно, потому замена штатного бута на оптибут и "лечит" ватчдог. Поэтому я не добавлял этот код в скетч, рассчитывая. что оптибут справится сам.
Перед тем, как писать, я проверил не только с оптибутом, но и вообще без бутлоадера. С разными фьюзами (и E2 DA и C2 DB - если понимаете, о чем я ).
Нет - работает ТОЛЬКО так.
Я всегда проверяю свои рекомендации (и софтовые и электронные) перед постингом, даже если ответ кажется очевидным.
Сперва я проверил вообще без бута, и добавив "wdr" в main() в ядре. Казалось, что это очевидное решение, что еще хотеть? Ан нет, однако, ответ написан выше ;) ;) ;)
wdrakula,, твой код тоже не работает.
Зато если поместить сброс регистра ватчдога MCUSR в сетап - работает.
Рабочий код получился таким:
#include <avr/wdt.h> int led =7; void setup() { MCUSR = 0; wdt_disable(); pinMode(led,OUTPUT); digitalWrite(led,HIGH); delay(16000); wdt_enable (WDTO_1S); } void loop() { //wdt_reset(); digitalWrite(led, ! digitalRead(led)); delay(1000); }Может ерунду предположу - но похоже на то, что при рестарте контроллера исполнение начинается прямо со скетча - без запуска бутлоадера и без пре-инит функций.
wdrakula,, твой код тоже не работает.
Выложен код и видео. Остальное - чушь какая-то.
Выложен код и видео. Остальное - чушь какая-то.
Влад, погоди
Я не сказал, что твой код неверный. Просто на моей атмеге он не работает. Возможно, я там уже слишком намудрил с конфигами...
Сижу. читаю апноуты и даташиты, разбираюсь. Пока нашел только указание, что работоспособность этого решения зависит от опций компилятора.
на чистую ИДЕ поставь ЭТУ надстройку для бредбоард.
Сперва перезапускаешь ИДЕ и вызываешь "Записать загрузчик".
Потом компилируешь и загружаешь программу.
Больше НИЧЕГО не делаешь.
---------------------------
Я написал, что проверил много вариантов. В том числе и ВООБЩЕ без загрузчика.
Я делал вообще отдельное ядро с отдельными библиотеками, чтобы скетч грузился по кнопке, а не через "Загрузить через программатор", для "голого" 328, без бута.
Решение с кодом в .init3 - самое простое и правильное. Работает с дефолтным бутлоадером и дефолтными фьюзами.
Твоя идея про загрузку - не соответствует даташиту, если у тебя хоть что-то и как-то запустилось без кода в секции .init3, то значит этот код есть в загрузчике, что маловероятно, так как в оптибуте его нет. Может его добавили во что-то еще? Иначе никак... честное пионерское! ;)
Ради спортивного интереса, можешь указать свою надстройку для голого контроллера и версию среды - посмотрю на ней. Только Виндоус ставить не стану, даже для проверки ;) - это "глубокая личная непереносимость", у меня есть древняя ХР на виртуалке - этого для меня вполне хватает, если приползает что-то виндовое.
на чистую ИДЕ поставь ЭТУ надстройку для бредбоард.
Сперва перезапускаешь ИДЕ и вызываешь "Записать загрузчик".
Потом компилируешь и загружаешь программу.
Больше НИЧЕГО не делаешь.
Ну я так и делаю. Моя настройка для голого контроллера есть в первом сообщении ветки (первый спойлер) - она практически идентична твоей. Версия ИДЕ 1,8,3 Win7 x64
Попробуй отсюда, на 168 проминьку недавно делал, как раз для собаки, нормально пашет.
сгенерил бутлоадер по ссылке, прошил - результат тот же.
Все больше прихожу к выводу. что причина во мне - не замечаю чего-то очевидного.
Может все ж-таки кто-то потратит 20 минут времени и попробует повторить мои тесты ?
У меня еще хужее, начал тратить 20 минут и уперся в стену. Сформировал HEX, секцию подготовил, залил через IDE Ar..ISP, все нормально влилось. А от когда попытался залить блинк через преобразователь на ch340: "Нет синхронизации", если вставить в Ардуину (RT232), аналогично. (((( У Вас нормально с этим загрузчиком скетчи заливались?
Вчера уже надоело, сегодня вернусь, фузы проверю и со скоростью поиграюсь. Для 168 на 16мГц все сразу взлетело. Загадка природы.((((
У меня еще хужее, начал тратить 20 минут и уперся в стену. Сформировал HEX, секцию подготовил, залил через IDE Ar..ISP, все нормально влилось. А от когда попытался залить блинк через преобразователь на ch340: "Нет синхронизации", если вставить в Ардуину (RT232), аналогично. (((( У Вас нормально с этим загрузчиком скетчи заливались?
Сорри, что втянул :)
Я заливаю скетчи через SPI - точно так же как загрузчик. После заливки загрузчика ничего не отсоединяете, можно вообще сразу же, как залился загрузчик - жмете "Скетч - Загрузить через программатор".
А через загрузчик я на голом контроллере не пробовал - везде написано, что без кварца UART может не работать.
на чистую ИДЕ поставь ЭТУ надстройку для бредбоард.
Сперва перезапускаешь ИДЕ и вызываешь "Записать загрузчик".
Потом компилируешь и загружаешь программу.
Больше НИЧЕГО не делаешь.
Ну я так и делаю. Моя настройка для голого контроллера есть в первом сообщении ветки (первый спойлер) - она практически идентична твоей. Версия ИДЕ 1,8,3 Win7 x64
Я еще переделывал platform.txt
без него не работает, вот он:
name=Atmega328bb version=0.22 # AVR compile variables # --------------------- # Default "compiler.path" is correct, change only if you want to overidde the initial value compiler.path={runtime.tools.avr-gcc.path}/bin/ compiler.c.cmd=avr-gcc compiler.c.flags=-c -g -Os -w -ffunction-sections -fdata-sections -MMD # -w flag added to avoid printing a wrong warning http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59396 # This is fixed in gcc 4.8.3 and will be removed as soon as we update the toolchain compiler.c.elf.flags=-w -Os -Wl,--gc-sections compiler.c.elf.cmd=avr-gcc compiler.S.flags=-c -g -x assembler-with-cpp compiler.cpp.cmd=avr-g++ compiler.cpp.flags=-c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD compiler.ar.cmd=avr-ar compiler.ar.flags=rcs compiler.objcopy.cmd=avr-objcopy compiler.objcopy.eep.flags=-O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 compiler.elf2hex.flags=-O ihex -R .eeprom compiler.elf2hex.cmd=avr-objcopy compiler.ldflags= compiler.size.cmd=avr-size # This can be overriden in boards.txt build.extra_flags= # These can be overridden in platform.local.txt compiler.c.extra_flags= compiler.c.elf.extra_flags= compiler.S.extra_flags= compiler.cpp.extra_flags= compiler.ar.extra_flags= compiler.objcopy.eep.extra_flags= compiler.elf2hex.extra_flags= # AVR compile patterns # -------------------- ## Compile c files recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" ## Compile c++ files recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" ## Compile S files recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.S.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.S.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" ## Create archives recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" ## Combine gc-sections, archives, and objects recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mmcu={build.mcu} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" -lm ## Create eeprom recipe.objcopy.eep.pattern="{compiler.path}{compiler.objcopy.cmd}" {compiler.objcopy.eep.flags} {compiler.objcopy.eep.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.eep" ## Create hex recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex" ## Compute size recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" recipe.size.regex=^(?:\.text|\.data|\.bootloader)\s+([0-9]+).* recipe.size.regex.data=^(?:\.data|\.bss|\.noinit)\s+([0-9]+).* recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).* # AVR Uploader/Programmers tools # ------------------------------ tools.avrdude.cmd.path={path}/bin/avrdude tools.avrdude.config.path={path}/etc/avrdude.conf tools.avrdude.upload.params.verbose=-v -v tools.avrdude.upload.params.quiet=-q -q tools.avrdude.upload.pattern="{cmd.path}" "-C{config.path}" {upload.verbose} -p{build.mcu} -c{upload.protocol} -P{serial.port} -b{upload.speed} -D "-Uflash:w:{build.path}/{build.project_name}.hex:i" tools.avrdude.program.params.verbose=-v -v tools.avrdude.program.params.quiet=-q -q tools.avrdude.program.pattern="{cmd.path}" "-C{config.path}" {program.verbose} -p{build.mcu} -c{protocol} {program.extra_params} "-Uflash:w:{build.path}/{build.project_name}.hex:i" tools.avrdude.erase.params.verbose=-v -v tools.avrdude.erase.params.quiet=-q -q tools.avrdude.erase.pattern="{cmd.path}" "-C{config.path}" {erase.verbose} -p{build.mcu} -c{protocol} {program.extra_params} -e -Uhfuse:w:{bootloader.high_fuses}:m -Ulfuse:w:{bootloader.low_fuses}:m tools.avrdude.bootloader.params.verbose=-v -v tools.avrdude.bootloader.params.quiet=-q -q tools.avrdude.bootloader.pattern= # "{cmd.path}" "-C{config.path}" {bootloader.verbose} -p{build.mcu} -c{protocol} {program.extra_params} # USB Default Flags # Default blank usb manufacturer will be filled it at compile time # - from numeric vendor ID, set to Unknown otherwise build.usb_manufacturer= build.usb_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} '-DUSB_MANUFACTURER={build.usb_manufacturer}' '-DUSB_PRODUCT={build.usb_product}'Сорри, что втянул :)
Я заливаю скетчи через SPI - точно так же как загрузчик. После заливки загрузчика ничего не отсоединяете, можно вообще сразу же, как залился загрузчик - жмете "Скетч - Загрузить через программатор".
А через загрузчик я на голом контроллере не пробовал - везде написано, что без кварца UART может не работать.
Та чеж сорри то? Самому интересно стало, да возможно грабли миновал (плату разведешь и будешь репу чесать). Если через SPI, то нахрена тогда и загрузчик нужен.
Если через SPI, то нахрена тогда и загрузчик нужен.
ну я ж не только по SPI гружу...
Тут уже тоже не только практический вопрос, но и просто интересно - почему загрузчик не работает?
А он, похоже, таки не работает... судя по результатам твоих и моих тестов.
Я еще переделывал platform.txt
А что именно переделывал, не помнишь?
Я еще переделывал platform.txt
А что именно переделывал, не помнишь?
конечно помню!
-flto отключай или добавь
__attribute__((used))
к описанию функции, что тебе проще. Сорри, все проверил, а этого тебе не рассказал. У меня -flto всегда отключено.
(это Линк Тайм Оптимизация, если знаешь... штука странная и не полезная)
Мдя, вести с полей. После загрузки первый цикл отрабатывает, а потом вечный ребут.((((
Други, если добьете, манул для лохов вроде меня, плиз, а то я уже давно потерялся.((((
Пля....
" When you use Arduino as ISP (or any other ISP programmer) to program an AVR microcontroller, it takes out the bootloader. There is only one instruction available via ISP programming to erase flash, and that is the chip erase command, which wipes the whole flash (and the lockbits - this is part of their code security model ), including the bootloader section.
So - if you did "upload using programmer", that'll wipe out the bootloader on the target."
и на это я потратил 5 дней :))))
ПОЗОР
Мдя, вести с полей. После загрузки первый цикл отрабатывает, а потом вечный ребут.((((
Други, если добьете, манул для лохов вроде меня, плиз, а то я уже давно потерялся.((((
Я потерялся в ваших вопросах: у тебя что не работает? Если Вочдог, то вот такой код должен работать на любом камне: (обрати внимание на атрибут "used")
#include <stdint.h> #include <avr/wdt.h> uint8_t mcusr_mirror __attribute__ ((section (".noinit"))); void get_mcusr(void) \ __attribute__((naked)) \ __attribute__((used)) \ __attribute__((section(".init3"))); void get_mcusr(void) { mcusr_mirror = MCUSR; MCUSR = 0; wdt_disable(); } #include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27,16,2); void setup() { pinMode(8,OUTPUT); lcd.init(); lcd.backlight(); lcd.setCursor(0,0); lcd.print("Setup..."); wdt_enable (WDTO_8S); lcd.print(" WDT on"); } void loop(){ static int timer = 0; if(!(millis()%1000)){ timer++; lcd.setCursor(0,1); lcd.print("Count: "); lcd.print(timer); digitalWrite(8, !digitalRead(8)); } }Мдя, вести с полей. После загрузки первый цикл отрабатывает, а потом вечный ребут.((((
bwn. так и должно быть, если ты загрузил скетч по SPI. Оказывается, при этом удаляется бутлоадер... (см предыдущее сообщение).
Способ "вылечить" ватчдог в этом случае - от wdrakula в сообщении 13. Или мой код чуть дальше.
Ну а я оптибут нашел, который с USB-UART дружит. Тот на который ссыль давал не синхронизируется.
Что по SPI загрузчик трет, знал, тока с собаком не смог это связать.))))
Всем спасибо за науку.
Ну а я оптибут нашел, который с USB-UART дружит. Тот на который ссыль давал не синхронизируется.
а ссылку можно - какой синхронизируется, а какой нет.
Ссыля нет, он у меня на диске валялся, Жека_ТМ давал. Если надо могу хекс скинуть.
Ссыля нет, он у меня на диске валялся, Жека_ТМ давал. Если надо могу хекс скинуть.
Хекс - это ж текстовой формат, выложи как код под спойлер
ОК.
Загрузочная:
ну понятно, в этом скорость UART задана 38400, а в том, что генерится по ссылке - 115200. Я нашел старую ветку обсуждения того генератора - там автору многие указывали. что 115200 для 8МГц без кварца - это слишком быстро. Он, вроде, согласился, но так и не поправил.
Спасибо!
wdrakula, код из сообщения №30 - РАБОТАЕТ (тот, который с атрибутом _used_)
Ну и вообще - полная победа! Проверил все варианты прошивки - и с бутлоадером, и без - все отлично работает!
Спасибо, мужики, огромное!!
Вот. С трудом нашел эту старую тему.
Выдалась пара часов на фоне чистки "снегопада века", починки китайского снегоочистителя, постоянной работы н\генератора, так как провода рвутся и электричество уходит! И ведь самогонка сама не выгоняется. Все сложно (с), короче.
====================================================================
Поправил бутлоадер, не "опти", а классику - она правда лучше. Теперь он раболтает на "голом" 328 на внутр. 8 МГц.
1. Makefile
настраивать можно скорость компорта и время ожидания перед закачкой (то время, за которое нужно успеть нажать ресет) - настраивается в "попугаях" то есть в количестве циклов ожидания. сейчас стоит F_CPU >> 2, что равно 8млн/4=2млн циклов... ну где-то пара секунд.
avr-gcc и все эти вещи, предполагаются на путях - или пишите полные пути в мейкфайле. У меня Линух и стоит все для АВР. На Винде можно все настроить - есть полные тулчейны, или пропишите путь к тому, что идет с АрдуиноИДЕ.
2. Сам бутлоадер. Там пара мест моих правок - ЛЕД не на той ноге. Мои места помечены //WLAD. Чужие комментарии я частично стер частично оставил - мне они нахер не сдались, может кому-то полезны будут. ЕЩЕ РАЗ: "Мопед не мой" - в том смысле, что код не мой, а стандартный из ИДЕ, я причесал чуть чуть.
НАЗЫВАТЬ ЕГО НАДО: ATmegaBOOT_328only.c И ТОЛЬКО ТАК. Ну или меняйте название в мейкфайле.
/* some includes */ #include <inttypes.h> #include <avr/io.h> #include <avr/pgmspace.h> #include <avr/interrupt.h> #include <avr/wdt.h> #include <util/delay.h> #define MAX_ERROR_COUNT 5 #ifndef BAUD_RATE #define BAUD_RATE 19200 #endif /* SW_MAJOR and MINOR needs to be updated from time to time to avoid warning message from AVR Studio */ /* never allow AVR Studio to do an update !!!! */ #define HW_VER 0x02 #define SW_MAJOR 0x01 #define SW_MINOR 0x10 #define BL_DDR DDRD #define BL_PORT PORTD #define BL_PIN PIND #define BL PIND6 #define LED_DDR DDRB #define LED_PORT PORTB #define LED_PIN PINB #define LED PINB1 //WLAD /* manufacturer byte is always the same */ #define SIG1 0x1E // Yep, Atmel is the only manufacturer of AVR micros. Single source :( #if defined __AVR_ATmega168__ #define SIG2 0x94 #define SIG3 0x06 #define PAGE_SIZE 0x40U //64 words #elif defined __AVR_ATmega328P__ #define SIG2 0x95 #define SIG3 0x0F #define PAGE_SIZE 0x40U //64 words #elif defined __AVR_ATmega328__ #define SIG2 0x95 #define SIG3 0x14 #define PAGE_SIZE 0x40U //64 words #endif /* function prototypes */ void putch(char); char getch(void); void getNch(uint8_t); void byte_response(uint8_t); void nothing_response(void); char gethex(void); void puthex(char); void flash_led(uint8_t); /* some variables */ union address_union { uint16_t word; uint8_t byte[2]; } address; union length_union { uint16_t word; uint8_t byte[2]; } length; struct flags_struct { unsigned eeprom : 1; unsigned rampz : 1; } flags; uint8_t buff[256]; uint8_t address_high; uint8_t pagesz=0x80; uint8_t i; uint8_t bootuart = 0; uint8_t error_count = 0; void (*app_start)(void) = 0x0000; /* main program starts here */ int main(void) { uint8_t ch,ch2; uint16_t w; ch = MCUSR; MCUSR = 0; //WLAD wdt Off!!! WDTCSR |= _BV(WDCE) | _BV(WDE); WDTCSR = 0; // Check if the WDT was used to reset, in which case we dont bootload and skip straight to the code. woot. // WLAD: Just comment this "if" to test. The bootloader will be restarting over and over again, and let you load your code through UART if (! (ch & _BV(EXTRF))) // if its a not an external reset... { asm volatile("nop\n\t"); app_start();} // skip bootloader /* check if flash is programmed already, if not start bootloader anyway */ if(pgm_read_byte_near(0x0000) != 0xFF) { } /* initialize UART(s) depending on CPU defined */ #ifdef DOUBLE_SPEED UCSR0A = (1<<U2X0); //Double speed mode USART0 UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*8L)-1); UBRR0H = (F_CPU/(BAUD_RATE*8L)-1) >> 8; #else UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1); UBRR0H = (F_CPU/(BAUD_RATE*16L)-1) >> 8; #endif UCSR0B = (1<<RXEN0) | (1<<TXEN0); UCSR0C = (1<<UCSZ00) | (1<<UCSZ01); /* Enable internal pull-up resistor on pin D0 (RX), in order to supress line noise that prevents the bootloader from timing out (DAM: 20070509) */ DDRD &= ~_BV(PIND0); PORTD |= _BV(PIND0); /* set LED pin as output */ LED_DDR |= _BV(LED); /* flash onboard LED to signal entering of bootloader */ flash_led(NUM_LED_FLASHES); /* 20050803: by DojoCorp, this is one of the parts provoking the system to stop listening, cancelled from the original */ //putch('\0'); /* forever loop */ for (;;) { /* get character from UART */ ch = getch(); /* A bunch of if...else if... gives smaller code than switch...case ! */ /* Hello is anyone home ? */ if(ch=='0') { nothing_response(); } /* Request programmer ID */ /* Not using PROGMEM string due to boot block in m128 being beyond 64kB boundry */ /* Would need to selectively manipulate RAMPZ, and it's only 9 characters anyway so who cares. */ else if(ch=='1') { if (getch() == ' ') { putch(0x14); putch('A'); putch('V'); putch('R'); putch(' '); putch('I'); putch('S'); putch('P'); putch(0x10); } else { if (++error_count == MAX_ERROR_COUNT) app_start(); } } /* AVR ISP/STK500 board commands DON'T CARE so default nothing_response */ else if(ch=='@') { ch2 = getch(); if (ch2>0x85) getch(); nothing_response(); } /* AVR ISP/STK500 board requests */ else if(ch=='A') { ch2 = getch(); if(ch2==0x80) byte_response(HW_VER); // Hardware version else if(ch2==0x81) byte_response(SW_MAJOR); // Software major version else if(ch2==0x82) byte_response(SW_MINOR); // Software minor version else if(ch2==0x98) byte_response(0x03); // Unknown but seems to be required by avr studio 3.56 else byte_response(0x00); // Covers various unnecessary responses we don't care about } /* Device Parameters DON'T CARE, DEVICE IS FIXED */ else if(ch=='B') { getNch(20); nothing_response(); } /* Parallel programming stuff DON'T CARE */ else if(ch=='E') { getNch(5); nothing_response(); } /* P: Enter programming mode */ /* R: Erase device, don't care as we will erase one page at a time anyway. */ else if(ch=='P' || ch=='R') { nothing_response(); } /* Leave programming mode */ else if(ch=='Q') { nothing_response(); #ifdef WATCHDOG_MODS // autoreset via watchdog (sneaky!) WDTCSR = _BV(WDE); while (1); // 16 ms #endif } /* Set address, little endian. EEPROM in bytes, FLASH in words */ /* Perhaps extra address bytes may be added in future to support > 128kB FLASH. */ /* This might explain why little endian was used here, big endian used everywhere else. */ else if(ch=='U') { address.byte[0] = getch(); address.byte[1] = getch(); nothing_response(); } /* Universal SPI programming command, disabled. Would be used for fuses and lock bits. */ else if(ch=='V') { if (getch() == 0x30) { getch(); ch = getch(); getch(); if (ch == 0) { byte_response(SIG1); } else if (ch == 1) { byte_response(SIG2); } else { byte_response(SIG3); } } else { getNch(3); byte_response(0x00); } } /* Write memory, length is big endian and is in bytes */ else if(ch=='d') { length.byte[1] = getch(); length.byte[0] = getch(); flags.eeprom = 0; if (getch() == 'E') flags.eeprom = 1; for (w=0;w<length.word;w++) { buff[w] = getch(); // Store data in buffer, can't keep up with serial data stream whilst programming pages } if (getch() == ' ') { if (flags.eeprom) { //Write to EEPROM one byte at a time address.word <<= 1; for(w=0;w<length.word;w++) { while(EECR & (1<<EEPE)); EEAR = (uint16_t)(void *)address.word; EEDR = buff[w]; EECR |= (1<<EEMPE); EECR |= (1<<EEPE); address.word++; } } else { //Write to FLASH one page at a time if (address.byte[1]>127) address_high = 0x01; //Only possible with m128, m256 will need 3rd address byte. FIXME else address_high = 0x00; address.word = address.word << 1; //address * 2 -> byte location /* if ((length.byte[0] & 0x01) == 0x01) length.word++; //Even up an odd number of bytes */ if ((length.byte[0] & 0x01)) length.word++; //Even up an odd number of bytes cli(); //Disable interrupts, just to be sure while(bit_is_set(EECR,EEPE)); //Wait for previous EEPROM writes to complete asm volatile( "clr r17 \n\t" //page_word_count "lds r30,address \n\t" //Address of FLASH location (in bytes) "lds r31,address+1 \n\t" "ldi r28,lo8(buff) \n\t" //Start of buffer array in RAM "ldi r29,hi8(buff) \n\t" "lds r24,length \n\t" //Length of data to be written (in bytes) "lds r25,length+1 \n\t" "length_loop: \n\t" //Main loop, repeat for number of words in block "cpi r17,0x00 \n\t" //If page_word_count=0 then erase page "brne no_page_erase \n\t" "wait_spm1: \n\t" "lds r16,%0 \n\t" //Wait for previous spm to complete "andi r16,1 \n\t" "cpi r16,1 \n\t" "breq wait_spm1 \n\t" "ldi r16,0x03 \n\t" //Erase page pointed to by Z "sts %0,r16 \n\t" "spm \n\t" "wait_spm2: \n\t" "lds r16,%0 \n\t" //Wait for previous spm to complete "andi r16,1 \n\t" "cpi r16,1 \n\t" "breq wait_spm2 \n\t" "ldi r16,0x11 \n\t" //Re-enable RWW section "sts %0,r16 \n\t" "spm \n\t" "no_page_erase: \n\t" "ld r0,Y+ \n\t" //Write 2 bytes into page buffer "ld r1,Y+ \n\t" "wait_spm3: \n\t" "lds r16,%0 \n\t" //Wait for previous spm to complete "andi r16,1 \n\t" "cpi r16,1 \n\t" "breq wait_spm3 \n\t" "ldi r16,0x01 \n\t" //Load r0,r1 into FLASH page buffer "sts %0,r16 \n\t" "spm \n\t" "inc r17 \n\t" //page_word_count++ "cpi r17,%1 \n\t" "brlo same_page \n\t" //Still same page in FLASH "write_page: \n\t" "clr r17 \n\t" //New page, write current one first "wait_spm4: \n\t" "lds r16,%0 \n\t" //Wait for previous spm to complete "andi r16,1 \n\t" "cpi r16,1 \n\t" "breq wait_spm4 \n\t" "ldi r16,0x05 \n\t" //Write page pointed to by Z "sts %0,r16 \n\t" "spm \n\t" "wait_spm5: \n\t" "lds r16,%0 \n\t" //Wait for previous spm to complete "andi r16,1 \n\t" "cpi r16,1 \n\t" "breq wait_spm5 \n\t" "ldi r16,0x11 \n\t" //Re-enable RWW section "sts %0,r16 \n\t" "spm \n\t" "same_page: \n\t" "adiw r30,2 \n\t" //Next word in FLASH "sbiw r24,2 \n\t" //length-2 "breq final_write \n\t" //Finished "rjmp length_loop \n\t" "final_write: \n\t" "cpi r17,0 \n\t" "breq block_done \n\t" "adiw r24,2 \n\t" //length+2, fool above check on length after short page write "rjmp write_page \n\t" "block_done: \n\t" "clr __zero_reg__ \n\t" //restore zero register : "=m" (SPMCSR) : "M" (PAGE_SIZE) : "r0","r16","r17","r24","r25","r28","r29","r30","r31" ); /* Should really add a wait for RWW section to be enabled, don't actually need it since we never */ /* exit the bootloader without a power cycle anyhow */ } putch(0x14); putch(0x10); } else { if (++error_count == MAX_ERROR_COUNT) app_start(); } } /* Read memory block mode, length is big endian. */ else if(ch=='t') { length.byte[1] = getch(); length.byte[0] = getch(); address.word = address.word << 1; // address * 2 -> byte location if (getch() == 'E') flags.eeprom = 1; else flags.eeprom = 0; if (getch() == ' ') { // Command terminator putch(0x14); for (w=0;w < length.word;w++) { // Can handle odd and even lengths okay if (flags.eeprom) { // Byte access EEPROM read while(EECR & (1<<EEPE)); EEAR = (uint16_t)(void *)address.word; EECR |= (1<<EERE); putch(EEDR); address.word++; } else { if (!flags.rampz) putch(pgm_read_byte_near(address.word)); address.word++; } } putch(0x10); } } /* Get device signature bytes */ else if(ch=='u') { if (getch() == ' ') { putch(0x14); putch(SIG1); putch(SIG2); putch(SIG3); putch(0x10); } else { if (++error_count == MAX_ERROR_COUNT) app_start(); } } /* Read oscillator calibration byte */ else if(ch=='v') { byte_response(0x00); } else if (++error_count == MAX_ERROR_COUNT) { app_start(); } } /* end of forever loop */ } char gethexnib(void) { char a; a = getch(); putch(a); if(a >= 'a') { return (a - 'a' + 0x0a); } else if(a >= '0') { return(a - '0'); } return a; } char gethex(void) { return (gethexnib() << 4) + gethexnib(); } void puthex(char ch) { char ah; ah = ch >> 4; if(ah >= 0x0a) { ah = ah - 0x0a + 'a'; } else { ah += '0'; } ch &= 0x0f; if(ch >= 0x0a) { ch = ch - 0x0a + 'a'; } else { ch += '0'; } putch(ah); putch(ch); } void putch(char ch) { while (!(UCSR0A & _BV(UDRE0))); UDR0 = ch; } char getch(void) { uint32_t count = 0; while(!(UCSR0A & _BV(RXC0))){ /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/ /* HACKME:: here is a good place to count times*/ count++; if (count > MAX_TIME_COUNT){ // flash_led(1); app_start(); } } return UDR0; } void getNch(uint8_t count) { while(count--) { getch(); } } void byte_response(uint8_t val) { if (getch() == ' ') { putch(0x14); putch(val); putch(0x10); } else { if (++error_count == MAX_ERROR_COUNT) app_start(); } } void nothing_response(void) { if (getch() == ' ') { putch(0x14); putch(0x10); } else { if (++error_count == MAX_ERROR_COUNT) app_start(); } } void flash_led(uint8_t count) { while (count--) { LED_PORT |= _BV(LED); _delay_ms(100); LED_PORT &= ~_BV(LED); _delay_ms(100); } } /* end of file ATmegaBOOT.c */3. ну и boards.txt к ним до кучи.
Скорость компорта тут и в мейкфайле должна совпадать.
=======================================
все это проверено в условиях:
Бутлоадер грузился через Нано с ArduinoISP из 1.8.5.
В качестве USB-UART использовалась Мега с закороченным на GND Ресетом.
В качестве тестового скетча был использован скетч из этой темы выше, мой вариант теста Вочдога. Только вывод был в Сериал, а не на дисплей.
Откомпилированный именно этот код, для тех, кого компилятор "не встает" на сборку бутлоадера ;) ;) ;)!!!.
В продолжение темы бутлоадеров с работоспособным вотчдогом.
Прикупил ПроМини с 168P и кварцом 8 мгц (3,3в). Заливал загрузчик из пакета оптибута: optiboot_pro_8MHz.hex. (USBASP)
Пробовал залить из "Конструктор Bootloader`а" с конфигурацией 168 / 8.
В обеих случаях потом не могу загрузить сектч через uart.
Using Port : COM3
Using Programmer : arduino
Overriding Baud Rate : 57600
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0xec
скорость порта менял от 9600 до 115200. результат тот же.
Фюзы - E:FC, H:DD, L:C6
Что делаю не так и где взять рабочий бутлоадер на 8мгц (маленький и с вотчдогом)
так через UART или через USBASP ? - это как бы принципиально разные вещи
бутлоадер через USBASP, потом уже скетч пытался через UART.
я брал отсюда: http://homes-smart.ru/index.php/oborudovanie/arduino/avr-zagruzchik
я брал отсюда: http://homes-smart.ru/index.php/oborudovanie/arduino/avr-zagruzchik
Брал и там тоже. Не работает. Если у вас работает, расскажите подробнее какая у вас конфигурация, какие фьюзы и на какой скорости заливаете скетчи, с помощью этого загрузчика. Вполне вероятно, я что-то сделал не так...
Как то так все работает, на 115200 шьется. Понятно, что верхний файлик переименовываешь в a168_8MHz_ff_de_4.hex и кладешь в паgку optiboot. в boards.txt добавляешь, что ниже. Далее перезагружаешь IDE, в списке видишь свою плату, Далее с помощью USBASP загрузить загрузчик, чтобы правильно прописались фьюзы. И пользуешься через UART.
То что у меня 168P роли не играет? просто скорректировать 168 на 168Р в board.txt?
Несколько человек уже отписывались, что через USBASP не могут нормально бутлоадер прописать. Уж не знаю в чем дело, толи дешевые USBASP глячат, то ли в ИДЕ какие несовместимости.
Ардуиной через SPI скетчем "Ардуино-ИСП" записывается надежнее.
А коллективный разум уже решил что цеплять к входу ресет программируемой ProMini ?
А то я встречал от "ничего" до "электролит 47-100мкф"...
Я прошивал голый 328р на собственной плате через АрдуиноИСП, ресет посоединял напрямую к 10 пину программатора, без резисторов и кондеров.