AVR947: бутлоадер, принимающий данные по одному проводу Печать
Добавил(а) microsin   

Здесь приведен перевод апноута "Atmel AVR947: Single-Wire Bootloader for any MCU with Self Programming Capability" [1]. Описывается бутлоадер (загрузчик), принимающий данные по 1 проводу данных, и подходящий для любого микроконтроллера AVR. Особенности бутлоадера:

• Не нужна секция загрузчика (bootloader section, которая есть не во всех микроконтроллерах AVR)
• Для обмена не используется никакая специальная периферия AVR
• Требуется только 1 вывод общего назначения GPIO (general purpose IO-pin)
• Имеется скрипт для интерфейса с компьютером PC (на основе утилиты AVROSP [2])
• Простая реализация запуска загрузчика и выхода из него
• Малый размер кода загрузчика (порядка 1371 байт)
• После программирования осуществляется проверка CRC
• В режиме загрузки устройство может засыпать (войти в режим sleep mode)
• Поддерживается обновление firmware у конечного потребителя продукции
• Защита от перезаписи firmware загрузчика

Этот загрузчик Single-Wire Bootloader разработан специально для устройств AVR, у которых отсутствует секция бутлоадера и какие-либо аппаратные модули для связи. Такое решение не требует от чипа никаких специальных ресурсов типа TWI (I2C), SPI или аппаратный UART. Вместо этого программно реализован однопроводный UART, описанный в апноуте [3], который требует только 1 вывода порта GPIO. Это особенно полезно для дешевых AVR, у которых ограниченное количество выводов портов GPIO (например, ATtiny45, ATtiny2313). Однако от AVR требуется возможность самопрограммирования [4], а также некоторое количество энергонезависимой памяти (внутренняя память EEPROM). Подключение к компьютеру, от которого передается код прошивки, осуществляется через стандартный интерфейс RS-232, как показано на рис. 1.

AVR947-connection-with-PC-fig1

Рис. 1. Подключение бутлоадера к компьютеру.

Прим. переводчика: COM-порты в современных компьютерах сейчас уже редкость. Поэтому в качестве аппаратного интерфейса, через который программируемое устройство подключается к компьютеру, может использоваться переходник USB - TTL RS232 (его еще называют VCP переходник, Virtual COM port), см. [5]. Аналогичный недорогой переходник на чипе FT232R или CP2102 можно купить на сайтах ebay, dealextreme или aliexpress (цена порядка 250 рублей).

[1. Теория функционирования бутлоадера]

1.1 Что такое загрузчик (bootloader) микроконтроллера, и как он работает?

В общем случае для программирования микроконтроллера (далее устройство, или AVR) нужен программатор, который его поддерживает. Такой программатор часто не только дорог, но и требует для подключения с программируемым устройством множества соединений, что создает неудобства. Модернизация программируемого оборудования становится затруднительной из-за недоступности аппаратного интерфейса программирования. Даже в лаборатории непрактично всегда иметь под рукой программатор, и лучшим решением будет поставлять устройства с уже запрограммированным в программ память (FLASH) бутлоадером. На рис. 1-1 показана основная идея деления памяти FLASH на секции приложения (Application segment) и бутлоадера (Bootloader segment).

AVR947-FLASH-memory-map-fig1-1

Рис. 1-1. Карта памяти FLASH микроконтроллера AVR.

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

Прим. переводчика: необходимо также задать и другие опции, в частности тактовую частоту устройства и его тип (модель микроконтроллера AVR).

Другой важный аспект, который нужно учитывать в такой архитектуре - вектор сброса RESET VECTOR всегда перехватывается бутлоадером, так что он всегда получает управления при событии сброса или включении питания. Бутлоадер программируется обычным программатором, и это требуется выполнить 1 раз. Далее при старте всегда будет работать бутлоадер, который можно использовать, чтобы перепрограммировать устройство.

Как только бутлоадер запрограммирован обычным программатором, то интерфейс бутлоадера (программно организованный UART) может использоваться для перепрограммирования остальной части памяти FLASH (секции приложения), и теперь уже программатор не нужен. Как уже упоминалось, бутлоадер использует однопроводный программный UART. В памяти EEPROM устанавливается флаг boot_flag (0x2A) для инициации процесса обновления. После сброса firmware бутлоадера проверяет состояние флага в EEPROM, и если он установлен, то начинается выполнение сконфигурированной секции загрузки (на рис. 1-1 это область памяти Bootloader segment). Если же флаг в EEPROM сброшен, то выполняется код секции приложения (на рис. 1-1 это область памяти Application segment). Бутлоадер также имеет отдельные команды для записи данных в секцию приложения и для выполнения перехода по коду (инструкция ассемблера JMP). В секции приложения расположен основной код, определяющий работу устройства как конечного изделия. Если переход не выполнен, то код приложения никогда не выполнится, даже если секция приложения была запрограммирована.

1.2 Архитектура системы

В этом апноуте загрузчик Single-Wire Bootloader рассматривается на примере реализации в устройстве Atmel ATMEGA16HVA.

1.2.1 Исходный код firmware загрузчика и скомпилированные бинарники

Предоставленное bootloader firmware написано с использование IAR Embedded Workbench®, и сконфигурировано для размещения в старших адресах памяти FLASH, начиная с адреса 0x3A00. Это сделано правкой файла настройки линкера: заменой _..X_FLASH_BASE на _..X_BOOT_START и установкой _..X_BOOT_START в значение 0x3A00. То же самое делает следующая секция файла линкера ATMEGA16HVA.

//Bootloader
-Z(CODE)INTVEC=0-(_..X_INTVEC_SIZE-1)
-D_..X_BOOT_START=3A00 //14K boundary i.e. Last 2K bytes
-Z(CODE)NEAR_F=_..X_BOOT_START-_..X_FLASH_NEND
-Z(CODE)SWITCH=_..X_BOOT_START-_..X_FLASH_NEND
-Z(CODE)DIFUNCT=_..X_BOOT_START-_..X_FLASH_NEND
-Z(CODE)CODE=_..X_BOOT_START-_..X_FLASH_END
-P(CODE)FAR_F=[_..X_BOOT_START-_..X_FLASH_END]/10000
-Z(CODE)INITTAB=_..X_BOOT_START-_..X_FLASH_END
-Z(CODE)HUGE_F=_..X_BOOT_START-_..X_FLASH_END
-Z(CODE)TINY_ID=_..X_BOOT_START-_..X_FLASH_END
-Z(CODE)NEAR_ID=_..X_BOOT_START-_..X_FLASH_END
-Z(CODE)CHECKSUM#_..X_FLASH_END

Загрузчик использует последний байт EEPROM по адресу 0xFF в качестве флага boot_flag. Если значение этого байта равно 0x2A, то это означает, что флаг загрузчика установлен, и управление получает бутлоадер (на рис. 1-1 это область памяти Bootloader segment), а не программа приложения. Если этот флаг имеет любое другое значение, то это означает неактивность загрузчика, и выполнение кода переходит в приложение пользователя (на рис. 1-1 это область памяти Application segment). Ниже показана последняя строка файла EEPROM.hex (этот файл поставляется вместе с загрузчиком, и должен быть запрограммирован в память EEPROM с использованием обычного программатора), которая указывает записать 0x2A в последний байт EEPROM.

Описанный пример загрузчика использует вывод PC0 для организации программного однопроводного UART (single-wire UART interface). Ножка порта (pin) и соответствующие ей регистры AVR определены следующими строками кода в файле Common_define.h:

#define SWUART_PORT_REG PORTC
#define SWUART_PIN_REG PINC
#define SWUART_PIN PC0

1.2.2 Простейший тестовый пример firmware пользователя

Предоставленное приложение, которое играет роль приложения пользователя (загрузчик будет записывать его в область памяти Application segment) называется "16HVADummy", и это приложение может использоваться как образец подключения приложения пользователя к загрузчику. Приложение 16HVADummy просто переключает вывод PB0 микроконтроллера ATMEGA16HVA. Оно размещено в области памяти FLASH от адреса 0x0000 до 0x0065, и имеет все необходимые изменения, которые требуются для работы совместно с загрузчиком. Эти необходимые изменения подробно рассмотрены в секции 7.2. Тестовый hex-файл приложения 16HVADummy может быть прошит загрузчиком.

1.2.3 Модифицированный код AVROSP

На компьютере PC необходима программа, которая будет отправлять команды бутлоадеру и передавать ему код приложения пользователя (в нашем примере это firmware приложения 16HVADummy). Для этой цели будет использоваться модифицированная утилита AVROSP [2]. Эта программа будет совместима только с поставляемым бутлоадером, и она нуждается в конфигурировании конечным пользователем для использования с выбранным устройством (микроконтроллером AVR). Пожалуйста обратитесь к секции 7.4.1, где описаны нужные изменения AVROSP. Готовый исполняемый файл AVROSP (UART_PROG.exe), поставляемый с этим апноутом (см. архив [8]), уже сконфигурирован для использования с устройством ATMEGA16HVA. В [8] также предоставлен и исходный код. Список команд для осуществления загрузки дается в далее в следующих секциях этой статьи.

[2. Описание возможностей Single-Wire Bootloader]

В этом загрузчике кроме обычной загрузки есть также много полезных возможностей. Эти возможности реализованы в firmware загрузчика, и поддерживаются управляющей программой PC (модифицированная AVROSP). Далее перечислены эти дополнительные функции.

2.1 Контрольная сумма CRC

В бутлоадере реализованы подсчет и проверка контрольных сумм для обновления как FLASH, так и EEPROM. Проверка CRC выполняется путем чтения содержимого FLASH/EEPROM после программирования устройства - чтобы убедиться, что устройство было успешно запрограммировано. Проверка CRC интегрирована в команды обновления FLASH и EEPROM.

2.2 Команда SLEEP

Этот бутлоадер может перевести устройство в режим сна (режим пониженного энергопотребления), при этом устройство все еще остается в состоянии загрузки. Устройство проснется, как только будет обнаружена любая активность со стороны single-wire UART. Эта команда очень полезна в разработках, для которых важен вопрос низкого энергопотребления.

2.3 Защита от перезаписи (Overwrite protection)

Этот загрузчик имеет защиту от перезаписи как кода самого бутлоадера, так и флага загрузки в EEPROM. Это обеспечит невозможность нежелательной перезаписи бутлоадера самого себя.

2.4 Обновление у конечного пользователя

Эта архитектура загрузчика поддерживает возможность обновления у конечного пользователя (обновление "в поле", field upgradeability). Эта возможность обсуждается в секции 7.3.

[3. Описание дизайна firmware загрузчика]

Как уже упоминалось, в этом загрузчике используются три апноута Atmel:

• AVR112: TWI Bootloader for devices without boot section [6]
• AVR274: однопроводный, программный UART на tinyAVR и megaAVR [3]
• AVR911: AVR Open Source Programmer [2]

Дизайн firmware загрузчика базируется на AVR112 [6], который был модифицирован для single-wire UART. Апноут AVR112 основывается на AVR109 [4], и обеспечивается совместимость с утилитой AVROSP, описанной в AVR911 [2]. Реализация AVR112, как и реализация AVROSP, модифицирована с расчетом на использование интерфейса single-wire UART. Целевое устройство AVR соединяется напрямую с хостом PC, как показано на рис. 1. Модифицированный бинарный код, как и исходный код, поставляется в архиве [8].

Описание дизайна и использования загрузчика основывается на 4 компонентах:

• Интерфейс пользователя с загрузчиком (Bootloader user interface)
• Однопроводный последовательный интерфейс (Single-wire UART)
• Программа загрузчика (Bootloader firmware)
• Тестовый пример программы пользователя для целевого AVR (Dummy target application)

3.1 Интерфейс пользователя с загрузчиком

Приложение загрузчика основано на использовании утилиты программирования с открытым исходным кодом (AVROSP), которая описана в [2]. AVROSP модифицирована, чтобы обеспечить работу single-wire UART. Готовый исполняемый файл модифицированной AVROSP предоставлен в пакете [8], файл UART_PROG.exe. Готовый bat-файл имеет примеры вызовов утилиты, использующих команды загрузчика.

3.2 Single-wire UART

Реализация однопроводного UART основана на апноуте AVR274 [3], но он модифицирован для реализации на основе опроса (polling). Метод опроса выбран по той причине, что в бутлоадере нельзя использовать никакие системные прерывания и векторы, это делает доступными все системные ресурсы микроконтроллера только для основного приложения. Эта реализация однопроводного UART улучшена для поддержки скорости до 38400 бод при тактовой частоте 4 МГц. Имейте в виду, что любое изменение тактовой частоты потребует коррекции тайминга UART.

3.3 Bootloader firmware

Дизайн этого загрузчика основывается на bootloader из апноута AVR112 [6], который был модифицирован для single-wire UART. В AVR112 обсуждается бутлоадер TWI для устройств AVR, у которых отсутствует секция загрузки (boot section). Описанный здесь single-wire загрузчик пошел еще дальше - ему не только не нужна секция загрузки, не нужен и TWI, и вообще не нужны никакие аппаратные интерфейсы для связи; требуется только одна ножка GPIO для загрузки. Дизайн AVR112 был модифицирован и упрощен для использования single-wire UART вместо TWI. Кроме того, этот дизайн уже не требует наличия другого MCU в качестве мастера шины (шина TWI, или I2C, требует на шине наличия мастера). Целевое программируемое устройство может быть подключено напрямую к компьютеру-хосту PC с использованием кабеля RS232 и трансивера RS232 (или с помощью USB переходника [5]). Компьютер PC с запущенной утилитой AVROSP является мастером загрузки, который передает загрузчику необходимые команды и, в конечном итоге, обеспечивает перепрограммирование FLASH и/или EEPROM целевого устройства.

3.4 Тестовый пример программы пользователя для целевого AVR

Этот апноут поставляется с демо-приложением "16HVADummy", которое, как уже упоминалось, не делает ничего, кроме переключения ножки порта. Это приложение может служить как образец интеграции друг с другом приложения пользователя и кода бутлоадера для программистов, которые создают собственные приложения для микроконтроллеров AVR. Это тестовое приложение может использоваться для быстрого прототипирования и тестирования этой архитектуры загрузки на других целевых устройствах AVR.

Файлы Cstartup.s90 (код стартовой загрузки проекта IAR), macro.m90 и файл настройки линкера (cfgm16hva.xcl) уже имеют готовые модификации, и они подключены к тестовой программе приложения. Файлы s90 и m90 не нуждаются в модификациях со стороны пользователя загрузчика, и программист может их просто скопировать и вставить их в свой проект. Но в файле линкера нужно сделать изменения, учитывающие код приложения пользователя и конкретную используемую архитектуру. Требуемые изменения разъяснены в секции 7.2. Тестовое приложение переключает ножку PB0, и это позволит удостовериться, что загрузчик успешно выполнил свою работу и запустил приложение пользователя.

[4. Содержимое пакета]

Пакет программного обеспечения [8], поставляемый с этим апноутом, содержит 4 директории:

• Single-wire bootloader source code
Эта папка содержит полный исходный код firmware загрузчика.

• 16HVADummy
Это тестовый пример целевого приложения, собранного для микроконтроллера Atmel ATMEGA16HVA. Тестовое приложение дергает ножкой порта PB0. Оно используется в целях демонстрации - как нужно реализовать и сконфигурировать приложение пользователя, чтобы оно работало вместе с загрузчиком.

• Bootloader UI source code
Эта папка содержит программу PC вместе с исходным кодом, основанную на утилите AVROSP [2]. Программа PC нужна для отправки firmware загрузчика команд, необходимых для загрузки приложения пользователя. Приложение PC написано на C++, и после его компиляции получается исполняемый файл Windows® UART_PROG.exe.

• Executables
Эта папка содержит скомпилированные бинарники всего программного обеспечения из вышеуказанных каталогов вместе со скриптом для их использования. С использованием этих файлов пользователь может быстро проверить архитектуру загрузчика на микроконтроллере ATMEGA16HVA, при этом не требуется никакая компиляция исходного кода. После проверки архитектуры модули кода могут быть портированы на любое устройство (любой микроконтроллер AVR).
After verifying the architecture, the code modules can be ported to any device.

[5. Требования к аппаратуре и программному обеспечению]

5.1 Hardware (аппаратура)

Загрузчик single-wire UART Bootloader не требует никакого соединения с аппаратным программатором. Однако необходимо следующее:

1. Хост PC (компьютер) с последовательным портом (или порт USB со специальным кабелем - мостом USB <-> Serial наподобие переходника [5]).
2. Трансивер RS-232 или схема адаптера (если используется стандартные уровни RS-232 напряжением +-12V).
3. Внешний верхний нагрузочный резистор (обычно 15 кОм) на ножке GPIO, которая используется под программный UART. Это не обязательно, если нагрузочный резистор есть в кабеле-конвертере USB <-> Serial.

После того, как соединения сделаны, как показано на рис. 1, аппаратура загрузчика готова к загрузке кода.

5.2 Software (программное обеспечение)

Код firmware микроконтроллера может быть скомпилирован следующим инструментарием разработки:

1. IAR™ Embedded Workbench IDE version 6.10.
2. DEV C++ version 4.9.

[6. Указания по применению загрузчика]

Как и любой бутлоадер, этот загрузчик тоже нуждается в программаторе для того, чтобы сделать первоначальную загрузку бутлоадера в память микроконтроллера (прим. переводчика: для некоторых моделей микроконтроллеров, например для AT90USB162, эта процедура выполняется прямо на заводе Atmel, т. е. микроконтроллер поставляется с уже прошитым бутлодером). Наш загрузчик состоит из из двух файлов - один для firmware (он записывается в память FLASH), а другой для флага загрузки (он записывается в EEPROM). После того, как эти два файла запрограммированы, нужно также запрограммировать фьюз SPMEN. Подключите интерфейс single-wire UART к компьютеру PC, как показано на рис. 1, и загрузчик готов принимать и выполнять полученные от PC команды. Команды можно посылать с помощью утилиты UART_PROG.exe, которая является результатом компиляции модифицированной AVROSP.

Процедуру программирования и запуска загрузчика можно более ясно показать в форме диаграммы на рис. 6-1.

Чтобы сделать интерфейс загрузчика более дружественным для пользователя, в пакете [8] предоставлены файлы скриптов. Они предоставляют простую текстовую оболочку для сложных и длинных инструкций загрузчика. Само собой разумеется, что все эти файлы скриптов должны находиться в том же каталоге, что и утилита UART_PROG.exe. Файлы скриптов перечислены в таблице 6-1.

Таблица 6-1. Файлы скриптов.

Файл Описание
SETCOM.CMD Устанавливает номер используемого COM-порта.
START.CMD Запускает командную строку пользовательского интерфейса с загрузчиком.
UART_COM.CFG Используется файлом SETCOM.CMD для сохранения номера COM-порта.
UARTBL.CMD Скрипт команд загрузчика. Он содержит скрипт текстовых оберток команд и соединяет все файлы друг с другом.
UARTBL_DUMP Вывод для команд может быть перенаправлен в этот файл для отладки.

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

6.1 Инициализация интерфейса пользователя

Когда загрузчик запущен впервые, он нуждается в указании номера COM-порта, к которому подключен single-wire UART (см. рис. 1). Если используется стандартный последовательный порт PC, этот номер COM-порта обычно 1, но когда используется кабель конвертера USB <-> Serial наподобие [5], правильный номер COM-порта может быть найден с помощью Менеджера Устройств Windows (Device Manager). Чтобы узнать номер COM-порта, сделайте правый клик на My computer, выберите Properties -> Hardware -> Device manager (Свойства -> Оборудование -> Диспетчер устройств). В Device Manager, в разделе "Порты (COM и LPT)", найдите установленный конвертер USB-to-serial, и узнайте номер COM-порта, который с ним связан.

Имейте в виду, что AVROSP поддерживает номера COM-портов в диапазоне от 1 до 8 включительно. Если у Вас номер COM-порта больше 8, то переназначьте номер COM-порта на меньшее значение, которое пока не используется.

Как только номер COM-порта определен, откройте запустите SETCOM.CMD и введите тот же самый номер. Скрипт установит этот порт для перенаправления команд загрузчику. Теперь запустите скрипт START.CMD и его интерфейс готов к отправке команд.

AVR947-procedure-fig6-1

Рис. 6-1. Процедура подготовки и запуска утилиты управления загрузчиком.

6.2 Команды загрузчика

Загрузчик поддерживает команды, которые пояснены в следующих подсекциях. Каждая команда может быть выдана из командной строки с помощью скрипта START.CMD, который запустит для этого модифицированную утилиту AVROSP (скрипт является оберткой для выдачи корректных параметров исполняемому файлу AVROSP). Больше информации по этому скрипту можно найти в UARTBL.CMD.

6.2.1 COMSETUP
Эта команда устанавливает номер используемого COM-порта.
Синтаксис: UARTBL COMSETUP x

Здесь X является номером COM-порта (в диапазоне от 1 до 8 включительно), к которому подключен single-wire UART загрузчика.

6.2.2 BVERSION
Эта команда запрашивает версию загрузчика (bootloader version).
Синтаксис: UARTBL BVERSION
В предоставленном в [8] firmware загрузчика версия равна 0x10.

6.2.3 FUPDATE
Эта команда обновляет (загружает из файла) содержимое секции приложения памяти FLASH микроконтроллера и проверяет его CRC.
Синтаксис: UARTBL FUPDATE < filename.hex >
Здесь filename.hex является именем файла приложения (с указанием полного пути до файла), загружаемое как программа пользователя в память микроконтроллера. Контрольная сумма CRC будет проверена после записи образа в память и чтения его содержимого. Код firmware загрузчика не позволяет делать никакую запись в bootloader segment для предотвращения нежелательного перезаписывания firmware загрузчика.

6.2.4 EUPDATE
Эта команда обновляет (загружает из файла) память EEPROM и проверяет её CRC.
Синтаксис: UARTBL EUPDATE < eep.hex >
Здесь eep.hex имя hex-файла целевого EEPROM (с указанием полного файлового пути). Контрольная сумма CRC будет проверена после записи образа в память и чтения его содержимого. Код firmware загрузчика не позволяет делать никакую запись в место расположения BOOT_FLAG (последняя ячейка EEPROM).

6.2.5 SLEEP
Эта команда переводит устройство в режим сна (sleep mode), используемый для снижения энергопотребления.
Синтаксис: UARTBL SLEEP
Как только произошел переход в режим сна, устройство будет разбужено только если будет произведено изменение уровня на выводе ножки порта single-wire UART. Для этого firmware использует внешнее прерывание (external interrupt) на этом выводе. Убедитесь, что следующие определения корректно установлены в файле main.c для выбранной ножки UART.

/* Макрос External interrupt. Он зависит от используемого устройства AVR. */
#define INITIALIZE_UART_EXTERNAL_INTERRUPT() (EICRA |= (1 << ISC01))
// Установка события генерации прерывания по спаду INT0.
#define ENABLE_EXTERNAL_INTERRUPT() (EIMSK |= (1 << INT0))

6.2.6 EXEC
Эта команда запускает приложение пользователя путем очистки флага загрузки в EEPROM и сброса устройства.
Синтаксис: UARTBL EXEC

6.3 Пошаговое описание процедуры

Чтобы пользователю запустить загрузчик в новом устройстве, ему нужно проделать следующие шаги:

Шаг 1 – Запрограммировать фьюз SPMEN.
Шаг 2 – С помощью стандартного программатора (например ISP [7]) запрограммировать в память чипа firmware загрузчика и файл EEPROM, который содержит флаг загрузки.
Шаг 3 – Инициализировать интерфейс пользователя, как описано в секции 6.1.
Шаг 4 – Послать команду UARTBL BVERSION, и посмотреть, что загрузчик выдал в ответ правильную версию.
Шаг 5 – Послать команду UARTBL FUPDATE < filename.hex > для обновления FLASH. Проверьте, что команда была успешно выполнена.
Шаг 6 – Если также нужно запрограммировать EEPROM, пошлите команду UARTBL EUPDATE < eep.hex > для обновления памяти EEPROM. Проверьте, что команда была успешно выполнена.
Шаг 7 – После успешного завершения всех этих команд, отправьте команду UARTBL EXEC. Загрузчик очистит флаг загрузки в EEPROM, и сбросит устройство с использованием сторожевого таймера (watchdog timer reset). При следующей загрузке (включении питания или сбросе) будет запущено приложение пользователя.

6.4 Возможные проблемы и их устранение

6.4.1 Симптом: первый ответ на BVERSION выдается как 0xff
Рекомендуется проверить настройку обмена путем отправки команды BVERSION, пока от неё не будет получен ожидаемый ответ. Иногда, когда система устройства находится в режиме глубокого сна, то ответ на BVERSION может быть получен в виде 0xff - это происходит потому, что система только проснулась от внешнего прерывания на ножке порта и пропустила первую команду.

6.4.2 Симптом: AVROSP жалуется на номер COM-порта
AVROSP поддерживает COM с номерами 1..8, так что если назначенный UART находится на COM-порте с номером больше 8, то AVROSP выдаст ошибку. Эту ситуацию можно просто исправить переназначением имеющегося номера порта на меньшее число. Это операцию можно проделать с помощью Менеджера Устройств, если войти в свойства COM-порта.

6.4.3 Повторяющиеся таймауты COM-порта
Если обмен данными несколько раз терпит неудачу, перезапустите устройство и переподключите кабель последовательного порта. Запустите SETCOM.CMD и введите номер COM-порта, к которому Вы пытаетесь подключиться. Это должно решить проблему.

[7. Подстройка программного обеспечения под нужды пользователя]

Предоставленное в этом апноуте программное обеспечение является решением для загрузчика, полностью подстроенным под устройство (микроконтроллер AVR) Atmel ATMEGA16HVA. Для этого устройства все программные компоненты написаны и протестированы. Этот апноут предлагает приведенную архитектуру ATMEGA16HVA в качестве базового примера, который пользователь может переделать по свои нужды (применить в любом выбранном микроконтроллере AVR). Чтобы адаптировать загрузчик для нового устройства, в каждом компоненте программного обеспечения нужно сделать определенные изменения. В этой секции рассматриваются нужные изменения.

7.1 Bootloader firmware

7.1.1 Определения (Definitions)

Загрузчик содержит следующие определения, зависящие от приложения пользователя и используемого микроконтроллера. Эти определения должны быть правильно заданы в файле заголовка Commands_define.h.

• #define INTVECT_PAGE_ADDRESS 0x00
Это задает место начального адреса таблицы векторов прерываний (interrupt vector table).

• #define PAGE_SIZE 128
Это задает размер страницы памяти FLASH.

• #define BOOT_PAGE_ADDRESS 0x3A00
Задает начало сегмента загрузчика.

• #define TOTAL_NO_OF_PAGES 128
Задает общее количество страниц памяти FLASH. Для FLASH размером 16 килобайт с размером страницы 128 байт, общее количество страниц составит 128.

• #define EEMEM_ADDR_AVERSION 0xFF
Задает место размещения флага загрузки (boot flag) в памяти EEPROM. Это место должно быть последней ячейкой EEPROM.

• #define BVERSION 0x10
Задает версию загрузчика.

• #define CSTARTUP_ADDRESS 0x800
Это задает адрес, куда загрузчик должен сделать безусловный переход после успешной загрузки. Адрес тот же самый, что и адрес CSTARTUPSEG в настроечном скрипте линковщика (target application linker script), это объяснено далее.

• #define BOOT_FLAG 0x2A
Это значение флага загрузки, по которому будет запущен загрузчик, а не программа пользователя.

• #define SWUART_PORT_REG PORTC
Это задает имя регистра порта для вывода (PORT), используемого под программный UART.

• #define SWUART_PIN_REG PINC
Это задает имя регистра порта для ввода (PIN), используемого под программный UART.

• #define SWUART_PIN PC0
Это задает разряд вывода порта, используемого под программный UART.

Примечание: если были сделаны любые изменения для EEMEM_ADDR_AVERSION или BOOT_FLAG, должен быть сгенерирован hex-файл EEPROM для загрузчика, чтобы в нем был в нужном месте (EEMEM_ADDR_AVERSION) записан BOOT_FLAG.

7.1.2 Изменения в файле настройки линкера

Предоставленный загрузчик настроен на использование устройства Atmel ATMEGA16HVA, так что он базируется на файле настройки линкера по умолчанию для этого устройства, модифицированном как было объяснено в секции Section 1.2.1. Для портирования этого загрузчика на другой устройство AVR, должны быть сделаны аналогичные изменения в настроечном файле линкера выбранного устройства.

7.1.3 System clock (тактовая частота устройства)

Предоставленный загрузчик должен работать на частоте 4 МГц. Так как целевое приложение пользователя может работать на любой тактовой частоте, загрузчик должен установить тактовую частоту путем установки регистра тактов. Эта процедура должна быть выполнена как часть кода инициализации (init code). Например, для ATMEGA16HVA, тактовая частота устанавливается на 4 МГц путем добавления следующих строк к коду firmware загрузчика:

CLKPR = (1 << CLKPCE);
CLKPR = 0x01;

Для любого другого устройства убедитесь, что в этом месте код заменен на другой, который правильно устанавливает тактовую частоту на 4 МГц.

7.2 Целевое программное обеспечение (Target application software)

Чтобы приложение пользователя (application firmware) могло использоваться совместно с описываемым загрузчиком, нужно провести некоторые изменения в конфигурации. Обычно эти файлы автоматически подключаются из своих мест размещения по умолчанию для компилятора, но поскольку нам нужны их модифицированные версии, то эти три файла должны быть подключены вручную. Файлы предоставлены в пакете [8], поставляемом совместно с этим апноутом. Вот они:

1. Файл настойки линкера (Linker file).
2. Файл кода инициализации (Cstartup.s90).
3. macros.m90.

Все изменения в этих файлах описаны далее.

Примечание: для применения пользовательского файла настройки линкера (custom linker file), в среде разработки IAR сделайте правый клик на проекте, выберите options, и на закладке linker, установите галочку "Override default", и задайте место расположения для linker file. Чтобы добавить Cstartup.s90, сделайте правый клик на проекте, выберите Add -> Add files и выберите файл Cstartup.s90. файл macros.m90 является файлом зависимости для файла Cstartup.s90, так что нет необходимости добавлять macros.m90 в проект. Файл macros.m90 должен просто находиться в том же каталоге, что и файл Cstartup.s90.

7.2.1 Настройка файла линкера для резервирования FLASH для загрузчика

В приложении пользователя старшая часть адресов памяти программ используется для кода firmware загрузчика (см. рис. 1-1). Стартовый адрес загрузчика является фиксированным, и жестко закодированным в коде firmware микроконтроллера. Доступная для приложения пользователя память не должна накладываться на сегмент загрузчика; следовательно, что должно быть тщательно определено в файле линкера приложения. Например, в предоставленном исходном коде загрузчика, загрузчик начинается с байтового адреса 0x3A00, так что доступная для приложения память FLASH должна заканчиваться на адресе 0x39FF несмотря на то, что в устройстве имеется 16 килобайт памяти FLASH. Этого можно достичь модификацией адреса конца FLASH (flash end address) в файле линкера.

Например, для устройства ATmega16HVA (16K flash) должны быть следующие изменения в файле линкера, чтобы зарезервировать для загрузчика сегмент памяти 0x3A00 .. 0x3FFF.

-D_..X_FLASH_NEND=39FF /* Конец памяти FLASH для near */
-D_..X_FLASH_END=39FF  /* Конец памяти FLASH */

Эти изменения делают последние 1.5 килобайта памяти FLASH (0x3A00 .. 0x3FFF) недоступными для линкера. Если двоичный код приложения пользователя становятся по размеру больше, чем 14.5K, то линкер выдаст ошибку.

7.2.2 Настройка файла линкера для резервирования одного байта в EEPROM под флаг загрузки

Один байт EEPROM (выбран последний байт) нужно зарезервировать для сохранения в нем флага загрузки. Например, для устройства ATmega16HVA в файл настройки линкера должно быть сделано следующее изменение, чтобы последний байт EEPROM был зарезервирован:

-D_..X_EEPROM_END=FE /* Конец памяти EEPROM */

Это делает последний байт EEPROM с адресом 0xFF недоступным для линкера.

7.2.3 Модификация файла линкера для создания нового сегмента для кода инициализации

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

Новый стартовый сегмент (startup segment) требуется в файле линкера приложения для предустановленного адреса FLASH кода инициализации приложения. Этот адрес жестко вшит в firmware загрузчика, и это адрес, по которому загрузчик переходит после успешной загрузки. Если этот адрес не установлен на отдельный сегмент, адрес кода инициализации может переместиться с пересборкой кода приложения (адрес получится нефиксированным). Этот сегмент должен быть установлен извне обычного кодового пространства приложения.

Например, в присоединенном тестовом приложении код приложения занимает место от 0x0000 до 0x0065, и бутлоадер стартует с адреса 0x3A00. Этот сегмент может быть установлено в любое место от 0x0066 до 0x39FF. Следующая строка кода в файле линкера настраивает новый сегмент по адресу 0x800. Важно использовать точно такое же имя сегмента, как и в модифицированном файле cstartup.s90. Стартовый адрес можно изменить в соответствии с требованиями пользователя.

-Z(CODE)CSTARTUPSEG=800

Примечание: как уже упоминалось, этот адрес и имя "CSTARTUPSEG" очень важны, так как адрес жестко прошит в загрузчик и модифицированный файл Cstartup.s90. Имя сегмента не должно меняться. Если будет изменен адрес, то это требует также перекомпиляции и загрузчика.

7.2.4 Модификации файла CSTARTUP.S90

Cstartup.s90 является системным файлом инициализации, который изменен, чтобы указать приложению поместить код инициализации по адресу, указанном для CSTARTUPSEG. Файл Cstartup.s90 может быть добавлен в проект, как и любой другой файл IAR правым кликом на проект и последующим выбором добавления файла. Этот файл имеет зависимость от файла macros.m90 (он также предоставлен, включается директивой #include, и его не надо специально добавлять в дерево проекта), и проект не будет скомпилирован, если файл macros.m90 не был скопирован вместе с файлом cstartup.s90 (т. е. он не находится в том же месте, что и файл cstartup.s90).

7.3 Требования к приложению, чтобы можно было организовать обновление у конечного пользователя (field upgradeability)

Чтобы сделать устройство "field upgradeable", приложение должно иметь возможность запустить загрузчик. Поскольку загрузчик можно запустить только при запуске системы (system startup), и для этого требуется послание в EEPROM (boot_flag), то нужно добавить следующие строки кода в главное приложение для установки флага загрузки в EEPROM и сброса устройства через сторожевой таймер (watchdog timer reset). Пользователю нужно выполнить следующий код, когда нужно выполнить обновление программного обеспечения (запустить загрузчик).

// Записать послание в EEPROM, означающее необходимость обновления firmware.
Write_EEPROM_byte(EEMEM_ADDR, BOOT_FLAG);
/* Разрешить режим Watchdog Reset Mode, установка таймаута Watchdog на 16 мс,
и задержка 20 мс, чтобы гарантированно произошел WDT reset */
WDT_ResetTimer();
WDTCSR |= (1 << WDE);
WDT_SetTimeOut( WDTO_16ms );
delay_cycles(20000); // Подразумевается, что MCU работает на частоте 1 МГц

Адрес EEMEM_ADDR_AVERSION является адресом, где находится байт флага загрузки. Он должен соответствовать firmware загрузчика и определениям в файле линкера. В предоставленном исходном коде это последний адрес EEPROM, т. е. адрес равен 0xFF. Функция Write_EEPROM_byte() записывает boot_flag по адресу, заданном в EEMEM_ADDR. В предоставленном firmware значение EEMEM_ADDR равно 0xFF BOOT_FLAG равен 0x2A. Описание функции Write_EEPROM_byte() выходит за рамки этого документа.

7.4 Настройка пользовательского интерфейса загрузчика

В предоставленном UI для загрузчика, в AVROSP, все настройки сделаны с учетом устройства ATMEGA16HVA. Но настройки также могут быть изменены для портирования на любое другое устройство (микроконтроллер AVR). В интерфейсе пользователя имеется два компонента, которые требуют модификации. Первый это код AVROSP, и второй это скрипт UARTBL.cmd.

7.4.1 Подстройка AVROSP

Изменения в утилите AVROSP минимальны, и заключаются в следующем.

1. Откройте проект в свободной среде разработки DEVC++.
2. Откройте файл AVRDevice.cpp и в конструкторе AVRDevice введите корректные значения для flashSize, eepromSize и pagesize для выбранного устройства. flashSize является размером доступной памяти FLASH в устройстве, eepromSize является размером доступной памяти EEPROM в устройстве, и является размером страницы памяти FLASH.
3. Сохраните файл и скомпилируйте проект. Скопируйте полученный файл UART_PROG.exe в ту же самую папку, где находятся другие скрипты.

7.4.2 Подстройка скрипта UARTBL.cmd

Откройте файл UARTBL.cmd в любом текстовом редакторе и замените текст ATmega16HVA на название модели чипа нового устройства AVR. Сохраните файл.

[Ссылки]

1. Atmel AVR947: Single-Wire Bootloader for any MCU with Self Programming Capability site:atmel.com.
2. AVR911: Open Source программатор для микроконтроллеров AVR.
3. AVR274: однопроводный, программный UART на tinyAVR и megaAVR.
4. AVR109: самопрограммирование AVR.
5. AVR-USB162MU: VCP переходник (TTL virtual COM port).
6. AVR112: TWI Bootloader for devices without boot section site:atmel.com.
7. Программаторы для AVR.
8. AVR947.zip - исходный код и готовые бинарники программного обеспечения для загрузчика, описанного в этой статье.