Главная Зерно Пингвин Колибри Сириус Ромашка


Разное

Превращение микроконтроллера в Arduino. Bootloader

Существует множество способов, как заставить работать скетч из Arduino IDE в обычном микроконтроллере. Самый популярный и логически обоснованный – установка загрузчика (bootloader) Arduino желаемой версии на микроконтроллер и добавление внешнего кварца на 16 МГц. 

Метод хорош тем, что дальнейшая работа с подобным микроконтроллером ничем не отличается от работы с обычной платой Arduino. Ещё бы – на нём же загрузчик!

Загрузчик, или в англоязычной литературе, bootloader, это небольшой фрагмент кода, располагающийся в специально отведенной области flash-памяти. Его задачей является организация загрузки и обновления основной программы. Загрузчик обычно запускается раньше основной программы и некоторое время мониторит последовательную шину - линии RX и TX шины UART. Если нет команд на загрузку новой программы, загрузчик переходит к запуску основной программы, находящейся во flash-памяти микроконтроллера. 

Расположение во flash-памяти загрузчика Arduino Nano на микроконтроллере ATMega168. Обратите внимание на адрес, с которого начинается код. При подаче питания на МК именно этот фрагмент будет прочитан первым, а только потом фрагмент с адресом 0000. 

Получается что-то наподобие программного программатора. В принципе, на этом и заканчивается работа загрузчика.  

Перейдём от теории к практике. И первое что нам потребуется для записи загрузчика - программатор. Можно использовать для прошивки микроконтроллеров AVR недорогой программатор USBASP. Также нужен будет адаптер, для подключения микроконтроллера к программатору. Из программ понадобится пока только Arduino IDE.

 
Программатор USBASP c адаптером для микроконтроллеров с корпусами TQFP32.

Распиновка колодки программатора USBASP и расположение необходимых для прошивки пинов у ATMEGA 168/328 в корпусе TQFP 32.


Загрузчики для разных версий плат Arduino хранятся в папке с установленной Arduino IDE:
Arduino/hardware/arduino/avr/bootloaders. Информацию о фьюз битах, частоте тактирования и какой загрузчик соответствует той или иной версии платы, можно узнать в файле boards.txt
(Arduino/hardware/arduino/avr/boards.txt).

  Для примера, попробуем превратить ATMEGA168p в Arduino Nano. 

Предупреждение: во время выполнения операций с микроконтроллером, будьте предельно внимательны – некорректно установленные фьюз биты могут заблокировать микроконтроллер и дальнейшая прошивка будет невозможна. Перед прошивкой не лишним будет проверить значения фьюз-битов в специальном калькуляторе.

Чтобы прошить загрузчик, потребуется еще одна программа – программа для прошивки микроконтроллеров. Для этих целей можно воспользоваться тем, что уже есть - в комплект пакета Arduino IDE входит Avrdude. Ее можно найти в папке C:/Program Files/Arduino/hardware/tools/avr/bin. Приложение Avrdude консольное, поэтому работает только из Командной строки Windows. Для прошивки, нужно лишь запустить командную строку из папки и ввести заранее подготовленную команду.

Совет: для Windows 7 и выше – щелчок правой клавишей мыши на пустом месте с зажатой клавишей Shift -> Открыть окно команд. Или просто введите в Командной строке команду cd полный_путь_к_директории.

Строка ниже, и есть та самая команда, позволяющая прошить микроконтроллер:

avrdude -C ../etc/avrdude.conf -c usbasp -p atmega168p
-U flash:w:имя_файла.hex -U lfuse:w:0xff:m -U hfuse:w:0xdd:m -U efuse:w:0xf8:m


Немного расшифровки «что есть что» в этой команде:
flash:w:имя_файла.hex – путь до файла прошивки. Для удобства, можно скопировать в папку с Avrdude.
atmega168p – тип микроконтроллера, который нужно прошить. Можно посмотреть в файле boards.txt.
-U lfuse:w:0xff:m – значение Low fuse byte. Берётся из файла boards.txt
-U hfuse:w:0xde:m – значение High fuse byte. Берётся из файла boards.txt
-U efuse:w:0x5:m – значение Extended fuse byte. Берётся из файла boards.txt
../etc/avrdude.conf –c – путь до конфигурационного файла. Без этой строки, Avrdude выдает ошибку, и, ничего не прошивает. Не советую тут что-то менять.
-c usbasp – тип программатора, который используется для прошивки. Можно заменить на тот, который есть у вас. Предварительно рекомендую заглянуть в документацию программы Avrdude.

Теперь немного о безопасности. Порою возникает необходимость защитить flash-память микроконтроллера от дальнейшего считывания. Для таких случаев и существуют lock биты, грамотная установка которых не препятствует последующим обновлениям программы. Считать содержимое flash-памяти при этом можно, только вместо реального содержимого памяти, считается набор шестнадцатеричных значений от 0000 до ffff. Именно так работает защита от считывания. 

Для прошивки lock-битов в Avrdude, добавьте к уже имеющейся команде небольшой фрагмент кода:
-U lock:w:0x0F:m. Следует учесть, что значение 0х0F в данном случае так же следует брать из boards.txt в соответствии с выбранной версией загрузчика. 

C:/Program Files/Arduino/hardware/tools/avr/bin>avrdude -C ../etc/avrdude.conf -
c usbasp -p atmega168p -U flash:w:имя_файла.hex -U lfuse:w:0xff:m
-U hfuse:w:0xdd:m -U efuse:w:0xf8:m -U lock:w:0x0F:m

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.06s

avrdude: Device signature = 0x1e940b (probably m168p)
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be perform
ed
To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "ATmegaBOOT_168_diecimila.hex"
avrdude: input file ATmegaBOOT_168_diecimila.hex auto detected as Intel Hex
avrdude: writing flash (16294 bytes):

Writing | ################################################## | 100% 0.13s

avrdude: 16294 bytes of flash written
avrdude: verifying flash memory against ATmegaBOOT_168_diecimila.hex:
avrdude: load data flash data from input file ATmegaBOOT_168_diecimila.hex:
avrdude: input file ATmegaBOOT_168_diecimila.hex auto detected as Intel Hex
avrdude: input file ATmegaBOOT_168_diecimila.hex contains 16294 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.07s

avrdude: verifying ...
avrdude: 16294 bytes of flash verified
avrdude: reading input file "0xff"
avrdude: writing lfuse (1 bytes):

Writing | ################################################## | 100% 0.03s

avrdude: 1 bytes of lfuse written
avrdude: verifying lfuse memory against 0xff:
avrdude: load data lfuse data from input file 0xff:
avrdude: input file 0xff contains 1 bytes
avrdude: reading on-chip lfuse data:

Reading | ################################################## | 100% 0.02s

avrdude: verifying ...
avrdude: 1 bytes of lfuse verified
avrdude: reading input file "0xdd"
avrdude: writing hfuse (1 bytes):

Writing | ################################################## | 100% 0.04s

avrdude: 1 bytes of hfuse written
avrdude: verifying hfuse memory against 0xdd:
avrdude: load data hfuse data from input file 0xdd:
avrdude: input file 0xdd contains 1 bytes
avrdude: reading on-chip hfuse data:

Reading | ################################################## | 100% 0.01s

avrdude: verifying ...
avrdude: 1 bytes of hfuse verified
avrdude: reading input file "0xf8"
avrdude: writing efuse (1 bytes):

Writing | ################################################## | 100% 0.03s

avrdude: 1 bytes of efuse written
avrdude: verifying efuse memory against 0xf8:
avrdude: load data efuse data from input file 0xf8:
avrdude: input file 0xf8 contains 1 bytes
avrdude: reading on-chip efuse data:

Reading | ################################################## | 100% 0.01s

avrdude: verifying ...
avrdude: 1 bytes of efuse verified
avrdude: reading input file "0x0F"
avrdude: writing lock (1 bytes):

Writing | ################################################## | 100% 0.03s

avrdude: 1 bytes of lock written
avrdude: verifying lock memory against 0x0F:
avrdude: load data lock data from input file 0x0F:
avrdude: input file 0x0F contains 1 bytes
avrdude: reading on-chip lock data:

Reading | ################################################## | 100% 0.01s

avrdude: verifying ...
avrdude: 1 bytes of lock verified

avrdude: safemode: Fuses OK (E:F8, H:DD, L:FF)

avrdude done. Thank you.

C:/Program Files/Arduino/hardware/tools/avr/bin

Пример удачно завершенной прошивки микроконтроллера при помощи Avrdude. 


Схема, представленная ниже, взята из документации на Arduino Nano. Это минимум деталей, при котором загрузчик и загружаемые в микроконтроллер скетчи будут работать так же, как и в случае с оригинальной Arduino Nano.   

Для загрузки скетчей в память микроконтроллера потребуется USB-TTL (UART) конвертер – устройство, служащее посредником между средой Arduino IDE и микроконтроллером. Конвертер преобразовывает интерфейс USB в UART, благодаря которому данные поступают загрузчику, а последний в свою очередь записывает их во flash-память микроконтроллера. 

Примечание: в случае, если у вашего конвертера уже имеется конденсатор в цепи DTR, конденсатор С4 можно исключить. Цепь VD1 R4 в принципе не является важной и её можно исключить. 

Два конвертера: верхний на микросхеме PL2303, а нижний - на CH340G. Для загрузки скетча подходит любой.


Процесс загрузки скетча в точности такой же, как и в случае с оригинальной платой Arduino. Микроконтроллер и USB-TTL конвертер соединяются по вот такой не хитрой схеме:

Если у вашего USB-TTL конвертера есть выход DTR, то вам повезло – подключать его следует обязательно к выводу RESET микроконтроллера. Если же такого вывода нет – нужно будет сбрасывать микроконтроллер вручную, кратковременно коммутируя вывод RESET к минусу питания. Делать это необходимо сразу же, как только заметите в Arduino IDE сообщение «Загрузка…». 

Обратите внимание на коричневый проводок. У моих конвертеров нет выхода DTR, поэтому при старте загрузки я просто размыкаю RESET и минус питания.

USB-TTL конвертер на микросхеме CH340G можно доработать: вывод 13 микросхемы и есть тот самый DTR, к которому можно подпаять проводок и использовать вывод по назначению. Всё же приятней когда всё автоматизировано, не так ли?..

Для тестов написан коротенький скетч, сначала на Arduino Nano, а затем на микроконтроллер с загрузчиком Arduino. Особой разницы в работе схемы не замечено. 

Есть чуть более легкий путь, чтобы добиться подобных результатов. И именно о нём я сейчас и расскажу.

Среда Arduino IDE позволяет выгружать готовый скетч в виде бинарного файла. Для этого нужно перейти в Скетч -> Экспорт бинарного файла.

В процессе выгрузки создаются 2 файла с расширением *.hex: с загрузчиком и без него. Внимательный читатель уже догадался, что файл без загрузчика, не подразумевает дальнейшего исправления загруженного скетча. Так оно и есть - вариант хорош в случае, когда исправлять уже больше ничего не нужно и вряд ли когда-нибудь понадобится. 

Запись во flash-память одного из файлов в точности такая же, как и в случае с загрузчиком – пример команды для Avrdude у вас уже есть. Значения фьюз битов так же берутся из boards.txt и зависят от платы, выбранной в среде Arduino IDE. Единственная разница вместо файла загрузчика – бинарный *.hex файл, экспортированный из Arduino IDE.

Поменял сообщение на экране, чтобы не казалось что это результат от предыдущего эксперимента. Хотя разницы в работе опять же никакой.

Настало время поговорить о возможных проблемах. Первое с чем я столкнулся - программатор не видит микроконтроллер. В окне Avrdude можно видеть вот такое сообщение:

avrdude: error: program enable: target doesn’t answer.
avrdude: initialization failed, rc=-1
Double check connections and try again, or use -F to override
this check.

Самая распространённая причина – ошибка в подключении микроконтроллера. Следует проверить правильность соединения МК и адаптера. Более редкая причина – плохой контакт между самим микроконтроллером и адаптером. В таком случае, можно зачистить дорожки адаптера, подогнуть слегка ножки микроконтроллера.  

Еще одна проблема - не загружается скетч. Причин может быть несколько: плохой контакт, неисправный чип, отсутствие питания или же перепутанные линии RX-TX. Последнее, к слову, самая частая беда. 

Всё то, что написано выше, может пригодиться, в случае если вам каким-то образом удалось умертвить микроконтроллер в плате Arduino. Либо, если возникнет потребность создать устройство на Ардуино с красивой и лаконичной топологией печатной платы, без каких-либо наслоений. Оба изложенных сценария вполне работоспособны и проверены, так как основная задача было научиться.

Спасибо за внимание и удачи в конструировании!

Просмотров: 249


06 . 05 . 2024