OpenOCD: руководство пользователя, окончание Печать
Добавил(а) microsin   

В этой заключительной части документации OpenOCD представлены разделы:

17. Команды архитектуры и ядра.
18. Команды JTAG.
19. Команды Boundary Scan.
20. TFTP.
21. GDB и OpenOCD.
22. API скриптов языка TCL (Tcl Scripting API).
23. FAQ (часто задаваемые вопросы по OpenOCD).
24. Краш-курс (быстрый экскурс) в Tcl.
Словарик.
Ссылки.

Непонятные термины и сокращения см. в разделе Словарик.

OpenOCD: руководство пользователя, начало
OpenOCD: руководство пользователя, продолжение

[17. Команды архитектуры и ядра]

Многие CPU имеют специализированные операции JTAG для поддержки отладки. OpenOCD упаковывает большинство таких операций в свою стандартную среду команд (command framework). Некоторые из этих операций не очень хорошо укладываются в эту среду команд, так что они предоставлены здесь как специальные команды архитектуры или реализации (core, ядро).

17.1. Аппаратная трассировка ARM (ARM Hardware Tracing)

CPU, основанные на ядрах ARM, могут включать в себе стандартные интерфейсы трассировки, основанные на "Embedded Trace Module” (ETM), который отправляет подробные отчеты по адресам и данным шины в "порт трассировки" ("Trace Port").

• Отладочные платы, ориентированные на разработку, иногда предоставляют высокоскоростной коннектор для сбора отладочных данных, когда отдельный CPU поддерживает такой интерфейс. (Стандартным является коннектор 38-pin Mictor, на котором имеется одновременно поддержка и JTAG, и trace port.) Такие коннекторы трассировки поддерживаются адаптерами JTAG более высокого класса, и некоторыми модулями логического анализатора; часто эти модули могут буферизировать несколько мегабайт данных трассировки. Конфигурирование ETM совместно с таким внешним trace port относится к задачам конфигурационного файла, специфичного для платы (board-specific configuration file).
• Если CPU не предоставляет внешнего интерфейса, то он возможно имеет ETB, встроенный в чип, который является выделенной SRAM. Размер 4 килобайта является часто встречающимся для ETB. Конфигурирование только ETM принадлежит конфигурационному файлу, отвечающему за CPU (target), поскольку он будет работать одинаково на всех платах.

Поддержка ETM OpenOCD пока еще широко не используется. Есть проблемы: поддержка ETM может быть недоработана и содержать ошибки, и должны быть обнаружены как минимум несколько параметров etm config при запросе к ETM. События триггера ETM могли бы также реализовать намного более сложные аппаратные точки останова, чем простая аппаратура watchpoint, экспортированная модулями EmbeddedICE. Такие точки останова могут срабатывать даже когда используется простой драйвер trace port. Кажется, что совместная работа с GDB возможна, также как и трассировка только в определенных состояниях (может быть обработано IRQ 23 или calls foo()). Здесь должны быть инструменты GUI для манипулирования сохраненными данными трассировки, чтобы помочь их проанализировать совместно с исходным кодом отлаживаемой программы. Пока непонятно, насколько поддержка ETM должна использовать общий с поддержкой XScale интерфейс, или должна быть реализована совместно с поддержкой модуля отладки в стиле Nexus, основанном на событиях. На момент написания этой документации (ноябрь 2009) была доступна поддержка модулей ETM только для ARM7, ARM9 и ARM11. Код должен работать с некоторыми более новыми ядрами; но не все они поддерживают оригинальный стиль доступа к JTAG.

17.1.1. Конфигурация ETM

Настройка ETM связана с конфигурацией драйвера trace port.

etm config target width mode clocking driver [Config Command]

Декларирует ETM, связанную с target, и ассоциирует её с имеющимся драйвером trace port. См. раздел 17.1.3. Драйверы порта трассировки (Trace Port Drivers).

Некоторые параметры должны отражать возможности trace port, реализованные в кремнии (о них выдает информацию упомянутая позже etm info) и должны указывать, какая аппаратура подключена к этому порту (такая как внешний порт или ETB). Параметр width должен быть 4, 8 или 16, за исключением ETMv3.0 и более новых модулей, которые могут также поддерживать ширину шины 1, 2, 24, 32, 48 и 64 бита. (В этих версиях etm info также показывает, поддерживает ли выбранный порт ширину width и режим mode.)

Параметр mode должен быть normal, multiplexed или demultiplexed. Параметр clocking должен быть half или full.

Внимание: с ETMv3.0 и более новой версией, установка битов с параметрами mode и clocking также управляют режимом. Этот модифицированный режим не привязан к значениям, поддерживаемым предыдущими модулями ETM, так что этот синтаксис вероятно будет изменен в будущем.

Примечание: Вы можете увидеть регистры ETM, используя команду reg. Не все возможные регистры представлены в каждой ETM. Большинство регистров работают только на чтение write-only, и используются для конфигурирования трассируемой активности CPU.

etm info [Command]

Отображает информацию о ETM текущей target. Это включает счетчик ресурсов из регистра ETM_CONFIG, также как возможности кристалла (за исключением довольно старых модулей) из регистра ETM_SYS_CONFIG.

etm status [Command]

Отображает состояние ETM и драйвера trace port текущей target: ETM в состоянии ожидания (idle), или она собирает данные? Есть ли переполнение в данных трассировки? Сработал ли триггер?

etm tracemode [type context_id_bits cycle_accurate branch_output] [Command]

Отображает, какие данные будет собирать ETM. Если предоставлены аргументы, то сначала конфигурирует данные. Когда конфигурация изменяется, трассировка останавливается и любые забуферизированные данные трассировки становятся недостоверными.

type описывает, как трассируются доступы к данным, когда они проходят любую фильтрацию ViewData, которая была настроена. Значение может быть либо none (ничего не сохраняется), data (сохраняются данные), address (сохраняются адреса), all (сохраняются данные и адреса).
context_id_bits этот параметр может быть 0, 8, 16 или 32.
cycle_accurate enable (разрешить) или disable (запретить) трассировку инструкции с точностью до цикла. До
ETMv3 разрешение приводило к большому количеству записываемых данных.
branch_output enable (разрешить) или disable (запретить). Запретите это за исключением случая, когда Вам надо попытаться реконструировать поток трассировки инструкций без изображения кода.

etm trigger_debug (enable|disable) [Command]

Отображать или нет запись срабатывания отладки ETM (triggering debug entry, наподобие точки останова), после необязательной модификации той конфигурации. Поведение по умолчанию disable (запрет). Любое изменение будет приведено в действие после следующей команды etm start.

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

17.1.2. Функционирование трассировки ETM (ETM Trace Operation)

После настройки ETM Вы можете использовать их для сбора данных. Эти данные могут быть экспортированы в файлы для последующего анализа. Они также могут быть проанализированы OpenOCD, для базовой проверки на корректность.

Для конфигурирования того, что будет трассироваться Вам нужно записать различные регистры трассировки с использованием команд reg ETM_*. Для определения этих регистров прочитайте ARM-публикацию IHI 0014, "Embedded Trace Macrocell, Architecture Specification". Имейте в виду, что большинство соответствующих регистров работают только на запись (write-only), и соответствующие ресурсы ETM ограничены. Их удобно использовать только как компараторы адреса, данных, счетчики и так далее. Вот примеры сценариев, которые Вы можете использовать для трассировки:

• Выполнение кода в теле функции, исключая вызывающие её подпрограммы. Используйте компараторы диапазона адресов для разрешения трассировки инструкций, которые относятся к телу функции.
• Выполнение кода в теле функции, включая вызывающие её подпрограммы. Используйте секвенсор и компараторы адреса для активизации трассировки на состояние входа в функцию, затем деактивируйте это путем выхода из такого состояния, когда выполняется код выхода из функции.
• Выполнение кода начиная с пятого вызова функции - комбинируя счетчик и вышеуказанные модели.
• Доступ данных CPU к регистрам какого-либо устройства, используя компараторы диапазона адресов и логику ViewData.
• Такой же доступ к данным, но только внутри обработки IRQ, комбинируя вышеуказанную модель с триггерами секвенсора, которые установлены на входе и выходе обработчика прерывания (IRQ handler).
• ... могут быть и другие варианты комбинации использования ETM для трассировки.

На момент написания этой документации (сентябрь 2009) не было процедур утилит Tcl, чтобы помочь настроить общие сценарии трассировки.

etm analyze [Command]

Читает данные трассировки в память, если они еще там не представлены. Декодирует и печатает содержимое данных, которые были собраны.

etm dump filename [Command]

Сохраняет захваченные данные трассировки в файл filename.

etm image filename [base_address] [type] [Command]

Открывает файл образа.

etm load filename [Command]

Загружает захваченные данные трассировки из файла filename.

etm start [Command]

Запускает сбор данных трассировки.

etm stop [Command]

Останавливает сбор данных трассировки.

17.1.3. Драйверы порта трассировки (Trace Port Drivers)

Чтобы использовать порт трассировки ETM, он должен быть ассоциирован с драйвером.

dummy [Trace Port Driver]

Используйте драйвер dummy, если Вы конфигурируете ETM, которая не подключена к чему-нибудь (ETB на чипе или коннектор трассировки вне чипа). Этот драйвер позволяет OpenOCD обмениваться данными с ETM, но она не предоставляет любые собранные данные трассировки.

    etm_dummy config target [Config Command]

Ассоциирует ETM для target с драйвером dummy.

etb [Trace Port Driver]

Используйте драйвер etb, если Вы конфигурируете ETM для использования памяти ETB на чипе.

    etb config target etb_tap [Config Command]

Ассоциирует ETM для target с ETB на etb_tap. Вы можете просмотреть регистры ETB с помощью команды reg.

    etb trigger_percent [percent] [Command]

Эта команда отображает или опционально изменяет поведение ETB после того, как сработает сконфигурированное событие trigger. Она управляет тем, сколько будет записано данных трассировки после того, как (один) триггер трассировки станет активным.

• Состояние по умолчанию соответствует трассировке вокруг использования, при этом записывается 50% данных перед событием и остальные данные после.
• Минимальное значение составляет 2%, при этом данные записываются исключительно перед триггером. Такая предельная настройка трассировки может помочь определить, что вызвало событие срабатывания триггера.
• Максимальное значение 100%, при этом данные записываются исключительно после события. Такая предельная настройки может помочь с проблемами, возникающими после события.

oocd_trace [Trace Port Driver]

Этот драйвер недоступен за исключением случая, когда OpenOCD была явно сконфигурирована с опцией --enable-oocd_trace. Возможно, Вы не захотите сконфигурировать это, если у Вас несоответствующего прототипа аппаратуры; это программное обеспечение, демонстрирующее идею (proof-of-concept). Используйте драйвер oocd_trace, если Вы сконфигурировали ETM, которая подключена к коннектору трассировки вне чипа.

    oocd_trace config target tty [Config Command]

Ассоциирует ETM для target с драйвером трассировки, который собирает данные через последовательный порт tty.

    oocd_trace resync [Command]

Ресинхронизация с тактами захвата (capture clock).

    oocd_trace status [Command]

Рапортует о блокировке (locked), или отсутствии тактов захвата.

17.2. Стандартный ARM (Generic ARM)

Эти команды должны работать на всех процессорах ARM. Они доступны как дополнение к другим специфичным для определенного ядра командам.

arm core_state [arm|thumb] [Command]

Отображает core_state (состояние ядра), опционально меняя обработку на инструкции arm или thumb. Цель (target) может позже возобновить работу с текущего состояния ядра. (Процессоры могут также поддерживать состояние Jazelle, но это в настоящий момент не поддерживается в OpenOCD.)

arm disassemble address [count [thumb]] [Command]

Дизассемблирует count инструкций начиная с адреса address. Если count не указано, то будет дизассемблирована только одна инструкция. Если указано thumb, или установлен младший бит у адреса, то используются инструкции Thumb2 (смешанные 16/32-bit); иначе используются инструкции ARM (32-bit). (Процессоры могут поддерживать состояние Jazelle, но такие инструкции OpenOCD пока не понимает.)

Имейте в виду, что все инструкции Thumb являются инструкциями Thumb2, так что для старых процессоров (без поддержки Thumb2) код Thumb все равно будет корректно дизассемблирован. Также коды операций ThumbEE такие же, как и у Thumb2, с полезными исключениями. Дизассемблирование ThumbEE в настоящий момент не имеет явной поддержки.

arm mcr pX op1 CRn CRm op2 value [Command]

Запишите значение в регистр сопроцессора pX с передачей параметров CRn, CRm, кодов операции opc1 и opc2, и используя инструкцию MCR. (Последовательность параметров соответствует инструкции ARM, но пропускает регистр ARM.)

arm mrc pX coproc op1 CRn CRm op2 [Command]

Чтение регистра сопроцессора pX с передачей параметров CRn, CRm, кодов операции opc1 и opc2, и инструкции MRC. Возвращает результат так, что им можно манипулировать через скрипты Jim. (Последовательность параметров соответствует инструкции ARM, но пропускает регистр ARM.)

arm reg [Command]

Отображает таблицу всех регистров ядра, относящихся к банку, захват текущего значения от каждого режима ядра, если это необходимо.

arm semihosting [enable|disable] [Command]

Отображение состояния семихостинга, после необязательного изменения статуса. Семихостинг позволяет коду выполняться на ARM target для использования возможностей I/O на компьютере хоста, к примеру системы, где запущена OpenOCD. Приложение на target должно быть слинковано со специальной библиотекой, которая реализует систему семихостинга ARM, так что перенаправляет запросы операций с помощью специальной инструкции SVC, которая перехватывается супервизором векторов вызова (Supervisor Call vector) OpenOCD.

17.3. Архитектуры ARMv4 и ARMv5

Архитектуры ARMv4 и ARMv5 широко используются во встраиваемых системах, и они представлены набором ядер инструкций, имеющимися сегодня. Это включает набор инструкций Thumb, представленный в варианте ARMv4T.

17.3.1. Команды, специфичные для ARM7 и ARM9

Эти команды относятся к ядрам ARM7 и ARM9, наподобие ARM7TDMI, ARM720T, ARM9TDMI, ARM920T или ARM926EJ-S. Они доступны в дополнении к командам стандартного ARM, и к другим командам, относящимся к специфике ядра.

arm7_9 dbgrq [enable|disable] [Command]

Отображает значение флага, управляющего использованием сигнала EmbeddedIce DBGRQ для принудительного входа в режим отладки, вместо точек останова. Если предоставлен двоичный параметр, то сначала назначает флаг на указанное значение. Это должно быть безопасно для всех кроме ядер ARM7TDMI-S (наподобие NXP LPC). Эта возможность разрешена по умолчанию для большинства ядер ARM9, включая ARM9TDMI, ARM920T и ARM926EJ-S.

arm7_9 dcc_downloads [enable|disable] [Command]

Отображает значение флага, управляющего использованием канала обмена для отладки (debug communications channel, DCC) для записи увеличенных (>128 байт) объемов памяти. Если предоставлен двоичный параметр, то сначала назначает флаг на указанное значение. Загрузка через DCC предоставляет большое увеличение скорости, но может быть небезопасной, особенно с target-ами, работающими на очень маленьких скоростях. Эта команда была представлена в OpenOCD rev. 60, и требует несколько байт для рабочей области.

arm7_9 fast_memory_access [enable|disable] [Command]

Отображает значение флага, управляющего использованием записью и чтением памяти, которые не проверяют завершение операции. Если предоставлен двоичный параметр, то сначала назначает флаг на указанное значение. Эта возможность предоставляет большое увеличение скорости, особенно с кабелями USB JTAG (на основе FT2232), но может быть небезопасной с target-ами, работающими на очень маленьких скоростях, наподобие 32 кГц стартовой тактовой частоты AT91RM9200.

17.3.2. Команды, специфичные для ARM720T

Эти команды доступны для CPU на базе ARM720T, которые являются реализациями архитектуры ARMv4T, основанной на целочисленном ядре ARM7TDMI-S. Эти команды дополняют команды ARM и ARM7/ARM9.

arm720t cp15 opcode [value] [Command]

Эта команда устарела – избегайте использовать её. Вместо этого используйте arm mrc или arm mcr. Отображает регистр cp15, возвращаемый командой opcode; иначе если предоставлено value, записывает value в этот регистр. Команда opcode должна быть либо MRC, либо MCR инструкцией.

17.3.3. Команды, специфичные для ARM9

Ядра семейства ARM9 построены на целочисленных процессорах ARM9TDMI или ARM9E (включая ARM9EJS). Такие ядра включают ARM920T, ARM926EJ-S и ARM966.

arm9 vector_catch [all|none|list] [Command]

Аппаратура Vector Catch (переводится как захват вектора) предоставляет вид выделенной точки останова для аппаратных событий, таких как reset (сброс), interrupt (прерывание) и abort (обрыв выполнения кода). Вы можете использовать это для экономии ресурсов обычных точек останова, пока Вас не волнует код, который делает ветвление на эти аппаратные вектора.

Команда всегда заканчивается перечислением текущей конфигурации. Если предоставлены параметры, то сначала будет произведено реконфигурирование аппаратуры захвата вектора. Значение all означает перехватывать все вектора, none ничего не перехватывать, list список, предоставляющий одну или большее количество записей reset undef swi pabt dabt irq fiq.

17.3.4. Команды, специфичные для ARM920T

Эти команды доступны для CPU на базе ARM920T, которые являются реализациями архитектуры ARMv4T, основанной на целочисленном ядре ARM9TDMI. Эти команды дополняют команды ARM, ARM7/ARM9 и ARM9.

arm920t cache_info [Command]

Печатает найденную информацию о кэше. Это позволяет увидеть, какая используется target, ARM920T (кэш 2x16 килобайта) или ARM922T (кэш 2x8 килобайта).

arm920t cp15 regnum [value] [Command]

Отображает регистр cp15 с номером regnum; иначе если предоставлено значение value, записывает его в этот регистр. Эта команда использует "физический доступ" и номер регистра, как он показан в битах 38..33 таблицы 9-9 в ARM920T TRM. (Не все регистры могут быть записаны.)

arm920t cp15i opcode [value [address]] [Command]

Эта команда устарела, избегайте использовать её. Вместо этого используйте arm mrc или arm mcr. Интерпретируемый доступ с использованием инструкции ARM opcode, которая должна быть либо MRC, либо MCR инструкцией (как показано в таблицах 9-11, 9-12 и 9-13 в ARM920T TRM). Если не предоставлено значение value, то просто отображает результат. Иначе если имеется value, то оно записывается с использованием указанного адреса, или если адрес не указан, то используется адрес 0.

arm920t read_cache filename [Command]

Выводит дамп кэша ICache и DCache в файл filename.

arm920t read_mmu filename [Command]

Выводит дамп кэша ITLB и DTLB в файл filename.

17.3.5. Команды, специфичные для ARM926ej-s

Эти команды доступны для CPU на базе ARM926ej-s, которые являются реализациями архитектуры ARMv5TEJ, основанной на целочисленном ядре ARM9EJ-S. Эти команды дополняют команды ARM, ARM7/ARM9 и ARM9. Ядра Feroceon также поддерживают эти команды, хотя они не основаны на дизайне ARM926ej-s.

arm926ejs cache_info [Command]

Печатает найденную информацию о кэшах.

17.3.6. Команды, специфичные для ARM966E

Эти команды доступны для CPU на базе ARM966, которые являются реализациями архитектуры ARMv5TE. Эти команды дополняют команды ARM, ARM7/ARM9 и ARM9.

arm966e cp15 regnum [value] [Command]

Отображает регистр cp15 с номером regnum; иначе если предоставлено значение value, записывает его в этот регистр. Шесть бит значений regnum являются битами 37..32 из таблицы 7-2 в ARM966E-S TRM. Здесь нет текущего управления через биты 31..30 из этой таблицы, как требуется для поддержки BIST.

17.3.7. Команды, специфичные для XScale

Далее приведены некоторые указания по поводу реализации отладки на процессорах XScale CPU. В них имеется специальная кэш, предназначенная только для отладки, так называемая mini-instruction cache (mini-IC), в которой находятся векторы исключений и резидентный код обработчика отладки target (debug handler), размещенный системой OpenOCD. Чтобы получить доступ к CPU, OpenOCD должна указать на vector 0 (вектор сброса reset vector) для входа в обработчик отладки. Однако это означает, что полностью вся первая линия кэша в mini-IC помечается как допустимая, что заставляет CPU забрать все обработчики исключений из mini-IC, игнорируя код в RAM.

Для такой ситуации OpenOCD предоставляет команду xscale vector_table, которая позволяет пользователю явно записывать индивидуальные записи или в верхнюю, или в нижнюю таблицу векторов, сохраненную в mini-IC.

Рекомендуется использовать в таблице векторов непрямое ветвление относительно счетчика команд pc, и разместить код места назначения ветвления где-нибудь в памяти. Если сделать так, то это обеспечит постоянство таблицы векторов, независимо от конфигурации кода в памяти:

_vectors:
        ldr     pc,[pc,#0x100-8]
        ldr     pc,[pc,#0x100-8]
        ldr     pc,[pc,#0x100-8]
        ldr     pc,[pc,#0x100-8]
        ldr     pc,[pc,#0x100-8]
        ldr     pc,[pc,#0x100-8]
        ldr     pc,[pc,#0x100-8]
        ldr     pc,[pc,#0x100-8]
        .org 0x100
        .long real_reset_vector
        .long real_ui_handler
        .long real_swi_handler
        .long real_pf_abort
        .long real_data_abort
        .long 0 /* unused */
        .long real_irq_handler
        .long real_fiq_handler

Альтернативно, Вы можете сохранять некоторые или все записи таблицы векторов mini-IC синхронизировавшими с записанным в память Вашим системным программным обеспечением. Кэш mini-IC не может быть модифицирован, пока процессор выполняет программу, но для каждой записи в таблице векторов, не заданной ранее командой xscale vector_table, OpenOCD сделает копию значения из памяти в mini-IC каждый раз, когда выполнение возобновляется (resume) из состояния останова (halt). Это выполняется для верхней и нижней таблиц векторов (хотя неиспользуемая таблица может быть не связана с допустимой памятью, и в этом случае такая операция копирования тихо потерпит неудачу). Это означает, что Вам нужно делать остановки выполнения в некоторой стратегической точке во время запуска системы; например после того, как программное обеспечение проинициализировало таблицу векторов, но перед разрешением исключений. Может использоваться точка останова для достижения соответствующего места, идентифицированного в коде запуска. Точка наблюдения watchpoint над регионом таблицы векторов может помочь в поиске места размещения, если Вы сами не уверены, где оно находится. Имейте в виду, что такая же ситуация существует всякий раз, когда таблица векторов модифицируется системным программным обеспечением.

Обработчик отладки (debug handler) должен быть размещен где-то в адресном пространстве, с использованием команд xscale debug_handler. Допустимые места для debug handler будут либо (0x800 - 0x1fef800), либо (0xfe000800 - 0xfffff800). Значение по умолчанию 0xfe000800.

XScale имеет ресурсы для поддержки 2 аппаратных точек останова (hardware breakpoint) и 2 точек слежения (watchpoint). Однако на функциональность watchpoint накладываются следующие ограничения: (1) аргументы значения и маски для команды wp не поддерживаются, (2) длина watchpoint должна быть результатом степени 2 и не меньше 4, и не может превышать значения адреса watchpoint, и (3) watchpoint, у которой длина больше чем 4, будет занимать все ресурсы аппаратуры watchpoint. Это означает, что Вы можете задать либо 2 watchpoint-а с длиной 4, либо только одну watchpoint с длиной больше 4.

Эти команды доступны на CPU, основанных на XScale, которые являются реализациями архитектуры ARMv5TE.

xscale analyze_trace [Command]

Отображает содержимое буфера трассировки.

xscale cache_clean_address address [Command]

Изменяет адрес address, используемый при очистке кэша данных.

xscale cache_info [Command]

Отображает информацию о кэшах CPU.

xscale cp15 regnum [value] [Command]

Отображает регистр cp15 с номером regnum; иначе если указано value, записывает его в этот регистр.

xscale debug_handler target address [Command]

Изменяет адрес address, используемый для указанного обработчика отладки (debug handler) target-а.

xscale dcache [enable|disable] [Command]

Разрешает или запрещает кэш данных CPU.

xscale dump_trace filename [Command]

Выводит сырое содержимое буфера трассировки в файл filename.

xscale icache [enable|disable] [Command]

Разрешает или запрещает кэш инструкций (команд) CPU.

xscale mmu [enable|disable] [Command]

Разрешает или запрещает узел управления памятью (memory management unit, MMU) CPU.

xscale trace_buffer [enable|disable [fill [n] | wrap]] [Command]

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

xscale trace_image filename [offset [type]] [Command]

Открывает образ трассировки из файла filename, и опционально меняет базу его адреса сегмента с помощью указанного смещения offset. Тип образа может быть один из bin (binary, двоичный), ihex (формат Intel hex), elf (файл формата ELF), s19 (Motorola s19), mem или builder.

xscale vector_catch [mask] [Command]

Отображает битовую маску, показывающую аппаратные вектора для захвата. Если указан необязательный параметр, то предварительно устанавливает битовую маску на указанное значение. Маска соответствует битам 16..23 в DCSR:

    0x01 Trap Reset (ловушка для сброса)
    0x02 Trap Undefined Instructions (ловушка для неопределенной инструкции)
    0x04 Trap Software Interrupt (ловушка для программного прерывания)
    0x08 Trap Prefetch Abort (ловушка для прекращения упреждающей выборки)
    0x10 Trap Data Abort (ловушка для состояния прекращения по недопустимым данным)
    0x20 зарезервировано
    0x40 Trap IRQ (ловушка для прерывания)
    0x80 Trap FIQ (ловушка для быстрого прерывания)
xscale vector_table [(low|high) index value] [Command]

Устанавливает запись в таблице векторов mini-IC. Здесь есть 2 таблицы: одна для нижних векторов (начиная с 0x00000000), и одна для верхних (0xFFFF0000), каждая содержит 8 векторов исключений (exception vector). Параметр index может быть 1-7, потому что вектор 0 указывает на запись debug handler и не может быть перезаписан. Параметр value содержит 32-bit код операции (opcode), который будет помещен в mini-IC. Без аргументов будут отображены текущие установки.

17.4. Архитектура ARMv6

17.4.1. Команды, специфичные для ARM11

arm11 memwrite burst [enable|disable] [Command]

Отображает значение флага разрешения быстрой записи в память (memwrite burst), который по умолчанию разрешен. Если предоставлен булевый параметр, то сначала флагу присваивается указанное значение. Ускоренные записи применяются только для записей в память блоков, которые имеют длину более 1 слова. Это улучшает быстродействие в предположении, что CPU прочитал каждое слово данных через JTAG и завершил его запись до поступления нового слова, вместо того чтобы опрашивать флаг статуса для проверки завершения. Это обычно безопасно, потому что JTAG работает намного медленнее, чем CPU.

arm11 memwrite error_fatal [enable|disable] [Command]

Отображает значение флага memwrite error fatal, который по умолчанию разрешен. Если предоставлен булевый параметр, то сначала флагу присваивается указанное значение. Когда установлен, то определенные ошибки записи в память приведут к раннему обрыву трансфера данных.

arm11 step_irq_enable [enable|disable] [Command]

Отображает значение флага, управляющего состоянием разрешения прерываний: либо IRQ разрешены во время одиночного шага, либо нет; по умолчанию прерывания во время одного шага запрещены. Если предоставлен булевый параметр, то сначала флагу присваивается указанное значение

arm11 vcr [value] [Command]

Отображает значение регистра захвата вектора Vector Catch Register (VCR), сопроцессор 14 регистр 7. Если указано значение value, то сначала оно присваивается.

Аппаратура Vector Catch предоставляет выделенные точки останова для определенных событий аппаратуры. Специальные значения бит соответствуют специфике ядра (как сам и факт использования сопроцессора 14 регистра 7), но все текущие ядра ARM11, за исключением ARM1176, используют те же самые 6 бит.

17.5. Архитектура ARMv7

17.5.1. Команды, специфичные для порта отладки (Debug Access Port, DAP) ARMv7

Эти команды предназначены для специфики архитектуры ARM v7 Debug Access Port (DAP), имеющийся на системах Cortex-M и Cortex-A. Они могут быть доступны как дополнение к другим специфичным для ядра командам.

dap apid [num] [Command]

Отображает регистр ID от AP номер num, по умолчанию выбирается текущий AP.

dap apsel [num] [Command]

Выбор AP num, по умолчанию 0.

dap baseaddr [num] [Command]

Отображает базовый адрес отладки из MEM-AP num, по умолчанию выбирается текущий AP.

dap info [num] [Command]

Отображает таблицу ROM для MEM-AP num, по умолчанию выбирается текущий AP.

dap memaccess [value] [Command]

Отображает количество дополнительных циклов tck в состоянии ожидания JTAG idle для использования в доступе к шине памяти MEM-AP [0-255], давая дополнительное время для ответа на чтения. Если указано значение value, то оно сперва будет назначено.

dap apcsw [0|1] [Command]

Фиксирует CSW_SPROT из регистра AP_REG_CSW на выбранном dap. По умолчанию для 0.

17.5.2. Команды, специфичные для Cortex-M

cortex_m maskisr (auto|on|off) [Command]

Управление маскированием (запретом) прерываний во время пошагового выполнения и возобновления target (step/resume). Опция auto обрабатывает прерывания во время пошагового выполнения таким способом, что оно обрабатывается, но не нарушает последовательность выполнения программы. Команда шага сначала разрешает выполнение ожидающих обработчиков прерывания, затем запрещает прерывания и делает шаг к следующей инструкции, где ядро будет остановлено. После шага прерывания снова разрешаются. Если обработчики прерывания не завершатся за 500 мс, команда шага завершится запуском ядра (остановки не будет).

Имейте в виду, что для работы опции auto необходимо наличие свободной точки останова. Если во время выполнения шага нет ресурсов для такой точки останова, то шаг выполняется с разрешенными прерываниями, то есть происходит то же самое, что было бы с выключенной опцией (off). По умолчанию задается auto.

cortex_m vector_catch [all|none|list] [Command]

Аппаратура захвата вектора Vector Catch предоставляет выделенные точки останова для определенных аппаратных событий. Параметр перехвата запроса all относится ко всем векторам аппаратных событий, none означает захват отключен, или можно указать одну из следующих опций: hard_err для исключения HardFault exception; mm_err для исключения MemManage; bus_err для исключения BusFault; irq_err, state_err, chk_err или nocp_err для различных UsageFault исключений; или reset (сброс). Если код настройки NVIC не разрешил их, то исключения MemManage, BusFault и UsageFault переведены на HardFault. Должны быть также обязательно разрешены проверки UsageFault для деления на 0 (divide-by-zero) и невыравненного доступа (unaligned access). Команда завершается выводом листинга текущей конфигурации захвата векторов.

cortex_m reset_config (srst|sysresetreq|vectreset) [Command]

Управляет обработкой сброса. По умолчанию srst для использования srst если применимо, иначе переход на vectreset.

- srst использует аппаратный srst, если это возможно, иначе происходит переход на vectreset.
- sysresetreq использует NVIC SYSRESETREQ для сброса системы.
- vectreset использует NVIC VECTRESET для сброса системы.

Опция vectreset безопасна для использования со всеми текущими ядрами Cortex-M. Однако у неё есть недостаток - сбрасывается только ядро, на аппаратуру такой сброс не распространяется. В качестве решения проблемы можно использовать обработчик события сброса и инициализации (reset-init event handler) для сброса периферийных устройств вручную. См. раздел 11.5. События цели (Target Events).

17.6. Программные отладочные сообщения (Software Debug Messages) и трассировка

OpenOCD может обработать определенные запросы от программного обеспечения target, когда target использует соответствующие библиотеки. Самым мощным механизмом такого рода является семихостинг, но есть также более простой и легкий механизм, который использует только канал DCC.

В настоящее время target_request debugmsgs поддерживается только для ядер arm7_9 и cortex_m. Эти сообщения принимаются как часть опроса target, так что Вам нужен активный опрос (poll on), чтобы их принять. Такой опрос нежелательно влияет на время выполнения программы. Если это составляет проблему, см. раздел 17.1. Аппаратная трассировка ARM (ARM Hardware Tracing).

Для получения подробной информации см. libdcc в папке contrib. В дополнение к отправке из target строк, символов и массивов чисел целого типа разных размеров, libdcc также экспортирует механизм точек программной трассировки. Отлаживаемая target может выдавать сообщения трассировки, которые включают уникальный 24-битный номер точки трассировки (trace point). Поддержка trace point включает 2 разных механизма, каждый поддерживается определенной командой:

• History может быть настроен кольцевой буфер точек трассировки, и который можно отобразить в любое время. Этим можно отследить, в каком месте выполнялся код, что может быть неоценимым в поиске места возникновения ошибки. Буфер может переполниться, так как он непрерывно собирает записи. Может быть полезным использовать некоторые из 24 бит для представления частного события, и другие биты для удержания данных.
• Counting может быть настроен массив счетчиков, который можно отобразить в любое время. Это может помочь для определения покрытия кода и идентификации горячих точек (по сути это профайлинг). Массив счетчиков прямо проиндексирован по номерам точки трассировки, так что точки с высокими номерами не подсчитываются.

Ядра (имеется в виду ядро операционной системы, не процессора, kernel) Linux-ARM имеют опцию "Kernel low-level debugging via EmbeddedICE DCC channel" ("Низкоуровневая отладка ядра через канал EmbeddedICE DCC", CONFIG_DEBUG_ICEDCC, зависящая от CONFIG_DEBUG_LL), которая использует этот механизм для доставки сообщений перед тем, как будет активизирована последовательная консоль. Это не тот же самый формат, как используется libdcc. Другое программное обеспечение, такое как бутлоадер U-Boot, иногда делает то же самое.

target_request debugmsgs [enable|disable|charmsg] [Command]

Отображает текущую обработку запросов сообщений DCC от target. Эти сообщения могут быть отправлены отладчику, когда работает target. Необязательные параметры enable и charmsg оба разрешают сообщения, в то время как disable запрещает их. С параметром charmsg слова DCC содержат по одному символу каждое, как использует Linux с CONFIG_DEBUG_ICEDCC; иначе используется формат libdcc.

trace history [clear|count] [Command]

Без параметров отображает все точки трассировки, которые сработали, в том порядке, в котором они сработали. С параметром clear, очищает все текущие записи истории трассировки. С параметром count выделяет место для указанного количества записей истории.

trace point [clear|identifier] [Command]

Без параметров отображает все идентификаторы точек трассировки, и сколько раз они сработали. С параметром clear очищает все текущие счетчики точек трассировки. С параметром в виде цифрового идентификатора (identifier) создает новый счетчик точки трассировки и связывает его с этим идентификатором.

Важно: идентификатор и номер точки трассировки ничем не связаны, за исключением этой команды. Эти номера точек трассировки всегда начинаются с 0 (от загрузки сервера, или после trace point clear) и начинают свой счет от этого момента.

[18. Команды JTAG]

Большинство команд JTAG общего назначения уже было представлено ранее - см. разделы 8.4. Скорость JTAG (JTAG Speed), [9. Конфигурация сброса (Reset Configuration)] и [10. Декларирование TAP]. Команды JTAG низкого уровня, которые представлены здесь, могут понадобиться для работы с target-ами, которые требуют специального внимания во время таких операций как сброс или инициализация.

Для использования этих команд Вам нужно понять некоторые базовые понятия JTAG:

• Цепочка сканирования JTAG (scan chain) состоит из последовательности индивидуальных устройств TAP, таких как CPU.
• Операции управления перемещение каждого TAP через те же самые стандартные машинные состояния (параллельно), используя общие TMS и тактовые сигналы.
• Передача данных вовлекает сдвиг данных через цепочку в регистры данных или инструкции для каждого TAP, запись новых значений регистра в одновременно с чтением старого значения.
• Размеры регистра данных являются функцией от активной инструкции на имеющемся TAP, в то время как размеры регистра инструкций являются фиксированными для каждого TAP. Все TAP-ы поддерживают инструкцию BYPASS с регистром данных в 1 бит.
• Метод, которым OpenOCD разделяет друг от друга устройства TAP - сдвиг разных инструкций в их регистры инструкций (или из них).

18.1. Низкоуровневые команды JTAG

Эти команды используют те разработчики, которые нуждаются в доступе к инструкциям JTAG или регистрам данных, возможно управляя порядком переходов состояний TAP. Если Вы не отлаживаете внутреннее устройство OpenOCD, или не запускаете новый адаптер JTAG или новый тип устройства TAP (наподобие CPU или роутера JTAG), то Вам скорее всего не нужно использовать эти команды. В сессии отладки, которая не использует JTAG для своего транспортного протокола, эти команды недоступны.

drscan tap [numbits value]+ [-endstate tap_state] [Command]

Загружает регистр данных tap последовательностью битовых полей, которые указывают весь регистр. Каждое поле состоит из некоторого количества бит, имеющих числовое значение (поддерживается формат hex). Возвращаемое значение содержит оригинальное значение каждого из этих полей.

Например, 38-битное число может указываться как одно поле из 32 бит, и одно их 6 бит. Для портируемости никогда не передавайте поля, которые размером больше 32 бит. Многие реализации OpenOCD не поддерживают 64-битные (или с большей разрядностью) целые числа.

Все TAP-ы, отличающиеся от tap должны быть в режиме BYPASS. Один бит в их регистре не имеет значения.

Когда указан параметр tap_state, машина состояния JTAG state будет оставлена в этом состоянии. Например может быть указан DRPAUSE чтобы больше инструкций могло быть выдано перед новым входом в состояние запуска/ожидания (run/idle). Если endstate не указано, то произойдет вход в состояние run/idle.

Внимание: OpenOCD не записывает информацию о длине регистра данных, так что важно, чтобы Вы правильно указывали длину битовых полей. Помните, что разные инструкции JTAG обращаются к разным регистрам данных, которые могут иметь разную длину. Кроме того, эти длины могут быть не фиксированными; инструкция SCAN_N может поменять длину регистра, к которому осуществляется доступ через инструкцию INTEST (путем подключения к другой scan chain).

flush_count [Command]

Возвращает количество сбросов (flush) очереди JTAG. Под сбросом тут понимается синхронизация буферов - передача тех значений из буфера, что уже накоплены, между хостом OpenOCD и отлаживаемым устройством. Это может использоваться для подстройки быстродействия. Например, сброс очереди через USB вовлекает минимальную задержку на латентность, что часто составляет несколько миллисекунд. Эта задержка не изменяется в зависимости от количества записываемых данных. Вы должны иметь возможность определить проблемы быстродействия путем нахождения задач, которые тратят попусту полосу пропускания, сбрасывая слишком часто мелкие перемещения данных, вместо того чтобы объединить их в более длинные операции.

irscan [tap instruction]+ [-endstate tap_state] [Command]

Для каждого перечисленного tap загружается регистр инструкции с этой ассоциированной числовой инструкцией (количество бит в этой инструкции может быть отображено с использованием команды scan_chain). Для других TAP-ов загружается инструкция BYPASS.

Когда указано tap_state машина состояния JTAG остается в этом указанном состоянии. Например может быть указано состояние IRPAUSE, так что регистр данных может быть загружен перед входом в состояние run/idle. Если endstate не указано, то произойдет вход в состояние run/idle.

Имейте в виду, что OpenOCD в настоящий момент поддерживает только одно поле для значений регистра инструкций в отличие от значений регистра данных. Для TAP-ов, где длина регистра инструкций больше 32 бит, портируемые скрипты в настоящий момент могут выдавать только инструкции BYPASS.

jtag_reset trst srst [Command]

Устанавливает значения сигналов сброса. Значения параметров trst и srst могут быть 0, что показывает неактивное состояние сброса (подтянут или переведен в высокий уровень), или 1, что подсказывает активное состояние (подтянут или переведен на низкий уровень). Команда reset_config уже должна была быть использована для конфигурирования того, как плата и адаптер JTAG обрабатывают эти два сигнала, и чтобы сказать, присутствует ли каждый из сигналов. См. раздел [9. Конфигурация сброса (Reset Configuration)].

Имейте в виду, что у сигнала TRST есть специальное предназначение. Он в обозначает актуальное состояние сброса JTAG-а. Так что если плата не поддерживает необязательный сигнал TRST, или он не поддерживается в соответствии с указанным значением SRST, то сброс JTAG срабатывает с сигналами TMS и TCK вместо сигнала TRST. Независимо от того, как срабатывает сброс JTAG, как только scan chain войдет в сброс с неактивным TRST, события после сброса TAP (TAP post-reset event) доставляется на все TAP-ы с обработчиками этого события.

pathmove start_state [next_state ...] [Command]

Старт путем перемещения в состояние start_state, которое должно быть одним из стабильных (stable) состояний. За исключением того, когда выдается только одно состояние, это часто будет текущее состояние, так что не нужны переходы TCK. Тогда в ряде одиночных изменений состояния (удовлетворяющих машине состояний JTAG) смещение к каждому следующему состоянию в последовательности происходит по одному с каждым циклом TCK. Конечное состояние должны быть также стабильным.

runtest num_cycles [Command]

Переход в состояние run/idle и выполнение как минимум num_cycles тактов JTAG (TCK). Инструкции часто нуждаются в некотором времени для выполнения перед тем, как они дадут эффект.

verify_ircapture (enable|disable) [Command]

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

verify_jtag (enable|disable) [Command]

Разрешает проверку сканов DR и IR, чтобы помочь определить ошибки программирования. Для сканов IR должно быть разрешено также verify_ircapture. По умолчанию разрешено.

18.2. Имена состояний TAP

Имена tap_state используемые OpenOCD в командах drscan, irscan и pathmove, те же самые как используемые в документах SVF boundary scan, за исключением того, что SVF использует IDLE вместо RUN/IDLE.

RESET ... stable (TMS в состоянии лог. 1); работает как если бы на TRST были импульсы.
RUN/IDLE ... stable; не подумайте, что это всегда означает IDLE.
DRSELECT
DRCAPTURE
DRSHIFT ... stable; TDI/TDO сдвиги через регистр данных.
DREXIT1
DRPAUSE ... stable; регистр данных готов для обновления или еще к сдвигам.
DREXIT2
DRUPDATE
IRSELECT
IRCAPTURE
IRSHIFT ... stable; TDI/TDO сдвиги через регистр инструкций.
IREXIT1
IRPAUSE ... stable; регистр инструкций готов для обновления или еще к сдвигам.
IREXIT2
IRUPDATE

Имейте в виду, что только 6 из этих состояний полностью "стабильны" (stable) перед лицом зафиксированного TMS (на низком уровне за исключением сброса) и свободно меняющимся тактами JTAG. Для всех других состояний следующее изменение TCK приводит к переходу в новое состояние.

• От DRSHIFT и IRSHIFT изменения тактов приведут к сторонним эффектам через изменение содержимого регистра. Значений для захвата в наступающих состояниях DRUPDATE или IRUPDATE может и не быть, хотя это не ожидалось.
• RUN/IDLE, DRPAUSE и IRPAUSE разумный выбор после команд DRSCAN или IRSCAN, поскольку они свободны от сторонних эффектов JTAG.
• RUN/IDLE могут иметь сторонние эффекты, которые появляются на не-JTAG уровнях, таких как продвинутая конвейеризация инструкций (instruction pipeline) ARM9E-S. Проконсультируйтесь с документацией на TAP(-ы), с которыми Вы работаете.

[19. Команды Boundary Scan]

Изначально интерфейс JTAG предназначался для тестирования аппаратуры, основанном на пограничном сканировании (boundary scan). Несмотря на то, что главное назначение OpenOCD - поддержка отладки, встроенной в чип (On-Chip Debugging), все-таки OpenOCD также включает в себя некоторые команды boundary scan.

19.1. SVF: Serial Vector Format

Serial Vector Format, который лучше известен как SVF, является методом представления тестовых паттернов JTAG в текстовых файлах. В сессии отладки, которая использует JTAG для своего транспортного протокола, OpenOCD поддерживает запуск таких тестовых файлов.

svf filename [quiet] [Command]

Эта команда выдает сброс JTAG (Test-Logic-Reset, сброс логики тестирования) и затем запускает скрипт SVF из файла filename. За исключением указанной опции quiet, каждая команда скрипта будет выведена в лог перед своим выполнением.

19.2. XSVF: Xilinx Serial Vector Format

Xilinx Serial Vector Format, который лучше известен как XSVF, является двоичным представлением SVF, которое оптимизировано для использования с устройствами Xilinx. В сессии отладки, использующей JTAG для своего транспортного протокола, OpenOCD поддерживает запуск таких файлов для теста.

Важно: не все команды XSVF поддерживаются.

xsvf (tapname|plain) filename [virt2] [quiet] [Command]

Выдает сброс JTAG (Test-Logic-Reset) и затем запускает скрипт XSVF из файла filename. Когда указан tapname, команды направляются в этот TAP. Когда указан параметр virt2, команда XRUNTEST подсчитывает интерпретированные циклы TCK вместо микросекунд. За исключением указанной опции quiet, будут выведены сообщения с комментариями и о повторных попытках.

Исходные коды OpenOCD также включают два скрипта утилит для работы с XSVF; в настоящий момент они не инсталлируются после сборки программного обеспечения. Вы можете решить, что они полезны:

• svf2xsvf конвертирует файлы SVF в расширенный синтаксис XSVF, который понимает команда xsvf; см. примечания далее.
• xsvfdump конвертирует файлы XSVF в выходной текстовый формат; понимает расширения OpenOCD.

Входной формат принимает полезные нестандартные расширения. Они включают 3 кода операции, соответствующие расширениям SVF от Lattice Semiconductor (LCOUNT, LDELAY, LDSR), и 2 кода операции, поддерживающих более точную трансляцию SVF (XTRST, XWAITSTATE). Если xsvfdump показывает в файле использование этих кодов операций, то возможно этот файл не может быть использован с другими инструментами для XSVF.

[20. TFTP]

Если OpenOCD работает на встроенном хосте (как делает ZY1000), то можно использовать TFTP для получения доступа к файлам на компьютере PC (это может быть компьютер разработчика или другой компьютер).

На ZY1000 это можно сделать с префиксом "/tftp/ip/" к имени файла и добавлением пути TFTP на сервере TFTP (tftpd). Например, следующая команда загрузит файл c:\temp\abc.elf с компьютера разработчика (который имеет IP-адрес 10.0.0.96) в память, как если бы этот файл был размещен на локально на встроенном хосте.

    load_image /tftp/10.0.0.96/c:tempabc.elf

Чтобы достичь приличной производительности, Вы должны выбрать сервер TFTP, который поддерживает размеры пакета больше, чем размер пакета по умолчанию (512 байт). Есть много серверов TFTP с такой возможностью (бесплатные и коммерческие), и Вам нужно немного прогуглить вопрос, чтобы найти что-нибудь удовлетворяющее Вашим запросам.

[21. GDB and OpenOCD]

Система OpenOCD совместима с сетевым протоколом gdbserver, так что её можно использовать для отладки target-ов через сеть. Настройка GDB для работы с OpenOCD может привлекать несколько компонентов:

• Сервер OpenOCD, поддерживающий GDB, может потребовать конфигурирования. См. раздел 7.4. Конфигурация GDB.
• GDB для поддержки OpenOCD может потребовать конфигурирования, как будет показано в этом разделе.
• Если у Вас имеется оконное GUI-окружения разработки наподобие Eclipse, то возможно и его также придется настроить.

Конечно, используемая Вами версия GDB должна быть собрана с поддержкой того target CPU, для которого Вы пишете программу. Например, если Вы производите кросс-разработку для ARM на компьютере x86 PC, то вместо использования обычной команды x86 gdb можете использовать arm-none-eabi-gdb, если этот тулчейн использовался для компиляции Вашего кода.

21.1. Подключение к GDB

Используйте GDB 6.7 или более свежий с OpenOCD, если Вы сталкиваетесь с проблемами. Например GDB 6.3 имеет известный баг, который приводит к ошибкам с доступом к памяти; это исправлено в последующих релизах.

OpenOCD может обмениваться данными с GDB двумя способами:

1. Соединение через сокет (TCP/IP) обычно запускается так:

    target remote localhost:3333

Это выполнит соединение gdbserver с локальным pc через порт 3333.

Также можно использовать расширенный сетевой протокол GDB:

    target extended-remote localhost:3333

2. Соединение через канал (pipe):

    target remote | openocd -c "gdb_port pipe; log_output openocd.log"

Этим GDB запустит OpenOCD и будет обмениваться с ним через именованные каналы (stdin/stdout). Использование этого метода имеет преимущество в том, что GDB может запускать/останавливать OpenOCD для сессии отладки. Опция log_output задает отправку вывода лога в файл, чтобы удостовериться, что канал (pipe) не забьется сообщениями отладки более высокого уровня.

Чтобы просмотреть доступные команды OpenOCD наберите monitor help в командной строке GDB.

21.2. Пример запуска сессии GDB

С использованием сетевого протокола сессии GDB запускаются немного по-другому чем когда Вы отлаживаетесь локально. Здесь приведены примеры, показывающие, как запустить сессию отладки с маленькой программой на ARM. В этом случае программа была слинкована для загрузки в SRAM на Cortex-M3. Большинство программ написаны с учетом записи их в память flash (по адресу 0) и запуска их оттуда.

    $ arm-none-eabi-gdb example.elf
    (gdb) target remote localhost:3333
    Remote debugging using localhost:3333
    ...
    (gdb) monitor reset halt
    ...
    (gdb) load
    Loading section .vectors, size 0x100 lma 0x20000000
    Loading section .text, size 0x5a0 lma 0x20000100
    Loading section .data, size 0x18 lma 0x200006a0
    Start address 0x2000061c, load size 1720
    Transfer rate: 22 KB/sec, 573 bytes/write.
    (gdb) continue
    Continuing.
    ...

Затем Вы можете прервать сессию GDB, чтобы остановить программу, ввести where чтобы увидеть стек, list чтобы увидеть код возле программного счетчика, step для пошагового выполнения кода, установить точки останова (breakpoint) или точки наблюдения (watchpoint) и так далее.

21.3. Конфигурирование GDB для OpenOCD

OpenOCD поддерживает пакет gdb qSupported, что позволяет для OpenOCD отправлять информацию на сетевой сервер GDB для отладки. Типичная информация включает размер пакета и карту памяти устройства (device memory map). Вам не нужно конфигурировать размер пакета вручную, и соответствующие части memory map должны быть автоматически настроены, когда Вы декларируете банки flash (NOR).

Однако есть другие моменты настройки, которые в настоящее время GDB не может опросить (и установить автоматически). Это может потребовать ручной настройки. При старте OpenOCD Вы можете часто увидеть строку сообщения наподобие следующей:

    Info : lm3s.cpu: hardware has 6 breakpoints, 4 watchpoints

Вы можете передать эту информацию к GDB командами:

    set remote hardware-breakpoint-limit 6
    set remote hardware-watchpoint-limit 4

Для некоторого железа (Cortex-M3) аппаратные точки останова (hardware breakpoint) работают только для кода из памяти flash. На многих других системах ARM таких ограничений нет.

Другой пример полезного конфигурирования GDB пришел от пользователя, который нашел, что пошаговое выполнение Cortex-M3 не работает хорошо с прерываниями (IRQ) и RTOS, пока не сказать GDB запретить IRQ при пошаговом выполнении:

    define hook-step
    mon cortex_m maskisr on
    end
    define hookpost-step
    mon cortex_m maskisr off
    end

Вместо того чтобы вводить эти команды каждый раз интерактивно, Вы можете предпочесть сохранить их в файл и дать GDB выполнить их при запуске, возможно используя директорию .gdbinit в Вашем проекте или через запуск GDB используя командную строку gdb -x filename.

21.4. Программирование с использованием GDB

По умолчанию карта памяти target отсылается к GDB. Это можно запретить следующей опцией конфигурации OpenOCD:

    gdb_memory_map disable

Чтобы эта функция работала корректно, также в OpenOCD должна быть корректно настроена конфигурация flash. Для увеличения быстродействия Вы также должны сконфигурировать правильную рабочую область.

Информирование GDB о карте память target разрешит GDB защитить все области flash на target и по умолчанию использовать аппаратные точки останова. Это означает, что OpenOCD опция option gdb_breakpoint_override не требуется, когда используется карта памяти. См. раздел 7.4. Конфигурация GDB.

Для просмотра сконфигурированной карты памяти в GDB используйте GDB-команду info mem. Все другие неназначенные адреса обрабатываются как RAM.

GDB версии 6.8 и более высокой не устанавливает любую область памяти как недоступную в карте памяти. Это можно изменить к старому поведению с использованием следующей GDB-команды:

    set mem inaccessible-by-default off

Если также используется gdb_flash_program enable, то GDB будет в состоянии программировать любую память flash, используя интерфейс vFlash.

GDB будет просматривать target memory map, когда дается команда загрузки; если любые области для программирования лежат внутри области target flash, то будут использоваться пакеты vFlash.

Если перед программированием через GDB нужно сконфигурировать target, может быть выполнен скрипт события (event script):

    $_TARGETNAME configure -event EVENTNAME BODY

Для проверки любого программирования flash можно использовать GDB-команду compare-sections.

21.5. Использование OpenOCD SMP вместе с GDB

Для поддержки SMP определены следующие пакеты последовательного протокола GDB:

• j - smp status request (запрос состояния SMP)
• J - smp set request (запрос установки SMP)

В OpenOCD реализовано:

• пакет jc для чтения core id, отображаемого соединением GDB. Ответ будет XXXXXXXX (8 hex цифр, дающих значение core id) или E01 для тех target-ов, которые не являются smp.
• пакет JcXXXXXXXX (8 hex цифр) для установки core id, отображаемого при дальнейшем возобновлении работы GDB (core id -1 зарезервирован для возврата в нормальный режим возобновления, normal resume mode). Возврат будет E01 для target-ов, не являющимися smp, или OK в случае успеха.

Обработка этого пакета внутри GDB может быть выполнена:

• Через создание внутренней переменной (например _core), подразумевается что из функции allocate_computed_value, позволив следующие GDB-команды.

    set $_core 1
    #Jc01 пакет отправлен
    print $_core
    #jc пакет отправлен, и результат затронет $

• Через команду обслуживания (GDB maintenance command), как описано в следующем примере (2 процессора в SMP с core id 0 и 1, см. раздел 6.3.4. Определение CPU target-ов, работающих в SMP).

    # переключение 0 (toggle0): отобразить coreid 0
    define toggle0
    maint packet Jc0
    continue
    main packet Jc-1
    end
    # переключение 1 (toggle1): отобразить coreid 1
    define toggle1
    maint packet Jc1
    continue
    main packet Jc-1
    end

[22. API скриптов языка TCL (Tcl Scripting API)]

22.1. Правила API

Команды не имеют своего состояния (stateless). К примеру, командная строка telnet имеет концепцию текущей активной цели. В Tcl API это реализовано через передачу информации о состоянии в качестве аргумента для каждой процедуры. Имеется три основных типа возвращаемого значения: одиночное значение (single value), список пар имя-значение (name value pair list) и списки (lists). В примере ниже процедура 'foo' возвращает список пар name/value.

> set foo(me) Duane
> set foo(you) Oyvind
> set foo(mouse) Micky
> set foo(duck) Donald

Если выполнить:

> set foo

то результат будет:

    me Duane you Oyvind mouse Micky duck Donald

Таким образом, можно просто получить имена ассоциативного массива:

    foreach { name value } [set foo] {
        puts "Name: $name, Value: $value"
    }

Возвращаемые списки должны быть относительно невелики. Иначе процедуре должен быть передан рассматриваемый диапазон.

22.2. Внутренние команды низкого уровня (Internal low-level Commands)

Команды низкого уровня не должны использоваться человеком напрямую. Они должны иметь префикс "ocd_", например ocd_flash_banks является командой low level API, с которой реализованы банки flash.

mem2array < varname > < width > < addr > < nelems >

Прочитать память и вернуть её как массив Tcl для обработки в скрипте.

array2mem < varname > < width > < addr > < nelems >

Сконвертировать массив Tcl в ячейки памяти и запись в них значений.

ocd_flash_banks < driver > < base > < size > < chip_width > < bus_width > < target > [driver
options ...]

Вернуть информацию о банках flash.

Команды OpenOCD могут состоять из двух слов например "flash banks". Скрипт startup.tcl оттранслирует эту неизвестную ("unknown") процедуру в процедуру Tcl, названную "flash_banks".

22.3. Глобальные переменные, относящиеся к OpenOCD (OpenOCD specific Global Variables)

Реальный язык Tcl имеет ::tcl_platform() и platform::identify, и множество других переменных. JimTCL, как это реализовано в OpenOCD, создает $ocd_HOSTOS, которая содержит одно из следующих значений:

cygwin работа идет в среде Cygwin.
darwin нижележащая операционная система Darwin (Mac-OS).
freebsd работа идет в среде FreeBSD.
linux нижележащая операционная система Linux.
mingw32 работа в среде MingW32 (Windows).
winxx собрано с использованием Microsoft Visual Studio (Windows).
other неизвестно, ничего из вышеперечисленного.

Примечания:
- было выбрано 'winxx', потому что на тот момент не было различий между Win32 и Win64.
- мы должны добавить поддержку для переменной наподобие Tcl переменной tcl_platform(platform), она должна называться jim_platform (потому что это jim,
не настоящий tcl).

[23. FAQ (часто задаваемые вопросы по OpenOCD)]

Q001. RTCK, также известное как Adaptive Clocking (адаптивное тактирование) - что это такое?

Разработка цифровых схем часто связано с "clock synchronisation" (тактовой синхронизацией) интерфейса JTAG, используя один тактовый сигнал (TCK или TCLK), работающий на некоторой скорости, при этом CPU target работает на другой скорости (на другой частоте). Эти две тактовые частоты не синхронизированы друг с другом, они "асинхронны".

Когда две задачи должны работать совместно, они так или иначе должны быть засинхронизированы; к примеру JTAG не может работать в 10 раз быстрее, чем CPU. Имеется 2 базовые опции:

(1). Использовать специальный узел "адаптивного тактирования" ("adaptive clocking") чтобы изменять тактовую частоту JTAG так, чтобы она соответствовала поддерживаемой для CPU в настоящий момент.
(2). Тактовая частота JTAG может быть зафиксирована на некотором значении, которая должна быть несколько ниже, чем тактовая частота CPU (чтобы он мог детектировать изменения сигналов TMS и TDI).

Имеет ли это в действительности какое-то значение? Для некоторых чипов и определенных ситуаций это не составит проблемы - например когда имеется 500 МГц ARM926 и линк JTAG на 5 МГц; CPU не будет сложно поддержать работу с JTAG. Последовательность запуска CPU может создать проблему, как и другие ситуации, когда изменяется тактовая частота CPU (возможно для входа в режим экономии энергии).

Например, чипы Atmel AT91SAM запускаются после сброса на системной тактовой частоте 32 кГц. Загрузочное firmware может активизировать главный генератор и PLL перед переключением на работу от повышенной тактовой частоты (возможно это будет 500 МГц для сценария с ARM926). Если Вы используете JTAG для отладки этой последовательности запуска (startup sequence), то Вы должны снизить тактовую частоту JTAG иногда до 1 .. 4 кГц. После завершения запуска JTAG может использовать повышенную тактовую частоту.

Имейте в виду, что при отладке 500 МГц ARM926 в портативном переносимом устройстве может перейти в режим низкого потребления на тактовой частоте 32 кГц (режим глубокого сна) - когда никаких операций не происходит, и пользователь не нажимает на клавиши. Разве будет в таком случае работать отладка с 5 МГц JTAG?

Решение №1 - специальный узел

Чтобы использовать эту возможность, Ваш CPU, плата и адаптер JTAG, все вместе должны поддерживать фичу RTCK. Не любое железо может поддерживать это, будьте внимательны!

Сигнал RTCK (означает "Return TCK", возвратный тактовый сигнал) на некоторых чипах ARM используется, чтобы помочь решить проблему с тактированием. По ссылке [6] для ARM есть хорошее описание проблемы. Заголовок статьи "How does the JTAG synchronisation logic work? / how does adaptive clocking work?" (Как работает логика синхронизации JTAG? Что делает адаптивное тактирование?).

Хорошая вещь, которую дает адаптивное тактирование - пример работы с переносным устройством, работающим от батарей - адаптивная подстройка частоты JTAG отлично работает все время. Можно установить точку останова или остановить систему прямо в коде глубокого сна (deep power down), и медленно выполнять шаги до тех пор, пока не повысится тактовая частота системы.

Имейте в виду, что адаптивное тактирование может потребовать поддержки работы на уровне платы, когда цепочка JTAG (scan chain) состоит из нескольких чипов. Системы параллельного тактирования (parallel clock voting scheme) хороший метод реализации и внутри чипов, и между чипами, и может быть просто реализована на CPLD. Несложно иметь модуль логической разводки входного сигнала TCK на каждый TAP в цепочке сканирования (scan chain), и затем ждать, пока RTCK каждого TAP-а вернется обратно в правильную полярность перед изменением выходного сигнала RTCK. Компания предоставила такую логику голосования тактов (clock voting logic) в форме кода VHDL (без техподдержки), см. "Adaptive Clocking site:processors.wiki.ti.com".

Решение №2 - работать всегда одинаково - может быть медленнее

Часто этот вариант является самым лучшим допустимым решением. Если объяснять просто, то часто тактовая частота JTAG должна быть от 1/10 до 1/12 от тактовой частоты target. Но такой "магический делитель" варьируется в зависимости от чипов на Вашей плате.

Базовое правило для большинства систем на ARM требует делителя 6:1; ядра ARM11 используют деление 8:1. Правило для Xilinx: 1/12 от тактовой частоты.

Внимание: большинство адаптеров на FT2232 в полноскоростном режиме (USB full speed) ограничены максимальной частотой 6 МГц. Те адаптеры, которые используют высокоскоростные чипы (USB high speed, наподобие FT2232H) часто поддерживают более высокую тактовую частоту (и адаптивное тактирование).

Вы все еще можете отлаживать ситуации с низким потреблением - Вам просто надо либо использовать очень низкую тактовую частоту JTAG (и мириться с низкой скоростью работы) ... либо каждый раз подстраивать тактовую частоту вручную (на практике подстройка слишком болезненна и сложна, чтобы её можно было использовать).

Однако может быть простым "кодировать вокруг" - т. е. немного подстроить Ваш код, чтобы он имел специальный режим отладки, когда Ваша программа переходит в "режим сна с высоким энергопотреблением". Если все сделать правильно, то 98% проблем можно отладить таким способом.

Имейте в виду, что на ARM может потребоваться избегать инструкции wait for interrupt в циклах ожидания, даже если Вы не меняете тактовую частоту CPU. Эта инструкция останавливает подачу тактовой частоты для CPU и часто также на JTAG, что не дает доступа к JTAG. Как следствие - нельзя остановить (halt) программу ядер, которые выполняют операцию wait for interrupt.

Для установки тактовой частоты JTAG используйте команду:

    # Пример установки 1.234 МГц:
    adapter_khz 1234

Q002. Имена и пути Win32. Почему обратные слеши (backslash) не работают в путях Windows?

OpenOCD использует язык Tcl и backslash является специальным управляющим символом escape. Используйте фигурные скобки { и } вокруг имен файловой системы Windows.

    > echo a
 
    > echo {a}
    a
    > echo "a"
 
    >

Q003. Missing: cygwin1.dll. OpenOCD жалуется на отсутствие cygwin1.dll.

Убедитесь, что установлен Cygwin, или как минимум установлена та версия OpenOCD, которая заявляет о наличии всех нужных DLL. Когда используется Cygwin, попробуйте запустить OpenOCD из шелла Cygwin.

Q004. Проблема с точкой останова. Я пытаюсь установить breakpoint, используя GDB (или оболочку наподобие Insight или Eclipse), но OpenOCD жалуется, что "Info: arm7_9_common.c:213 arm7_9_add_breakpoint(): sw breakpoint requested, but software breakpoints not enabled" (выдан запрос на установку breakpoint, но точки останова не разрешены).

GDB выдает программную точку останова (software breakpoint) когда был запрос на обычную точку останова (normal breakpoint), или для реализации пошагового выполнения по тексту исходного кода. На системах ARMv4T, наподобие ARM7TDMI, ARM720T или ARM920T, программные точки останова задействуют две доступные аппаратные точки останова (hardware breakpoint). Помните, что количество аппаратных точек останова ограничено.

Q005. LPC2000 Flash. Когда очищается или записывается встроенная в чип flash кристалла LPC2000, система падает случайным образом.

Убедитесь, что частота ядра, указанная в строке flash lpc2000 соответствует тактовой частоте в тот момент, когда Вы программируете flash. Если Вы указали частоту кристалла, то убедитесь, что PLL запрещена. Если Вы указали действительную частоту ядра (например 60 МГц), то убедитесь, что PLL разрешена и тактовая частота CPU установлена правильно.

Q006. Amontec Chameleon. При отладке с использованием Amontec Chameleon в его конфигурации с акселератором JTAG, я получаю ошибку "Error: amt_jtagaccel.c:184 amt_wait_scan_busy(): amt_jtagaccel timed out while waiting for end of scan, rtck was disabled" (таймаут при ожидании окончания сканирования, сигнал RTCK был запрещен). Убедитесь, что параллельный порт PC (LPT) работает в режиме EPP. Вы можете попробовать разные установки в BIOS (ECP, EPP и другие варианты настройки LPT).

Q007. Data Abort-ы. При отладке через OpenOCD и GDB (чистый GDB, Insight или Eclipse), я получаю много ошибок "Error: arm7_9_common.c:1771 arm7_9_read_memory(): memory read caused data abort".

Ошибки не фатальные, и в результате GDB пытается трассировать фреймы стека возле последнего нормального фрейма. Возможно, что получится предотвратить это установкой правильного "изначального" фрейма стека, так что если Вы знаете, что нужно для этого сделать, то не стесняйтесь.

Простой случай: в коде запуска (startup code) - задвиньте (push) 8 обнуленных регистров в стек перед вызовом main(). GDB поднимается по стеку времени выполнения путем чтения разных значений в стеке с использованием стандартных фреймов вызова target. GDB продолжает этот делать, пока не произойдет одна из двух вещей - #1 нахождение недопустимого фрейма, или #2 обрабатывается некоторое большое число стековых фреймов. Путем проталкивания нулей в стек GDB корректно останавливается.

Отладка обработчиков прерываний - в Вашем ISR до вызова кода на C, сделайте то же самое - искусственно протолкните (push) несколько нулей в стек, и не забудьте их потом вытолкнуть (pop) оттуда, когда ISR завершит свою работу.

Также имейте в виду: если у Вас многопоточная операционная система, то она часто тратит впустую эти несколько байтов.

Q008. JTAG Reset Config (конфигурация сброса JTAG). Я получаю следующее сообщение в консоли OpenOCD (или в log-файле): "Warning: arm7_9_common.c:679 arm7_9_assert_reset(): srst resets test logic, too" (сигнал SRST также сбросил и логику тестирования).

Это предупреждение не показывает на какую-нибудь серьезную проблему, пока Вы не хотите отладить поведение ядра сразу после сигнала сброса. Ваш файл .cfg указал jtag_reset trst_and_srst srst_pulls_trst, чтобы сказать OpenOCD, что либо Ваша плата, Ваш отладчик или Ваш target-микроконтроллер (например LPC2000) не может выдать два сигнала сброса независимо. С этой настройкой нельзя остановить ядро сразу после сброса, все остальное должно работать нормально.

Q009. USB Power (питание от порта USB). Когда используется OpenOCD совместно с Amontec JTAGkey и тулчейном Yagarto (Eclipse, arm-elf-gcc, arm-elf-gdb), отладка выглядит нестабильной. При пошаговом выполнении через большие блоки кода, GDB и OpenOCD делают выход с сообщением об ошибке. Это проблема стабильности OpenOCD?

Нет, это не проблема стабильности OpenOCD. Большинство пользователей решают эту проблему, просто используя USB хаб с отдельным питанием, к которому они подключают свой Amontec JTAGkey. Очевидно, что некоторые компьютеры не могут предоставить стабильное питание от USB той мощности, которую потребляет Amontec JTAGkey. Лаптопы, которые работаю от батареи, также имеют такую проблему...

Q010. USB Power (питание от порта USB). Когда используется Amontec JTAGkey, иногда OpenOCD падает со следующими сообщениями об ошибках: "Error: ft2232.c:201 ft2232_read(): FT_Read returned: 4" (подпрограмма чтения чипа FTDI вернула 4) и "Error: ft2232.c:365 ft2232_send_and_recv(): couldn’t read from FT2232" (не работает чтение из FT2232). Что это означает и в чем причина?

Прежде всего причиной могло бы быть электропитание USB. Попробуйте использовать хаб с самостоятельным отдельным питанием вместо прямого подключения к Вашему компьютеру. Второе, что может быть - код ошибки 4 соответствует FT_IO_ERROR; это означает, что драйвер для чипа FTDI USB столкнулся с некоторыми проблемами, что указывает на проблему с интерфейсом USB.

Q011. GDB Disconnects (отладчик GDB отключается). Когда используется Amontec JTAGkey, иногда OpenOCD падает со следующим сообщением об ошибке: "Error: gdb_server.c:101 gdb_get_char(): read: 10054". Что это означает и в чем причина?

Код ошибки 10054 соответствует WSAECONNRESET, что означает, что отладчик (GDB) закрыл соединение с OpenOCD. Это может быть проблема GDB.

Q012. LPC2000 Flash. В файле конфигурации, в той секции, что описывается конфигурация устройства flash, имеется параметр для указания тактовой частоты для внутренних flash-устройств LPC2000 (например flash bank $_FLASHNAME lpc2000 0x0 0x40000 0 0 $_TARGETNAME lpc2000_v1 14746 calc_checksum), который должен быть указан в килогерцах. Однако у меня кристалл кварца на частоту, которая содержи дробную часть от килогерца (например 14745600 Гц, или 14745.600 кГц). Можно ли использовать для тактовой частоты не целые, а реальные числа?

Нет. Тактовая частота, которая указывается здесь, должна быть указана в виде целого числа. Однако эта тактовая частота используется подпрограммами In-Application-Programming (IAP) только для семейства LPC2000, которые весьма толерантно относятся к указанной тактовой частоте, так что незначительная разница между указанной частотой тактов и актуальной не приведет ни к каким проблемам.

Q013. Command Order (порядок следования команд). Нужно ли мне придерживаться определенного порядка команд в конфигурационном файле?

И да, и нет. Команды можно указывать в произвольном порядке, но все же перечисленные устройства для JTAG scan chain должны быть даны в правильном порядке (jtag newdevice), при этом устройства, находящиеся ближе к выводу TDO, должны быть в списке первыми. Общее правило - когда имеются объекты одного типа, которые требуют номера индекса, эти объекты должны появляться в правильном порядке (jtag newtap, targets и flash banks - ссылки на target в jtag newtap и ссылки на flash bank для target).

Вы можете использовать команду "scan_chain" для проверки и отображения порядка следования tap.

Также некоторые команды не могут быть обработаны, пока не произойдет инициализация init. Такие команды включают nand probe и многие другие, для которых нужно записывать регистры контроллера, возможно для настройки DRAM и загрузки в него кода.

Q014. JTAG TAP Order (порядок следования JTAG TAP). Нужно ли мне декларировать TAP-ы в некотором особом порядке?

Да; всякий раз, когда TAP-ов больше одного, Вы должны декларировать их в том же самом порядке, как они используются в аппаратуре.

Многие новые устройства имеют несколько JTAG TAP. Например чипы STM32 компании ST Microsystems имеют два TAP-а, "boundary scan TAP" (TAP для пограничного сканирования) и "Cortex-M3" TAP. Пример: STM32 reference manual, Document ID: RM0008, секция 26.5, рисунок 259, страницы 651/681, ножка "TDI" подключена к boundary scan TAP, который затем подключен к Cortex-M3 TAP, выход которого затем подключен к выводу TDO. Таким образом, правильный порядок конфигурирования для чипа STM32 такой: (1) Cortex-M3, затем (2) boundary scan TAP. Если Ваша плата включает дополнительные чипы JTAG в scan chain (например Xilinx CPLD или FPGA), Вы должны их разместить в цепочке сканирования раньше или позже STM32 (в зависимости от схемы включения сигналов TDI и TDO). Например:

• OpenOCD TDI (выход) -> STM32 ножка TDI (вход BS)
• STM32 BS TDO (выход) -> STM32 Cortex-M3 TDI (вход)
• STM32 Cortex-M3 TDO (выход) -> SM32 ножка TDO
• STM32 ножка TDO (выход) -> Xilinx ножка TDI (вход)
• Xilinx ножка TDO -> OpenOCD TDO (вход)

Таким образом, команды "jtag device" должны следовать в порядке, указанном ниже. Обратите внимание:

• jtag newtap Xilinx tap -irlen ...
• jtag newtap stm32 cpu -irlen ...
• jtag newtap stm32 bs -irlen ...
• # Создание target отладки, и указание, где она находится
• target create stm32.cpu -chain-position stm32.cpu ...

Q015. SYSCOMP. Иногда моя сессия отладки прекращается с ошибкой. Когда я смотрю в лог-файл, то вижу сообщения об ошибке: "Error: arm7_9_common.c:561 arm7_9_execute_sys_speed(): timeout waiting for SYSCOMP" (таймаут ожидания SYSCOMP). Эта проблема пока не исправлена (TODO).

[24. Краш-курс (быстрый экскурс) в Tcl]

Не все знают Tcl и этот раздел не предназначен для замены обучения Tcl, его назначение дать Вам некоторые идеи по поводу токо, как работают скрипты Tcl. Раздела предназначен для 2 категорий пользователей. (1) пользователи OpenOCD, которые хотят понять несколько больше о работе Jim-Tcl, чтобы его можно было полезнее использовать, и (2) пользователи, которые хотели бы добавить новую команду к OpenOCD.

24.1. Tcl правило №1

Может показаться смешным, но правила работают примерно так:

1. Правило №1: жена права всегда.
2. Правило №2: если Вы думаете иначе, то см. правило №1.

Эквивалент для языка Tcl следующий:

1. Правило №1: абсолютно все является строкой.
2. Правило №2: если Вы думаете иначе, то см. правило №1.

Как и в известной шутке, следствия из правила #1 весьма глубоки. Если Вы поймете правило №1, то Вы поймете Tcl.

24.2. Tcl правило №1b

Вот вторая пара правил.

1. Правило №1: нет управления потоком выполнения (control flow) does not exist. Есть только команды.
Например: классические циклы FOR или операторы IF не являются элементов управления потоком выполнения, они команды, в Tcl нет такого понятия как поток выполнения.

2. Правило №2: если Вы думаете иначе, то см. правило №1.
На самом деле вот что происходит: есть команды, которые по соглашению работают наподобие ключевых слов управления потоком в других языках. Одна из таких команд слово "for", другая команда "if".

24.3. Из правила №1 следует - все результаты являются строками

Результат каждой команды Tcl является строкой. Слово "результат" используется сознательно. Отсутствие результата является пустой строкой. Помните правило №1: абсолютно все является строкой.

24.4. Операторы кавычек Tcl (Quoting Operators)

В жизни скрипта Tcl есть два важных периода времени, различие между ними тонкое.

1. Время анализа скрипта (Parse).
2. Время вычислений скрипта (Evaluation).

Эти два ключевых понятия дают понять о том, как в Tcl работает "нечто заковыченное". Tcl имеет 3 главные конструкции со кавычками, [квадратные скобки], {фигурные скобки} и "двойные кавычки".

Вы уже должны знать, что переменные ($VARIABLES) всегда начинаются со значка доллара ($DOLLAR). Кстати: чтобы установить переменную, Вы должны использовать команду "set", как в "set VARNAME VALUE", который работает как оператор LET в древнем языке BASIC "let x = 1", но без знака '='.

• [square-brackets]

[квадратные скобки] являются заменой команды. Они работают как в скриптах Unix Shell работает символ '`' (backtick). Результатом операции [квадратные скобки] является 1 строка (помните правило №1). Эти два оператора полностью идентичны:

    # пример bash
    X=‘dateecho "The Date is: $X"
    # пример Tcl
    set X [date]
    puts "The Date is: $X"

• "double-quoted-things"

"Двойные кавычки" являются просто заключенным в кавычки текстом. Переменные $VARIABLES и [квадратные скобки] расширяются, и в результате однако получается снова 1 строка (правило №1: абсолютно все является строкой).

    set x "Dinner"
    puts "It is now "[date]", $x is in 1 hour"

• {Curly-Braces}

{Фигурные скобки} являются магическими: $VARIABLES и [square-brackets] анализируются, но не расширяются и не выполняются. {Фигурные скобки} работают как операторы 'одиночная кавычка' в скриптах BASH shell, с добавленной особенностью: {фигурные скобки} можно иерархически встраивать друг в друга, а одиночные кавычки нельзя: {{{это встроено трижды}}}. Имейте в виду: [date] является плохим примером; на момент написания этого текста Jim/OpenOCD не имел команды date.

24.5. Следствия из правил Rule 1/2/3/4

Самые важные последствия исходят из правила 1.

24.5.1. Разделение на токены и выполнение (Tokenisation & Execution)

Конечно, пробелы, пустые строки и #комментарии обрабатываются как обычно. При анализе скрипта каждая строка (или блок из нескольких строк) в файле скрипта токенизируется по правилам кавычек. После токенизации каждая строка немедленно выполняется. Многострочные операторы с одной или большим количеством "все еще открытых" {фигурных скобок}, которые впоследствии будут закрыты на несколько строк дальше.

24.5.2. Выполнение команд

Помните, о чем мы уже говорили: в Tcl нет операторов управления потоком выполнения. Вместо этого есть КОМАНДЫ, которые просто работают так же, как и обычные операторы управления потоком.

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

1. Анализируется следующая строка, в результате получаются (argc) и (argv[]).
2. Просматривается (argv[0]) в таблице и вызывается его функция.
3. Все повторяется до окончания файла (End Of File).

Алгоритм можно представить так:

    for(;;)
    {
        ReadAndParse( &argc, &argv );
        cmdPtr = LookupCommand( argv[0] );
        (*cmdPtr->Execute)( argc, argv );
    }

Когда команда "proc" анализируется (это создает процедуру функции), она получает 3 параметра командной строки. 1 имя proc (процедуры) или function (функции), 2 список параметров, и 3 тело функции. Не перепутайте LIST (список) и BODY (тело). Команда PROC сохраняет эти элементы в таблице, откуда их можно получить через "LookupCommand()".

24.5.3. Команда FOR

Самая интересная для рассмотрения команда FOR. В Tcl команда FOR нормально реализована на C. Помните, что FOR является такой же командой, как и все остальные. Когда анализируется (parse) текст ascii, содержащий команду FOR, парсер создает строки 5 параметров (если есть сомнения, то см. правило №1), вот они:

0. Текст ascii 'for'.
1. Начальные текст (start text).
2. Выражение для проверки условия (test expression).
3. Дальнейший текст (next text).
4. Текст тела (body text).

Не напоминает ли это Вам "main( int argc, char **argv )"? Помните правило №1 - все является строкой. Ключевая точка в следующем: часто многие из этих параметров заключены в {фигурные скобки} - так что переменные внутри пока не расширяются и не заменяются. Помните, что любая команда Tcl выглядит наподобие классической функции "main( argc, argv )" на C. В JimTCL она выглядит примерно так- they actually look like this:

    int MyCommand( Jim_Interp *interp,
                   int *argc,
                   Jim_Obj * const *argvs );

Реальный Tcl работает примерно так же. Хотя новые версии представляют побайтный парсер и интерпретатор, но все равно он работает по такому же базовому принципу.

24.5.4. Реализация команды FOR

Для понимания возможно полезнее всего рассмотреть команду FOR. Помните, что это КОМАНДА, не структура управления потоком.

В Tcl имеется две нижележащие функции-помощника C (helper function). Всегда помните правило №1 - Вы являетесь строкой.

Первый хелпер анализирует (parse) и исполняет команды, которые находит в строке ascii. Команды могут отделяться друг от друга точками с запятой (semicolon), или новыми строками. При анализе переменные расширяются по правилам кавычек.

Второй хелпер вычисляет строку ascii как числовое выражение, и возвращает значение. Здесь приведен пример того, как могла бы быть реализована команда FOR. В псевдокод ниже не показана обработка ошибок.

void Execute_AsciiString( void *interp, const char *string );
 
int Evaluate_AsciiExpression( void *interp, const char *string );
 
int MyForCommand( void *interp,
                  int argc,
                  char **argv )
{
    if( argc != 5 )
    {
        SetResult( interp, "WRONG number of parameters");
        return ERROR;
    }
    // argv[0] = строка ascii как в C
    // Выполнение стартового оператора.
    Execute_AsciiString( interp, argv[1] );
    // вершина цикла с проверкой
    for(;;)
    {
        i = Evaluate_AsciiExpression(interp, argv[2]);
        if( i == 0 )
            break;
        // Выполнение тела
        Execute_AsciiString( interp, argv[3] );
        // Выполнение части LOOP (переводится как ЦИКЛ)
        Execute_AsciiString( interp, argv[4] );
    }
    // Возврат, что нет ошибки
    SetResult( interp, "" );
    return SUCCESS;
}

Все другие команды IF, WHILE, FORMAT, PUTS, EXPR, работают по такому же базовому принципу.

24.6. Как использовать Tcl в OpenOCD (OpenOCD Tcl Usage)

24.6.1. Команды source и find

Где находятся: во многих файлах конфигурации.
Пример: source [find FILENAME]

Помните о правилах анализа Tcl (parsing rules):

1. Команда find в квадратных скобках, и она выполняется с параметром FILENAME. Эта команда найдет и вернет полный путь до файла с указанным именем; при этом используется внутренний путь поиска. Результатом является строка, которая подставляется в командную строку заместо заключенной в квадратные скобки команды find. Не пытайтесь использовать FILENAME, содержащее символ '#'. С этого символа начинаются комментарии Tcl.
2. Команда source выполняется с найденным именем файла; она читает и выполняет файла как скрипт.

24.6.2. Команда format

Где находится: обычно в разных местах.

В языке Tcl нет команды типа printf(), вместо неё имеется format, которая больше похожа на sprintf(). Пример:

    set x 6
    set y 7
    puts [format "The answer: %d" [expr $x * $y]]

1. Команда SET создает 2 переменные, X и Y.
2. Дважды [вложенная] команда EXPR производит математические действия. Команда EXPR производит числовой результат в виде строки (см. правило №1).
3. Выполняется команда format, в результате чего получается снова одна строка (см. правило №1).
4. Команда PUTS выводит текст.

24.6.3. Тело или встроенный текст (Body or Inlined Text)

Где находится: различные скрипты для TARGET.

    #1 Хорошо
       proc someproc {} {
           ... multiple lines of stuff ...
       }
    $_TARGETNAME configure -event FOO someproc
    #2 Хорошо - нет переменных
       $_TARGETNAME confgure -event foo "this ; that;"
    #3 Хорошие фигурные скобки
       $_TARGETNAME configure -event FOO {
           puts "Time: [date]"
       }
    #4 ОПАСНО ОПАСНО ОПАСНО
       $_TARGETNAME configure -event foo "puts "Time: [date]""

1. $_TARGETNAME соответствует соглашениям об именах переменных OpenOCD. $_TARGETNAME представляет последнюю созданную target, значение меняется каждый раз при создании новой target. Помните правила парсинга. Когда парсируется текст ascii, $_TARGETNAME становится простой строкой, передающей имя target к команду TARGET (объект).
2. 2-й параметр -event является TCBODY.

Имеется 4 случая:

1. TCLBODY является простой строкой, которая является именем процедуры.
2. TCLBODY это несколько простых команд, разделенных друг от друга точками с запятой.
3. TCLBODY является многострочным блоком в {фигурных скобках}.
4. TCLBODY является строкой, куда были расширены переменные.

В результате, когда происходит target-событие FOO, вычисляется TCLBODY. Методы #1 и #2 функционально идентичны. Методы #3 и #4 являются более интересными. Что же такое TCLBODY?

Вспомните правила парсинга. В случае #3 {фигурные скобки} означают, что переменные $VARS и [все что в квадратных скобках] будут расширены позже, когда произойдет событие EVENT, и текст будет вычислен. В случае #4 они будут заменены до выполнения "Target Object Command (команда объекта цели)". Это произойдет тогда, когда будет заменено $_TARGETNAME. В случае #4 date не поменяется. {Кстати: [date] является плохим примером; на момент написания этого текста в Jim/OpenOCD не было команды date}

24.6.4. Глобальные переменные

Где искать: разберитесь с этим, когда будете писать собственные процедуры.

В простых терминах: если внутри процедуры Вам нужно получить доступ к глобальным переменным, то нет проблем. См. также "upvar". Пример:

    proc myproc { } {
        set y 0 #Local variable Y
        global x #Global variable X
        puts [format "X=%d, Y=%d" $x $y]
    }

24.7. Другие хитрости языка TCL (Other Tcl Hacks)

Динамическое создание переменных (Dynamic variable creation)

    # Динамическое создание набора переменных.
    for { set x 0 } { $x < 32 } { set x [expr $x + 1]} {
        # Создание имени переменной
        set vn [format "BIT%d" $x]
        # Переменная делается глобальной
        global $vn
        # Переменная устанавливается.
        set $vn [expr (1 << $x)]
    }

Динамическое создание процедуры/команды (Dynamic proc/command creation)

    # Одна функция "X" - 5 функций uart.
    foreach who {A B C D E} {
        proc [format "show_uart%c" $who] { } "show_UARTx $who"
    }

[Словарик]

adaptive clocking адаптивное тактирование JTAG [6]. Суть в том, что тактовая частота интерфейса автоматически выбирается близкой к максимально возможной тактовой частоте - с целью увеличить скорость и надежность отладки.

AP Access Port - порт доступа, имеется в виду DAP.

big endian - порядок следования байт в многобайтовых типах данных (short, int, long, long long, int64 и т. п.), когда старший байт идет в памяти первым.

BIST built-in self-test, встроенная самопроверка (самотестирование).

bitbang, bit-banging программное управление состоянием бит.

Boiler Plate Code шаблон (кусок) кода, часто используемый повторно. Выполняет те же функции, что и макросы или процедуры.

boundary scan дословный перевод "периферийное сканирование", имеется в виду внутрисхемное тестирование электронных схем через интерфейс JTAG [2].

breakpoint точка останова.

BS Boundary Scan - специальная технология, предназначенная для внутрисхемного тестирования цифровых схем.

BSDL от сокращения Boundary Scan Description Language — это текстовый файл, написанный на VHDL-подобном языке описания для периферийного сканирования, содержащий информацию об архитектуре регистров периферийного сканирования микросхемы. Является частью стандарта IEEE 1149.1. Эти файлы обычно доступны для скачивания с сайтов производителей. Системы периферийного сканирования используют эти файлы для доступа к JTAG-цепи электронной платы, а также для автоматической генерации тестовых векторов для проверки цепей, связанных с данной микросхемой.

CPLD Complex Programmable Logic Device — программируемая логическая интегральная схема (ПЛИС) в диапазоне сложности между микросхемами PAL (Programmable Array Logic) и FPGA (Field-Programmable Gate Array), сочетающая их архитектурные решения.

DAP Debug Access Port - порт доступа для отладки.

DCC Debug Communications Channel, отладочный канал обмена.

debug adapter, hardware interface dongle специальный интерфейс, который с одной стороны подключен к хосту отладки через USB, а с другой через JTAG к отлаживаемой системе. Примеры таких адаптеров - R-Link, MT-LINK, J-Link, Wiggler, opendous и т. п.

debug host хост отладки - компьютер PC, на котором запущено отладочное программное обеспечение (в нашем случае OpenOCD), и к которому через USB (с помощью debug adapter) подключена отлаживаемая система. Обычно на хосте отладки работает разработчик - на этом компьютере запущена IDE (программная система разработки).

dongle донгл - в контексте данной статьи имеется в виду маленькое аппаратное устройство, которое соединяет компьютер (подключаясь через USB или LPT) и отлаживаемое устройство.

DWT Data Watchpoint and Trace - предоставляет набор функций, которые собирают информацию из системных шин и генерируют события для ITM, чтобы отладочная информация вместе с метками времени была упакована и далее передавалась через канал SWO.

ECC Error Correcting Code, код коррекции и исправления ошибок.

ENDIAN, endianness установленный для чипа порядок байт для слова, см. big endian, little endian. То есть в каком порядке размещается слово (shord, int, long, long long, WORD, DWORD, int64 и т. п.) в памяти, от старшего байта к младшему.

errata - официальное подтверждение собственных ошибок производителем чипа. В errata приводится описание ошибок (в чем ошибка заключается, при каких условиях возникает). Также имеются советы как избежать или устранить (если это возможно) проблемы, связанные с ошибкой.

ETB Embedded Trace Buffer

ETM Embedded Trace Macrocell

firmware, application code программное обеспечение микроконтроллера, которое обычно отлаживается с помощью адаптера отладки JTAG.

FPGA Field Programmable Gate Array - массив программируемых логических вентилей.

GDB GNU Debugger, бесплатное программное обеспечение для отладки (исполняемый файл имеет имя gdb) - стандартный отладчик для операционных систем GNU (Linux и т. п.). Однако, применение GDB не ограничено строго именно для GNU operating system; этот отладчик может быть запущен на многих Unix-совместимых системах для многих языков программирования, включая Ada, C, C++, Objective-C, Free Pascal, Fortran, Java и некоторых других.

GPIO General Purpose Input/Output, порт ввода/вывода общего назначения. Обычно это ножка микроконтроллера, режим работы которой (вход это или выход, подключен или нет нагрузочный резистор и т. п.) и состояние (для выхода: лог. 0 или лог. 1) может программироваться и изменяться под управлением firmware.

GPNVM General Purpose Non-Volatile Memory - дословный перевод "энергонезависимая память общего назначения". Термин, относящийся к микроконтроллерам ARM от Atmel, обычно обозначает специальные биты для конфигурирования этих чипов.

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

I/O Input/Output, ввод/вывод, обычно относится к портам ввода/вывода.

ISC In-System-Configurable - устройства, конфигурируемые в системе.

ISR Interrupt Service Routine

ITM Instrumentation Trace Macrocell - основная часть логики отладки ядер ARM Cortex-M3/M4. Это облегченная трассировка, которая предоставляет выбранные данные трассировки через низкоскоростной порт доступа. Польза состоит в том, что Вам не нужна отдельная проба трассировки, чтобы это использовать, большинство проб SWD могут поддерживать функционал трассировки, доступный в ITM.

JRC JTAG route controller - специальная микросхема, которая переключает несколько интерфейсов JTAG в один.

JTAG [1] специальный стандартный последовательный интерфейс, предназначенный для подключения электронных устройств к оборудованию тестирования и отладки (обычно персональный компьютер со специальным программным обеспечением).

JTAG scan chain цепочка сканирования JTAG.

LED Light Emitting Diode, светодиод.

little endian порядок следования байт в многобайтовых типах данных (short, int, long, long long, int64 и т. п.), когда младший байт идет в памяти первым.

memory map карта памяти, обычно имеется в виду распределение адресного пространства target под разные функциональные части процессора - RAM, FLASH, таблица векторов прерываний, регистры периферийных устройств и т. д.

MLC Multilevel cell - специальная технология производства ячеек памяти (обычно для NAND flash).

MMU Memory Management Unit - блок управления памятью.

MPU Memory Protection Unit

NVIC Nested Vectored Interrupt Controller - контроллер приоритетных векторных прерываний.

OOB аббревиатура от out of band (вне диапазона) - дополнительные данные сектора, содержащие коды коррекции ошибок (Error Correcting Code, ECC)

PLD Programmable Logic Device - программируемая логическая микросхема.

PLL Phase Looked Loop (дословно "цикл фиксации фазы") - фазовая автоподстройка частоты. Применяется в синтезаторах (умножителях) тактовой частоты микроконтроллера.

pulldown нижний нагрузочный резистор, притягивающий логический уровень сигнала к земле (получается лог. 0, если все выходы на этом сигнале находятся в третьем состоянии).

pullup верхний нагрузочный резистор, притягивающий логический уровень сигнала к + питания (получается лог. 1, если все выходы на этом сигнале находятся в третьем состоянии).

push-pull двухтактный выход.

RPC Remote Procedure Call - сетевой вызов процедуры. Термин относится к программированию и к операционным системам.

RTCK тактовый сигнал, используемый опцией адаптивного тактирования на синтезируемых ядрах (Adaptive clocking). Эта возможность представлена ARM® Ltd., здесь входная тактовая частота тестирования (TCK) выдается в задержке (с синхронизацией) перед тем, как получить результирующую выходную тактовую частоту (resulting output clock, RTCK).

RTOS Real-Time Operational System - операционная система реального времени.

semihosting, семихостинг механизм для ARM targets для обмена входными/выходными сообщениями из кода приложения с хостом, на котором запущен отладчик. Этот механизм должен использоваться, к примеру, чтобы разрешить функции библиотеки C, такие как printf() and scanf(), для использования экрана и клавиатуры хоста, а не экрана и клавиатуры target system. Такая возможность полезна, так как разрабатываемая аппаратура часто не имеет всех входных и выходных возможностей конечной системы. Семихостинг позволяет хосту предоставить такие возможности.

SMP symmetric multiprocessing - симметричная многопроцессорная среда выполнения программ.

SoC system-on-chip система на чипе.

SVF Serial Vector Format

SWD Serial Wire Debug - специальный режим (протокол) интерфейса отладки.

SWO Serial wire output - высокоскоростной канал, который передает пакеты от ITM (instrumentation trace macrocell, инструментальные макроячейки трассировки) к отладчику без остановки выполнения кода ядром. Использует кодирование либо serial, либо Manchester. Это предоставляет очень полезный функционал вместе с использование ITM и DWT. SWO требует режима отладки SWD, и не может использоваться в режиме JTAG.

TAP Test Access Port, порт тестирования (термин относится к JTAG) - четыре или пять выделенных выводов микросхемы: ТСК, TMS, TDI, TDO и (опционально) TRST.

target, target device, target system, target chip цель отладки, обычно обычно это подключенный через JTAG микроконтроллер или тестируемая схема.

target board целевая плата - обычно на ней стоит отлаживаемый через JTAG микроконтроллер или тестируемая схема.

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

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

WFI специальная команда Wait for Interrupt, переводящая микроконтроллер в режим ожидания прерывания. Обычно в этом режиме процессор потребляет меньше энергии, пока не произойдет прерывание.

OpenOCD: руководство пользователя, начало
OpenOCD: руководство пользователя, продолжение

[Ссылки]

1. JTAG site:ru.wikipedia.org.
2. Boundary scan, периферийное сканирование site:ru.wikipedia.org.
3. OpenOCD web site site:openocd.sourceforge.net.
4. Самая свежая документация по OpenOCD, Latest HTML OpenOCD User’s Guide site:openocd.sourceforge.net. PDF OpenOCD User’s Guide site:openocd.sourceforge.net.
5. Цоколевка интерфейсов JTAG.
6. How does the JTAG synchronisation logic work? / How does adaptive clocking work? site:infocenter.arm.com.