Основы разработки загрузчика для Arduino. Часть 2

Загрузчик для ардуино

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

Как запрограммировать ардуино с помощью IDE?

Загрузчик Arduino использует последовательный протокол UART для загрузки шестнадцатеричного файла программы с ПК/ноутбука. На стороне ПК/ноутбука работает Arduino IDE, которая компилирует прикладную программу и последовательно отправляет скомпилированный шестнадцатеричный код на плату Arduino по кабелю USB.

Arduino IDE использует инструмент avrdude, который используется для загрузки/выгрузки кода/содержимого данных в/из ROM/EEPROM микроконтроллеров AVR.

AVRDUDE (AVR Downloader Uploader, в народе «дудка») — это программа для загрузки и выгрузки встроенной памяти микроконтроллеров Atmel AVR. Он может программировать флэш-память и EEPROM, и поддерживается протоколом последовательного программирования. Он также может программировать биты фьюзов.

Протокол связи от STK500 используется avrdude для последовательной загрузки скомпилированного шестнадцатеричного файла в Arduino. По этой причине мы включаем/используем заголовочный файл команд STK500 в программе загрузчика.

Связь STK500 используется между avrdude (работает на стороне ПК/ноутбука) и загрузчиком (работает на стороне Arduino) для записи/чтения шестнадцатеричного файла.

Теперь давайте посмотрим, как загрузить программу загрузчика в раздел загрузки.

Как загрузить загрузчик в ардуино?

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

Как правило, мы программируем любую микросхему перед ее пайкой на печатной плате. В то время как многие производители микроконтроллеров (например, Atmel, Microchip) предоставляют специализированный метод системного программирования (ISP), известный как внутрисхемное последовательное программирование (ICSP). В таких методах на плате предусмотрен разъем ISP для прошивки внешним программатором.

Arduino имеет встроенный разъем ICSP для программирования, как показано на рисунке ниже.

Разъемы ICSP на плате arduino uno
Рисунок 1. Разъемы ICSP на плате arduino uno

Как показано на рисунке выше, Arduino UNO имеет два разъема ICSP. Один для ATmega16U2 и один для ATmega328. Чтобы прошить загрузчик, нам нужно использовать разъем ICSP для ATmega328.

Заметка


Мы можем собрать и прошить загрузчик Arduino с помощью Atmel Studio и программатора USBasp. Чтобы узнать, как собрать и прошить шестнадцатеричный файл в микроконтроллеры avr, обратитесь к разделу сайта «Начало работы с Atmel Studio».


Кроме того, мы можем прошить загрузчик, используя другую плату Arduino, т.е. если у нас есть вторая плата Arduino, мы можем использовать ее в качестве программатора ISP. Откройте среду разработки Arduino и откройте пример ArduinoISP из его меню примеров, как показано на рисунке ниже.

Где найти пример кода загрузчика Arduino ISP
Рисунок 2. Где найти пример кода загрузчика Arduino ISP

Загрузите программу ArduinoISP на плату Arduino, которую мы используем в качестве программатора ISP Programmer. Теперь подключите (как показано на рисунке 3) этот программатор arduino isp к плате arduino, которую необходимо запрограммировать.

Рисунок 3. Подключение ардуино к программатору arduino isp

Выберите в меню Плата плату, отвечающую за роль программатора ISP, а в меню Программатор выберите программатор Arduino as ISP, как показано на рисунке ниже.

Выбор программатора в Arduino IDE
Рисунок 4. Выбор программатора в Arduino IDE

Затем просто нажмите Записать загрузчик в меню инструментов (показано на изображении выше). Дождитесь завершения процесса записи загрузчика. Мы видим, что светодиод мигает, пока идет процесс записи.

После успешной записи плата Arduino (на которою записан загрузчик) готова к программированию.

Как изменить загрузчик Arduino?

Также доступна модифицированная версия загрузчика Arduino, которая имеет несколько правильных функций и одно существенное изменение. Изменение заключается в том, что причина сброса (регистр состояния MCUSR) передается из программы загрузчика в прикладную программу через регистр r2. Он передается через функцию app_start(), как показано на рисунке 5.

Функция appStart()
Рисунок 5. Функция appStart()

Имея достаточную квалификацию, мы можем создавать свои варианты загрузчика. Например, загрузчик Arduino использует последовательную связь UART для чтения шестнадцатеричного файла с ПК/ноутбука. Мы также можем использовать другие доступные варианты последовательной связи, такие как последовательная связь SPI, I2C. Используя эти связи, мы можем прочитать шестнадцатеричный файл из внешнего источника (например, карты памяти, eeprom).

Размер раздела загрузчика

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

Если мы возьмем пример Arduino, то увидим, что размер загрузчика выбирается пользователем. Например. Arduino UNO, который использует микроконтроллер AVR Atmega328P, имеет размер загрузчика, который выбирается в соответствии с данными, указанными в их техническом описании на этот микроконтроллер.

Таблица загрузочных разделов в Atmega328
Рисунок 6. Таблица загрузочных разделов в Atmega328

Как показано на приведенном выше рисунке конфигурации загрузки, размер их загрузочного раздела можно выбрать. Размер загрузки указывается в словах, что составляет половину размера в байтах, то есть 256 слов означают 512 байт.

Начальный адрес сброса загрузки также выбирается в соответствии с конфигурацией размера загрузки, т. е. если мы выбираем размер 256 слов для раздела загрузки, нам нужно написать программу загрузчика, которая поместится только в 256 слов (512 байт) памяти, и ее начальный адрес будет 0x3F00 (0x7E00 в байтах). Следовательно, программа загрузчика должна находиться в пределах от 0x3F00 до 0x3FFF (512 байт).

Настройки свойств проекта Atmel Studio при разработке загрузчика

Когда создаете новый проект для загрузчика Arduino в Atmel Studio, просто внесите некоторые важные изменения в их свойства для целей оптимизации. Сначала откройте окно свойств проекта из меню Проект (Project), как показано на рисунке 7.

Открытие окна свойств проекта в Atmel Studio
Рисунок 7. Открытие окна свойств проекта в Atmel Studio

Затем появятся свойства проекта. Затем перейдите в ToolchainSymbols в компиляторе AVR/GNU, чтобы определить скорость передачи как 115200 и частоту как 16000000 Гц, как показано на рисунке 8.

Определение скорости передачи и частоты в настройках Atmel Studio
Рисунок 8. Определение скорости передачи и частоты в настройках Atmel Studio

Затем перейдите к параметру оптимизации, сразу после параметра Символы (Symbols), и выберите Уровень оптимизации (Optimization Level) ⇒ Оптимизировать по размеру (-Os) (Optimize for size (-Os)), который оптимизирует наш код для минимального размера.

Оптимизация кода в Atmel Studio
Рисунок 9. Оптимизация кода в Atmel Studio

Теперь перейдите к общим настройкам (General) в AVR/GNU Linker и отметьте галочками первые три метки, так как мы не используем их в загрузчике. Эти варианты

  • Не использовать стандартные стартовые файлы (-nostartfiles)
  • Не использовать библиотеки по умолчанию (-nodefaultlibs)
  • Нет загрузочных или стандартных библиотек (-nostdlib)
Общие настройки AVR/GNU в Atmel Studio
Рисунок 10. Общие настройки AVR/GNU в Atmel Studio

Теперь важным моментом являются настройки памяти (опция в AVR/GNU Linker), где мы можем определить начальный адрес сегментов флэш-памяти, сегментов SRAM, сегментов eeprom и начальный адрес стека.

Для загрузчика Arduino мы выбираем размер конфигурации загрузки 256 слов (512 байт). После каждого сброса/сбоя питания контроллер должен будет сначала перейти к разделу загрузчика. Итак, нам нужно определить начальный адрес сегмента флэш-памяти по начальному адресу загрузчика. Поэтому просто определите сегмент флэш-памяти с адресом .text=0x3F00, как показано на рисунке 11.

Настройки памяти
Рисунок 11. Настройки памяти

Кроме того, мы добавляем флаги компоновщика. Нужно для того, чтобы близлежащие функции (скажем, в диапазоне от +2k до -2k от текущего адреса памяти программы) вызывались с использованием инструкции RCALL вместо прямой инструкции CALL, что сэкономит дополнительный необходимый цикл в режиме вызова.

Флаги компоновщика в Atmel Studio
Рисунок 12. Флаги компоновщика в Atmel Studio
1 2 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest
0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии