В этом руководстве (перевод [1]) объясняется, как использовать OpenOCD [2] для платы с микроконтроллером (MCU) AT91SAM7SE. Однако вместо того, чтобы сразу дать готовую к запуску конфигурацию, мы пройдем все шаги её создания от самого начала, описывая процесс настройки OpenOCD по шагам. Имейте в виду, что это руководство касается только конфигурации OpenOCD, и вопросы её сборки и использования для отладки не рассматриваются.
[Начальные требования]
Для использования этого руководства понадобится некоторая аппаратура и ПО:
• Компьютер PC, работающий под управлением операционной системы Windows или Linux. Скорее всего, на OS X также все будет работать, но к сожалению такой вариант не тестировался. Для описания действий использовалась Windows, но в действительности это не имеет большого значения. • Пакет OpenOCD, установленный на PC. Описываемая процедура настройки тестировалась на 0.6.0-rc1, и вероятно также будет работать и на более новой версии. • Любой адаптер USB JTAG, основанный на чипе FTDI. Использовался Turtelizer 2 [5] (чип FT2232L), но с успехом подойдет плата с аналогичным чипом, например FT2232H Board [6]. Предполагается, что необходимые драйвер для него уже установлен. Драйвер можно свободно скачать с сайта компании FTDI, процедура установки очень проста, поэтому здесь не рассматривается.
Замечание: новые версии OpenOCD могут быть рассчитаны на другой драйвер, WinUSB, см. врезку ниже.
С новыми версиями OpenOCD может иногда наблюдаться ошибка:
Error: unable to open ftdi device: usb_open() failed
Эта ошибка вызвана драйвером libusb в Windows, поскольку новые версии OpenOCD используют другой драйвер, WinUSB.
Сначала убедитесь, что Вы дали указание Windows не устанавливать драйвер автоматически:
Затем удалите драйвер FTDI по умолчанию. Вы можете использовать утилиту от FTDI, которая называется CDM Uninstaller x.x - Windows Device Driver Uninstaller [8]. Для его использования нужно просто ввести VID и PID вашего адаптера с чипом FT2232H.
По умолчанию FTDI Vendor ID (VID) равен 0x0403. По умолчанию значения идентификаторов Product ID (PID) следующие:
Одноканальные устройства (чипы с буквой R): 0x6001 Двухканальные устройства (чипы FT2232C, FT2232D, FT2232H): 0x6010 Четырехканальные устройства (чипы FT4232H): 0x6011
Подробнее про CDM Uninstaller см. [9].
После удаления используйте Zadig Tool [10] для установки драйвера WinUSB.
• Любая целевая плата с интерфейсом JTAG, на которой применяется AT91SAM7SE. В этом примере использовалась плата Elektor Internet Radio (EIR). Можно использовать плату с другим чипом, например AT91SAM7X [7], но потребуется небольшая правка конфигурационных файлов.
Подключите Ваш адаптер JTAG к целевой плате через 20-выводный коннектор на плоском кабеле, и кабелем USB к компьютеру PC. Если цоколевка коннектора JTAG адаптера соответствует коннектору JTAG платы (обычно это так, если используется стандартный 20-выводный коннектор JTAG). Если у Вас адаптер Turtelizer 2 подключается к плате Elektor Internet Radio, также понадобится дополнительный переходник с плоским кабелем (см. рисунок).
Если у Вас самодельный адаптер, то нужно правильно подключить выводы адаптера к контактам коннектора JTAG отладочной платы. Ниже в качестве примера показано подключение платы FT2232H Board [6] к плате AT91SAM7X [7].
[]Рисунок с подключениями
[]Таблица
[2. Конфигурирование адаптера JTAG]
Чтобы запустить OpenOCD, мы должны сначала сконфигурировать интерфейс JTAG. Если этого не сделать, то при запуске OpenOCD будет выведено сообщение об ошибке, и работа OpenOCD остановится. Пример такого сообщения об ошибке:
Open On-Chip Debugger 0.6.0-rc1 (2012-08-08-20:04)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.sourceforge.net/doc/doxygen/bugs.html
Runtime Error: embedded:startup.tcl:47: Can't find openocd.cfg
in procedure 'script'
at file "embedded:startup.tcl", line 47
Error: Debug Adapter has to be specified, see "interface" command
in procedure 'init'
Когда OpenOCD запускается без указания опций в командной строке, то она ожидает наличие конфигурационного файла по умолчанию с именем openocd.cfg, находящийся в текущей директории (директория, откуда запускается OpenOCD). Давайте создадим такой файл, используя текстовый редактор.
Выбор интерфейса. Первое, что надо сделать - указать в конфигурационном файле имя используемого интерфейса. Оно зависит от адаптера JTAG, который Вы используете. Для большинства адаптеров USB JTAG, основанных на чипах FTDI, это имя будет ft2232 или ftdi:
interface ft2232
Для Turtelizer имя будет другое:
interface turtle
Здесь Вы можете столкнуться с небольшой проблемой. С некоторых пор команда разработчиков отказалась от официального распространения OpenOCD в двоичном коде (т. е. в виде скомпилированного пакета, готового к использованию). Они предоставляют только исходный код, подразумевая, что производители адаптеров JTAG самостоятельно выполнят сборку исполняемого кода для выбранной платформы, и предоставят необходимые конфигурационные файлы и документацию. Все поддерживаемые OpenOCD интерфейсы как раз выбираются на этапе компиляции/сборки, поэтому иногда может произойти ситуация, когда Ваша сборка OpenOCD по какой-то причине не содержит поддержки необходимого для Вас железа (адаптера JTAG или целевого MCU).
К счастью, если указанный интерфейс не поддерживается, то OpenOCD выведет список известных для неё интерфейсов, примерно так:
Если Ваш адаптер в этом списке отсутствует (не поддерживается), то запросите у производителя Вашего адаптера JTAG подходящий исполняемый код OpenOCD (или попробуйте самостоятельно найти такую сборку в Интернете, см. например [3, 4]).
Выбор разводки сигналов. Следующий шаг - выбор правильного назначения сигналов на коннекторе JTAG (разводка сигналов интерфейса, interface layout). Причина этого в том, что основные сигналы JTAG привязаны к определенным, фиксированным выводам микросхемы FTDI. Также выбираются выводы общего назначения GPIO для сигналов наподобие сброса (RESET) или подключения индикационных светодиодов (LED), что может зависеть от производителя адаптера. Возможные варианты разводок жестко встроены в двоичный код OpenOCD, и можно выбрать какой-либо из вариантов командой ft2232_layout. Для Turtelizer 2, добавьте в файл openocd.cfg следующую строку:
ft2232_layout turtelizer2
Начиная с OpenOCD версии 0.6.0 появилась возможность задать разводку сигналов прямо в конфигурационном файле. Однако на момент написания этого руководства такая возможность не была хорошо документирована. Скорее всего, в новых сборках OpenOCD будут добавлена поддержка для Turtelizer 2 ревизий Rev-B и Rev-C.
Для платы FT2232H Board с указанной выше схемой подключений можно выбрать следующую разводку:
ft2232_layout[]
Выбор устройства USB. Если сохранить эти 2 строчки (которые указывают interface и layout) в файле openocd.cfg, и попробовать запустить OpenOCD, то все еще будет выдаваться ошибка, но уже другая:
Error: neither device description nor serial number specified
Error: please add "ft2232_device_desc " or "ft2232_serial " to your .cfg file
in procedure 'init'
Для OpenOCD нужно знать, к какому устройству USB нужно подключаться. Для этого можно либо указать описание интерфейса (interface description), либо его серийный номер. При использовании Turtelizer 2 добавьте в файл openocd.cfg следующую строку:
ft2232_device_desc"Turtelizer JTAG/RS232 Adapter"
Сохраните файл, и попробуйте снова запустить OpenOCD. На этот раз должно быть выведено примерно такое сообщение:
Info : only one transport option; autoselect 'jtag'
Info : device: 4 "2232C"
Info : deviceID: 67354056
Info : SerialNumber: TLVE8EUJA
Info : Description: Turtelizer JTAG/RS232 Adapter A
Error: An adapter speed is not selected in the init script.
Insert a call to adapter_khz or jtag_rclk to proceed.
in procedure 'init'
OpenOCD снова прекратила работу, но эта последняя ошибка, которую мы исправим на следующем шаге.
Еще один совет. Если Вы увидели вышеуказанное сообщение, то скорее всего в нем будет присутствовать информация о серийном номере устройства (SerialNumber). Это уникальный идентификатор, который можно использовать вместо описания устройства. Он может Вам пригодиться, когда Вы будете подключать несколько плат Turtelizer к одному и тому же PC:
ft2232_serial TLVE8EUJA
Выбор начальной скорости работы адаптера. В отличие от привычных интерфейсов наподобие RS-232 или Ethernet, интерфейс JTAG не определяет никаких стандартных скоростей своей работы. Выгрузка в память MCU файлов большого размера может быть раздражающе долгой, поэтому желательно настроить скорость как можно выше. Однако здесь мы ограничены двумя факторами: максимально допустимая скорость адаптера JTAG и максимально допустимая скорость JTAG на целевой плате, где установлен наш программируемый MCU.
Если у Вас используется современный адаптер JTAG (на высокоскоростном чипе FT2232H), то ограничителем будет допустимая скорость JTAG целевой платы. Этот параметр часто уточняют позже, путем экспериментального подбора. Также большинство ядер ARM CPU запускаются после включения питания / сброса на пониженной частоте. Это также верно и для платы Elektor Internet Radio, которая изначально использует тактовую частоту от генератора 32 кГц. Обычно загрузчик платы (bootloader) поменяет тактовую частоту процессора на рабочую, чтобы CPU работал на полной скорости. Но когда CPU управляется через JTAG, у загрузчика нет шансов запустить свой код, либо он может вообще отсутствовать. С другой стороны, большинство ARM CPU не могут обслуживать тактовые частоты JTAG намного выше, чем частота тактов CPU.
Есть хорошая новость: существует механизм так называемого адаптивного тактирования, где CPU возвращает частоту JTAG на отдельном выводе. Этот сигнал используется адаптером JTAG для синхронизации своей выходной частоты. OpenOCD поддерживает этот режим, когда в конфигурационный файл добавлена следующая строка:
jtag_rclk3000
Эта команда установит тактовую частоту JTAG на 3 МГц, и автоматически подстроит её к низкой тактовой частоте, если это необходимо.
Есть и плохая новость. В первую очередь Turtelizer не поддерживает адаптивное тактирование, потому что в нем используется чип FT2232D, не поддерживающий эту функцию. Имеется множество адаптеров на основе микросхемы FT2232H (в том числе и платка [6]), которые поддерживают адаптивное тактирование. Но все-таки они не могут подстраивать свою частоту в полном диапазоне. Все еще требуется "вручную" настроить начальную частоту. И вторым тормозом является AT91SAM7SE CPU, который не поддерживает никакое адаптивное тактирование.
Мы решим эту проблему путем установки низкой начальной частоты 8 кГц. Впоследствии мы будем использовать OpenOCD, чтобы запустить PLL, завести CPU на полной скорости и довести скорость работы Turtelizer JTAG до максимума. Добавьте в openocd.cfg следующую строку:
adapter_khz8
Для ясности, у нас получится следующее содержимое файла openocd.cfg:
interface ft2232
ft2232_layout turtelizer2
ft2232_device_desc"Turtelizer JTAG/RS232 Adapter"
adapter_khz8
Если Вы используете пакет с поддержкой Turtelizer 2, то замените первую строку на следующую:
interface turtle
Запустите OpenOCD, и Вы должны увидеть лог успешной инициализации, и работа OpenOCD больше не будет прервана по ошибке, её исполняемый файл останется работать как сервис:
Open On-Chip Debugger 0.6.0-rc1 (2012-08-08-20:04)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.sourceforge.net/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'jtag'
8 kHz
Info : device: 4 "2232C"
Info : deviceID: 67354056
Info : SerialNumber: TLVE8EUJA
Info : Description: Turtelizer JTAG/RS232 Adapter A
Info : clock speed 8 kHz
Warn : There are no enabled taps. AUTO PROBING MIGHT NOT WORK!!
Warn : AUTO auto0.tap - use "jtag newtap auto0 tap -expected-id 0x3f0f0f0f ..."
Warn : AUTO auto0.tap - use "... -irlen 4"
Warn : gdb services need one or more targets defined
Само собой, в зависимости от версии OpenOCD и используемой Вами конфигурации это сообщение может несколько отличаться. Однако общий смысл его будет понятен - OpenOCD автоматически переключилась в режима "auto probing", и даже советует Вам добавить в конфигурационный файл поддержку цепочки JTAG с новым тестируемым узлом (jtag newtap, новый узел TAP). Кое-что об этом будет объяснено в следующей главе.
[3. Конфигурирование CPU]
Декларация TAP. На предыдущем шаге OpenOCD советовала добавить команду jtag newtap к существующей конфигурации. Общая форма этой команды следующая:
jtag newtap < chipname >< tapname >< options >
Нам нужно заполнить параметры команды в угловых скобках. Их назначение следующее:
Параметр
Описание
chipname
На плате может быть установлено несколько процессоров (chip) с интерфейсами JTAG. Вы должны указать уникальное имя для каждого, чтобы идентифицировать их.
tapname
Чип процессора может содержать несколько точек для доступа к тестированию (test access points, TAP). Вы должны указать для них уникальные TAP-имена для идентификации.
options
Какк минимум мы должны задать длину регистра инструкции JTAG в TAP, используя опцию -irlen. Также хорошей идеей будет предоставить для OpenOCD информацию об ожидаемом коде идентификатора процессора (JTAG ID-Code) с помощью опции -expected-id.
Вспомним вывод, который мы получили в прошлый раз:
Warn : There are no enabled taps. AUTO PROBING MIGHT NOT WORK!!
Warn : AUTO auto0.tap - use "jtag newtap auto0 tap -expected-id 0x3f0f0f0f ..."
Warn : AUTO auto0.tap - use "... -irlen 4"
В большинстве случаев функция autoprobe работает хорошо, и OpenOCD советует использовать:
jtag newtap auto tap -irlen 4-expected-id 0x3f0f0f0f
Давайте заменим для AT91SAM7SE512 значение chipname на sam7se512 и значение tapname на cpu. В результате получится следующая строка, которую Вы должны добавить в файл openocd.cfg. Кстати, перед этим остановите работу OpenOCD нажатием клавиш Ctrl-C.
jtag newtap sam7se512 cpu -irlen 4-expected-id 0x3f0f0f0f
Мы можем позже обращаться к этому специфичному TAP по его имени с точкой sam7se512.cpu.
Запуск OpenOCD с этой модифицированной конфигурацией выведет следующее сообщение:
Open On-Chip Debugger 0.6.0-rc1 (2012-08-08-20:04)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.sourceforge.net/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'jtag'
8 kHz
Info : device: 4 "2232C"
Info : deviceID: 67354056
Info : SerialNumber: TLVE8EUJA
Info : Description: Turtelizer JTAG/RS232 Adapter A
Info : clock speed 8 kHz
Info : JTAG tap: sam7se512.cpu tap/device found: 0x3f0f0f0f (mfg: 0x787, part: 0xf0f0, ver: 0x3)
Warn : gdb services need one or more targets defined
Все еще осталось одно предупреждение, с которым мы разберемся далее.
Декларация цели отладки (Debug Target). Вы можете просто использовать OpenOCD только для прошивки памяти MCU на целевой плате, однако в первую очередь OpenOCD используют для отладки (debug). Пока что мы сконфигурировали только интерфейс JTAG ничего не зная о внутреннем устройстве CPU.
Хотя OpenOCD в основном используется для ARM CPU, она с большим или меньшим успехом поддерживает и некоторые другие целевые процессоры. Поддержка многообразия целей через JTAG не простое дело. Например, цели отладки могут переключаться в разные режимы или состояния, могут иметь или не иметь в своем составе MMU (memory management unit, т. е. блок управления памятью), и даже сброс цели может приводить к различным побочным эффектам, которые не всегда тривиальны для обработки. Даже если ограничиться поддержкой определенного набора ядер ARM, существует много их вариаций с полностью отличающимися друг от друга функциями и аппаратными возможностями.
В результате большинство информации (база знаний) о целевых чипах CPU в OpenOCD жестко задана в её коде, и подходящие подпрограммы выбираются простым указанием для OpenOCD, какой вид чипа подключен на существующий TAP. Это делается командой конфигурации target create, вот её основная форма:
target create < targetname >< type >< options >
Назначение параметров этой команды приведено в таблице ниже.
Параметр
Описание
chipname
Плата системы (board) может содержать несколько чипов с интерфейсами JTAG. Вы должны указать уникальное имя для каждого чипа, чтобы OpenOCD могла их идентифицировать.
tapname
Чип микроконтроллера может содержать несколько точек доступа для тестирования (test access points, TAP). Вы должны указать уникальные имена TAP, чтобы идентифицировать их.
options
Как минимум здесь нужно указать длину регистра инструкций JTAG для TAP, используя опцию -irlen. Также хорошей идеей будет дать OpenOCD информацию об ожидаемом JTAG ID-Code микроконтроллера с использованием опции -expected-id.
После добавления этой строки в файл openocd.cfg (не забудьте сохранить его), OpenOCD должна запуститься без каких-либо ошибок или предупреждений.
Open On-Chip Debugger 0.6.0-rc1 (2012-08-08-20:04)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.sourceforge.net/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'jtag'
8 kHz
sam7se512.cpu
Info : device: 4 "2232C"
Info : deviceID: 67354056
Info : SerialNumber: TLVE8EUJA
Info : Description: Turtelizer JTAG/RS232 Adapter A
Info : clock speed 8 kHz
Info : JTAG tap: sam7se512.cpu tap/device found: 0x3f0f0f0f (mfg: 0x787, part: 0xf0f0, ver: 0x3)
Info : Embedded ICE version 1
Info : sam7se512.cpu: hardware has 2 breakpoint/watchpoint units
Начиная с этого момента полное содержимое openocd.cfg должно быть таким:
interface ft2232
ft2232_layout turtelizer2
ft2232_device_desc"Turtelizer JTAG/RS232 Adapter"
adapter_khz8jtag newtap sam7se512 cpu -irlen 4-expected-id 0x3f0f0f0f
Напомним еще раз, если используете OpenOCD с пакетом поддержки Turtelizer, то замените в первой строке имя адаптера интерфейса ft2232 на имя turtle.
Заскучали? Не беспокойтесь, наступают сложные времена - в следующей главе мы рассмотрим, как конфигурировать PLL процессора. Придется углубиться в чтение даташита AT91SAM7SE.
[4. Конфигурирование тактирования CPU]
Использование Tcl. Несмотря на то, что конфигурационные файлы OpenOCD выглядят как простые текстовые файлы, это не совсем так. На самом деле это интерпретируемый выполняемый код, и если быть точнее, то это скрипты языка Tcl. В тело OpenOCD встроен маленький интерпретатор Tcl, который называется Jim Tcl. Использование скриптового языка вместо сносящих крышу опций командной строки делает конфигурирование понятнее и удобнее.
OpenOCD при запуске читает наш конфигурационный файл строка за строкой, и немедленно выполняет каждую строку. Чтобы настроить систему PLL чипа и запустить его CPU на полной скорости, нам понадобится доступ к определенным его регистрам ввода/вывода. Мы не могли этого сделать, пока не создали и сконфигурировали TAP и debug target (цель отладки) через команды jtag newtap и target create. Проблем нет, пока команды в нашем конфигурационном файле указаны в правильном порядке.
Но что произойдет, когда мы нажмем на кнопку сброса платы? CPU вернется в свое исходное состояние с низкой частотой тактирования, и OpenOCD должна повторно прочитать и снова выполнить конфигурацию. Это только простой пример. Существуют и другие события кроме сброса, которые нам нужно обработать, чтобы поддержать отладку на целевой плате.
OpenOCD предоставляет мощное решение таких проблем, но оно может сбить с толку, если не знать о нем. Программа запускается в так называемом режиме конфигурации (configuration stage), когда все команды выполняются немедленно по мере их чтения из конфигурационного файла. Когда эта стадия завершится, OpenOCD переключится в так называемый рабочий режим (run state). Следует иметь в виду, что некоторые команды отклоняются на configuration stage, в то время как другие команды отклоняются в run state. Конечно, многие команды можно выполнить в любом из этих состояний. Кроме того, команды Tcl, которые должны выполняться во время run state, должны быть определены в процедурах Tcl.
Скорее всего кое-кто из Вас не захочет учить новый язык программирования, им захочется сразу получить OpenOCD готовой к работе. Однако некоторые правила синтаксиса Tcl (очень простые) рассмотреть все же придется.
Доступ к адресам памяти. OpenOCD предоставляет несколько команд для чтения и записи данных по указанным адресам памяти. Очевидно, что эти команды будут обрабатываться только в рабочем режиме (run state). Как мы уже узнали, в рабочем режиме потребуется создать процедуру языка Tcl. Но это верно только для конфигурационного файла. Как только OpenOCD закончит читать файл конфигурации (или файлы, как мы увидим позже), она автоматически переключится в run state. Чтобы интерактивно выполнять команды в run state, мы можем использовать интерфейс (командную строку) Telnet, встроенную в OpenOCD в виде сервера telnet. Если это еще не сделано, запустите OpenOCD в одном окне команд. Откройте еще одно окно команд, и введите следующую команду:
telnet localhost 4444
В результате Вы получите приглашение для ввода команд OpenOCD, которые она готова обработать. Наиболее важная команда mww (она получила имя от сокращения memory write word, т. е. "запись слова в память"), за которой указывается адрес, куда осуществляется запись, после чего идут данных для записи. Давайте попробуем сделать запись в SRAM процессора AT91SAM7SE, которая начинается по адресу 0x200000:
mww0x2000000x12345678
В большинстве случаев это немедленно закончится неудачей, потому что CPU работает, и он занял шину памяти. Чтобы остановить CPU, введите команду:
halt
Теперь попробуем снова выполнить запись в память. Можно использовать клавиши курсора клавиатуры вверх/вниз для прокрутки истории ранее введенных команд. Чтобы прочитать данные по тому же самому адресу, используйте команду mdw (аббревиатура от memory display word), за которой укажите адрес для чтения:
mdw0x200000
В результате должно отобразиться значение, которое было ранее записано командой mww.
OK, теперь нужно открыть даташит на процессор, изучить его, и записать нужные значения в нужные регистры, чтобы правильно запустить PLL и запустить CPU на нужной скорости.
Настройка PLL. Из главы 29.7 даташита AT91SAM7SE можно узнать, что сначала нам надо разрешить главный генератор записью 0x701 в регистр CKGR_MOR. Время запуска (startup time) устанавливается на 56 периодов медленных тактов (slow clock cycles).
mww0xfffffc200x00000701
Далее мы установим делитель ФАПЧ (PLL divider) и умножитель ФАПЧ (PLL multiplier), чтобы из частоты кварца получилась частота 96 МГц. Мы будем настраивать делитель на 14 и умножитель на 72. Из частоты кварца 18.432 МГц мы получим частоту 18.432MHz * (72 + 1) / 14 = 96.11 МГц. Время запуска (startup time) должно быть 28 медленных тактов. Это устанавливается записью в регистр CKGR_PLLR.
mww0xfffffc2C0x00481c0e
Теперь записью в регистр PMC_MCKR мы выберем деление частоты PLL на 2 для получения главной частоты тактов.
mww0xfffffc300x00000007
После выполнения этих действий наш CPU будет работать на частоте 48 МГц.
В завершении мы установим регистр MC_FMR для настройки 1 wait state на чтение 2 wait state на запись при доступе к внутренней памяти flash (количество тактов ожидания). Это не требуется, пока не осуществляется доступ к памяти flash (если код и данные размещены только в SRAM). Но мы это сделаем, потому что требуемое количество тактов ожидания зависит от настройки тактовой частоты.
mww0xffffff600x00480100
Теперь следует поместить всю последовательность этих действий в процедуру Tcl, находящуюся в файле конфигурации openocd.cfg. Но еще нам следует учесть, что по даташиту нужно подождать, пока тактовая частота не станет стабильной. Когда команды вводятся вручную, это не составляет проблемы, потому что тактовая частота стабилизируется, пока мы вводим следующую команду. Однако при выполнении тех же команд в скрипте может произойти слишком быстро. Одно из решений этой проблемы состоит в применении команды mem2array для чтения и проверки содержимого регистра (у AT91SAM7SE есть бит состояния в регистре, сигнализирующий о стабилизации частоты тактов). Но намного проще добавить в список команд записи в регистры команду sleep, которая принимает в качестве параметра количество миллисекунд, которое OpenOCD должно ожидать перед выполнением следующей команды.
Если вернуться назад, то можно заметить, что наш скрипт разросся, и его код становится достаточно сложным и непонятным. Что можно сделать для улучшения читаемости скрипта? Во-первых, можно ввести переменные для адресов регистров. Во-вторых, можно снабдить скрипт понятными комментариями, описывающими выполняемые действия. Ниже приведен код процедуры TCL, которая делает инициализацию тактов процессора AT91SAM7SE платы Elektor Internet Radio (EIR).
# Инициализация тактов платы Elektor Internet Radio (EIR).
#
# На плате установлен кварц 18.432 МГц.
# CPU запускается на частоте 48 МГц.
#
proc eir_init_clock {}{# Разрешение главного генератора.## Start-up устанавливается 7 x 8 медленных тактов (slow clocks).#mww0xfffffc200x00000701;# CKGR_MORsleep2
# Конфигурирование PLL (ФАПЧ).## 18.432 МГц * (72 + 1) / 14 = 96 МГц## Делитель на 14 (0x0e)# Start-up time 28 (0x1c) медленных тактов# Умножитель на 72 (0x48)#mww0xfffffc2C0x00481c0e;# CKGR_PLLRsleep1
# Выбор частоты тактов от PLL, поделенной на 2## 96 МГц / 2 = 48 МГц#mww0xfffffc300x00000007;# PMC_MCKRsleep1
# 1 такт ожидания при чтении flash,# 2 такта ожидания для записи flash# В одной микросекунде у нас получится 48 тактовmww0xffffff600x00480100;# MC_FMR
}
Примечание: в приведенном коде процедуры eir_init_clock можно заметить странное сочетание ;#, используемое для комментария в конце строки, в которой находится рабочий код. Это сделано для того, чтобы обойти проблему некоторых релизов OpenOCD, неправильно обрабатывающие комментарии в конце строк. В действительности это не всегда решает проблему таких комментариев (в зависимости от релиза OpenOCD), что следует иметь в виду. В остальном OpenOCD достаточно надежный инструмент.
Добавьте процедуру eir_init_clock в свой текущий файл openocd.cfg. Если у Вас все еще открыт сеанс Telnet, то можно ввести команду:
shutdown
Это завершит оба сеанса, Telnet и OpenOCD.
Вы можете проверить работу процедуры Tcl если просто ввести её имя eir_init_clock в командной строке сессии Telnet, но в этом нет большого смысла, пока не определен обработчик события сброса (reset event handler). Пока что в нашей текущей конфигурации сброс платы не будет согласован с работой OpenOCD. Это мы исправим на следующем шаге.
Сброс конфигурации. Стандарт JTAG определяет 2 сигнала сброса, nSRST и nTRST. Первый из них используется для сброса аппаратуры (делает то же самое, что и кнопка сброс), а второй используется для сброса JTAG TAP. Фактически оба этих сигнала не обязательны, потому что целевые процессоры могут предоставлять альтернативные способы сброса системы и/или TAP для перевода из в известное начальное состояние. Проблема состоит в том, что иногда эти сигналы реализованы странными способами. Например, большинство целей отладки (target) позволяют коммуникацию через JTAG при nSRST в лог. 0, а другие этого не позволяют. Это делает невозможным для отладчика остановить target перед выполнением первого кода операции (opcode). Многие target-ы и адаптеры JTAG, включая AT91SAM7SE и Turtelizer 2 board revision B, не требуют или не предоставляют nTRST. В результате нам нужно добавить еще один элемент конфигурации, чтобы указать для OpenOCD, какой из механизмов сброса доступен. Для AT91SAM7SE мы декларируем:
reset_config srst_only
Это сделает доступной команду сброса (reset), и мы можем реализовать связанный с ней обработчик.
Создание обработчика события сброса (Reset Handler). Рано или поздно нам понадобится нечто большее, чем просто настройка тактовой частоты процессора. Давайте определим процедуру обработчика сброса, которая будет вызывать процедуру eir_init_clock, которую мы определили ранее.
# Инициализация платы Elektor Internet Radio (EIR).
#
proc eir_init {}
{eir_init_clock
}
Эта процедура будет зарегистрирована как reset-init handler для нашей цели отладки:
Вы можете добавить в свой файл openocd.cfg в любом порядке (это не имеет значение) процедуры eir_init_clock и eir_init, как и команду configure. Попробуйте запустить OpenOCD с этой новой конфигурацией, установите сессию Telnet и введите команду:
reset init
Окно Telnet должно показать следующее сообщение:
JTAG tap: sam7se512.cpu tap/device found: 0x3f0f0f0f (mfg: 0x787, part: 0xf0f0, ver: 0x3)
target state: halted
target halted in ARM state due to debug-request, current mode: Supervisor
cpsr: 0x600000d3 pc: 0x00000000
NOTE! DCC downloads have not been enabled, defaulting to slow memory writes. Type 'help dcc'.
NOTE! Severe performance degradation without working memory enabled.
NOTE! Severe performance degradation without fast memory access enabled. Type 'help fast'.
Программа OpenOCD определила, что наша текущая конфигурация может замедлить загрузку прошивки в память, и вывела соответствующие замечания. Давайте пока их проигнорируем.
Перед тем, как перейти к следующей части, проверим текущее содержимое нашего конфигурационного файла openocd.cfg:
interface turtle
ft2232_layout turtelizer2
ft2232_device_desc"Turtelizer JTAG/RS232 Adapter"
adapter_khz8
jtag newtap sam7se512 cpu -irlen 4-expected-id 0x3f0f0f0f
# Инициализация платы Elektor Internet Radio (EIR).
#
proc eir_init {}{eir_init_clock
}
# Инициализация тактов платы Elektor Internet Radio (EIR).
#
# На плате установлен кварц 18.432 МГц.
# CPU запускается на частоте 48 МГц.
#
proc eir_init_clock {}{# Разрешение главного генератора.## Start-up устанавливается 6 x 8 медленных тактов (slow clocks).#mww0xfffffc200x00000601;# CKGR_MORsleep2
# Конфигурирование PLL (ФАПЧ).## 18.432 МГц * (72 + 1) / 14 = 96 МГц## Делитель на 14 (0x0e)# Start-up time 28 (0x1c) медленных тактов# Умножитель на 72 (0x48)#mww0xfffffc2C0x00481c0e;# CKGR_PLLRsleep1
# Выбор частоты тактов от PLL, поделенной на 2## 96 МГц / 2 = 48 МГц#mww0xfffffc300x00000007;# PMC_MCKRsleep1
# 1 такт ожидания при чтении flash,# 2 такта ожидания для записи flash# В одной микросекунде у нас получится 48 тактовmww0xffffff600x00480100;# MC_FMR
}
[5. Использование SDRAM]
Если сравнивать с другими платами на основе ARM7TDMI, платка EIR предоставляет ОЗУ (RAM) на целых 64 мегабайта (это динамическая память, SDRAM). Это делает разработку новых приложений очень удобным. Автор статьи [1] часто использует плату EIR для создания новых приложений Nut/OS, предназначенных для других плат. Памяти в EIR достаточно для добавления любых тестовых подпрограмм, расширенного отладочного вывода и т. д. Позднее этот добавочный код можно удалить, чтобы уменьшить рабочий код, который будет записан в память flash и RAM готовой рабочей системы. Другие достоинства ОЗУ: загрузка в него кода происходит намного быстрее, чем прошивка кода в память flash, и в ОЗУ можно добавить любое количество точек останова (breakpoints) без всяких проблем.
Инициализация шины памяти. В предыдущей главе мы научились осуществлять доступ к 32 килобайтам статического ОЗУ (static RAM, или SRAM которая находится непосредственно на кристалле микроконтроллера AT91SAM7SE) с помощью команды mww. SDRAM большого размера, к которой мы хотим получить доступ, подключена к AT91SAM7SE снаружи по внешней шине (external memory bus) как дополнительная микросхема памяти, установленная на плате EIR. Таким образом, нам сначала нужно разрешить работу external memory bus микроконтроллера. Это осуществляется путем разрешения на соответствующих выводах AT91SAM7SE функции шины памяти. И опять это выполняется командами mww, чтобы установить в нужное состояние определенные регистры ввода/вывода. Подробности этих операций Вы можете узнать из даташита AT91SAM7SE.
# Инициализация шины внешней памяти (external memory bus).
#
proc eir_init_membus {}{# Разрешить шину адреса (A0, A2-A11, A13-A17) на порте PIO Bmww0xfffff6740x0003effd;# PIOB_BSRmww0xfffff6040x0003effd;# PIOB_PDR# Разрешить 16-битную шину данных на порте PIO Cmww0xfffff8700x0000ffff;# PIOC_ASRmww0xfffff8040x0000ffff;# PIOC_PDR
}
После вызова этой подпрограммы мы должны получить доступ к чипу SDRAM, для чего понадобится его инициализация.
Инициализация SDRAM. Статическая память SRAM сразу готова к работе после включения питания, но в отличие от неё динамическая память SDRAM требует для своей работы специальной последовательности инициализации. Когда AT91SAM7SE загружается из flash, это делает runtime-код инициализации приложения. Если мы хотим записать код через JTAG непосредственно в SDRAM, то OpenOCD сначала должна сама выполнить эту часть инициализации.
Правильно настроить интервалы времени SDRAM непросто, требуется предварительное изучение даташита на SDRAM и дополнительные вычисления. Чтобы объяснить все детали, потребуется написать отдельное руководство. Пока что просто скопируйте код ниже в свой файл openocd.cfg. В нем добавлены дополнительные комментарии, которые помогут Вам самостоятельно разобраться в тонкостях инициализации SDRAM.
# Инициализация EIR SDRAM.
#
# Плата EIR использует микросхему Samsung K4S511632D-UC75 SDRAM:
# Организация: 32M x 16
# 8k строк, 1k столбцов
# 20 нс время предзаряда строки (row precharge time)
# 45 нс минимум и 100 мкс максимум время активности строки (row active time)
#
# Длительность периода MCK 20 нс при работе на частоте 48 МГц.
#
proc eir_init_sdram {}{# Разрешить управление SDRAM на порте PIO A#mww0xfffff4740x3f800000;# PIOA_BSRmww0xfffff4040x3f800000;# PIOA_PDR
# Выдача команды 16 бит SDRAM: Set mode register#mww0xffffffb00x00000013;# SDRAMC_MRmww0x200000140xcafedede
# Установка счетчика обновления (refresh rate count) ???#mww0xffffffb40x00000013;# SDRAMC_TR
# Выдача команды 16 бит SDRAM: Normal mode#mww0xffffffb00x00000010;# SDRAMC_MRmww0x200000000x00000180
}
Эта процедура требует, чтобы главная частота процессора была 48 МГц, и была разрешена шина памяти. Это должно быть учтено путем добавления вызовов соответствующих процедур в нашем обработчике сброса:
# Инициализация платы Elektor Internet Radio (EIR).
Как только Вы добавили еще 2 вызова процедур eir_init_membus и eir_init_sdram, команда reset init в сессии Telnet OpenOCD должна разрешить для OpenOCD загрузку и выполнение кода в SDRAM.
Но это еще не все. Многие приложения разрабатываются для работы из памяти flash, которая находится в адресном пространстве по адресу 0. Нужен как минимум другой скрипт линкера, чтобы код, работающий в SDRAM, находился по адресу 0x20000000. Когда используются прерывания, ARM7 CPU ожидает, что его адреса исключений (exception vectors, таблица переходов в обработчики прерываний) начинаются с адреса 0. Таким образом, нам нужна новая runtime-инициализация, которая меняет отображение внутренней SRAM на адрес 0, и копирует туда таблицу векторов исключений из образа SDRAM. Однако в этом руководстве не описывается эта процедура, здесь мы сосредоточены только на настройке OpenOCD.
Хотя SDRAM очень хороша для разработки и отладки, конечная рабочая система скорее всего будет рассчитана на работу из памяти flash. В следующей главе будет рассмотрено, как использовать OpenOCD для прошивки кода в память flash процессора AT91SAM7SE.
[6. Прошивка целевого процессора]
Почти все мелкие и средние по объему памяти микроконтроллеры сегодня используют память flash для хранения памяти программ - там находится либо загрузчик (bootloader), который загружает рабочий код, либо (что чаще всего) в памяти flash находится полный рабочий код, и программа запускается прямо оттуда. Стандарт JTAG сам по себе не предоставляет какую-либо технологию программирования памяти flash. Вместо этого JTAG используется для получения доступа к аппаратным регистрам программируемого микроконтроллера. Некоторые из них, являясь частью интерфейса JTAG CPU, даже могут использоваться для эмуляции значений кода и данных, что дает возможность запустить код CPU без доступной реальной памяти. Эта функция может использоваться для запуска фрагментов кода, которые работают как драйвер для контроллера flash.
Драйверы OpenOCD. Разработано несколько стандартов для программирования микросхем внешней памяти flash, однако принципы программирования внутренней flash-памяти микроконтроллеров, таких как микроконтроллеры серии AT91SAM7, обычно несовместимы между производителями кристаллов микроконтроллеров. OpenOCD содержит некоторое количество жестко вшитых в код драйверов flash, включая один с именем at91sam7, который хорошо работает для внутренней памяти flash AT91SAM7SE CPU, и даже позволяет программировать биты GPNVM [12].
Память flash обычно делится на блоки, так называемые банки flash. Один чип микроконтроллера может содержать в себе один или большее количество банков. AT91SAM7SE256 содержит один банк, а у AT91SAM7SE512 их два. Это важный момент, который надо учитывать, так как у процессора AT91SAM7SE каждый банк подключен к отдельному контроллеру, и поэтому каждый банк должен быть отдельно декларирован в конфигурационном файле с помощью команды flash bank. Общая форма этой команды:
flash bank < name >< driver >< base >< size >< chip_width >
< bus_width >< target >< driver_options >
Некоторые из этих параметров относятся только к внешней памяти flash, и игнорируются драйверами для внутренней памяти flash. Для нашего CPU мы декларируем 2 банка:
flash bank sam7se512.flash.0 at91sam7 0000 sam7se512.cpu 000000018432
flash bank sam7se512.flash.1 at91sam7 0000 sam7se512.cpu 100000018432
После добавления этих 2 строк в openocd.cfg и перезапуска OpenOCD, Вы должны получить информацию о памяти flash путем ввода следующих команд в сессии Telnet:
flash info 0
flash info 1
Вы можете обратить внимание на то, что выполнение этих команд занимает некоторое время. Реальная прошивка памяти flash занимает еще больше времени, и пока что это время недопустимо большое. В следующей главе мы решим эту проблему.
[7. Оптимизация конфигураций OpenOCD]
Помните замечания в сообщениях OpenOCD, когда мы выполняли команду reset init?
NOTE! DCC downloads have not been enabled, defaulting to slow memory writes. Type 'help dcc'.
NOTE! Severe performance degradation without working memory enabled.
NOTE! Severe performance degradation without fast memory access enabled. Type 'help fast'.
В этой главе мы покажем, как увеличить скорость обмена данными через JTAG. Кроме этого мы обсудим, как изменить конфигурацию, чтобы сделать её немного более удобной для использования.
Рабочая область. Как было отмечено в предыдущей главе, драйверы flash OpenOCD могут использовать интерфейс JTAG, чтобы представить код и данные для CPU без использования реальной памяти. Код и данные вдвигаются в специальные регистры JTAG, находящиеся в ядре и периферийных устройствах, так что CPU будет думать, что эти значения находятся в реальной памяти. Это иногда очень помогает для запуска маленьких фрагментов кода на совершенно чистой системе. Но это также медленно работает, потому что требуется выполнение большого количества команд на уровне JTAG. Особенно это важно на дешевых адаптерах наподобие Turtelizer 2, где USB становится реальным узким местом.
К счастью OpenOCD предоставляет решение этой проблемы, если мы можем предоставить некоторое количество ОЗУ на целевой плате. В этом случае OpenOCD не будет реализовывать каждый доступ к flash через эмуляции кода и памяти, которые связаны через медленными операции загрузки данных в регистры сдвига JTAG. Вместо этого OpenOCD может загрузить в ОЗУ специально подготовленный код доступа к памяти flash и запустить его. Этот код позволит CPU напрямую работать с flash, без промежуточных операций JTAG. Через JTAG при прошивке/чтении flash будут поступать только данные, для которых в ОЗУ выделяется специальный буфер. Эта технология требует для себя несколько килобайт ОЗУ, для чего будет хорошим кандидатом внутренняя память SRAM AT91SAM7SE.
Очевидно, что связанная с этой технологией конфигурация является частью цели отладки (debug target), и следовательно она должна быть добавлена к команде target create. Эта возможность появилась в OpenOCD позже, поэтому реализована она не очень-то гибко. Хотя debug target должна быть декларирована на стадии конфигурации, и может быть декларирована только 1 раз, иногда требуется настроить рабочую область после того, как прошли определенные стадии аппаратной инициализации. Кроме того, часто требуется выбрать разные рабочие области для разных задач. Обратите внимание, что рабочая область занимает память, и может пересечься с firmware, которая уже работает в целевом процессоре (target).
OpenOCD позволяет динамически конфигурировать определенные параметры debug target через команду configure, перед которой должно идти имя с точкой связанной с ней debug target. Чтобы позволить OpenOCD использовать последние 8 килобайт внутренней памяти SRAM в качестве рабочей области, мы сделали определение:
Эту строку Вы также можете добавить в файл openocd.cfg.
Канал обмена для отладки (Debug Communication Channel). Даже если мы установили рабочую область для target, заполнение её данными или кодом через операции сдвига JTAG все еще остаются громоздкими. Некоторые CPU, включая AT91SAM7SE, предоставляют для JTAG дополнительный интерфейс наподобие UART, который называется debug communication channel, или сокращенно DCC, что значительно упрощает работу с машиной состояний JTAG. Следующая команда дает указание OpenOCD использовать DCC:
arm7_9 dcc_downloads enable
К сожалению, это может не работать на целевых процессорах, работающих на низкой скорости. В нашем случае это возможно не заработает, пока мы не переключим главную тактовую частоту процессора на высокую частоту PLL. Пока не добавляйте эту строку в файл openocd.cfg. Как мы скоро увидим, есть более подходящее место для этой конфигурации.
Быстрый доступ к памяти. Откровенно говоря, совершенно непонятно, как работает следующая внутренняя конфигурация:
arm7_9 fast_memory_access enable
Однако это значительно увеличивает скорость обмена между компьютером PC и целевым процессором (target). Опять-таки, это может не работать, когда CPU тактируется низкой частотой, и эта конфигурация должна быть добавлено в правильное место openocd.cfg.
Повышение тактовой частоты JTAG. Вы уже знаете, что мы установили частоту тактирования JTAG в нашем файле openocd.cfg. Однако как только мы повысили тактовую частоту CPU до 48 МГц, нужно также увеличить и тактовую частоту JTAG. И мы можем также выполнить все другие оптимизации, которые не работают надежно на низких тактовых частотах. Как Вы наверное уже догадались, правильное место для повышения тактовой частоты и для дополнительных оптимизаций - обработчик события сброса (reset-init handler).
# Инициализация платки EIR.
#
proc eir_init {}{eir_init_clock
# Минимальное время такта ICE составляет 102 нс (частота 9800 кГц)adapter_khz9800arm7_9 dcc_downloads enable
arm7_9 fast_memory_access enable
eir_init_membuseir_init_sdram
}
В результате у нас получится вот такой полный конфигурационный файл openocd.cfg, предназначенный для нашей платы EIR:
interface turtle
ft2232_layout turtelizer2
ft2232_device_desc"Turtelizer JTAG/RS232 Adapter"
reset_config srst_only
adapter_khz8
jtag newtap sam7se512 cpu -irlen 4-expected-id 0x3f0f0f0f
# Минимальное время такта ICE составляет 102 нс (частота 9800 кГц)adapter_khz9800arm7_9 dcc_downloads enable
arm7_9 fast_memory_access enable
eir_init_membuseir_init_sdram
}
# Инициализация тактов EIR.
#
# Платка EIR использует кварц 18.432 МГц.
# CPU запускается на частоте 48 МГц.
#
proc eir_init_clock {}{# Разрешение работы главного генератора.## Время запуска (Start-up time) составляет 6 x 8 медленных такта.#mww0xfffffc200x00000601;# CKGR_MORsleep2
# Выбор частоты тактирования от PLL, поделенной на 2## 96 МГц / 2 = 48 МГц#mww0xfffffc300x00000007;# PMC_MCKRsleep1
# Доступ к flash настраивается с задержкой 1 wait state# для чтения, и 2 wait state для записи.# За 1 мкс получится 48 тактов главной частоты.mww0xffffff600x00480100;# MC_FMR
}
# Инициализация внешней шины памяти (external memory bus).
#
proc eir_init_membus {}{# Разрешить шину адреса (A0, A2-A11, A13-A17) на порте PIO Bmww0xfffff6740x0003effd;# PIOB_BSRmww0xfffff6040x0003effd;# PIOB_PDR
# Разрешить 16-битную шину данных на порте PIO Cmww0xfffff8700x0000ffff;# PIOC_ASRmww0xfffff8040x0000ffff;# PIOC_PDR
}
# Инициализация SDRAM, установленной на платке EIR.
#
# EIR использует Samsung K4S511632D-UC75 SDRAM:
# Организация: 32M x 16
# 8k строк, 1k столбцов
# 20 нс row precharge time (время предзаряда строки)
# 45 нс минимум и 100 мкс максимум row active time
#
# Длительность периода MCK равна 20 нс при работе на 48 МГц.
#
proc eir_init_sdram {}{# Разрешить управление SDRAM через порт PIO A#mww0xfffff4740x3f800000;# PIOA_BSRmww0xfffff4040x3f800000;# PIOA_PDR
# Выдача команды 16-бит SDRAM: Set mode register#mww0xffffffb00x00000013;# SDRAMC_MRmww0x200000140xcafedede
# Установка счетчика обновления (refresh rate count) ???#mww0xffffffb40x00000013;# SDRAMC_TR
# Выдача команды 16-бит SDRAM: Normal mode#mww0xffffffb00x00000010;# SDRAMC_MRmww0x200000000x00000180
}
[8. Принципы организации скриптов OpenOCD]
В предыдущей главе мы сохранили полную конфигурацию в локальном файле с именем openocd.cfg, который автоматически загружается OpenOCD, если он существует.
В этой главе мы разделим эту конфигурацию на отдельные файлы, чтобы сделать её более удобной для повторного использования. OpenOCD позволяет подключать внешние конфигурационные файлы в свою локальную конфигурацию. Мы перепишем openocd.cfg чтобы он выглядел примерно так:
add_script_search_dir[/usr/share/openocd/scripts]
source[find interface/turtelizer2.cfg]
source[find board/eir.cfg]
Здесь файл board/eir.cfg дополнительно подключает конфигурацию CPU командой:
source[find target/at91sam7se512.cfg]
Пакет OpenOCD предоставляет некоторое количество готовых скриптов конфигурации, которые можно использовать для Вашей конкретной конфигурации железа. Мы также обсудим принципы организации этих скриптов.
Выделение конфигурации адаптера. Очевидно, что имеет определенный смысл поместить конфигурацию, относящуюся только к адаптеру JTAG, в отдельный конфигурационный файл. Такой принцип организации позволит использовать ту де самую целевую плату с разными адаптерами JTAG. Однако, здесь дьявол кроется в деталях. В качестве примера давайте взглянем на конфигурацию сброса. Мы определили:
reset_config srst_only
Это хорошо подходит при использовании Turtelizer 2 Rev-B с платкой EIR, потому что здесь не предоставляется сигнал nTRST для сброса TAP. Однако Turtelizer 2 Rev-C предоставляет такой сигнал, и то же самое верно для адаптера Ethernut 5. В следующей таблице показано, что конфигурация сброса не может быть четко назначена адаптеру или плате, потому что она зависит и от адаптера, и от платы.
Turtelizer 2.0B
Turtelizer 2.0C
EIR
srst_only
srst_only
Ethernut 5
srst_only
trst_and_srst
Руководство OpenOCD устанавливает правило, что reset_config (конфигурация сброса) относится к конфигурации платы. Это также не имеет большого смысла, потому что сброс чаще всего еще зависит и от CPU. В очень редких случаях плата может не иметь разведенного сигнала nTRST на коннектор JTAG, хотя этот сигнал доступен на корпусе CPU. Фактически в официальном дистрибутиве OpenOCD reset_config предоставлен примерно для 75 конфигураций плат, однако также, в противоречии к установленному правилу, в примерно 50 конфигурациях CPU. Это включает конфигурацию и для AT91SAM7SE, которая даже определена неправильно:
reset_config srst_only srst_pulls_trst ;# Это некорректно, не используйте!
Как уже объяснялось, nTRST не имеет значения для AT91SAM7SE, и мы можем безболезненно следовать правилу, назначив конфигурацию сброса для конфигурации платы. Так что в нашей конфигурации адаптера останутся следующие строки:
interface ft2232
ft2232_layout turtelizer2
ft2232_device_desc"Turtelizer JTAG/RS232 Adapter"
ft2232_vid_pid0x04030xbdc8
Также обратите внимание, что в последней строке, где указаны VID и PID, в действительности не требуется. Когда используется больше одного адаптера Turtelizer, подключенных к одному PC, Вы должны создать отдельный конфигурационный файл для каждого из них, и дополнительно декларировать уникальный серийный номер для для каждого адаптера в каждом из этих файлов:
ft2232_serial< serial number >
Разделение конфигураций CPU и платы. Без вопросов, отделение друг от друга конфигураций, специфичных для CPU и платы, даст преимущество, потому что можно будет повторно использовать конфигурации CPU для других плат, которые основаны на том же самом CPU. И снова, некоторые элементы конфигурации не может быть четко выделена, куда её следует определить - для CPU или для платы.
Определенно обработчик события сброса (reset-init event handler) и все процедуры, которые оттуда вызываются, принадлежат конфигурации платы. Другие платы могут использовать:
• Другие частоты кварца (eir_init_clock). • Другую память SDRAM, либо SDRAM может вообще отсутствовать (eir_init_sdram). • Другие выводы шины памяти для GPIO (eir_init_membus).
Как рассматривалось ранее, мы будем также назначать конфигурацию сброса в конфигурации платы. Вот файл результата (eir.cfg):
# Минимальное время цикла ICE равно 102 нс (частота 9800 кГц)adapter_khz9800arm7_9 dcc_downloads enable
arm7_9 fast_memory_access enable
eir_init_membuseir_init_sdram
}
# Инициализация тактов EIR.
#
# Плата использует кварц 18.432 МГц.
# CPU запускается на частоте 48 МГц.
#
proc eir_init_clock {}{# Разрешение основного генератора.## Время запуска (start-up time) 6 x 8 медленных тактов.#mww0xfffffc200x00000601;# CKGR_MORsleep2
# Выбор тактирования от частоты PLL, поделенной на 2## 96 МГц / 2 = 48 МГц#mww0xfffffc300x00000007;# PMC_MCKRsleep1
# Доступ к flash настраивается с задержкой 1 wait state# для чтения, и 2 wait state для записи.# За 1 мкс получится 48 тактов главной частоты.mww0xffffff600x00480100;# MC_FMR
}
# Инициализация внешней шины памяти (external memory bus).
#
proc eir_init_membus {}{# Разрешение шины адреса (A0, A2-A11, A13-A17) на порте PIO Bmww0xfffff6740x0003effd;# PIOB_BSRmww0xfffff6040x0003effd;# PIOB_PDR
# Разрешение 16-битной шины данных на порте PIO Cmww0xfffff8700x0000ffff;# PIOC_ASRmww0xfffff8040x0000ffff;# PIOC_PDR
}
# Инициализация SDRAM платы EIR.
#
# Платка EIR использует Samsung K4S511632D-UC75 SDRAM:
# Организация: 32M x 16
# 8k строк, 1k столбцов
# 20 нс row precharge time (время предзаряда строки)
# 45 нс минимум и 100 мкс максимум row active time
#
# Длительность периода MCK равна 20 нс при работе на 48 МГц.
#
proc eir_init_sdram {}{# Разрешить управление SDRAM через порт PIO A#mww0xfffff4740x3f800000;# PIOA_BSRmww0xfffff4040x3f800000;# PIOA_PDR
# Выдача команды 16-бит SDRAM: Set mode register#mww0xffffffb00x00000013;# SDRAMC_MRmww0x200000140xcafedede
# Установка счетчика обновления (refresh rate count) ???#mww0xffffffb40x00000013;# SDRAMC_TR
# Выдача команды 16-бит SDRAM: Normal mode#mww0xffffffb00x00000010;# SDRAMC_MRmww0x200000000x00000180
}
Конфигурация TAP, цели отладки (debug target) и внутренней памяти flash полностью относится к CPU.
Все же определение рабочей области составляет проблему. При использовании внутренней памяти RAM мы можем назначить это для конфигурации CPU. Однако это зависит и от firmware, которое работает на плате, сколько RAM у нас есть в наличии, и какую область RAM мы можем использовать - в младших адресах или в старших.
Хотя определение рабочей области не является обязательным, это важно для повышения удобства использования, потому что значительно повышает передачу данных через JTAG. Как вариант можно определить конфигурацию рабочей области в конфигурации CPU. Если есть конфликт с работой firmware, то можно поменять эту конфигурацию в пользовательском конфигурационном файле.
В результате получится следующая конфигурация CPU для AT91SAM7SE512:
jtag newtap sam7se512 cpu -irlen 4-expected-id 0x3f0f0f0f
flash bank sam7se512.flash.0 at91sam7 0000 sam7se512.cpu 000000018432
flash bank sam7se512.flash.1 at91sam7 0000 sam7se512.cpu 100000018432
Определение переменных Tcl. В главе 4 этого руководства было указано, что язык скриптов в конфигурационных файлах позволяет нам определять процедуры для конфигураций, основанных на событиях. Еще одно очевидное преимущество языка скриптов - определение переменных. Их использование не требуется, поэтому пока что переменные мы не применяли.
Однако переменные позволяют упростить поддержку кода скриптов. Например, во многих местах мы обращаемся к имени чипа sam7se512. Если поместить это имя в переменную, которая используется по всей конфигурации вместо литерального имени, то изменение этого имени значительно упрощается. Вы можете спросить: почему кому-то это может понадобиться? В действительности причин несколько.
Самая очевидная причина модификации имени чипа это плата, которая может содержать два чипа AT91SAM7SE512. Если мы поместим в наш конфигурационный файл платы:
... то переменная _CHIPNAME по умолчанию будет sam7se512. Использование _CHIPNAME вместо sam7se512 в оставшейся части конфигурации позволит нам использовать один и тот же конфигурационный файл для обоих CPU на плате:
set CHIPNAME sam7se512.0
source[find target/at91sam7se512.cfg]
set CHIPNAME sam7se512.1
source[find target/at91sam7se512.cfg]
Здесь CHIPNAME и _CHIPNAME это разные имена переменных. Если Вы хотите обратиться к содержимому переменной, то добавьте спереди знак доллара. Например, $CHIPNAME будет заменен содержимым переменной CHIPNAME.
Почти все существующие скрипты используют своего рода стандартный набор переменных. Некоторые переменные также объясняются в руководстве OpenOCD. Так что хорошей идеей будет использовать это соглашение, даже если Вам не нужны переменные, чтобы создать и запустить свою локальную конфигурацию.
Здесь мы представим окончательный файл конфигурации CPU. Вы должны дать ему имя at91sam7se512.cfg, и сохранить его в подкаталог target, находящийся в каталоге установки OpenOCD, когда она работает на Windows, или в каталоге /usr/share/openocd/scripts на большинстве Linux PC. Может оказаться, что такой файл уже существует, тогда сначала создайте для него резервную копию. В любом случае, если Вы сравните существующий файл с тем, чтобы создали в этом руководстве, то не должно быть больших отличий. Если отличия будут, то можете решить, какой из файлов будет лучше.
# ATMEL sam7se512
# Пример конфигурации процессора для платы Elektor Internet Radio (EIR)
flash bank $_FLASHNAME.0 at91sam7 0000$_TARGETNAME000000018432
flash bank $_FLASHNAME.1 at91sam7 0000$_TARGETNAME100000018432
И ниже показан окончательный файл конфигурации платы для Elektor Internet Radio. Ему следует дать имя eir.cfg, и сохранить в подкаталог. Опять-таки, если такой файл там уже существует, сделайте его резервную копию.
# Разрешение пользовательского сбросаmww0xfffffd080xa5000001;# RSTC_MR
}
# Разрешить тактирование процессора EIR.
#
# Плата использует кварцевый резонатор на 18.432 МГц.
# CPU запускается на частоте 48 МГц.
#
proc eir_init_clock {}{# Разрешить работу главного генератора.## Время запуска (start-up time) 6 x 8 медленных такта.#mww0xfffffc200x00000601;# CKGR_MORsleep2
# Выбор тактирования от частоты PLL, поделенной на 2## 96 МГц / 2 = 48 МГц#mww0xfffffc300x00000007;# PMC_MCKRsleep1
# Доступ к flash настраивается с задержкой 1 wait state# для чтения, и 2 wait state для записи.# За 1 мкс получится 48 тактов главной частоты.mww0xffffff600x00480100;# MC_FMR
}
# Инициализация SDRAM, установленной на плате EIR.
#
# Плата EIR использует Samsung K4S511632D-UC75 SDRAM:
# Организация: 32M x 16
# 8k строк, 1k столбцов
# 20 нс row precharge time (время предзаряда строки)
# 45 нс минимум и 100 мкс максимум row active time
#
# Длительность периода MCK равна 20 нс при работе на 48 МГц.
#
proc eir_init_sdram {}{# Разрешить управление SDRAM через порт PIO A#mww0xfffff4740x3f800000;# PIOA_BSRmww0xfffff4040x3f800000;# PIOA_PDR
В последней главе рассмотрим несколько примеров использования. Хотя примеры фокусируются на приложениях Nut/OS, возможно они окажутся для Вас полезными.
[9. Интеграция с Nut/OS]
На операционной системе Linux пакет OpenOCD просто устанавливается из пакета исходного кода. Поскольку это требует некоторых инструментов из мира Unix, которые полагаются на определенные возможности нижележащей операционной системы, сборка OpenOCD на операционной системе Windows весьма непроста, и скорее всего многие Ваши попытки сборки окончатся неудачей, если вообще что-то получится.
Для обычного использования в среде Windows рекомендуется готовая сборка, например от Freddie Chopin, доступная на сайте www.freddiechopin.info. Если Вы хотите использовать EIR с Nut/OS, то пакет поддержки Turtelizer скорее всего окажется самым лучшим выбором. Инсталляция определит наличие установленной Nut/OS, и поместит исполняемый код OpenOCD в каталог nut\tools\win32, который следует добавить в переменную окружения PATH [13]. Скрипты конфигурации сохранены в каталоге nut\tools\turtelizer2, для которых есть готовые скрипты makefile, позволяющие выполнять сборку и выгрузку/прошивку Вашего двоичного кода приложения (все в одном) без всяких проблем.
Командная строка OpenOCD. В этом руководстве мы просто запускали OpenOCD без указания каких-либо опций в её командной строке. Вся требуемая конфигурация либо явно находится в локальном файле openocd.cfg, либо используется подключение внешних конфигурационных файлов.
Это станет неудобным, если Вы работаете с несколькими разными проектами, потому что каждый раз понадобится создавать локальный файл openocd.cfg, и с течением времени некоторые из этих созданных файлов станут устаревшими, когда происходит обновление OpenOCD или Nut/OS, и их потребуется корректировать/обновлять вручную. Если же Вы будете полагаться на готовые файлы конфигурации, поставляемые вместе с OpenOCD или Nut/OS, этой проблемы можно избежать. Даже если эти конфигурационные файлы не будут соответствовать, Вам потребуется сделать коррекцию только в одном месте, чтобы снова заставить работать все Ваши проекты.
Если нет локального конфигурационного файла, нам нужно указать OpenOCD, где их можно найти. Это можно сделать таким же способом, как и в нашей локальной конфигурации. Если точнее - вместо чтения команд из файла Вы можете предоставить команды в командной строки с помощью опции -c. Вместо того, чтобы использовать openocd.cfg со строками:
Nut/OS Makeburn. Nut/OS предоставляет несколько скриптов Makefile, которые автоматически запускают OpenOCD с правильными опциями, когда пользователь запрашивает собрать прошивку для target. Например, если ввести команду:
make burn
... в директории приложении примера, сконфигурированного для сборки приложений во внешней RAM, то будет выполнена сборка двоичного образа и будет вызвана OpenOCD со следующими опциями:
Опция
Функция опции
-s ../../nut/tools/turtelizer2
Задает для OpenOCD путь поиска файлов, которые находятся в дереве каталогов Nut/OS.
-c "source [find interface/turtelizer2.cfg]"
Загружает конфигурацию программатора JTAG, которая была выбрана у утилите Nut/OS Configurator.
-c "source [find board/eir.cfg]"
Загружает конфигурацию платы (board) для устройства EIR.
-c init
Переключает OpenOCD из configuration stage в run stage.
-c "reset init"
Вызывает обработчик события сброса (reset init handler), чтобы инициализировать аппаратуру.
-c "load_image firmware.bin 0x20000000"
Передает образ программного обеспечения (firmware) в память SDRAM, смонтированную на плате EIR.
-c "verify_image webradio.bin 0x20000000"
Проверяет образ firmware на соответствие содержимому SDRAM. Это не обязательное действие, но оно достаточно быстрое, и добавляет безопасности.
-c "resume 0x20000000"
Запускает выгруженное firmware.
-c shutdown
Завершает работу OpenOCD, так что командная строка, откуда она была запущена, освобождается для ввода следующей команды.
В результате Ваше собранное приложение начнет работать в целевой системе. Еще более интересная функция - если Вы сконфигурируете Nut/OS собирать приложения, которые должны запускаться из памяти flash, вместо этого двоичный код будет запрограммирован в память flash целевой системы. Интересно, как это может работать?
Когда осуществляется запрос на сборку target burn, скрипты Makefile Nut/OS запустят файл Makeburn с соответствующим расширением. Для OpenOCD это nut/app/Makeburn.arm-oocd. Среди всего прочего этот файл содержит следующий фрагмент:
Эта часть выполняется, когда выполняется сборка приложения для EIR, и тогда PLATFORM устанавливается в значение ELEKTOR_IR утилитой Nut/OS Configurator. Теперь определяется базовое имя скрипта линкера. Если он сконфигурировано как at91sam7se512_xram, то BURNCMD будет загружен с опциями, которые мы перечислили в таблице выше. Если это сконфигурировано как at91sam7se512_rom, то BURNCMD будет загружен с опциями командной строки, требующими программирования двоичного образа программы в память flash.