Программирование ARM Настройка OpenOCD для AT91SAM7SE Fri, March 29 2024  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

Настройка OpenOCD для AT91SAM7SE Печать
Добавил(а) microsin   

В этом руководстве (перевод [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 не устанавливать драйвер автоматически:

OpenOCD FT Driver step1 OpenOCD FT Driver step2

Затем удалите драйвер 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], но потребуется небольшая правка конфигурационных файлов.

Все руководство поделено на 9 частей:

1. Настройка аппаратуры.
2. Конфигурирование адаптера JTAG.
3. Конфигурирование CPU.
4. Конфигурирование тактирования CPU.
5. Использование SDRAM
6. Прошивка целевого процессора.
7. Оптимизация конфигураций OpenOCD.
8. Принципы организации скриптов OpenOCD.
9. Интеграция с Nut/OS.

[1. Настройка аппаратуры]

Подключите Ваш адаптер JTAG к целевой плате через 20-выводный коннектор на плоском кабеле, и кабелем USB к компьютеру PC. Если цоколевка коннектора JTAG адаптера соответствует коннектору JTAG платы (обычно это так, если используется стандартный 20-выводный коннектор JTAG). Если у Вас адаптер Turtelizer 2 подключается к плате Elektor Internet Radio, также понадобится дополнительный переходник с плоским кабелем (см. рисунок).

EIR JTAG TURT

Если у Вас самодельный адаптер, то нужно правильно подключить выводы адаптера к контактам коннектора 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 выведет список известных для неё интерфейсов, примерно так:

The following debug interfaces are available:
1: parport
2: ft2232
3: ftdi
4: usb_blaster
5: amt_jtagaccel
6: gw16012
7: presto
8: usbprog
9: jlink
10: vsllink
11: rlink
12: ulink
13: arm-jtag-ew
14: stlink

Если Ваш адаптер в этом списке отсутствует (не поддерживается), то запросите у производителя Вашего адаптера 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_rclk 3000

Эта команда установит тактовую частоту JTAG на 3 МГц, и автоматически подстроит её к низкой тактовой частоте, если это необходимо.

Есть и плохая новость. В первую очередь Turtelizer не поддерживает адаптивное тактирование, потому что в нем используется чип FT2232D, не поддерживающий эту функцию. Имеется множество адаптеров на основе микросхемы FT2232H (в том числе и платка [6]), которые поддерживают адаптивное тактирование. Но все-таки они не могут подстраивать свою частоту в полном диапазоне. Все еще требуется "вручную" настроить начальную частоту. И вторым тормозом является AT91SAM7SE CPU, который не поддерживает никакое адаптивное тактирование.

Мы решим эту проблему путем установки низкой начальной частоты 8 кГц. Впоследствии мы будем использовать OpenOCD, чтобы запустить PLL, завести CPU на полной скорости и довести скорость работы Turtelizer JTAG до максимума. Добавьте в openocd.cfg следующую строку:

adapter_khz 8

Для ясности, у нас получится следующее содержимое файла openocd.cfg:

interface ft2232
ft2232_layout turtelizer2
ft2232_device_desc "Turtelizer JTAG/RS232 Adapter"
adapter_khz 8

Если Вы используете пакет с поддержкой 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.

Для AT91SAM7SE512 мы должны использовать:

target create sam7se512.cpu arm7tdmi -chain-position sam7se512.cpu

После добавления этой строки в файл 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_khz 8jtag newtap sam7se512 cpu -irlen 4 -expected-id 0x3f0f0f0f
target create sam7se512.cpu arm7tdmi -chain-position sam7se512.cpu

Напомним еще раз, если используете 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:

mww 0x200000 0x12345678

В большинстве случаев это немедленно закончится неудачей, потому что CPU работает, и он занял шину памяти. Чтобы остановить CPU, введите команду:

halt

Теперь попробуем снова выполнить запись в память. Можно использовать клавиши курсора клавиатуры вверх/вниз для прокрутки истории ранее введенных команд. Чтобы прочитать данные по тому же самому адресу, используйте команду mdw (аббревиатура от memory display word), за которой укажите адрес для чтения:

mdw 0x200000

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

OK, теперь нужно открыть даташит на процессор, изучить его, и записать нужные значения в нужные регистры, чтобы правильно запустить PLL и запустить CPU на нужной скорости.

Настройка PLL. Из главы 29.7 даташита AT91SAM7SE можно узнать, что сначала нам надо разрешить главный генератор записью 0x701 в регистр CKGR_MOR. Время запуска (startup time) устанавливается на 56 периодов медленных тактов (slow clock cycles).

mww 0xfffffc20 0x00000701

Далее мы установим делитель ФАПЧ (PLL divider) и умножитель ФАПЧ (PLL multiplier), чтобы из частоты кварца получилась частота 96 МГц. Мы будем настраивать делитель на 14 и умножитель на 72. Из частоты кварца 18.432 МГц мы получим частоту 18.432MHz * (72 + 1) / 14 = 96.11 МГц. Время запуска (startup time) должно быть 28 медленных тактов. Это устанавливается записью в регистр CKGR_PLLR.

mww 0xfffffc2C 0x00481c0e

Теперь записью в регистр PMC_MCKR мы выберем деление частоты PLL на 2 для получения главной частоты тактов.

mww 0xfffffc30 0x00000007

После выполнения этих действий наш CPU будет работать на частоте 48 МГц.

В завершении мы установим регистр MC_FMR для настройки 1 wait state на чтение 2 wait state на запись при доступе к внутренней памяти flash (количество тактов ожидания). Это не требуется, пока не осуществляется доступ к памяти flash (если код и данные размещены только в SRAM). Но мы это сделаем, потому что требуемое количество тактов ожидания зависит от настройки тактовой частоты.

mww 0xffffff60 0x00480100

Теперь следует поместить всю последовательность этих действий в процедуру 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).
   #
   mww 0xfffffc20 0x00000701       ;# CKGR_MOR
   sleep 2
 
   # Конфигурирование PLL (ФАПЧ).
   #
   # 18.432 МГц * (72 + 1) / 14 = 96 МГц
   #
   # Делитель на 14 (0x0e)
   # Start-up time 28 (0x1c) медленных тактов
   # Умножитель на 72 (0x48)
   #
   mww 0xfffffc2C 0x00481c0e       ;# CKGR_PLLR
   sleep 1
 
   # Выбор частоты тактов от PLL, поделенной на 2
   #
   # 96 МГц / 2 = 48 МГц
   #
   mww 0xfffffc30 0x00000007       ;# PMC_MCKR
   sleep 1
 
   # 1 такт ожидания при чтении flash,
   # 2 такта ожидания для записи flash
   # В одной микросекунде у нас получится 48 тактов
   mww 0xffffff60 0x00480100       ;# 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 для нашей цели отладки:

sam7se512.cpu configure -event reset-init { eir_init }

Вы можете добавить в свой файл 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_khz 8
jtag newtap sam7se512 cpu -irlen 4 -expected-id 0x3f0f0f0f
target create sam7se512.cpu arm7tdmi -chain-position sam7se512.cpu
reset_config srst_only
 
sam7se512.cpu configure -event reset-init { eir_init }
 
# Инициализация платы 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).
   #
   mww 0xfffffc20 0x00000601       ;# CKGR_MOR
   sleep 2
 
   # Конфигурирование PLL (ФАПЧ).
   #
   # 18.432 МГц * (72 + 1) / 14 = 96 МГц
   #
   # Делитель на 14 (0x0e)
   # Start-up time 28 (0x1c) медленных тактов
   # Умножитель на 72 (0x48)
   #
   mww 0xfffffc2C 0x00481c0e       ;# CKGR_PLLR
   sleep 1
 
   # Выбор частоты тактов от PLL, поделенной на 2
   #
   # 96 МГц / 2 = 48 МГц
   #
   mww 0xfffffc30 0x00000007       ;# PMC_MCKR
   sleep 1
 
   # 1 такт ожидания при чтении flash,
   # 2 такта ожидания для записи flash
   # В одной микросекунде у нас получится 48 тактов
   mww 0xffffff60 0x00480100       ;# 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 B
   mww 0xfffff674 0x0003effd ;# PIOB_BSR
   mww 0xfffff604 0x0003effd ;# PIOB_PDR
   # Разрешить 16-битную шину данных на порте PIO C
   mww 0xfffff870 0x0000ffff ;# PIOC_ASR
   mww 0xfffff804 0x0000ffff ;# 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
   #
   mww 0xfffff474 0x3f800000 ;# PIOA_BSR
   mww 0xfffff404 0x3f800000 ;# PIOA_PDR
 
   # Разрешить сигнал выборки (SDRAM chip select)
   #
   mww 0xffffff80 0x00000002 ;# EBI_CSA
 
   # Установка характеристик SDRAM в регистре конфигурации.
   # На 48 МГц 2 такт занимает около 21 нс.
   #
   # 0x00000003 NC: количество бит столбца
   # 0x00000002 10 бит, 1k столбцов
   #
   # 0x0000000C NR: количество бит строки
   # 0x00000008 13 бит, 8k строк
   #
   # 0x00000010 NB: количество банков
   # 0x00000010 4 банка
   #
   # 0x00000060 CAS: CAS latency (задеркжа выборки столбца)
   # 0x00000040 2 такта
   #
   # 0x00000780 TWR: время задержки восстановления записи
   # 0x00000100 2 такта
   #
   # 0x00007800 TRC: задержка цикла строки
   # 0x00002000 4 такта
   #
   # 0x00078000 TRP: время задержки precharge строки
   # 0x00020000 4 такта
   #
   # 0x00780000 TRCD: задержка от строки к столбцу
   # 0x00100000 2 такта
   #
   # 0x07800000 TRAS: задержка между состояниями active и precharge
   # 0x01800000 3 такта
   #
   # 0x78000000 TXSR: задержка между выходом из self refresh и состоянием active
   # 0x20000000 4 такта
   #
   mww 0xffffffb8 0x2192215a ;# SDRAMC_CR
   sleep 10
 
   # Выдача команды 16 бит SDRAM: NOP
   #
   mww 0xffffffb0 0x00000011 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
 
   # Выдача команды 16 бит SDRAM: Precharge all
   #
   mww 0xffffffb0 0x00000012 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
 
   # Выдача 8 циклов auto-refresh
   #
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
 
   # Выдача команды 16 бит SDRAM: Set mode register
   #
   mww 0xffffffb0 0x00000013 ;# SDRAMC_MR
   mww 0x20000014 0xcafedede
 
   # Установка счетчика обновления (refresh rate count) ???
   #
   mww 0xffffffb4 0x00000013 ;# SDRAMC_TR
 
   # Выдача команды 16 бит SDRAM: Normal mode
   #
   mww 0xffffffb0 0x00000010 ;# SDRAMC_MR
   mww 0x20000000 0x00000180
}

Эта процедура требует, чтобы главная частота процессора была 48 МГц, и была разрешена шина памяти. Это должно быть учтено путем добавления вызовов соответствующих процедур в нашем обработчике сброса:

# Инициализация платы Elektor Internet Radio (EIR).
#
proc eir_init {} {
   eir_init_clock
   eir_init_membus
   eir_init_sdram
}

Как только Вы добавили еще 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 0 0 0 0 sam7se512.cpu 0 0 0 0 0 0 0 18432
flash bank sam7se512.flash.1 at91sam7 0 0 0 0 sam7se512.cpu 1 0 0 0 0 0 0 18432

После добавления этих 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 в качестве рабочей области, мы сделали определение:

sam7se512.cpu configure -work-area-phys 0x00206000 -work-area-size 0x4000

Эту строку Вы также можете добавить в файл 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_khz 9800
   arm7_9 dcc_downloads enable
   arm7_9 fast_memory_access enable
 
   eir_init_membus
   eir_init_sdram
}

В результате у нас получится вот такой полный конфигурационный файл openocd.cfg, предназначенный для нашей платы EIR:

interface turtle
ft2232_layout turtelizer2
ft2232_device_desc "Turtelizer JTAG/RS232 Adapter"
 
reset_config srst_only
adapter_khz 8
 
jtag newtap sam7se512 cpu -irlen 4 -expected-id 0x3f0f0f0f
target create sam7se512.cpu arm7tdmi -chain-position sam7se512.cpu
sam7se512.cpu configure -work-area-phys 0x00206000 -work-area-size 0x4000
 
flash bank sam7se512.flash.0 at91sam7 0 0 0 0 sam7se512.cpu 0 0 0 0 0 0 0 18432
flash bank sam7se512.flash.1 at91sam7 0 0 0 0 sam7se512.cpu 1 0 0 0 0 0 0 18432
 
sam7se512.cpu configure -event reset-init { eir_init }
 
# Инициализация платки EIR.
#
proc eir_init {} {
   eir_init_clock
 
   # Минимальное время такта ICE составляет 102 нс (частота 9800 кГц)
   adapter_khz 9800
   arm7_9 dcc_downloads enable
   arm7_9 fast_memory_access enable
 
   eir_init_membus
   eir_init_sdram
}
 
# Инициализация тактов EIR.
#
# Платка EIR использует кварц 18.432 МГц.
# CPU запускается на частоте 48 МГц.
#
proc eir_init_clock {} {
   # Разрешение работы главного генератора.
   #
   # Время запуска (Start-up time) составляет 6 x 8 медленных такта.
   #
   mww 0xfffffc20 0x00000601       ;# CKGR_MOR
   sleep 2
 
   # Конфигурация PLL (ФАПЧ).
   #
   # 18.432 МГц * (72 + 1) / 14 = 96 МГц
   #
   # Делитель 14 (0x0e)
   # Время запуска 28 (0x1c) медленных такта
   # Умножитель 72 (0x48)
   #
   mww 0xfffffc2C 0x00481c0e       ;# CKGR_PLLR
   sleep 1
 
   # Выбор частоты тактирования от PLL, поделенной на 2
   #
   # 96 МГц / 2 = 48 МГц
   #
   mww 0xfffffc30 0x00000007       ;# PMC_MCKR
   sleep 1
 
   # Доступ к flash настраивается с задержкой 1 wait state
   # для чтения, и 2 wait state для записи.
   # За 1 мкс получится 48 тактов главной частоты.
   mww 0xffffff60 0x00480100       ;# MC_FMR
}
 
# Инициализация внешней шины памяти (external memory bus).
#
proc eir_init_membus {} {
   # Разрешить шину адреса (A0, A2-A11, A13-A17) на порте PIO B
   mww 0xfffff674 0x0003effd ;# PIOB_BSR
   mww 0xfffff604 0x0003effd ;# PIOB_PDR
 
   # Разрешить 16-битную шину данных на порте PIO C
   mww 0xfffff870 0x0000ffff ;# PIOC_ASR
   mww 0xfffff804 0x0000ffff ;# 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
   #
   mww 0xfffff474 0x3f800000 ;# PIOA_BSR
   mww 0xfffff404 0x3f800000 ;# PIOA_PDR
 
   # Разрешить сигнал выборки (SDRAM chip select)
   #
   mww 0xffffff80 0x00000002 ;# EBI_CSA
 
   # Установка характеристик SDRAM в регистре конфигурации.
   # На 48 МГц 1 такт занимает около 21 нс.
   #
   # 0x00000003 NC: количество бит столбца
   # 0x00000002 10 бит, 1k столбцов
   #
   # 0x0000000C NR: количество бит строки
   # 0x00000008 13 бит, 8k строк
   #
   # 0x00000010 NB: количество банков
   # 0x00000010 4 банка
   #
   # 0x00000060 CAS: CAS latency (задержка выборки столбца)
   # 0x00000040 2 такта
   #
   # 0x00000780 TWR: задержка восстановления записи
   # 0x00000100 2 такта
   #
   # 0x00007800 TRC: задержка цикла строки
   # 0x00002000 4 такта
   #
   # 0x00078000 TRP: задержка precharge строки
   # 0x00020000 4 такта
   #
   # 0x00780000 TRCD: задержка между строкой и столбцом
   # 0x00100000 2 такта
   #
   # 0x07800000 TRAS: задержка между active и precharge
   # 0x01800000 3 такта
   #
   # 0x78000000 TXSR: задержка между выходом из self refresh и active
   # 0x20000000 4 такта
   #
   mww 0xffffffb8 0x2192215a ;# SDRAMC_CR
   sleep 10
 
   # Выдача команды 16-бит SDRAM: NOP
   #
   mww 0xffffffb0 0x00000011 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
 
   # Выдача команды 16-бит SDRAM: Precharge all
   #
   mww 0xffffffb0 0x00000012 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
 
   # Выдача 8 циклов автообновления (auto-refresh)
   #
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
 
   # Выдача команды 16-бит SDRAM: Set mode register
   #
   mww 0xffffffb0 0x00000013 ;# SDRAMC_MR
   mww 0x20000014 0xcafedede
 
   # Установка счетчика обновления (refresh rate count) ???
   #
   mww 0xffffffb4 0x00000013 ;# SDRAMC_TR
 
   # Выдача команды 16-бит SDRAM: Normal mode
   #
   mww 0xffffffb0 0x00000010 ;# SDRAMC_MR
   mww 0x20000000 0x00000180
}

[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.0BTurtelizer 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_pid 0x0403 0xbdc8

Также обратите внимание, что в последней строке, где указаны 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):

reset_config srst_only
adapter_khz 8
 
sam7se512.cpu configure -event reset-init { eir_init }
 
# Инициализация платки EIR.
#
proc eir_init {} {
   eir_init_clock
 
   # Минимальное время цикла ICE равно 102 нс (частота 9800 кГц)
   adapter_khz 9800
   arm7_9 dcc_downloads enable
   arm7_9 fast_memory_access enable
 
   eir_init_membus
   eir_init_sdram
}
 
# Инициализация тактов EIR.
#
# Плата использует кварц 18.432 МГц.
# CPU запускается на частоте 48 МГц.
#
proc eir_init_clock {} {
   # Разрешение основного генератора.
   #
   # Время запуска (start-up time) 6 x 8 медленных тактов.
   #
   mww 0xfffffc20 0x00000601       ;# CKGR_MOR
   sleep 2
 
   # Конфигурация PLL.
   #
   # 18.432 МГц * (72 + 1) / 14 = 96 МГц
   #
   # Делитель 14 (0x0e)
   # Start-up time 28 (0x1c) медленных такта
   # Умножитель 72 (0x48)
   #
   mww 0xfffffc2C 0x00481c0e       ;# CKGR_PLLR
   sleep 1
 
   # Выбор тактирования от частоты PLL, поделенной на 2
   #
   # 96 МГц / 2 = 48 МГц
   #
   mww 0xfffffc30 0x00000007       ;# PMC_MCKR
   sleep 1
 
   # Доступ к flash настраивается с задержкой 1 wait state
   # для чтения, и 2 wait state для записи.
   # За 1 мкс получится 48 тактов главной частоты.
   mww 0xffffff60 0x00480100       ;# MC_FMR
}
 
# Инициализация внешней шины памяти (external memory bus).
#
proc eir_init_membus {} {
   # Разрешение шины адреса (A0, A2-A11, A13-A17) на порте PIO B
   mww 0xfffff674 0x0003effd ;# PIOB_BSR
   mww 0xfffff604 0x0003effd ;# PIOB_PDR
 
   # Разрешение 16-битной шины данных на порте PIO C
   mww 0xfffff870 0x0000ffff ;# PIOC_ASR
   mww 0xfffff804 0x0000ffff ;# 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
   #
   mww 0xfffff474 0x3f800000 ;# PIOA_BSR
   mww 0xfffff404 0x3f800000 ;# PIOA_PDR
 
   # Разрешить сигнал выборки (SDRAM chip select)
   #
   mww 0xffffff80 0x00000002 ;# EBI_CSA
 
   # Установка характеристик SDRAM в регистре конфигурации.
   # На частоте 48 МГц 1 такт занимает около 21 нс.
   #
   # 0x00000003 NC: количество бит столбцов
   # 0x00000002 10 бит, 1k столбцов
   #
   # 0x0000000C NR: количество бит строк
   # 0x00000008 13 бит, 8k строк
   #
   # 0x00000010 NB: количество банков
   # 0x00000010 4 банка
   #
   # 0x00000060 CAS: CAS latency (задержка сигнала выборки столбца)
   # 0x00000040 2 такта
   #
   # 0x00000780 TWR: задержка восстановления записи
   # 0x00000100 2 такта
   #
   # 0x00007800 TRC: задержка цикла строки
   # 0x00002000 4 такта
   #
   # 0x00078000 TRP: задержка precharge строки
   # 0x00020000 4 такта
   #
   # 0x00780000 TRCD: задержка от строки к столбцу
   # 0x00100000 2 такта
   #
   # 0x07800000 TRAS: задержка между active и precharge
   # 0x01800000 3 такта
   #
   # 0x78000000 TXSR: задержка между выходом из self refresh и active
   # 0x20000000 4 такта
   #
   mww 0xffffffb8 0x2192215a ;# SDRAMC_CR
   sleep 10
 
   # Выдача команды 16-бит SDRAM: NOP
   #
   mww 0xffffffb0 0x00000011 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
 
   # Выдача команды 16-бит SDRAM: Precharge all
   #
   mww 0xffffffb0 0x00000012 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
 
   # Выдача 8 циклов автообновления (auto-refresh)
   #
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
 
   # Выдача команды 16-бит SDRAM: Set mode register
   #
   mww 0xffffffb0 0x00000013 ;# SDRAMC_MR
   mww 0x20000014 0xcafedede
 
   # Установка счетчика обновления (refresh rate count) ???
   #
   mww 0xffffffb4 0x00000013 ;# SDRAMC_TR
 
   # Выдача команды 16-бит SDRAM: Normal mode
   #
   mww 0xffffffb0 0x00000010 ;# SDRAMC_MR
   mww 0x20000000 0x00000180
}

Конфигурация TAP, цели отладки (debug target) и внутренней памяти flash полностью относится к CPU.

Все же определение рабочей области составляет проблему. При использовании внутренней памяти RAM мы можем назначить это для конфигурации CPU. Однако это зависит и от firmware, которое работает на плате, сколько RAM у нас есть в наличии, и какую область RAM мы можем использовать - в младших адресах или в старших.

Хотя определение рабочей области не является обязательным, это важно для повышения удобства использования, потому что значительно повышает передачу данных через JTAG. Как вариант можно определить конфигурацию рабочей области в конфигурации CPU. Если есть конфликт с работой firmware, то можно поменять эту конфигурацию в пользовательском конфигурационном файле.

В результате получится следующая конфигурация CPU для AT91SAM7SE512:

jtag newtap sam7se512 cpu -irlen 4 -expected-id 0x3f0f0f0f
target create sam7se512.cpu arm7tdmi -chain-position sam7se512.cpu
sam7se512.cpu configure -work-area-phys 0x00206000 -work-area-size 0x4000
 
flash bank sam7se512.flash.0 at91sam7 0 0 0 0 sam7se512.cpu 0 0 0 0 0 0 0 18432
flash bank sam7se512.flash.1 at91sam7 0 0 0 0 sam7se512.cpu 1 0 0 0 0 0 0 18432

Определение переменных Tcl. В главе 4 этого руководства было указано, что язык скриптов в конфигурационных файлах позволяет нам определять процедуры для конфигураций, основанных на событиях. Еще одно очевидное преимущество языка скриптов - определение переменных. Их использование не требуется, поэтому пока что переменные мы не применяли.

Однако переменные позволяют упростить поддержку кода скриптов. Например, во многих местах мы обращаемся к имени чипа sam7se512. Если поместить это имя в переменную, которая используется по всей конфигурации вместо литерального имени, то изменение этого имени значительно упрощается. Вы можете спросить: почему кому-то это может понадобиться? В действительности причин несколько.

Самая очевидная причина модификации имени чипа это плата, которая может содержать два чипа AT91SAM7SE512. Если мы поместим в наш конфигурационный файл платы:

if { [info exists CHIPNAME] } {
   set _CHIPNAME $CHIPNAME
} else {
   set _CHIPNAME sam7se512
}

... то переменная _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)
# http://www.ethernut.de/en/hardware/eir/index.html
 
if { [info exists CHIPNAME] } {
   set _CHIPNAME $CHIPNAME
} else {
   set _CHIPNAME sam7se512
}
 
if { [info exists ENDIAN] }
 {
   set _ENDIAN $ENDIAN
} else {
   set _ENDIAN little
}
 
if { [info exists CPUTAPID] } {
   set _CPUTAPID $CPUTAPID
} else {
   set _CPUTAPID 0x3f0f0f0f
}
 
# JTAG Test Access Point (TAP)
jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID
 
# JTAG Debug Target (цель отладки)
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME arm7tdmi -endian $_ENDIAN -chain-position $_TARGETNAME -variant arm7tdmi
 
# Рабочая область OpenOCD
$_TARGETNAME configure -work-area-phys 0x00200000 -work-area-size 0x4000 -work-area-backup 0
 
# Банки памяти Flash
set _FLASHNAME $_CHIPNAME.flash
flash bank $_FLASHNAME.0 at91sam7 0 0 0 0 $_TARGETNAME 0 0 0 0 0 0 0 18432
flash bank $_FLASHNAME.1 at91sam7 0 0 0 0 $_TARGETNAME 1 0 0 0 0 0 0 18432

И ниже показан окончательный файл конфигурации платы для Elektor Internet Radio. Ему следует дать имя eir.cfg, и сохранить в подкаталог. Опять-таки, если такой файл там уже существует, сделайте его резервную копию.

# Плата Elector Internet Radio (EIR)
# http://www.ethernut.de/en/hardware/eir/
 
source [find target/at91sam7se512.cfg]
 
# Target events (события целевого процессора)
#
$_TARGETNAME configure -event reset-init { eir_init }
 
adapter_khz 200
 
# Инициализация платы EIR.
#
proc eir_init {} {
   eir_init_reset
   eir_init_clock
 
   # Минимальный период ICE составит 102 нс (9800 кГц)
   adapter_khz 5000
   arm7_9 dcc_downloads enable       ;# Разрешить ускоренные загрузки через DCC
   arm7_9 fast_memory_access enable
   #jtag_khz 9800
 
   eir_init_sdram
#   flash probe 0
}
 
# Инициализация логики сброса EIR.
#
proc eir_init_reset {} {
   # Запрет сторожевого таймера (watchdog)
   mww 0xfffffd44 0x00008000       ;# WDT_MR
 
   # Разрешение пользовательского сброса
   mww 0xfffffd08 0xa5000001       ;# RSTC_MR
}
 
# Разрешить тактирование процессора EIR.
#
# Плата использует кварцевый резонатор на 18.432 МГц.
# CPU запускается на частоте 48 МГц.
#
proc eir_init_clock {} {
   # Разрешить работу главного генератора.
   #
   # Время запуска (start-up time) 6 x 8 медленных такта.
   #
   mww 0xfffffc20 0x00000601       ;# CKGR_MOR
   sleep 2
 
   # Конфигурация PLL (ФАПЧ).
   #
   # 18.432 МГц * (72 + 1) / 14 = 96 МГц
   #
   # Делитель 14 (0x0e)
   # Start-up time of 28 (0x1c) slow clocks
   # Умножитель 72 (0x48)
   #
   mww 0xfffffc2C 0x00481c0e       ;# CKGR_PLLR
   sleep 1
 
   # Выбор тактирования от частоты PLL, поделенной на 2
   #
   # 96 МГц / 2 = 48 МГц
   #
   mww 0xfffffc30 0x00000007       ;# PMC_MCKR
   sleep 1
 
   # Доступ к flash настраивается с задержкой 1 wait state
   # для чтения, и 2 wait state для записи.
   # За 1 мкс получится 48 тактов главной частоты.
   mww 0xffffff60 0x00480100       ;# 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
   #
   mww 0xfffff474 0x3f800000 ;# PIOA_BSR
   mww 0xfffff404 0x3f800000 ;# PIOA_PDR
 
   # Разрешить сигнал выборки (SDRAM chip select)
   #
   mww 0xffffff80 0x00000002 ;# EBI_CSA
 
   # Установка характеристик SDRAM в регистре конфигурации.
   # На частоте 48 МГц 1 такт занимает около 21 нс.
   #
   # 0x00000003 NC: количество бит столбцов
   # 0x00000002 10 бит, 1k столбцов
   #
   # 0x0000000C NR: количество бит строк
   # 0x00000008 13 бит, 8k строк
   #
   # 0x00000010 NB: количество банков
   # 0x00000010 4 банка
   #
   # 0x00000060 CAS: CAS latency (задержка сигнала выборки столбца)
   # 0x00000040 2 такта
   #
   # 0x00000780 TWR: задержка восстановления записи
   # 0x00000100 2 такта
   #
   # 0x00007800 TRC: задержка цикла строки
   # 0x00002000 4 такта
   #
   # 0x00078000 TRP: задержка precharge строки
   # 0x00020000 4 такта
   #
   # 0x00780000 TRCD: задержка от строки к столбцу
   # 0x00100000 2 такта
   #
   # 0x07800000 TRAS: задержка между active и precharge
   # 0x01800000 3 такта
   #
   # 0x78000000 TXSR: задержка между выходом из self refresh и active
   # 0x20000000 4 такта
   #
   mww 0xffffffb8 0x2192215a ;# SDRAMC_CR
   sleep 10
 
   # Выдача команды 16-бит SDRAM: NOP
   #
   mww 0xffffffb0 0x00000011 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
 
   # Выдача команды 16-бит SDRAM: Precharge all
   #
   mww 0xffffffb0 0x00000012 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
 
   # Выдача 8 циклов автообновления (auto-refresh)
   #
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
   mww 0xffffffb0 0x00000014 ;# SDRAMC_MR
   mww 0x20000000 0x00000000
 
   # Выдача команды 16-бит SDRAM: Set mode register
   #
   mww 0xffffffb0 0x00000013 ;# SDRAMC_MR
   mww 0x20000014 0xcafedede
 
   # Установка счетчика обновления (refresh rate count) ???
   #
   mww 0xffffffb4 0x00000013 ;# SDRAMC_TR
 
   # Выдача команды 16-бит SDRAM: Normal mode
   #
   mww 0xffffffb0 0x00000010 ;# SDRAMC_MR
   mww 0x20000000 0x00000180
}

И наконец заключительная конфигурация для Turtelizer 2, которую нужно поместить в файл interface/turtelizer2.cfg.

#
# egnite Turtelizer 2
#
# http://www.ethernut.de/en/hardware/turtelizer/index.html
#
 
# Замените на строку
#interface turtle
# когда используете пакет с поддержкой Turtelizer
interface ft2232
 
ft2232_device_desc "Turtelizer JTAG/RS232 Adapter"
ft2232_layout turtelizer2
ft2232_vid_pid 0x0403 0xbdc8

В последней главе рассмотрим несколько примеров использования. Хотя примеры фокусируются на приложениях 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 со строками:

add_script_search_dir [../../nut/tools/turtelizer2]
source [find interface/turtelizer2.cfg]
source [find board/eir.cfg]

... мы можем использовать следующие опции командной строки OpenOCD:

openocd -s ../../nut/tools/turtelizer2 -c "source [find interface/turtelizer2.cfg]"
 -c "source [find board/eir.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. Среди всего прочего этот файл содержит следующий фрагмент:

ifeq ($(PLATFORM), ELEKTOR_IR1)
BURNBOARD = eir
# Инициализация тактов и SDRAM.
BURNCMDS += -c "reset init"
ifeq ($(LDNAME), at91sam7se512_xram)
# Загрузка образа firmware в external SDRAM.
BURNCMDS += -c "load_image $(ITARG) 0x20000000"
# Проверка образа firmware в external SDRAM.
BURNCMDS += -c "verify_image $(ITARG) 0x20000000"
# Запуск firmware в external SDRAM.
BURNCMDS += -c "resume 0x20000000"
endif
ifeq ($(LDNAME), at91sam7se512_rom)
BURNCMDS += -c "flash write_image erase $(ITARG) 0x100000 bin"
BURNCMDS += -c "verify_image $(ITARG) 0x100000 bin"
BURNCMDS += -c "at91sam7 gpnvm 2 set"
BURNCMDS += -c "reset run"
endif
endif

Эта часть выполняется, когда выполняется сборка приложения для EIR, и тогда PLATFORM устанавливается в значение ELEKTOR_IR утилитой Nut/OS Configurator. Теперь определяется базовое имя скрипта линкера. Если он сконфигурировано как at91sam7se512_xram, то BURNCMD будет загружен с опциями, которые мы перечислили в таблице выше. Если это сконфигурировано как at91sam7se512_rom, то BURNCMD будет загружен с опциями командной строки, требующими программирования двоичного образа программы в память flash.

[Ссылки]

1. Configuring OpenOCD for the AT91SAM7SE site:ethernut.de.
2. OpenOCD: руководство пользователя, начало.
3. Getting OpenOCD site:openocd.org.
4. OpenOCD Intel x86 site:packages.debian.org.
5. Introducing Turtelizer 2 site:ethernut.de.
6FT2232H Board - макетная плата на высокоскоростном чипе моста USB фирмы FTDI.
7. Макетная плата AT91SAM7X.
8. CDM Uninstaller Windows Device Driver Uninstaller site:ftdichip.com.
9. Readme Future Technology Devices International Ltd CDM Uninstaller site:ftdichip.com.
10. Zadig Tool site:zadig.akeo.ie.
11. Запуск SWD отладчика на основе OpenOCD и FT2232H.
12ARM Atmel серии AT91SAM7X: назначение бит GPNVM.
13. Переменные окружения Windows.

 

Добавить комментарий


Защитный код
Обновить

Top of Page