Как проверить связь с чипом (определить, подключен ли чип) с помощью OpenOCD
1. Проблема объяснена
Я пытаюсь использовать OpenOCD для чего-то необычного. Вместо того, чтобы подключаться к чипу, я хотел бы просто обнаружить чип.
Процедура, которую я имею в виду, будет выглядеть так:
Запустите OpenOCD с помощью файла конфигурации зонда (например,
stlink.cfg
) дано как-f
параметр. Таким образом, OpenOCD знает, какой зонд использовать, но не знает, какой чип он найдет.OpenOCD обнаруживает чип и как-то сообщает об этом (например, записывает что-то в стандартный вывод). Если возможно, это действие не должно быть навязчивым для чипа (например, его сброс).
OpenOCD закрывается.
Вот еще несколько заметок о процедуре:
Примечание 1: Было бы хорошо, если бы OpenOCD не достиг состояния сервера, где мне нужно настроить клиент Telnet или GDB для взаимодействия с ним. Я был бы рад сообщить об обнаружении чипа более удобным способом, например, получить информацию о чипе на канале stdout.
Примечание 2: Обнаружение должно быть незаметным для чипа. Однако, если OpenOCD ничего не находит, я бы хотел использовать метод резервного копирования, при котором OpenOCD пытается найти чип более агрессивно (например, удерживая нажатой клавишу nRST
штырь). Я могу при необходимости использовать этот другой подход самостоятельно (поэтому OpenOCD не нужно делать это автоматически).
Примечание 3: Сначала я просто применю это "обнаружение микросхем" только к микросхемам STM32 с пробниками STLinkV2 или STLinkV3, а позже и к другим пробникам и микросхемам.
Примечание 4: Некоторые платы имеют только подключение SWD (без JTAG).
Примечание 5: я работаю на компьютере с Windows 10 и получил очень свежую сборку OpenOCD (версия 0.10.0_dev00921, построенную 06 июля 2019 года), загруженную с https://www.playembedded.org/blog/download/
2. Что я пробовал до сих пор
Г-н Томми Мерфи направил меня к разделу 10.7 справочного руководства по OpenOCD (см. Http://openocd.org/doc/pdf/openocd.pdf). Я прочитал раздел и заметил следующий пример:
# openocd.cfg file
# -----------------
source [find interface/olimex-arm-usb-tiny-h.cfg]
reset_config trst_and_srst
jtag_rclk 8
Поскольку моя микросхема подключается череззонд STLink и использует транспортный протокол SWD (вместо JTAG), я сделал несколько изменений в примере:
# openocd.cfg file
# -----------------
source [find interface/stlink.cfg]
transport select hla_swd
reset_config srst_only
adapter_khz 480
Я подключаю плату NUCLEO_F303K8 к своему ПК для этого теста. Затем я запускаю следующую команду в моей консоли:
> openocd -s "C:\...\scripts" -f "C:\...\openocd.cfg"
OpenOCD выводит следующее и затем завершается:
Open On-Chip Debugger 0.10.0+dev-00921-gef8c69ff9 (2019-07-06-01:00)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
adapter speed: 480 kHz
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : clock speed 480 kHz
Error: BUG: current_target out of bounds
Таким образом, я заканчиваю несколькими вопросами, касающимися автопробинга.
3. Мои вопросы
Вопрос 1:
Является ли "Автопробинг" (как описано в разделе 10.7) действительно то, что мне нужно здесь? Если ответ " Нет", игнорируйте следующие вопросы.
Вопрос 2:
Я попытался подражать примеру, приведенному в Разделе 10.7, с некоторыми незначительными изменениями, чтобы сделать пример подходящим для моей платы Nucleo. К сожалению, автопробинг не работает. Это потому, что OpenOCD не поддерживает автопробирование по протоколу SWD? Или я просто ошибаюсь в своем .cfg
файл?
Вопрос 3:
Я заметил, что пример Autoprobing из Раздела 10.7 настраивает поведение сброса OpenOCD. Означает ли это, что автопробинг всегда будет "навязчивым" в том смысле, что он сбрасывает чип?
Вопрос 4:
Пример Autoprobing из Раздела 10.7, похоже, переводит OpenOCD в состояние сервера. Можно ли этого избежать? Я хочу, чтобы эта штука с "обнаружением микросхем" была простой, без использования клиента Telnet или GDB.
редактирует
Спасибо @nattgris за ваш замечательный ответ. У меня есть еще несколько практических вопросов.
1. С ST-Link
Предположим, мы используем ST-Link, несмотря на его неоптимальное сотрудничество с OpenOCD. Вы сказали:
... если все, что вам нужно, это знать, есть ли вообще чип, в некоторых конфигурациях ST-Link, вероятно, можно будет убедить вас предоставить эту информацию.
Как я могу практически убедить ST-Link сделать это? Другими словами, что я должен положить в мой openocd.cfg
файл для достижения этого?
2. С SWD-зондом (но не ST-Link)
Предположим, мы используем настоящий SWD-зонд. Вы сказали:
Автопробинг, как описано в разделе 10.7, относится только к JTAG [...]. Простое подключение через SWD печатает соответствующую информацию (
DPIDR
зарегистрироваться вместо TAPIDCODE
). Так или иначе, вы можете получить одинаковую информацию о чипе по обоим протоколам. [...]
Для всех чипов Cortex вы получите "ARM" вместо фактического производителя чипа (например, "ST"). Хотя чипы ST (и, возможно, других производителей) имеют отдельный TAP сканирования границ (т.е. только JTAG), который обеспечивает фактический STIDCODE
это может быть использовано для идентификации чипа.
Из этого я заключаю, что:
Автопробинг, как описано в разделе 10.7, применим только к JTAG, а не к SWD.
Поскольку автопробинг недоступен для SWD, альтернативный подход заключается в простом подключении к микросхеме, после чего OpenOCD автоматически печатает
DPIDR
регистр. ЭтотDPIDR
регистр является SWD-эквивалентом JTAG TAPIDCODE
так сказать, и может идентифицировать чип в некоторой степени.
Но как просто подключиться к чипу, если он не знает, какой чип изначально подключен к ПК? Если я не ошибаюсь, OpenOCD всегда нужен определенный файл конфигурации, напримерstm32f7x.cfg
,stm32f4x.cfg
,stm32l0.cfg
... для подключения к чипу.Видимо, JTAG
IDCODE
и SWD-эквивалентDPIDR
регистр предоставит разработчик чипа, который всегда будет "ARM" для чипов ARM-Cortex. Этого недостаточно для полной идентификации чипа. Тем не менее, вы говорите, что ARM-чипы имеют отдельные TAP с граничным сканированием, обеспечивая дальнейшееIDCODE
регистрирует для более полной идентификации. К сожалению, это только JTAG. Это означает, что SWD находится здесь в тупике с точки зрения идентификации чипа?Автопробинг с JTAG (и, следовательно, чтение
IDCODE
reg) может быть абсолютно ненавязчивым. Поэтому можно сделать сигнал сброса системы недоступным:reset_config none
Вы говорите, что читаяDPIDR
сверх SWD (который я считаю SWD-эквивалентом JTAG-автопробинга) также не является навязчивым. Могу ли я также применить эту "ненавязчивость", сделав сигнал сброса недоступным?
3. С JTAG-зондом (но не ST-Link)
Протокол JTAG, по-видимому, обеспечивает наилучшую поддержку идентификации чипа (с использованием автопробинга). Мои выводы:
Автопробинг, описанный в разделе 10.7, напечатает TAP
IDCODE
из чипа. Для ARM-чипов, которые будут просто печатать "ARM", а не фактический производитель (например, "ST") и название чипа (например, "STM32F767ZI").Как я могу практически убедиться, что процедура также печатает эту дополнительную информацию, в частности фактическое название чипа? Другими словами, что я должен положить в мой
openocd.cfg
файл (и, возможно, команда запуска openocd), чтобы достичь этого?
Большое спасибо:-)
2 ответа
Вопрос 1:
Это то, что тебе надо? Зависит. Автопробинг, как описано в разделе 10.7, относится только к JTAG. Так что само по себе это не покроет ваши потребности. Но простое подключение через SWD печатает соответствующую информацию (регистр DPIDR вместо TAP IDCODE), так что в любом случае вы можете получить одинаковую информацию о чипе по обоим протоколам.
Однако я не уверен, достаточно ли этого для вас. Если вы только хотите обнаружить, что чип (любой чип) реагирует, этого, вероятно, достаточно. Если вам также необходимо детально идентифицировать микросхему, в общем случае потребуется дополнительная проверка, поскольку идентификаторы, которые вы получаете с помощью обоих методов, идентифицируют разработчика микросхемы. Таким образом, для всех чипов Cortex вы получите "ARM" вместо фактического производителя чипа (например, "ST"). Хотя чипы ST (и, возможно, других производителей) имеют отдельный TAP сканирования границы (т.е. только JTAG), который обеспечивает фактический ST IDCODE, который можно использовать для идентификации чипа.
Однако, поскольку SWD относится только к целям ARM Cortex-типа (или, скорее, ADI v5), если вы можете использовать SWD, вы также можете прочитать таблицу ПЗУ компонентов отладки, которые среди прочего предоставляют производителя чипа:
# Your JTAG adapter config
script interface.cfg
transport select swd
adapter_khz 100
swd newdap chip cpu -enable
dap create chip.dap -chain-position chip.cpu
target create chip.cpu cortex_m -dap chip.dap
init
dap info
shutdown
Выход для STM32F103:
Info : SWD DPIDR 0x1ba01477
Info : chip.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : gdb port disabled
AP ID register 0x14770011
Type is MEM-AP AHB
MEM-AP BASE 0xe00ff003
Valid ROM table present
Component base address 0xe00ff000
Peripheral ID 0x00000a0410
Designer is 0x0a0, STMicroelectronics
Part is 0x410, Unrecognized
Component class is 0x1, ROM table
MEMTYPE system memory present on bus
ROMTABLE[0x0] = 0xfff0f003
Component base address 0xe000e000
Peripheral ID 0x04001bb000
Designer is 0x4bb, ARM Ltd.
Part is 0x0, Cortex-M3 SCS (System Control Space)
Component class is 0xe, Generic IP component
ROMTABLE[0x4] = 0xfff02003
Component base address 0xe0001000
Peripheral ID 0x04001bb002
Designer is 0x4bb, ARM Ltd.
Part is 0x2, Cortex-M3 DWT (Data Watchpoint and Trace)
Component class is 0xe, Generic IP component
ROMTABLE[0x8] = 0xfff03003
Component base address 0xe0002000
Peripheral ID 0x04000bb003
Designer is 0x4bb, ARM Ltd.
Part is 0x3, Cortex-M3 FPB (Flash Patch and Breakpoint)
Component class is 0xe, Generic IP component
ROMTABLE[0xc] = 0xfff01003
Component base address 0xe0000000
Peripheral ID 0x04001bb001
Designer is 0x4bb, ARM Ltd.
Part is 0x1, Cortex-M3 ITM (Instrumentation Trace Module)
Component class is 0xe, Generic IP component
ROMTABLE[0x10] = 0xfff41003
Component base address 0xe0040000
Peripheral ID 0x04001bb923
Designer is 0x4bb, ARM Ltd.
Part is 0x923, Cortex-M3 TPIU (Trace Port Interface Unit)
Component class is 0x9, CoreSight component
Type is 0x11, Trace Sink, Port
ROMTABLE[0x14] = 0xfff42002
Component not present
ROMTABLE[0x18] = 0x0
End of ROM table
Для чипов, не относящихся к Cortex, вы получите хорошую идентификацию с помощью JTAG TAP IDCODE, используя только автоматическое тестирование, как в этом примере со старым STR750:
# Your JTAG adapter config
script interface.cfg
transport select jtag
adapter_khz 100
init
shutdown
Info : JTAG tap: auto0.tap tap/device found: 0x4f1f0041 (mfg: 0x020 (STMicroelectronics), part: 0xf1f0, ver: 0x4)
Вопрос 2:
Как описано выше, "autoprobing" относится только к JTAG, но вы получаете те же функциональные возможности (чтение идентификационного кода), что и SWD. К сожалению, это не поможет вам, потому что у вас нет доступа ни к одному протоколу!
Проблема в том, что вы используете ST-Link. Несмотря на то, что люди склонны думать, это НЕ настоящий адаптер JTAG/SWD. Да, он говорит как на JTAG, так и на SWD, но полностью скрывает протокол внутри прошивки адаптера. Он предоставляет только высокоуровневую команду, установленную для хоста (OpenOCD), типа "Сброс цели", "Шаг цели", "Чтение этой памяти" и т. Д. Как следствие, поддержка OpenOCD ST-Link это уродливый хак, где он находится на целевом уровне, а не на уровне адаптера. Таким образом, большинство функций OpenOCD на уровне адаптера, транспорта или DAP просто не существует, и автоматическое зондирование в смысле OpenOCD совершенно не имеет значения для вашей установки.
Для простой перепрошивки и базовой отладки GDB работает ST-Link. Но для чего-то более низкого уровня, просто держитесь подальше от ST-Link. Это не совсем подходит для OpenOCD.
Тем не менее, если все, что вам нужно, это знать, есть ли вообще чип, в некоторых конфигурациях ST-Link, вероятно, можно убедить предоставить вам эту информацию, например, с помощью следующего файла конфигурации:
script interface/stlink.cfg
transport select hla_swd
adapter_khz 100
hla newtap chip cpu -enable
dap create chip.dap -chain-position chip.cpu
target create chip.cpu cortex_m -dap chip.dap
Вы получите либо
Warn : UNEXPECTED idcode: 0x2ba01477
или же
Error: init mode failed (unable to connect to the target)
Остальные вопросы не имеют отношения к ST-Link, поэтому я предполагаю, что вы переключаетесь на настоящий адаптер JTAG/SWD.
Вопрос 3:
Автопробирование JTAG, а также чтение DPIDR через SWD абсолютно не навязчиво. В целом, для целей Cortex-M большинство отладочных обращений к цели не являются навязчивыми, поэтому вы можете читать / записывать память и т. Д., Пока цель работает с трудом, не затрагивая ее.
JTAG вообще не определяет и не требует наличия сигнала сброса системы. Автопробинг работает без него, вы должны быть в состоянии использовать
reset_config none
Вопрос 4:
Вы хотите вообще не запускать сервер gdb /telnet? Затем вы можете отключить их с помощью следующей конфигурации:
gdb_port disabled
telnet_port disabled
tcl_port disabled
Однако если вы просто запустите OpenOCD для обнаружения микросхемы, а затем закроете ее, временный запуск этих служб в любом случае может не быть проблемой.
Более того, по крайней мере, сервер GDB запускается только после создания цели, которая не является обязательной для выполнения автоматического зондирования JTAG.
Резюме
Да, вы должны иметь возможность делать то, что вы хотите, но, возможно, не с ST-Link. С реальным адаптером вы можете выполнить автоматическое зондирование JTAG для печати обнаруженных TAP в цепочке сканирования. Для SWD OpenOCD всегда печатает обнаруженный регистр DPIDR (и обычно прерывается, если цель не найдена; выходные данные будут отличаться по крайней мере).
Подключение / обнаружение может быть полностью не навязчивым, если сама цель поддерживает это, как это делают большинство Cortex-M. Если в целевой микропрограмме отключены контакты отладки или отключена логика отладки, может потребоваться удержание или импульсный сброс в зависимости от цели.
С помощью основного кода OpenOCD вы можете легко получить доступ к памяти цели. Вы можете прочитать некоторые идентификационные данные из цели, декодировать ее и обнаружить чип.
Кстати, это, вероятно, не будет работать с адаптерами высокого уровня, такими как STLink. Пожалуйста, используйте универсальные адаптеры (J-Link, адаптеры на основе FTDI, CMSIS-DAP и т. Д.).
source [find interface/jlink.cfg]
transport select swd
adapter_khz 1000
set _CHIPNAME generic_dap_access
# 1. DECLARE A DAP
# -----------------
# Declare a single DAP (a DAP is the SWD counterpart for a JTAG TAP)
# for the chip's cpu. The command `swd newdap` has the same parameters
# as `jtag newtap`.
# param one: Name of the module in the JTAG scan chain (usually a chip).
# param two: Tapname, reflects the role of the TAP (bs, cpu, flash, ...).
# -irlen 4: Instruction register length is 4 bits
# -ircapture 0x1: The bit pattern loaded by the TAP into the JTAG shift register on entry
# to the ircapture state. Default is 0x01.
# -irmask 0xf: A mask used with-ircaptureto verify that instruction scans work correctly.
swd newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf
# 2. CREATE (?) A DAP AND LINK TO JTAG TAP
# -----------------------------------------
# Since OpenOCD version 0.11.0, the Debug Access Port (DAP) is no longer implicitely
# created together with the target. It must be explicitely declared.
# Declare a DAP instance named $_CHIPNAME.dap linked to the JTAG tap $_CHIPNAME.cpu.
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
# Note: Observe important note in manual
# for ARMv6-M, ARMv7 and ARMv8 targets.
# 3. DECLARE SOME PROCEDURES
# ---------------------------
# 3.1 Writes 'val' to address 'addr' via AP 'ap'
proc mww_ll { ap addr val } {
global _CHIPNAME
# I'm a bit confused how the following commands achieve just that.
$_CHIPNAME.dap apreg $ap 0x04 $addr
$_CHIPNAME.dap apreg $ap 0x0C $val
}
# 3.2 Reads and displays data from address 'addr' via AP 'ap'
proc mdw_ll { ap addr } {
global _CHIPNAME
$_CHIPNAME.dap apreg $ap 0x04 $addr
$_CHIPNAME.dap apreg $ap 0x0C
}
# 3.3 Reads data from address 'addr' via AP 'ap' and returns it
# Can be used to read data and pass it to other commands
proc mrw_ll { ap addr } {
global _CHIPNAME
$_CHIPNAME.dap apreg $ap 0x04 $addr
set ap [ocd_$_CHIPNAME.dap apreg $ap 0x0C]
regsub -all {(\s*\n)+} $ap "" ap
return $ap
}
# 4. INITIALIZE
# --------------
init # <- What does this actually do? I'm used to see `reset-init`
# everywhere in OpenOCD, but I don't know what simple `init` does.
# 5. READ VALUE AT 0x10000000
# ----------------------------
# Reads and displays value at 0x10000000 <- Why? What's special about
mdw_ll 0 0x10000000 # this memory location?
# 6. MODIFY RAM DATA
# -------------------
# Modify some data in RAM <- Why?
mdw_ll 0 0x08000000
mww_ll 0 0x08000000 0xdeadbeef
mdw_ll 0 0x08000000
exit
Вывод OpenOCD:
Open On-Chip Debugger 0.10.0+dev-01116-gfc2e5110d-dirty (2019-07-11-16:04)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
adapter speed: 1000 kHz
Info : J-Link Ultra V4 compiled May 27 2019 15:49:24
Info : Hardware version: 4.00
Info : VTarget = 4.850 V
Info : clock speed 1000 kHz
Info : SWD DPIDR 0x6ba02477
Warn : gdb services need one or more targets defined
0x976562e5
0x20004602
0xdeadbeef