четверг, 19 июля 2018 г.

Arduino as ISP - программатор из Ардуино

Arduino as ISP - программатор из Ардуино

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

Что такое ISP?


ISP (In-System Programming) расшифровывается как внутрисхемное программирование. Это технология, которая позволяет программировать микроконтроллер, установленный в устройство. До появления этой технологии микроконтроллеры программировались перед установкой в устройство, а для их перепрограммирования требовалось их извлечение из устройства.

Существует 2 основных подхода внутрисхемного программирования:

  • С использованием программатора. В этом случае программатор работает напрямую с памятью микроконтроллера, самостоятельно размещая байты прошивки по нужным адресам. Микроконтроллер в этом процессе не участвует.
  • С использованием загрузчика. Загрузчик, он же бутлоадер (от английского bootloader) - это программа, записанная обычно в конце ПЗУ микроконтроллера, которая берет на себя функции программатора. При включении микроконтроллера управление сначала передается загрузчику. Он проверяет наличие определенных условий, сообщающих о необходимости перейти в режим программирования. Если условия не выполнены, то управление передается основной программе, в противном случае загрузчик принимает данные по заранее определенному интерфейсу и размещает их в ПЗУ. Таким образом микроконтроллер перепрограммирует сам себя.
Одной из важнейших особенностей Ардуино является возможность программирования непосредственно через USB порт, без дополнительного программатора. Сразу после включения Ардуино запускается загрузчик, который работает несколько секунд. Если за это время загрузчик получает команду программирования от IDE по последовательному интерфейсу UART, то он принимает и загружает новую программу в память микроконтроллера.

Использование загрузчика существенно упрощает процесс перепрограммирования микроконтроллера, что особенно полезно при отладке. Но за удобство приходится платить. Во-первых, загрузчик занимает часть ПЗУ и для программы пользователя остается меньший объем памяти. Во-вторых, загрузчик не может изменить Fuse-биты и Lock-биты (в отличие от программаторов). Ну и, конечно, не обойтись без программатора, если вы хотите обновить бутлоадер или загрузить его в чистый МК. Таким образом существует ряд задач, которые могут быть выполнены только с использованием программатора. Если же у вас нет аппаратного программатора, то вместо него можно воспользоваться Ардуино, о чем и будет рассказано дальше.

Arduino as ISP. Прошивка загрузчика в Ардуино.

Итак, мы решили превратить Ардуино в программатор. Для примера попробуем прошить загрузчик в целевую плату Ардуино. Сначала подготовим плату, которую будем использовать в качестве программатора. Для этого загрузим в нее скетч ArduinoISP, его можно найти в стандартных примерах:

ArduinoISP sketch file

Теперь подсоединим к ней плату, в которую хотим прошить загрузчик. При прошивке используются линии SPI (Serial Peripheral Interface - последовательный периферийный интерфейс). Выводы MOSI, MISO и SCK обеих плат должны быть соединены, а вывод SS Ардуино-программатора подключается к выводу Reset целевой платы. И еще 2 провода нужны чтобы запитать целевую плату. Также может потребоваться предотвратить автоматическую перезагрузку платы-программатора, для этого между ее выводами Reset и GND нужно установить электролитический конденсатор на 10мкФ. Сначала можно попробовать без конденсатора, если же прошивка не начнется, то попробуйте добавить в схему конденсатор. По моим наблюдениям конденсатор нужен при использовании дешевых Ардуино-клонов (без контроллера ATmega8u2) в качестве программатора.

Если мы работаем с двумя платами Arduino Uno, то схема их подключения может выглядеть следующим образом:

Arduino as ISP схема подключения

Если используются не Uno, а другие платы Ардуино, то перед подключением программатора к целевой плате необходимо уточнить расположение на них выводов MOSI, MISO и SCK. Их расположение для различных плат приведено ниже в таблице. Как вы можете видеть, не на всех платах Ардуино линии SPI мультиплексированны с цифровыми выводами, поэтому для подключения к данному интерфейсу необходимо использовать разъем ICSP. Ниже показан пример подключения Uno в качестве программатора к плате Nano через ICSP разъем.

Плата Ардуино MOSI MISO SCK Уровень
Uno, Duemilanove 11 или ICSP-4 12 или ICSP-1 13 или ICSP-3
Nano 11 или ICSP-4 12 или ICSP-1 13 или ICSP-3
Pro Mini 11 12 13 3.3В или 5В
Mega1280, Mega2560 51 или ICSP-4 50 или ICSP-1 52 или ICSP-3
Leonardo ICSP-4 ICSP-1 ICSP-3 
Due ICSP-4 ICSP-1 ICSP-3  3.3В
Zero ICSP-4 ICSP-1 ICSP-3 3.3В
101 11 или ICSP-4 12 или ICSP-1 13 или ICSP-3 3.3В


Arduino as ISP схема подключения Nano
Подключение Uno в качестве программатора к плате Nano через ICSP
Обратите внимание на нумерацию выводов ICSP платы Nano: она начинается с правого нижнего угла. Поэтому на приведенной схеме Arduino Nano перевернута.

Теперь необходимо вернуться в Arduino IDE и изменить в ней параметры:

  1. В меню Инструменты > Плата выбираем вариант, соответствующий нашей целевой плате.
  2. В меню Инструменты > Программатор выбираем Arduino as ISP.

Подключаем плату-программатор к компьютеру, открытый в данный момент скетч значения не имеет, выбираем пункт меню Инструменты > Записать загрузчик и дожидаемся сообщения об успешном завершении операции. На этом прошивка бутлоадера в Ардуино завершена. Кроме того процедура прошивки бутлоадера включает в себя установку фьюзов микроконтроллера. Подробнее о фьюзах будет рассказано в следующей публикации.

Резюмируя вышеописанное, выделим основные шаги для прошивки загрузчика с использованием Ардуино в качестве ISP программатора:

  • Запускаем Arduino IDE, открываем из примеров скетч ArduinoISP и загружаем его в плату Ардуино, которую будем использовать как программатор.
  • Подключаем к Ардуино-программатору целевую плату по приведенной схеме.
  • Меняем плату в Arduino IDE на целевую.
  • Выбираем в IDE программатор Arduino as ISP.
  • Записываем загрузчик в целевую плату командой из меню IDE.

Прошивка скетча с использованием Arduino as ISP

Еще один пример использования программатора - это загрузка скетча в целевую плату. Разумеется, это проще сделать привычным способом, подключив ее напрямую к компьютеру, но это может оказаться невозможным, например, при выходе из строя контроллера ATmega8u2/ATmega16u2 или преобразователя USB/UART. Если при этом основной микроконтроллер Ардуино остался рабочим, то мы можем прошить его, используя программатор. Для этого выполняем все шаги, описанные выше, но на последнем этапе вместо записи загрузчика необходимо:

  • Открыть в Arduino IDE интересующий скетч.
  • Загрузить скетч в целевую плату командой из меню IDE: Скетч > Загрузить через программатор.
Таким образом можно подарить вторую жизнь плате Ардуино, которую компьютер уже не видит через USB.

31 комментарий:

  1. Спасибо восстановил плату

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

    ОтветитьУдалить
  3. А как через такой программатор считать EEPROM с той же ардуино??

    ОтветитьУдалить
    Ответы
    1. Посмотрите следующую публикацию: https://tsibrov.blogspot.com/2018/08/fuse-bits.html
      В ней описано, как работать с фьюзами с использованием входящей в IDE Arduino программы avrdude. Чтение/запись EEPROM, а так же flash, lock битов, байтов калибровки и прочего выполняется аналогично, просто указываем в команде что из этого мы хотим прочитать/записать. Например, следующая команда выполнит чтение EEPROM и сохранит результат в файл eeprom_dump.hex:
      avrdude -C ../etc/avrdude.conf -c arduino -p m328p -P com1 -b 19200 -U eeprom:r:eeprom_dump.hex:h

      COM порт не забудьте на свой изменить.

      Команда для чтения flash точно такая же, только тип памяти указываем flash:
      avrdude -C ../etc/avrdude.conf -c arduino -p m328p -P com1 -b 19200 -U flash:r:flash_dump.hex:h

      Для записи в микроконтроллер вместо r указываем w в опции -U. Подробная информация о параметрах запусках avrdude приведена здесь:
      https://ph0en1x.net/77-avrdude-full-howto-samples-options-gui-linux.html

      Удалить
  4. Здравствуйте!
    Загрузка скетча Arduinino ISP проходит в штатном режиме на UNO(хочу ипользовать как программатор).
    Но при загузке бутлодера на NANO(целевая) выдаётся ошибка
    "***failed;
    avrdude: WARNING: invalid value for unused bits in fuse "efuse", should be set to 1 according to datasheet
    This behaviour is deprecated and will result in an error in future version
    You probably want to use 0xfd instead of 0x05 (double check with your datasheet first)."
    Если кто в курсе, помогите пожалуйста.

    ОтветитьУдалить
    Ответы
    1. Добрый день. В сообщении avrdude в общем-то всё сказано. Поправьте значение efuse для соответствующей платы (той, в которую заливаете загрузчик). Значения фьюзов прописаны в файле boards.txt, найдёте его в папке Ардуино: ...\hardware\arduino\avr\
      У вас там 0x05. Измените на 0xfd.

      Удалить
    2. Добрый день. А чтобы это могло значить, постоянно выдаёт такую ошибку?
      Используя порт: \\. \ COM5
                Использование программатора: stk500v1
                Превосходящая скорость передачи данных: 19200
      avrdude: Отправить: 0 [30] [20]
      avrdude: Отправить: 0 [30] [20]
      avrdude: Отправить: 0 [30] [20]
      avrdude: Recv:
      avrdude: stk500_getsync (): не синхронизировано: resp = 0x00
      Чтонужно синхронизировать?

      Удалить
    3. Добрый день.
      В какой момент получаете это сообщение?

      Удалить
    4. Всё выполняю, как и у вас записано. Запускаем Arduino IDE, открываем из примеров скетч ArduinoISP и загружаем его в плату Ардуино, которую будем использовать как программатор.
      Подключаем к Ардуино-программатору целевую плату по приведенной схеме.
      Меняем плату в Arduino IDE на целевую.
      Выбираем в IDE программатор Arduino as ISP.
      Записываем загрузчик в целевую плату командой из меню IDE.
      Идёт запись, но в самом конце красным шрифтом постоянно выдаёт, avrdude: Recv:
      avrdude: stk500_getsync (): не синхронизировано: resp = 0x00. Что такое resp = 0x00?
      Предполагаю, что это respective, соответствующее = 0x00? И в каком-то файле Arduino IDE нужно менять данные.

      Удалить
    5. А avrdude: Recv вероятно означает, recv failure connection reset by peer (сбой приёма соединения сброс по пирингу) это вообще тёмный лес.

      Удалить
    6. Проверьте соединение. Грузится ли скетч через программатор в целевую плату (например, Blink через меню Скетч -> загрузить через программатор)? Попробуйте другую версию IDE, другую плату если есть.
      Файлы IDE править не нужно, всё должно работать.

      Удалить
    7. Столкнулся с аналогичной проблемой stk500_recv(): programmer is not responding
      stk500_getsync() attempt 1 of 10: not in sync: resp=0x03

      Притом что скетч грузится по примеру Blink и светодиод моргает. Как вы думаете в чем проблема?

      Удалить
    8. Добрый день!
      Вы пробуете с установленным конденсатором между землёй и reset?

      Удалить
  5. Спасибо, а то китайский USB ISP программатор отказался работать и затер загрузчик.

    ОтветитьУдалить
  6. Здравствуйте!
    Спасибо за оперативный овет.
    К сожалению заменить фьюзы у меня не получилось, но вроде решил проблему по-другому. Посредством AVR Dude указал файл ...\ideV2\hardware\arduino\avr\bootloaders\atmega\ATmegaBOOT_168_atmega328.hex и загнал в NANO328. После чего мой пользовательский скеч заработал. Ответьте пожалуйста, это приемлемый вариант?

    ОтветитьУдалить
    Ответы
    1. Добрый день!
      Что значит не получилось заменить фьюзы? Вы заменили значения 0x05 на 0xFD в файле boards.txt? Это всё, что нужно было сделать. Потом повторить запись загрузчика из IDE Arduino.
      Если сейчас работает, значит вариант приемлемый. Только это старый загрузчик, лучше бы вместо него залить optiboot.

      Удалить
  7. Добрый день Владимир!
    Спасибо за предоставленную информацию. Вопрос следующий на двух Leonardo (причем одна фирменная) тестировал программу с прерываниями в результате этого как я подозреваю у плат слетел загрузчик. То есть платы работают отрабатывают программу которая в них залита но в ID платы не определяются. Поиск в интернете однозначного решения вопроса не дал. У одних что-то получилось у других нет. А может и получилось совсем по другим причинам у авторов не такой фундаментальный подход к вопросу как у вас. Итог такой если у вас в программе есть прерывания категорически не используйте Leonardo. И повторю вопрос реально ли через UNO перепрошить загрузчик на Leonardo. Заранее спасибо за ответ.

    ОтветитьУдалить
    Ответы
    1. Добрый день!
      Я не работал с Leonardo и по поводу ошибки не могу подсказать. Но точно знаю, что использовать прерывания в ней можно. Попробуйте залить загрузчик, описанный здесь способ подойдет и для Leonardo

      Удалить
    2. Добрый день Владимир
      При перепрошивке Leonardo через UNO процесс зависает при этом в комментариях появляются следующие сообщения:
      java.io.IOException: jssc.SerialPortException: Port name - COM9; Method name - setEventsMask(); Exception type - Can't set mask.
      at processing.app.Serial.dispose(Serial.java:158)
      at processing.app.SerialMonitor.close(SerialMonitor.java:116)
      at processing.app.AbstractMonitor.suspend(AbstractMonitor.java:96)
      at processing.app.Editor$DefaultExportHandler.run(Editor.java:2141)
      at java.lang.Thread.run(Thread.java:748)
      Caused by: jssc.SerialPortException: Port name - COM9; Method name - setEventsMask(); Exception type - Can't set mask.
      at jssc.SerialPort.setEventsMask(SerialPort.java:279)
      at jssc.SerialPort.removeEventListener(SerialPort.java:1064)
      at jssc.SerialPort.closePort(SerialPort.java:1090)
      at processing.app.Serial.dispose(Serial.java:155)
      ... 4 more
      Можете пояснить в чем тут дело.

      Удалить
  8. Не то написал хотел удалить. Не так сделал если делать по статье пишет сразу ошибка загрузчика.

    ОтветитьУдалить
  9. Все получилось большое спасибо за информацию как всегда вначале подвела привычка читать по диагонале (торопливость) и не внимательность. Еще раз спасибо плата ожила которую я же почти похоронил.

    ОтветитьУдалить
    Ответы
    1. Добрый день!
      Хорошо, что все получилось. Теперь есть опыт записи загрузчика, наверняка, пригодится

      Удалить
  10. Добрый день!
    Сегодня удачно прошил вторую LEONARDO еще раз спасибо за статью.

    ОтветитьУдалить
  11. На днях придёт кварцевый резонатор, буду прошивать бутлоадер и скетч на ATmega328P, надеюсь две эти статьи мне помогут, если что, отпишусь.

    ОтветитьУдалить
  12. Здравствуйте! Спасибо за полезную статью. Если не секрет, в каком графическом редакторе Вы создавали иллюстрации с платами?

    ОтветитьУдалить
    Ответы
    1. Добрый день!
      Это Fritzing. На самом деле не очень удобная программа для рисования схем.

      Удалить
  13. На Ардуине можно собрать и более продвинутый программатор, включающий высоковольтное программирование: http://arduino.ru/forum/apparatnye-voprosy/universalnyi-avr-programmator-na-arduino.

    ОтветитьУдалить