Разработка приложений для встраиваемых систем (firmware) обычно осуществляется на настольной рабочей станции (компьютер PC, работающий под Windows или Linux), на языке ассемблера и высокоуровневом языке C. С помощью кросс-платформенных инструментов (компилятор, линкер и т. д.) генерируется исполняемый двоичный код, который должен быть выгружен в память целевой платы. В большинстве случаев это энергонезависимая память (non-volatile memory), требующая выполнения специальных процедур для своего программирования.
На самых ранних этапах развития микроконтроллеров и процессоров энергонезависимая память была представлена микросхемами EPROM, EEPROM или FLASH с параллельным интерфейсом, которые для своего перепрограммирования требовали извлечения из сокета целевой системы и установки в сокет программатора (иногда перед этим требовалось стирание с помощью ультрафиолетовой лампы). Сегодня память микроконтроллеров и внешних микросхем памяти может быть перепрограммирована без извлечения из схемы, где они работают. Эта технология называется внутрисхемное (in-ciruit) или внутрисистемное (in-system) программирование, часто обозначаемая аббревиатурой ISP (от in-system programming).
Для реализации ISP требуются следующие составляющие:
1. Программный инструмент, работающий на PC (утилита программирования), который может управлять интерфейсом программирования через любой стандартный порт (сегодня это чаще всего USB). Компьютер, где работает это программное обеспечение, называют еще хостом PC.
2. Адаптер программирования, который позволяет подключиться к интерфейсу программирования целевой платы через любой стандартный порт компьютера PC (сегодня это чаще всего USB, раньше также использовались порты RS-232, принтер порта LPT).
3. Специальный интерфейс программирования наподобие SPI [2], JTAG [3] (иногда используются и другие интерфейсы).
Все 3 этих требования должны быть так или иначе реализованы, однако в реальном мире существует множество вариантов реализации. Например, адаптер программирования может быть интегрирован в целевую плату. В этом примере кабель USB будет подключаться напрямую к PC и к целевой плате. Иногда интерфейс программирования доступен через специальные инструкции или регистры микроконтроллера, которые позволяют загрузить в память новое firmware.
Здесь (перевод [1]) представлен обзор различных методов ISP, используемые сегодня с популярными семействами микроконтроллеров AVR и ARM. Эта статья не претендует на полноценный обзор ISP, потому что в мире существует множество семейств микроконтроллеров и процессоров с различными особеностями реализации технологии внутрисхемного программирования.
[Программное обеспечение PC]
Есть множество инструментов (утилит программирования), каждый поддерживает свой набор интерфейсов программирования, адаптеров и целей (микроконтроллеров) для программирования. Довольно важен тот момент, что не все инструменты доступны для каждой операционной системы PC.
Утилита программирования взаимодействует с пользователем либо через командную строку (command line, CLI) или через графический интерфейс (окно диалога с кнопками и галочками, GUI). Каждый из этих методов взаимодействия имеет свои достоинства и недостатки. В то время как CLI лучше всего подходят для автоматизации (очень важно в производстве, когда нужно многократно повторять одну и ту же последовательность операций), интерфейс GUI упрощает ручное изменение различных опций программирования, избавляя от запоминания команд CLI. Некоторые утилиты поддерживают оба метода использования, CLI и GUI. Иногда графический интерфейс служит надстройкой над ниже лежащим интерфейсом командной строки, формируя командную строку из опций графического интерфейса.
Некоторые адаптеры программирования наподобие Zylin ZY1000 (см. ниже) имеют встроенное программное обеспечение программирования, управляемое через web-интерфейс. Это делает возможность программирования практически независимой от используемой операционной системы настольного компьютера PC.
В таблице ниже представлено популярное бесплатное программное обеспечение (некоторые из них с открытым исходным кодом) для программирования встраиваемых систем.
Адаптеры, использующие для подключения порт принтера LPT, являются самыми простыми. Обычно в них нет ничего, кроме микросхем буфера или преобразователя уровней, подключаемых с одной стороны к сигналам LPT, а с другой стороны к программируемой целевой системе. Иногда в качестве преобразователей уровня используются обычные резисторы. Интерфейс LPT был широко распространен в 80-х и 90-х годах двадцатого века, но эти времена прошли. Сегодня уже трудно найти компьютер PC, на котором был бы интерфейс LPT, однако в продаже все еще можно найти карты расширения для шины PCI, на которых есть интерфейс LPT.
Как и порты принтера LPT, последовательные интерфейсы RS-232 (COM-порт) сегодня заменил интерфейс USB. Однако последовательные порты RS-232 все еще остаются популярными для встраиваемых систем. Многие продвинутые адаптеры программирования основаны на микроконтроллерах, и почти у всех микроконтроллеров есть в распоряжении как минимум один последовательный порт UART. Это аппаратная логическая составляющая, которая делает возможным обмен данными через RS-232. Таким образом, адаптеры программирования с портами RS-232 сегодня все еще используются. Некоторые производители продают преобразователи USB - RS-232, которые можно использовать для подключения программатора с интерфейсом RS-232 к компьютеру, но иногда подключение через преобразователь не работает (это зависит от реализации программного обеспечения PC и аппаратуры преобразователя USB - UART, насколько он хорошо совместим с интерфейсом программатора).
USB намного сложнее, чем параллельный порт LPT или последовательный интерфейс RS-232, однако сегодня уже имеется много микроконтроллеров, аппаратно поддерживающих этот интерфейс, и их ассортимент с каждым днем увеличивается. Таким образом, появляется все больше и больше адаптеров программирования, подключаемых через порт USB, потому что интерфейс USB есть практически на каждом компьютере PC. После того, как компания FTDI предоставила специальные микросхемы [11], которые дают возможность просто реализовать программирование JTAG через USB без необходимости писать для этого какое-либо firmware, цена адаптеров программирования для JTAG, которые работают через USB, значительно упала.
Примечание: если говорить о цене на адаптеры, то она может меняться в широких пределах - от нескольких долларов до нескольких тысяч долларов. Цена основана на поддержке больших скоростей, реализации гальванической изоляции, поддержке отладки, качества буферизации сигналов, уникальных возможностях и т. д.
Одним из недостатков USB является ограниченная длина кабеля. Чем короче кабель, тем вся система программирования работает надежнее. Сегодня наиболее продвинутые адаптеры программирования поддерживают подключение через Ethernet, что дает возможность программирования и отладку даже через сеть Интернет.
[AVR ISP]
Есть несколько способов реализации внутрисхемного программирования для программирования внутренней flash-памяти микроконтроллеров AVR. Ниже приведены названия этих интерфейсов по терминологии Atmel:
• ISP, который иногда называют SPI, потому что он основан на последовательном периферийном интерфейсе [2]. • JTAG, доступный на мощных микроконтроллерах AVR, он может служить альтернативой для ISP. JTAG позволяет не только программировать память AVR, но еще позволяет выполнять отладку программ по исходному коду и поддерживает внутрисхемное тестирование системы (технология boundary scan). Микроконтроллеры AVR, на которых есть JTAG, также дополнительно могут программироваться не только через JTAG, но еще и через ISP. • DebugWire, используется на многих микроконтроллерах AVR, у которых малое количество выводов. Для передачи данных используется только один сигнальный вывод микроконтроллера. Этот интерфейс кроме программирования памяти также поддерживает и отладку. • PDI можно найти на новых чипах XMEGA. • TPI используется на некоторых TinyAVR, у которых мало внешних выводов и мало доступной памяти.
Примечание: для AVR существуют еще так называемые методы программирования HVSP (высоковольтное последовательное программирование) и HVPP (высоковольтное параллельное программирование), но эти технологии здесь не рассматриваются, потому что они не относятся к внутрисхемному программированию. Высоковольтное прогаммирование часто используется для восстановления фьюзов, в частности HVSP использует устройство AVR fuse doctor [12].
STK200 это простой, недорогой адаптер программирования ISP, подключаемый через параллельный порт принтера LPT. Изначально этот адаптер входил в состав комплекта начинающего разработчика Atmel STK200 starter kit, сейчас этот адаптер компанией Atmel больше не поддерживается. Однако существует множество утилит программирования, поддерживающих этот адаптер, и многие компании все еще представляют клоны этого адаптера. Из-за простоты STK200 и доступности его принципиальной схемы такой адаптер можно собрать самому (ниже приведена одна из таких схем).
Сегодня Atmel официально предоставляет 3 адаптера для программирования AVR. Ниже приведен их список в порядке возрастания цены и увеличения возможностей. Все эти адаптеры подключаются через USB.
AVR ISP mkII. Это программатор ISP, поддерживает интерфейсы ISP, PDI и TPI, отладка не поддерживается.
Схема и прошивка программатора AVR ISP mkII компанией Atmel не опубликована, однако в Интернете давно доступны варианты реализации (клоны) этого программатора на основе чипов AT90USB162, ATmega16U2 и ATmega32U4 (см. описание одного из вариантов такой реализации в статье [13]), прошивка для него сделана на основе библиотеки LUFA [14]. Таким образом, Вы сами можете изготовить такой программатор и залить в него готовую прошивку, либо можете скомпилировать эту прошивку для исходного кода.
AVR Dragon. Поддерживает программирование через ISP и отладку по исходному коду через DebugWire.
JTAGICE mkII. Поддерживает программирование через ISP и JTAG, а также отладку по исходному коду через JTAG и DebugWire.
[Альтернативные адаптеры AVR]
1. SP Duo JTAG Programmer site:embedded-creations.com. 2. AVR DUO ICE site:avrfreaks.net.
Эти адаптеры интересны тем, что предоставляют программирование через ISP и JTAG. SP Duo подключается через интерфейс RS-232, и он поставляется со своим собственным firmware, отладка JTAG не поддерживается. AVR DUO ICE подключается через USB, и поддерживает отладку JTAG.
Открытым сообществом разработчиков было сделано несколько попыток использования чипов FT2232 для реализации недорогого адаптера JTAG для AVR, но без особого успеха. Программирование происходит довольно медленно, и отладка JTAG работает ненадежно из-за того, что политика Atmel держит в секрете тонкости реализации технологии отладки AVR.
Внутрисхемное программирование внутренней памяти FLASH микроконтроллеров ARM обычно осуществляется через JTAG. Наиболее простым адаптером JTAG в плане аппаратуры является адаптер Wiggler, который подключается через параллельный порт принтера LPT. Изначально этот адаптер предлагала компания Macraigor Systems, и в Интернет можно найти различные схемы его клонов.
Turtelizer [15] это один из примеров адаптера JTAG, подключаемого через RS-232. Он основан на микроконтроллере ATmega8 или ATmega168. Дизайн и прошивка адаптера Turtelizer опубликованы под лицензией BSD.
Сегодня многие адаптеры JTAG основаны на чипе FT2232 компании FTDI. На основе одного такого чипа можно создать два независимых интерфейса - один это JTAG, другой дополнительный порт RS-232. Turtelizer 2 [16] это пример одного из таких адаптеров, опубликованных как открытая разработка (Open Source Hardware).
Норвежская компания Zylin AS, известная как разработчик плагина Embedded CDT для Eclipse и поставщик пакетов OpenOCD, предоставляет сегодня наиболее подвинутые адаптеры JTAG. Адаптер программирования ZY1000, основанный на открытом программном обеспечении, это в действительности маленькая система Linux со встроенным интерфейсом Ethernet и JTAG, где интегрирован пакет OpenOCD и web-сервер. Все, что Вам нужно для программирования устройств ARM, это только браузер.
[Программирование внешней памяти через ISP]
Из-за Гарвардской архитектуры, где 8-битная шина данных микшируется с 16-битной шиной кода инструкции, выполнение программы всех микроконтроллеров семейства AVR ограничено только внутренней памятью FLASH. Это остается верным даже если доступна внешняя шина памяти. Тем не менее для хранения энергонезависимой памяти данных (non-volatile data memory) может использоваться внешняя память FLASH.
Микроконтроллеры ARM с внешней памяти не ограничены использованием внутренней памяти для памяти программ, для этого может использоваться и внешняя шина. Большое количество микроконтроллеров ARM представляются не только с внутренней памятью FLASH для памяти программ, куда записывается firmware, но также для firmware может записываться и во внешнюю FLASH-память, подключаемую к микроконтроллеру ARM в виде внешней микросхемы.
Существуют как минимум два основных метода для реализации внутрисхемного программирования внешних устройств памяти. Первый основан на технологии пограничного сканирования JTAG (JTAG boundary scan), которая позволяет переключать любой вывод и считывать его состояние у тестируемого микроконтроллера ARM. Если все выводы программирования совмещены с управляемыми выводами микроконтроллера, то JTAG boundary scan может использоваться для генерации сигналов последовательности программирования памяти чипа. Достоинство этого метода в том, что на целевой плате не требуется наличие никакого дополнительного поддерживающего кода, потому что технология JTAG boundary scan в чипе ARM полностью реализована аппаратно. Но, как можно было бы ожидать, это довольно медленный способ программирования.
Второй метод использует интерфейс отладки JTAG, который позволяет CPU выполнять отдельные инструкции. Этот метод программирования внешней памяти чипа позволяет использовать выполняемую по шагам последовательность инструкций. Это значительно быстрее метода boundary scan, но требует, чтобы CPU был инициализирован и запущен в работу на выполнение процедуры программирования. Вариант этого метода может быть использован, когда доступна некоторая область оперативной RAM. Вместо эмуляции отдельных инструкций в RAM выгружается и запускается целый кусок кода, осуществляющий программирование данных, поступающих в буфер RAM через JTAG. Программируемые данные могут поступать и через JTAG, и через дополнительный канал передачи данных, так называемый интерфейс JTAG COMM.
[Использование загрузчика (bootloader)]
Как правило загрузчики получают исполняемый двоичный код через один из внешних интерфейсов микроконтроллера, и записывают этот код в некую встроенную энергонезависимую память (она может находиться на кристалле микроконтроллера или установлена на плате в виде отдельной микросхемы). После того, как код передан и записан, он может быть запущен на выполнение специальной командой или последующим сбросом или включением питания системы. Часто в качестве интерфейса связи с хостом PC загрузчик использует UART, иногда USB и другие интерфейсы.
Загрузчик также может брать исполняемый код из энергонезависимой памяти, установленной на плате системы, загружать этот код в RAM и запускать его. Это происходит всякий раз при включении питания или сбросе системы.
Таким образом, различают 2 вида загрузчиков - один предназначен для получения кода firmware из внешнего источника (хоста PC) и прошивки его в энергонезависимую память системы, а второй вид загрузчика берет код из энергонезависимой памяти системы, записывает его в RAM и запускает на выполнение. Первый вид загрузчиков предназначен для обновления программного обеспечения без специального программатора. Подразумевается, что микроконтроллер системы поддерживает самопрограммирование. Второй вид загрузчика используется, когда этого требуют особенности реализации микроконтроллера и всей встраиваемой системы (используется реже).
Загрузчики AVR. Многие модели микроконтроллеров AVR поддерживают самопрограммирование, т. е. они могут перезаписывать собственную память программ [17]. Некоторая часть области кода памяти FLASH может быть предоставлена под код загрузчика. Из-за того, что этот код находится в отдельной секции, он может получить доступ на запись к другим секциям памяти FLASH микроконтроллера AVR. Краткий обзор загрузчиков AVR дан в статье [18].
Загрузчики ARM. Почти все микроконтроллеры серии AT91SAM компании Atmel имеют на борту записанный в ПЗУ специальный загрузчик кода, это так называя технология SAM-BA [8]. Работой этой технологии управляет энергонезависимый бит - он определяет, будет ли запущен при включении питания/сбросе код загрузчика, или же будет запущена ранее записанная в память FLASH программа приложения (firmware). Загрузчик активируется при очистке памяти микроконтроллера.