Сага об отладчиках

разделы: Программаторы , STM32 , дата: 07 августа 2022г.

Недавно у меня сгорел мой единственный ST-Link v2 с оригинальным STM32, который верой и правдой прослужил мне семь лет. Выкидывать его у меня не поднялась рука, и я что называется "приобрел практический опыт" восстанавливая его работу. Данная проблема заставила меня провести личное исследование о доступных альтернативах отладчику ST-Link V2, и результаты этого мини исследования легли в основу данной статьи.

Вторым мотивом которым я руководствовался, была ситуация сложившаяся на рынке микроконтроллеров. Полагаю, что все уже понимают, что микроконтроллеры STM32 скорее всего уже не будут доступны никогда, и нужно искать альтернативы. В виду этого теряется ценность брендированных отладчиков таких как ST-LinkV2, которые могут работать только с микроконтроллерами STM, и соответственно вопрос опять упирается в поиск альтернатив.

В своих проблемах и поисках я не был одинок, поэтому ниже привожу список материалов, на которые я опирался.

Содержание:

  1. Реанимация ST-Link V2
  2. Отладчик CMSIS-DAP (или DAP-Link)
  3. PyOCD - аналог OpenOCD и st-flash для отладчика CMSIS-DAP
  4. Перепрошивка STLinkV2 в JLink_OB
  5. JLink_V8 (клон)
  6. ESP-STLINK
  7. Прошивка и отладка китайского ARM микроконтроллера AT32F403RC (добавлено позже)

Для работы я использовал Slackware Linux и виртуальную машину с Windows. Если вы пользуетесь Windows, то вам соответствено понадобится виртуальная машина с Linux.

1) Реанимация ST-Link V2

Неприятная история началась довольно обыденно: я подключаю ST-Link v2 к компьютеру, пытаюсь залить прошивку в микроконтроллер STM8, в ответ флешер ругается ошибкой. После некоторого метания и перебора вариантов догадываюсь заглянуть в dmesg и там вижу страшное - ST-Link не определяется драйвером:

Скрин не мой, но выглядело примерно также.

Первое что приходит в голову - это статика. Симптомы типовые: работал нормально до того, как выдернул из компьютера. Снова подключил - он не работает. И хотя USB разъем конструктивно защищен от статики, стопроцентной защиты никто не гарантирует.

Если китайский клон ST-Link у кого-то сгорает, то полагаю, что его выкидывают и покупают другой. Новый ST-Link я заказал сразу же и получил на следующий день. Стоило в два раза дороже, чем напрямую с али, зато не надо было ждать месяц-полтора. Он был в мерзком розово-перламутровом корпусе:

Как и ожидалось, чип был не оригинальным:

Очередной китайский новодел Geehy APM32F103C8:

Согласно справки на keil.com APEXMIC APM32F103C8 здесь 64кБ флеш-памяти, в то время как в оригинале должно быть 128кБ.

Тем не менее, отладчик делает свою работу, определяется и ST-Link Utility и STM32Cube_Programmer версия прошивки V2J29S7. Обновлять не пробовал, работает и ладно.

Но вернемся к старому ST-Link. Первая мысль которая пришла в голову - попытаться подключится к чипу через SWD и посмотреть насколько там все плохо. При вскрытии ST-Link видим 4-х пиновый интерфейс. С помощью прозвонки определяем назначение каждого контакта:

Кварц пока выпаивать не нужно. Разъем с шагом 2.0 мм, обычную гребенку туда не запаяешь, да и мешаться она будет металлическому корпусу. Но т.к. нам нужно подключиться к чипу всего на минут пять, мы можем сделать так:

Главное ничего не перепутать. Поэтому перед подключением чипа к отладчику, все следует проверить три раза.

При подключении чипа к ST-Link Utility начинается интересное. Сперва чип естественно никак не определялся в программе:

Однако, когда я выставил в настройках режим "Hot Plug", чип успешно определился программой:

Но хорошие новости на этом и закончились. Прошивка ST-Link защищенная от чтения, чтобы разблокировать чип, следует снять защиту от чтения:

Однако при попытке снять защиту с чипа или стереть содержимое флеш-памяти, ST-Link Utility выдавал ошибку:

Примерно также обстояло дело и с OpenOCD. Можно было даже подключиться к чипу:

Но на команду "halt" чип никак не реагировал, стирание флеш-памяти было невозможно:

Программа STM32CubeProgrammer не желала узнавать чип вовсе.

Т.о., раз до чипа достучаться не удалось, было решено менять чип на оригинальный STM32f101CBT6. К счастью, такой чип был в местном радиомагазине моего города по сходной цене.

Любопытно, что чипы STM32f101xx не имеют USB интерфеса, если верить документации.

Я выпаял старый чип вместе с кварцем, т.к. он затруднял доступ к чипу:

Далее запаиваем новый чип:

Кварц пока ставить не обязательно. Проверяем ножки на непропай. Все проверять не обязательно. Нужны линии питания(пины 9,24,36,48), земли(пины 8,23,35,47), SWDIO(34), SWCLK(37. Пины коннектора: NRST (PB6 - 42), SWIM (PB8 - 48), SWDIO (PB14 - 27), SWCLK (PB13 - 26).

Примерная схема ST-Link V2 представлена ниже:


Схема взята с сайта https://adelectronics.ru/

Далее через 4-х пиновый разъем подключаем к ST-Link и запускаем программу ST-Link Utility. Коннектимся к чипу обычным способом(настройки по умолчанию) и если этот процесс проходит успешно, прошиваем чип загрузчиком ST-Link.

Загрузчик можно взять здесь: https://github.com/Krakenw/Stlink-Bootloaders

Я использовал "Unprotected-2-0-Bootloader.bin". Утверждается, что загрузчики были скопированы с оригинальных ST-Link, что теоретически невозможно из-за включенного ROP на последних. Однако, факт есть факт.

После прошивки загрузчика впаиваем обратно кварц и подключаем реанимированный ST-Link в USB. Он должен определиться как ST-Link V2:

[ 3996.296138] usb 5-3: new full-speed USB device number 2 using ohci-pci
[ 3996.467233] usb 5-3: New USB device found, idVendor=0483, idProduct=3748, bcdDevice= 1.00
[ 3996.467243] usb 5-3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 3996.467248] usb 5-3: Product: STM32 STLink
[ 3996.467253] usb 5-3: Manufacturer: STMicroelectronics
[ 3996.467256] usb 5-3: SerialNumber: Wÿt\x06RwUW7\x14!g

Последнее, что остается, запустить ST-Link Utility и выбрать upgrade firmware. Будет предложено несколько вариантов:

Выбираем вариант "STM32+STM8". Затем идет загрузка прошивки, после чего наш ST-Link V2 готов к работе!

2) Отладчик CMSIS-DAP (или DAP-Link)

В последний год на али проявилось много недорогих отладчиков DAP-Link или CMSIS-DAP. Они выпускаются в разных форматах: с SWD интерфейсом или JTAG, с коннектором USB-A или USB-C, с корпусом или без, с drag and drop функцией или без нее.

CMSIS-DAP предназначены для работы с ARM микроконтроллерами вообще, а не только с STM32 как ST-Link.

Я на пробу заказал самый дешевый вариант с UART интерфейсом:

На плате установлен якобы оригинальный stm32f103c8 c 64кБ флеш-памяти. Имеется разъем 2.5 мм под прошивку чипа отладчика. Можно предположить, что буквы V,G,K,D означают - Vcc, GND, SWCLK и SWDIO.

Отладчик CMSIS-DAP является частью проекта MBED RTOS (проект www.keil.com), и может использоваться в Keil uVision вместо J-Link. Данная IDE меня никогда не интересовала, убогий внешний вид, платформо-зависимость, дикая цена и пр. прелести. Т.о. CMSIS-DAP - это просто еще один бюджетный SWD отладчик c UART'ом. Максимальная скорость работы UART - 115200 бод.

При подключении отладчика к USB, в dmesg появляется такой лог:

usb 5-3: new full-speed USB device number 3 using ohci-pci
usb 5-3: New USB device found, idVendor=c251, idProduct=f001, bcdDevice= 1.00
usb 5-3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 5-3: Product: CMSIS-DAP_LU
usb 5-3: Manufacturer: jixin.pro
usb 5-3: SerialNumber: LU_2022_8888
hid-generic 0003:C251:F001.0006: hiddev97,hidraw5: USB HID v1.00 Device [jixin.pro CMSIS-DAP_LU] on usb-0000:00:13.0-3/input2
cdc_acm 5-3:1.0: ttyACM0: USB ACM device
usbcore: registered new interface driver cdc_acm
cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters

Здесь у нас композитное устройство из самого отладчика и Communication Device Class (CDC) UART-USB преобразователя.

Чтобы отладчиком можно было пользоваться из непривилегированного пользователя, в систему добавляем udev правило "98-cmsis-daplink.rules"

# CMSIS-DAP compatible adapters
ATTRS{product}=="*CMSIS-DAP*", MODE="664", GROUP="plugdev"

Не забываем перезагружать правила:

udevadm control --reload-rules && udevadm trigger

В качестве "подопытного кролика"" выберем плату Bluepill c чипом STM32F103C8T6. Скачиваем примеры для данного микроконтроллера:

$ git clone https://gitlab.com/flank1er/stm32_bare_metal.git 
Клонирование в «stm32_bare_metal»…
remote: Enumerating objects: 212, done.
remote: Counting objects: 100% (212/212), done.
remote: Compressing objects: 100% (96/96), done.
remote: Total 212 (delta 109), reused 201 (delta 106), pack-reused 0
Получение объектов: 100% (212/212), 283.83 КиБ | 5.35 МиБ/с, готово.
Определение изменений: 100% (109/109), готово.

Выбираем пример "03_uart_tx"

$ cd ./stm32_bare_metal/03_uart_tx 

Проверяем наш компилятор:

$ make clean && make all 
удалён 'blink.elf'
удалён 'blink.bin'
удалён 'main.o'
удалён 'init.o'
удалён 'startup.o'
удалён 'uart.o'
arm-none-eabi-gcc -c -o main.o main.c -mthumb -mcpu=cortex-m3 -g -O0  -DSTM32F10X_MD -DSYSCLK_FREQ_72MHz -ICMSIS/device -ICMSIS/core -ISPL/inc -Iinc
arm-none-eabi-gcc -c -o init.o asm/init.s -mthumb -mcpu=cortex-m3 -g 
arm-none-eabi-gcc -c -o startup.o src/startup.c -mthumb -mcpu=cortex-m3 -g -O0  -DSTM32F10X_MD -DSYSCLK_FREQ_72MHz -ICMSIS/device -ICMSIS/core -ISPL/inc -Iinc
arm-none-eabi-gcc -c -o uart.o src/uart.c -mthumb -mcpu=cortex-m3 -g -O0  -DSTM32F10X_MD -DSYSCLK_FREQ_72MHz -ICMSIS/device -ICMSIS/core -ISPL/inc -Iinc
arm-none-eabi-ld -Tscript.ld -g  -o blink.elf  main.o  init.o startup.o uart.o
arm-none-eabi-objcopy -O binary blink.elf blink.bin
arm-none-eabi-size  blink.elf
   text    data     bss     dec     hex filename
   1302       0       4    1306     51a blink.elf

Прежде чем прошивать микроконтроллер, должен рассказать о поджидающем нас подводном камене. Дело в том, что DAP-Link отказался у меня работать с OpenOCD v0.11. Выглядело это так:

$ openocd -f interface/cmsis-dap.cfg -f target/stm32f1x.cfg -c "init" -c "reset halt"
Open On-Chip Debugger 0.11.0
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "swd". To override use 'transport select '.
Warn : Using CMSIS-DAPv2 interface 1 with wrong class 10 subclass 0 or protocol 0
Info : Using CMSIS-DAPv2 interface with VID:PID=0xc251:0xf001, serial=LU_2022_8888
Warn : could not claim interface: Resource busy
Error: error writing data: Input/Output Error
Error: CMSIS-DAP command CMD_INFO failed.

На форуме PlatformioIO я нашел подсказку о том, что OpenOCD v0.10 работает с данным отладчиком нормально. Поэтому я буду использовать именно эту версию OpenOCD.

Если собираем OpenOCD из исходников, то смотрим чтобы CMSIS-DAP поддерживался (требуется библиотека hidapi):

Теперь подключаем DAP-Link к USB порту компьютера, и проверяем работу OpenOCD:

$ openocd -f interface/cmsis-dap.cfg -f target/stm32f1x.cfg -c "init" -c "reset halt"
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "swd". To override use 'transport select '.
adapter speed: 1000 kHz
adapter_nsrst_delay: 100
none separate
cortex_m reset_config sysresetreq
Info : CMSIS-DAP: SWD  Supported
Info : CMSIS-DAP: JTAG Supported
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : CMSIS-DAP: FW Version = 1.0
Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 1 TDO = 1 nTRST = 0 nRESET = 0
Info : CMSIS-DAP: Interface ready
Info : clock speed 1000 kHz
Info : SWD DPIDR 0x1ba01477
Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x080002dc msp: 0x20005000

Подключение успешное!

Теперь можно подключить плату Bluepill к отладчику DAP-Link, не забыв при этом выдернуть его из компа. SWD разъемы DAP-Link и Bluepill зеркально совпадают по порядку следования контактов - это удобно. Для получения вывода от UART, нужно соединить пин PA9 Bluepill с контактом RXD на DAP-Link.

Снова подключаем отладчик DAP-Link к компьютеру и прошиваем микроконтроллер:

$ openocd -f interface/cmsis-dap.cfg -f target/stm32f1x.cfg -c "init" -c "reset halt" -c "flash write_image erase /tmp/03_uart_init/blink.bin 0x08000000" -c "reset" -c "exit" 
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "swd". To override use 'transport select '.
adapter speed: 1000 kHz
adapter_nsrst_delay: 100
none separate
cortex_m reset_config sysresetreq
Info : CMSIS-DAP: SWD  Supported
Info : CMSIS-DAP: JTAG Supported
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : CMSIS-DAP: FW Version = 1.0
Info : SWCLK/TCK = 1 SWDIO/TMS = 1 TDI = 1 TDO = 1 nTRST = 0 nRESET = 0
Info : CMSIS-DAP: Interface ready
Info : clock speed 1000 kHz
Info : SWD DPIDR 0x1ba01477
Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x08000410 msp: 0x20005000
auto erase enabled
Info : device id = 0x20036410
Info : flash size = 64kbytes
wrote 2048 bytes from file /tmp/stm32_bare_metal/03_uart_tx/blink.bin in 0.453006s (4.415 KiB/s)

После прошивки зеленый светодиод на плате Bluepill должен замигать с интервалом, примерно 1 сек.

Запускаем любую терминальную программу и видим отладочный вывод:

Т.о. отладчик DAP-Link избавляет нас от возни с UART-USB преобразователем для отладочного вывода, что опять же, довольно удобно.

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

Конкретно с тем примером который мы использовали, отладка не заработала. Т.к. трассировка постоянно валилась в обработчик WWDG, который в свою очередь перенаправлял в "Infinity Loop". Но на аналогичном примере, собранном с нормальным скриптом компоновщика и библиотекой newlib, вроде все работает.

3) PyOCD - аналог OpenOCD и st-flash для отладчика CMSIS-DAP

К сожалению, утилита для прошивки микроконтроллеров STM32 "st-flash" не работает с отладчиками CMSIS-DAP и J-Link, а вводить постоянно команду:

openocd -f interface/cmsis-dap.cfg -f target/stm32f1x.cfg -c "init" -c "reset halt" -c "flash write_image erase /tmp/03_uart_init/blink.bin 0x08000000" -c "reset" -c "exit"

для прошивки микроконтроллера - не совсем удобно. И в поисках аналога утилите "st-flash" я набрел на PyOCD.

PyOCD - это аналог OpenOCD, но в упрощенном виде и только ARM микроконтроллеров. Сайт проекта PyOCD с документацией https://pyocd.io

Главным образом - PyOCD может заменить утилиту "st-link" в случае использования отладчика CMSIS-DAP.

Устанавливаем программу PyOCD с помощью команды:

$ python3 -m pip install -U pyocd

Т.к. мы установку производили из непривилегированного пользователя, PyOCD установится в домашний каталог в "$HOME/.local/bin". этот каталог нужно будет прописать в переменной окружения "PATH", если этого еще не сделано:

$ export PATH=$PATH:/home/flanker/.local/bin

Проверяем:

$ pyocd -V
0.34.1

Краткий справочник по командам:

$ pyocd
usage: pyocd [-h] [-V] [--help-options]  ...

PyOCD debug tools for Arm Cortex devices

optional arguments:
  -h, --help       show this help message and exit
  -V, --version    show program's version number and exit
  --help-options   Display available session options.

subcommands:
  
    commander (cmd)
                   Interactive command console.
    erase          Erase entire device flash or specified sectors.
    load (flash)   Load one or more images into target device memory.
    gdbserver (gdb)
                   Run the gdb remote server(s).
    json           Output information as JSON.
    list           List information about probes, targets, or boards.
    pack           Manage CMSIS-Packs for target support.
    reset          Reset a target device.
    server         Run debug probe server.
    rtt            SEGGER RTT Viewer.
  • list - это показать список подключенных к данному компьютеру отладчиков.
  • erase - стереть прошивку
  • load - загрузить прошивку в микроконтроллер
  • pack - управление пакетами

Этих четырех команд нам будет достаточно для работы с PyOCD. На все остальное есть OpenOCD.

Подключаем DAP-Link с Bluepill к компьютеру, и вводим команду "pyocd list":

$ pyocd list
  #   Probe/Board              Unique ID      Target  
------------------------------------------------------
  0   jixin.pro CMSIS-DAP_LU   LU_2022_8888   n/a 

Однако, если мы попытаемся прошить микроконтроллер своей прошивкой, то нам выкинет ошибку:

$ pyocd load --target stm32f103c8 ./blink.bin
0000698 C Target type stm32f103c8 not recognized. Use 'pyocd list --targets' to see currently available target types. See <https://pyocd.io/docs/target_support.html> for how to install addit
ional target support. [__main__]
Traceback (most recent call last):
  File "/home/flanker/.local/lib/python3.9/site-packages/pyocd/board/board.py", line 111, in __init__
    self.target = TARGET[self._target_type](session)
KeyError: 'stm32f103c8'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/flanker/.local/lib/python3.9/site-packages/pyocd/__main__.py", line 161, in run
    status = cmd.invoke()
  File "/home/flanker/.local/lib/python3.9/site-packages/pyocd/subcommands/load_cmd.py", line 81, in invoke
    session = ConnectHelper.session_with_chosen_probe(
  File "/home/flanker/.local/lib/python3.9/site-packages/pyocd/core/helpers.py", line 265, in session_with_chosen_probe
    return Session(probe, auto_open=auto_open, options=options, **kwargs)
  File "/home/flanker/.local/lib/python3.9/site-packages/pyocd/core/session.py", line 216, in __init__
    self._board = probe.create_associated_board() or Board(self)
  File "/home/flanker/.local/lib/python3.9/site-packages/pyocd/board/board.py", line 113, in __init__
    raise exceptions.TargetSupportError(
pyocd.core.exceptions.TargetSupportError: Target type stm32f103c8 not recognized. Use 'pyocd list --targets' to see currently available target types. See <https://pyocd.io/docs/target_suppor
t.html> for how to install additional target support.

Пробуем ввести команду "pyocd list --targets" для получения списка поддерживаемых микроконтроллеров, и получаем такой вот огромный список

  Name                      Vendor                  Part Number                  Families   Source   
-----------------------------------------------------------------------------------------------------
  cc3220sf                  Texas Instruments       CC3220SF                                builtin  
  cortex_m                  Generic                 CoreSightTarget                         builtin  
  cy8c64_sysap              Cypress                 cy8c64_sysap                            builtin  
  cy8c64x5_cm0              Cypress                 cy8c64x5_cm0                            builtin  
  cy8c64x5_cm0_full_flash   Cypress                 cy8c64x5_cm0_full_flash                 builtin  
  cy8c64x5_cm4              Cypress                 cy8c64x5_cm4                            builtin  
  cy8c64x5_cm4_full_flash   Cypress                 cy8c64x5_cm4_full_flash                 builtin  
  cy8c64xa_cm0              Cypress                 cy8c64xA_cm0                            builtin  
  cy8c64xa_cm0_full_flash   Cypress                 cy8c64xA_cm0_full_flash                 builtin  
  cy8c64xa_cm4              Cypress                 cy8c64xA_cm4                            builtin  
  cy8c64xa_cm4_full_flash   Cypress                 cy8c64xA_cm4_full_flash                 builtin  
  cy8c64xx_cm0              Cypress                 cy8c64xx_cm0                            builtin  
  cy8c64xx_cm0_full_flash   Cypress                 cy8c64xx_cm0_full_flash                 builtin  
  cy8c64xx_cm0_nosmif       Cypress                 cy8c64xx_cm0_nosmif                     builtin  
  cy8c64xx_cm0_s25hx512t    Cypress                 cy8c64xx_cm0_s25hx512t                  builtin  
  cy8c64xx_cm4              Cypress                 cy8c64xx_cm4                            builtin  
  cy8c64xx_cm4_full_flash   Cypress                 cy8c64xx_cm4_full_flash                 builtin  
  cy8c64xx_cm4_nosmif       Cypress                 cy8c64xx_cm4_nosmif                     builtin  
  cy8c64xx_cm4_s25hx512t    Cypress                 cy8c64xx_cm4_s25hx512t                  builtin  
  cy8c6xx5                  Cypress                 CY8C6xx5                                builtin  
  cy8c6xx7                  Cypress                 CY8C6xx7                                builtin  
  cy8c6xx7_nosmif           Cypress                 CY8C6xx7_nosmif                         builtin  
  cy8c6xx7_s25fs512s        Cypress                 CY8C6xx7_S25FS512S                      builtin  
  cy8c6xxa                  Cypress                 CY8C6xxA                                builtin  
  hc32f003                  HDSC                    HC32F003                                builtin  
  hc32f005                  HDSC                    HC32F005                                builtin  
  hc32f030                  HDSC                    HC32F030                                builtin  
  hc32f072                  HDSC                    HC32F072                                builtin  
  hc32f120x6                HDSC                    HC32F120x6TA                            builtin  
  hc32f120x8                HDSC                    HC32F120x8TA                            builtin  
  hc32f160xa                HDSC                    HC32F160xA                              builtin  
  hc32f160xc                HDSC                    HC32F160xC                              builtin  
  hc32f190                  HDSC                    HC32F190                                builtin  
  hc32f196                  HDSC                    HC32F196                                builtin  
  hc32f451xc                HDSC                    HC32F451xC                              builtin  
  hc32f451xe                HDSC                    HC32F451xE                              builtin  
  hc32f452xc                HDSC                    HC32F452xC                              builtin  
  hc32f452xe                HDSC                    HC32F452xE                              builtin  
  hc32f460xc                HDSC                    HC32F460xC                              builtin  
  hc32f460xe                HDSC                    HC32F460xE                              builtin  
  hc32f4a0xg                HDSC                    HC32F4A0xG                              builtin  
  hc32f4a0xi                HDSC                    HC32F4A0xI                              builtin  
  hc32l072                  HDSC                    HC32L072                                builtin  
  hc32l073                  HDSC                    HC32L073                                builtin  
  hc32l110                  HDSC                    HC32L110                                builtin  
  hc32l130                  HDSC                    HC32L130                                builtin  
  hc32l136                  HDSC                    HC32L136                                builtin  
  hc32l190                  HDSC                    HC32L190                                builtin  
  hc32l196                  HDSC                    HC32L196                                builtin  
  hc32m120                  HDSC                    HC32M120                                builtin  
  hc32m120x6                HDSC                    HC32M120                                builtin  
  hc32m423xa                HDSC                    HC32M423xA                              builtin  
  k20d50m                   NXP                     K20D50M                                 builtin  
  k22f                      NXP                     K22F                                    builtin  
  k22fa12                   NXP                     K22FA12                                 builtin  
  k28f15                    NXP                     K28F15                                  builtin  
  k32l2b3                   NXP                     K32L2B3                                 builtin  
  k32w042s                  NXP                     K32W042S                                builtin  
  k64f                      NXP                     K64F                                    builtin  
  k66f18                    NXP                     K66F18                                  builtin  
  k82f25615                 NXP                     K82F25615                               builtin  
  ke15z7                    NXP                     KE15Z7                                  builtin  
  ke17z7                    NXP                     KE17Z7                                  builtin  
  ke18f16                   NXP                     KE18F16                                 builtin  
  kinetis                   NXP                     Kinetis                                 builtin  
  kl02z                     NXP                     KL02Z                                   builtin  
  kl05z                     NXP                     KL05Z                                   builtin  
  kl25z                     NXP                     KL25Z                                   builtin  
  kl26z                     NXP                     KL26Z                                   builtin  
  kl27z4                    NXP                     KL27Z4                                  builtin  
  kl28z                     NXP                     KL28x                                   builtin  
  kl43z4                    NXP                     KL43Z4                                  builtin  
  kl46z                     NXP                     KL46Z                                   builtin  
  kl82z7                    NXP                     KL82Z7                                  builtin  
  kv10z7                    NXP                     KV10Z7                                  builtin  
  kv11z7                    NXP                     KV11Z7                                  builtin  
  kw01z4                    NXP                     KW01Z4                                  builtin  
  kw24d5                    NXP                     KW24D5                                  builtin  
  kw36z4                    NXP                     KW36Z4                                  builtin  
  kw40z4                    NXP                     KW40Z4                                  builtin  
  kw41z4                    NXP                     KW41Z4                                  builtin  
  lpc11u24                  NXP                     LPC11U24                                builtin  
  lpc11xx_32                NXP                     LPC11XX_32                              builtin  
  lpc1768                   NXP                     LPC1768                                 builtin  
  lpc4088                   NXP                     LPC4088                                 builtin  
  lpc4088dm                 NXP                     LPC4088dm                               builtin  
  lpc4088qsb                NXP                     LPC4088qsb                              builtin  
  lpc4330                   NXP                     LPC4330                                 builtin  
  lpc54114                  NXP                     LPC54114                                builtin  
  lpc54608                  NXP                     LPC54608                                builtin  
  lpc5526                   NXP                     LPC5526                                 builtin  
  lpc55s28                  NXP                     LPC55S28                                builtin  
  lpc55s36                  NXP                     LPC55S36                                builtin  
  lpc55s69                  NXP                     LPC55S69                                builtin  
  lpc800                    NXP                     LPC800                                  builtin  
  lpc824                    NXP                     LPC824                                  builtin  
  lpc845                    NXP                     LPC845                                  builtin  
  m2354kjfae                Nuvoton                 M2354KJFAE                              builtin  
  m252kg6ae                 Nuvoton                 M252KG6AE                               builtin  
  m263kiaae                 Nuvoton                 M263KIAAE                               builtin  
  m467hjhae                 Nuvoton                 M467HJHAE                               builtin  
  m487jidae                 Nuvoton                 M487JIDAE                               builtin  
  max32600                  Maxim                   MAX32600                                builtin  
  max32620                  Maxim                   MAX32620                                builtin  
  max32625                  Maxim                   MAX32625                                builtin  
  max32630                  Maxim                   MAX32630                                builtin  
  max32660                  Maxim                   MAX32660                                builtin  
  max32670                  Maxim                   MAX32670                                builtin  
  mimxrt1010                NXP                     MIMXRT1011xxxxx                         builtin  
  mimxrt1015                NXP                     MIMXRT1015xxxxx                         builtin  
  mimxrt1020                NXP                     MIMXRT1021xxxxx                         builtin  
  mimxrt1024                NXP                     MIMXRT1024xxxxx                         builtin  
  mimxrt1050                NXP                     MIMXRT1052xxxxB_hyperflash              builtin  
  mimxrt1050_hyperflash     NXP                     MIMXRT1052xxxxB_hyperflash              builtin  
  mimxrt1050_quadspi        NXP                     MIMXRT1052xxxxB_quadspi                 builtin  
  mimxrt1060                NXP                     MIMXRT1062xxxxA                         builtin  
  mimxrt1064                NXP                     MIMXRT1064xxxxA                         builtin  
  mimxrt1170_cm4            NXP                     MIMXRT1176xxxxx_CM4                     builtin  
  mimxrt1170_cm7            NXP                     MIMXRT1176xxxxx_CM7                     builtin  
  mps3_an522                Arm                     AN522                                   builtin  
  mps3_an540                Arm                     AN540                                   builtin  
  musca_a1                  Arm                     MuscaA1                                 builtin  
  musca_b1                  Arm                     MuscaB1                                 builtin  
  musca_s1                  Arm                     MuscaS1                                 builtin  
  ncs36510                  ONSemiconductor         NCS36510                                builtin  
  nrf51                     Nordic Semiconductor    NRF51                                   builtin  
  nrf51822                  Nordic Semiconductor    NRF51                                   builtin  
  nrf52                     Nordic Semiconductor    NRF52832                                builtin  
  nrf52832                  Nordic Semiconductor    NRF52832                                builtin  
  nrf52833                  Nordic Semiconductor    NRF52833                                builtin  
  nrf52840                  Nordic Semiconductor    NRF52840                                builtin  
  rp2040                    Raspberry Pi            RP2040Core0                             builtin  
  rp2040_core0              Raspberry Pi            RP2040Core0                             builtin  
  rp2040_core1              Raspberry Pi            RP2040Core1                             builtin  
  rtl8195am                 Realtek Semiconductor   RTL8195AM                               builtin  
  s5js100                   Samsung                 S5JS100                                 builtin  
  stm32f051                 STMicroelectronics      STM32F051                               builtin  
  stm32f103rc               STMicroelectronics      STM32F103RC                             builtin  
  stm32f412xe               STMicroelectronics      STM32F412xE                             builtin  
  stm32f412xg               STMicroelectronics      STM32F412xG                             builtin  
  stm32f429xg               STMicroelectronics      STM32F429xG                             builtin  
  stm32f429xi               STMicroelectronics      STM32F429xI                             builtin  
  stm32f439xg               STMicroelectronics      STM32F439xG                             builtin  
  stm32f439xi               STMicroelectronics      STM32F439xI                             builtin  
  stm32f767zi               STMicroelectronics      STM32F767xx                             builtin  
  stm32l031x6               STMicroelectronics      STM32L031x6                             builtin  
  stm32l432kc               STMicroelectronics      STM32L432xC                             builtin  
  stm32l475xc               STMicroelectronics      STM32L475xC                             builtin  
  stm32l475xe               STMicroelectronics      STM32L475xE                             builtin  
  stm32l475xg               STMicroelectronics      STM32L475xG                             builtin  
  w7500                     WIZnet                  W7500                                   builtin  

В этом списке нет stm32f103c8, зато есть stm32f103rc, пробуем подставить это значение:

$ pyocd load --target stm32f103rc ./blink.bin
0000977 I Loading /tmp/04_uart_print/blink.bin [load_cmd]
[==========                                        ]  21%0001570 C flash program page failure (address 0x08000000; result code 0x1) [__main__]
Traceback (most recent call last):
  File "/home/flanker/.local/lib/python3.9/site-packages/pyocd/__main__.py", line 161, in run
    status = cmd.invoke()
  File "/home/flanker/.local/lib/python3.9/site-packages/pyocd/subcommands/load_cmd.py", line 125, in invoke
    programmer.program(filename,
  File "/home/flanker/.local/lib/python3.9/site-packages/pyocd/flash/file_programmer.py", line 170, in program
    self._loader.commit()
  File "/home/flanker/.local/lib/python3.9/site-packages/pyocd/flash/loader.py", line 289, in commit
    perf = builder.program(chip_erase=chipErase,
  File "/home/flanker/.local/lib/python3.9/site-packages/pyocd/flash/builder.py", line 509, in program
    flash_operation = self._sector_erase_program_double_buffer(progress_cb)
  File "/home/flanker/.local/lib/python3.9/site-packages/pyocd/flash/builder.py", line 953, in _sector_erase_program_double_buffer
    raise FlashProgramFailure('flash program page failure', address=current_addr, result_code=result)
pyocd.core.exceptions.FlashProgramFailure: flash program page failure (address 0x08000000; result code 0x1)

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

$ pyocd pack find stm32f103c8
.. бла ..
.. бла .. 
... бла ..
  Part          Vendor               Pack                 Version   Installed  
-------------------------------------------------------------------------------
  STM32F103C8   STMicroelectronics   Keil.STM32F1xx_DFP   2.4.0     False

Лог вывода был длинным и малоинформативным, поэтом пришлось его немного сократить. В итоге нам нашли пакет "Keil.STM32F1xx_DFP". Скачиваем его:

$ pyocd pack install stm32f103c8
Downloading packs (press Control-C to cancel):
    Keil.STM32F1xx_DFP.2.4.0
Downloading descriptors (001/001)

Скачивание занимает около минуты, так что можно пойти заварить чай.

Пробуем еще раз залить прошивку:

$ pyocd load --target stm32f103c8 ./blink.bin
0001472 I Loading /tmp/04_uart_print/blink.bin [load_cmd]
[==================================================] 100%
0002263 I Erased 1024 bytes (1 sector), programmed 1024 bytes (1 page), skipped 1024 bytes (1 page) at 2.53 kB/s [loader]

И в этот раз все успешно получается. Аналогичным образом происходит работа с ST-Link v2. Т.о. мы имеем универсальный инструмент, который умеет работать не только c ST-LinkV2, но так же с CMSIS-DAP. C JLink-ми, о которых далее пойдет речь, данная утилита к сожалению не работает.

4) Перепрошивка STLinkV2 в JLink_OB

Внимание! Данная перепрошивка НЕ позволит работать с чипами отличными от stm32! Смотрите главу: Прошивка и отладка китайского ARM микроконтроллера AT32F403RC (добавлено позже)

Однажды, фирма Segger, производитель отладчиков J-Link, выложила у себя на сайте утилиту которая перепрошивала отладчики ST-Link в J-Link, которые после этого могли работать с фирменным ПО Segger для прошивки и отладки не только STM32 но и тысяч других микросхем разных производителей, которые поддерживали протокол SWD.

На веб-странице проекта https://www.segger.com/products/debug-probes/j-link/models/other-j-links/st-link-on-board/ можно скачать саму утилиту, драйвера и ПО для JLink, а также ознакомиться со списком поддерживаемых плат с ST-Link для перепрошивки. Среди поддерживаемых плат: Discovery STM32, Nucleo и еще парочка других. Китайские клоны ST-Link не поддерживаются))

По самой правдоподобной версии, о том, почему китайские клоны не получается прошить в JLink, предполагается для прошивки нужен ST-Link STM32 only(без поддержки прошивки STM8), который ставится на фирменные платы ST: Discovery и Nucleo. Т.к. утилита перепрошивки "STLinkReflash" может вернуть ST-Link в исходное состояние, это звучит логично. Откуда же ей знать вариант ST-Link до перепрошивки в Jlink? Проще предполагать что-то одно.

Теперь, когда я освоил восстановление отладчика ST-LinkV2, и у меня появился один лишний ST-LINK, я решил заняться этим колдовством.

Я прошивал своего восстановленного клона из виртуалки по этой статье: "Прошивка ST-Link в J-Link". В конце статьи выложен архив с патченой утилитой "STLinkReflash".

В начале я пытался прошить ST-Link не пропатченной утилитой, и вполне ожидаемо получил ошибку следующего вида:

После чего, ничего не оставалось делать, как запустить пропатченную утилиту, которая вполне успешно отработала из под виртуалки.

Для работы утилиты требуется провести в виртуалку интернет, т.к. "STLinkReflash" тащит прошивку из сети. После прошивки ST-Link "отваливается" от виртуалки, т.к. он теперь определяется как JLink:

Забыл сказать, перед перепрошивкой следует установить драйвера на виртуалку с официального сайта: https://www.segger.com/products/debug-probes/j-link/models/other-j-links/st-link-on-board/. После перепрошивки в диспечере устройств должен появиться наш новоиспеченный J-Link:

Теперь для работы с данным отладчиком нам нужно скачать ПО фирмы Segger с официального сайта https://www.segger.com/downloads/jlink/ :

После распаковки архива у нас появляются следующие файлы:

Первым делом следует скопировать udev-правило "99-jlink.rules" в каталог "/etc/udev/rules.d/".

Не забываем перезагрузить правила (выполняется от root):

udevadm control --reload-rules && udevadm trigger

На этом этапе можно подключит какую-нибудь плату к STLink/JLink. Я буду использовать Bluepill.

Давайте заглянем в dmesg:

usb 5-3: new full-speed USB device number 2 using ohci-pci
usb 5-3: New USB device found, idVendor=1366, idProduct=0101, bcdDevice= 1.00
usb 5-3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 5-3: Product: J-Link
usb 5-3: Manufacturer: SEGGER
usb 5-3: SerialNumber: 000783201214

Устройство определяется как Segger J-Link

OpenOCD версий 0.10 и 0.11 имеют разный синтаксис конфигурационных файлов для JLink, но в обоих случаях, OpenOCD в случае использования JLink, по умолчанию будет пытаться подключиться по JTAG протоколу. Поэтому нам нужен специальный конфиг. Для версии 0.11 он будет выглядеть так:

#
# SEGGER J-Link
#
# http://www.segger.com/jlink.html
#

adapter driver jlink
adapter speed  1000
transport select swd

# The serial number can be used to select a specific device in case more than
# one is connected to the host.
#
# Example: Select J-Link with serial number 123456789
#
# jlink serial 123456789

Для OpenOCD версии 0.10 он будет следующим:

# SEGGER J-Link
#
# http://www.segger.com/jlink.html
#

interface jlink
transport select swd

# The serial number can be used to select a specific device in case more than
# one is connected to the host.
#
# Example: Select J-Link with serial number 123456789
#
# jlink serial 123456789

Далее я буду использовать OpenOCD версии 0.11, который у меня установлен в нестандартный каталог "/opt". Поэтом будут полные пути к конфигурационным файлам.

Запускаем OpenOCD:

$ /opt/bin/openocd-v11 -f ./jlink.cfg -f  /opt/share/openocd/scripts/target/stm32f1x.cfg  -c "init" -c "reset halt"
Open On-Chip Debugger 0.11.0
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
swd
Info : J-Link STLink V2 compiled Aug 12 2019 10:28:03
Info : Hardware version: 1.00
Info : VTarget = 3.300 V
Info : clock speed 1000 kHz
Info : SWD DPIDR 0x1ba01477
Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : starting gdb server for stm32f1x.cpu on 3333
Info : Listening on port 3333 for gdb connections
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x08000458 msp: 0x20005000
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections

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

На данном этапе мы можем подключаться к OpenOCD отладчиком GDB, и в принципе пользоваться J-Link также как обычным ST-Link'ом. Разве что st-flash для прошивки не будет работать.

В комплекте утилит Segger также имеется GDB-сервер - "JLinkGDBServer". Давайте запустим его:

$ ./JLinkGDBServer -device stm32f103c8
SEGGER J-Link GDB Server V7.68b Command Line Version

JLinkARM.dll V7.68b (DLL compiled Jul 22 2022 17:22:14)

Command line: -device stm32f103c8
-----GDB Server start settings-----
GDBInit file:                  none
GDB Server Listening port:     2331
SWO raw output listening port: 2332
Terminal I/O port:             2333
Accept remote connection:      yes
Generate logfile:              off
Verify download:               off
Init regs on start:            off
Silent mode:                   off
Single run mode:               off
Target connection timeout:     0 ms
------J-Link related settings------
J-Link Host interface:         USB
J-Link script:                 none
J-Link settings file:          none
------Target related settings------
Target device:                 stm32f103c8
Target interface:              JTAG
Target interface speed:        4000kHz
Target endian:                 little

Connecting to J-Link...
J-Link is connected.
Firmware: J-Link STLink V2 compiled Aug 12 2019 10:28:03
Hardware: V1.00
S/N: 783201214
Checking target voltage...
Target voltage: 3.30 V
Listening on TCP/IP port 2331
Connecting to target...
ERROR: Debugger tries to select target interface JTAG.
This interface is not supported by the connected emulator.
Selection will be ignored by the DLL.

J-Link found 1 JTAG device, Total IRLen = 4
JTAG ID: 0x1BA01477 (Cortex-M3)
Connected to target
Waiting for GDB connection...

При первом запуске вылезет окно с лицензией:

А если GDB-сервер запускать без параметра "-device stm32f103c8" то еще появится окно с выбором девайса.

Для подключения к данному серверу следует использовать порт 2331

(gdb) target remote localhost:2331
Remote debugging using localhost:2331
0x080002e6 in SetSysClockTo72 () at src/system_stm32f10x.c:1074
1074        }

(gdb) monitor help
SEGGER J-Link GDB Server V7.68b

Available remote commands are:

  cp15            clrbp           ci              clrwp           
  cd              device          flash device    endian          
  ExcludeFlashCacheRange  flash breakpoints  flash cpuclock  flash download  
  flash erase     getargs         go              halt            
  IsHalted        interface       if              jtagconf        
  loadbin         rtos            rtosconf        MemU16          
  WriteU16        MemU32          WriteU32        mww             
  long            MemU8           WriteU8         reg             
  regs            remoteport      port            reset           
  STRACE Config   STRACE Read     STRACE Start    STRACE Stop     
  SWO DisableTarget  SWO EnableTarget  SWO GetMaxSpeed  SWO GetSpeedInfo  
  SWOSpeed        SWO Start       SWO Stop        select          
  semihosting ARMSWI  semihosting disable  semihosting enable  semihosting IOClient  
  semihosting BreakOnError  semihosting ThumbSWI  setargs         setbp           
  bi              ReadMemAP       WriteDP         WriteAP         
  ReadAPEx        ReadDP          ReadAP          bdh             
  bd              bdb             sleep           speed           
  step            si              waithalt        wh              
  wice            rmib            WriteCSR        ReadCSR 

Команды монитора как видите иные.

Наверное самая универсальная утилита Segger - зто JLink Commander, она имеет имя файла JLinkExe, и у нее имеется диалоговый интерфейс:

$ ./JLinkExe  -device STM32F103C8
SEGGER J-Link Commander V7.68b (Compiled Jul 22 2022 17:22:29)
DLL version V7.68b, compiled Jul 22 2022 17:22:14

Connecting to J-Link via USB...O.K.
Firmware: J-Link STLink V2 compiled Aug 12 2019 10:28:03
Hardware version: V1.00
J-Link uptime (since boot): N/A (Not supported by this model)
S/N: 783201214
VTref=3.300V


Type "connect" to establish a target connection, '?' for help
J-Link>

Если ввести знак вопроса, то перед нами появится внушительный список команд:

Available commands are:
Command name     Command syntax                                      Command function
----------------------
?                ? []                                       Show information about all or specific commands.
Exit             Exit                                                Close J-Link connection and quit.
ExitOnError      EoE <1/0>                                           Exit on error.
Sleep            Sleep                                        Waits the given time (in milliseconds).
Log              Log                                       Enables log to file.
ExpDevList       ExpDevList                                Export device names from DLL internal device list to text file.
ExpDevListXML    ExpDevListXML                             Export device names from DLL internal device list to XML file.
USB              USB []                                          Connect to J-Link via USB.
IP               IP                       Connect to J-Link  via TCP/IP or to Remote Server.
SelectProbe      SelectProbe [  ...]         Show list of all connected probes via specified interface. The Probe to communicate with can then be selected.
ShowEmuList      ShowEmuList [  ...]         Show list of all connected probes via specified interface.
Power            Power  [perm]                               Switch power supply for target.
VTREF            VTREF . 0 == Auto detection              Set fixed value for VTref on J-Link.
VCOM             VCOM                                Enable/disable VCOM. Takes effect after power cycle of the Probe.
ShowFWInfo       ShowFWInfo                                          Show firmware info.
ShowHWStatus     ShowHWStatus                                        Show hardware status.
IPAddr           IPAddr                                              Show/Assign IP address and subnetmask of/to connected Probe.
GWAddr           GWAddr                                              Show/Assign network gateway address of/to connected Probe.
DNSAddr          DNSAddr                                             Show/Assign network DNS server address of/to connected Probe.
ShowConf         ShowConf                                            Show configuration of the connected Probe.
Calibrate        Calibrate                                           Calibrate the target current measurement.
Connect          Connect                                             Connect to target device.
Device           Device                                  Select specific device J-Link shall connect to.
SelectInterface  SelectInterface                          Select target interface.
Speed            Speed                           Set target interface speed.
LE               LE                                                  Change mode to little endian.
BE               BE                                                  Change mode to big endian.
Halt             Halt                                                Halt CPU.
IsHalted         IsHalted                                            Return current CPU state.
WaitHalt         WaitHalt [] (default: 1000 ms)           Wait until CPU is halted or timeout is reached.
Go               Go                                                  Start CPU if halted.
Reset            Reset                                               Reset CPU.
ResetX           ResetX                             Reset CPU with delay after reset.
RSetType         RSetType                                      Set the current reset type.
Step             Step [ (decimal)] (default is 1)          Execute step(s) on the CPU.
IS               IS                                                  Identify length of scan chain select register.
MS               MS                                      Measure length of scan chain.
Regs             Regs                                                Display CPU register contents.
RReg             RReg                                       Read register.
WReg             WReg ,                              Write register.
MoE              MoE                                                 Shows mode-of-entry (CPU halt reason).
SetBP            SetBP  [A/T] [S/H]                            Set breakpoint.
ClearBP          ClearBP                                  Clear breakpoint.
SetWP            SetWP  [R/W] [ [] [A-Mask]]     Set Watchpoint.
ClearWP          ClearWP                                  Clear watchpoint.
VCatch           VCatch                                       Write vector catch.
SetPC            SetPC                                         Set the PC to specified value.
ReadAP           ReadAP                                    Read CoreSight AP register. Note: First read returns data of the previous read. An additional read of DP reg 3 is necessary to get the data.
WriteAP          WriteAP                                   Write CoreSight AP register.
ReadDP           ReadDP                                    Read CoreSight DP register. Note: SWD: Data is returned immediately. JTAG: Data of the previous read is returned. An additional read of DP reg 3 is necessary to get the data.
WriteDP          WriteDP                                   Write CoreSight DP register.
RCP15Ex          RCE , , ,                       Read CP15 register.
WCP15Ex          WCE , , , ,               Write CP15 register.
Term             Term                                                Visualize printf output using DCC (SEGGER DCC handler running on target).
Mem              Mem  [:],  (hex)              Read memory and show corresponding ASCII values.
Mem8             Mem8  [:],  (hex)             Read  8-bit items.
Mem16            Mem16 [:],  (hex)             Read 16-bit items.
Mem32            Mem32 [:],  (hex)             Read 32-bit items.
Write1           W1 [:],  (hex)                    Write  8-bit items.
Write2           W2 [:],  (hex)                    Write 16-bit items.
Write4           W4 [:],  (hex)                    Write 32-bit items.
JTAGConf         JTAGConf ,                            Set number of IR/DR bits before Target device.
JTAGId           JTAGId                                              Read JTAG Id.
WJTAGIR          WJTAGIR , [] (default IRLen=4)  Write JTAG command (IR).
WJTAGDR          WJTAGDR ,                Write JTAG data (DR).
WJTAGRaw         WJTAGRaw                                            Write Raw JTAG data.
ResetTAP         ResetTAP                                            Reset TAP Controller using state machine (111110).
ResetTRST        ResetTRST                                           Reset TAP Controller using nTRST.
ICE              ICE                                                 Show state of the embedded ICE macrocell (ICE breaker).
ReadICE          RI (hex)                                  Read Ice reg.
WriteICE         WI , (hex)                          Write Ice reg.
TClear           TClear                                              TRACE - Clear buffer.
TSetSize         TSS                                      TRACE - Set Size of trace buffer.
TSetFormat       TSF <4|8|16>                                        TRACE - SetFormat.
TShowRegions     TShowRegions                                        TRACE - Show Regions (and analyze trace buffer).
TStart           TStart                                              TRACE - Start.
TStop            TStop                                               TRACE - Stop.
SWOSpeed         SWOSpeed                                            SWO - Show supported speeds.
SWOStart         SWOStart []. Default:  == Autodetect  SWO - Start.
SWOStop          SWOStop                                             SWO - Stop.
SWOStat          SWOStat                                             SWO - Display SWO status.
SWORead          SWORead                                             SWO - Read and display SWO data.
SWOShow          SWOShow                                             SWO - Read and analyze SWO data.
SWOFlush         SWOFlush                                            SWO - Flush data.
SWOView          SWOView                                             SWO - View terminal data.
Erase            Erase [, ]                            Erase flash (range) of selected device.
LoadFile         LoadFile , [ (.bin only)].          Load data file into target memory. Supported ext.: *.bin, *.mot, *.hex, *.srec
SaveBin          SaveBin , ,               Save target memory range into binary file.
VerifyBin        VerifyBin ,                         Verfy if specified .bin file is at the specified target memory location.
FWrite           FWrite   [ []]  (Flasher only) Write file to emulator.
FRead            FRead   [ []]  (Flasher only) Read file from emulator.
FShow            FShow  [ []]            (Flasher only) Read and display file from emulator.
FDelete          FDelete                                   (Flasher only) Delete file on emulator.
FSize            FSize                                     (Flasher only) Display size of file on emulator.
FList            FList                                               (Flasher only) List directory on emulator.
SecureArea       SecureArea                               (Flasher only) Creates/Removes secure area on probe.
PowerTrace       PowerTrace  [ ]  Perform power trace (not supported by all models)
TestWSpeed       TestWSpeed [ []]                        Measure download speed into target memory.
TestRSpeed       TestRSpeed [ [] []]          Measure upload speed from target memory.
TestCSpeed       TestCSpeed []                              Measure CPU speed.
TestNWSpeed      TestNWSpeed [ []]                Measure network download speed.
TestNRSpeed      TestNRSpeed [ []]                Measure network upload speed.
MR               MR                                                  Measure RTCK react time.
Clock            Clock                                               TCK - Clock.
Clock00          Clock00                                             TCK - Clock with TDI = TMS = 0.
ClrTCK           ClrTCK                                              TCK - Clear.
SetTCK           SetTCK                                              TCK - Set.
ClrTDI           ClrTDI                                              TDI - Clear.
SetTDI           SetTDI                                              TDI - Set.
ClrTMS           ClrTMS                                              TMS - Clear.
SetTMS           SetTMS                                              TMS - Set.
ClrTRST          ClrTRST                                             TRST - Clear.
SetTRST          SetTRST                                             TRST - Set.
ClrRESET         ClrRESET                                            RESET - Clear.
SetRESET         SetRESET                                            RESET - Set.
----------------------

На сайте segger имеется вики с пояснениями для каждой команды: https://wiki.segger.com/J-Link_Commander

С помощю данного командера можно в том числе прошивать микроконтроллеры. Для этого выполняем следующию последовать команд:

Type "connect" to establish a target connection, '?' for help
J-Link>connect
Please specify target interface:
  J) JTAG (Default)
  S) SWD
  T) cJTAG
TIF>s
Specify target interface speed [kHz]. : 4000 kHz
Speed>Вводим Enter
Device "STM32F103C8" selected.


Connecting to target via SWD
InitTarget() start
InitTarget() end
Found SW-DP with ID 0x1BA01477
DPv0 detected
CoreSight SoC-400 or earlier
Scanning AP map to find all available APs
AP[1]: Stopped AP scan as end of AP map has been reached
AP[0]: AHB-AP (IDR: 0x14770011)
Iterating through AP map to find AHB-AP to use
AP[0]: Core found
AP[0]: AHB-AP ROM base: 0xE00FF000
CPUID register: 0x411FC231. Implementer code: 0x41 (ARM)
Found Cortex-M3 r1p1, Little endian.
FPUnit: 6 code (BP) slots and 2 literal slots
CoreSight components:
ROMTbl[0] @ E00FF000
[0][0]: E000E000 CID B105E00D PID 001BB000 SCS
[0][1]: E0001000 CID B105E00D PID 001BB002 DWT
[0][2]: E0002000 CID B105E00D PID 000BB003 FPB
[0][3]: E0000000 CID B105E00D PID 001BB001 ITM
[0][4]: E0040000 CID B105900D PID 001BB923 TPIU-Lite
Cortex-M3 identified.
J-Link>loadbin /home/flanker/mydev/mcu/bluepill/03_uart_init/blink.bin 0x8000000
Halting CPU for downloading file.
Downloading file [/home/flanker/mydev/mcu/bluepill/03_uart_init/blink.bin]...
J-Link: Flash download: Bank 0 & 0x08000000: Skipped. Contents already match
O.K.
J-Link>r
Reset delay: 0 ms
Reset type NORMAL: Resets core & peripherals via SYSRESETREQ & VECTRESET bit.
Reset: Halt core after reset via DEMCR.VC_CORERESET.
Reset: Reset device via AIRCR.SYSRESETREQ.
J-Link>g
J-Link>qc

Чтобы постоянно не вбивать все эти команды вручную, предусмотрен режим работы с командным файлом. Для примера создаем такой файл "flash.jlink":

si 1
speed 4000
r
h
loadbin /home/flanker/mydev/qtcreator_projects/build/stm32f103c8-STM32F103xx-Release/Release_STM32F10_19fd02a79000e855/firmware.9bcf18e4/firmware.bin,0x08000000
r
g
qc

И запускаем прошивку:

$ ./JLinkExe  -device STM32F103C8 -commanderscript ./flash.jlink

И в ответ получаем такой длиннющий лог:

SEGGER J-Link Commander V7.68b (Compiled Jul 22 2022 17:22:29)
DLL version V7.68b, compiled Jul 22 2022 17:22:14


J-Link Command File read successfully.
Processing script file...
J-Link>si 1
J-Link connection not established yet but required for command.
Connecting to J-Link via USB...O.K.
Firmware: J-Link STLink V2 compiled Aug 12 2019 10:28:03
Hardware version: V1.00
J-Link uptime (since boot): N/A (Not supported by this model)
S/N: 783201214
VTref=3.300V
Selecting SWD as current target interface.
J-Link>speed 4000
Selecting 4000 kHz as target interface speed
J-Link>r
Target connection not established yet but required for command.
Device "STM32F103C8" selected.


Connecting to target via SWD
InitTarget() start
InitTarget() end
Found SW-DP with ID 0x1BA01477
DPv0 detected
CoreSight SoC-400 or earlier
Scanning AP map to find all available APs
AP[1]: Stopped AP scan as end of AP map has been reached
AP[0]: AHB-AP (IDR: 0x14770011)
Iterating through AP map to find AHB-AP to use
AP[0]: Core found
AP[0]: AHB-AP ROM base: 0xE00FF000
CPUID register: 0x411FC231. Implementer code: 0x41 (ARM)
Found Cortex-M3 r1p1, Little endian.
FPUnit: 6 code (BP) slots and 2 literal slots
CoreSight components:
ROMTbl[0] @ E00FF000
[0][0]: E000E000 CID B105E00D PID 001BB000 SCS
[0][1]: E0001000 CID B105E00D PID 001BB002 DWT
[0][2]: E0002000 CID B105E00D PID 000BB003 FPB
[0][3]: E0000000 CID B105E00D PID 001BB001 ITM
[0][4]: E0040000 CID B105900D PID 001BB923 TPIU-Lite
Cortex-M3 identified.
Reset delay: 0 ms
Reset type NORMAL: Resets core & peripherals via SYSRESETREQ & VECTRESET bit.
Reset: Halt core after reset via DEMCR.VC_CORERESET.
Reset: Reset device via AIRCR.SYSRESETREQ.
J-Link>h
PC = 0800040C, CycleCnt = 00000000
R0 = 000003E8, R1 = 000000F0, R2 = E000E010, R3 = 00000104
R4 = 40011000, R5 = 00002000, R6 = 2000070C, R7 = 00000014
R8 = 7FFFDFF9, R9 = FFFFFFFC, R10= 1ED00F3F, R11= 2A0052C8
R12= 20000638
SP(R13)= 20005000, MSP= 20005000, PSP= BC2D7FC8, R14(LR) = FFFFFFFF
XPSR = 01000000: APSR = nzcvq, EPSR = 01000000, IPSR = 000 (NoException)
CFBP = 00000000, CONTROL = 00, FAULTMASK = 00, BASEPRI = 00, PRIMASK = 00
FPU regs: FPU not enabled / not implemented on connected CPU.
J-Link>loadbin /home/flanker/mydev/qtcreator_projects/build/stm32f103c8-STM32F103xx-Release/Release_STM32F10_19fd02a79000e855/firmware.9bcf18e4/firmware.bin,0x08000000
Downloading file [/home/flanker/mydev/qtcreator_projects/build/stm32f103c8-STM32F103xx-Release/Release_STM32F10_19fd02a79000e855/firmware.9bcf18e4/firmware.bin]...
J-Link: Flash download: Bank 0 @ 0x08000000: 1 range affected (1024 bytes)
J-Link: Flash download: Total: 0.277s (Prepare: 0.119s, Compare: 0.054s, Erase: 0.031s, Program & Verify: 0.042s, Restore: 0.030s)
J-Link: Flash download: Program & Verify speed: 23 KB/s
O.K.
J-Link>r
Reset delay: 0 ms
Reset type NORMAL: Resets core & peripherals via SYSRESETREQ & VECTRESET bit.
Reset: Halt core after reset via DEMCR.VC_CORERESET.
Reset: Reset device via AIRCR.SYSRESETREQ.
J-Link>g
J-Link>qc

Script processing completed.

Проблема в том, что имя файла прошивки в командном файле прописано хардкорно, что потребует дополнительных действий при интеграции данного способа прошивки в какую-либо IDE.

Прошивка через OpenOCD на мой взгляд в данном случае более оправдана.

$ /opt/bin/openocd-v11 -f /home/flanker/jlink.cfg -f  /opt/share/openocd/scripts/target/stm32f1x.cfg  -c "init" -c "reset halt" -c "flash write_image erase /mnt/tmp/mcu/bluepill/03_uart_init/blink.bin 0x08000000" -c "reset" -c "exit" 
Open On-Chip Debugger 0.11.0
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
swd
Info : J-Link STLink V2 compiled Aug 12 2019 10:28:03
Info : Hardware version: 1.00
Info : VTarget = 3.300 V
Info : clock speed 1000 kHz
Info : SWD DPIDR 0x1ba01477
Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : starting gdb server for stm32f1x.cpu on 3333
Info : Listening on port 3333 for gdb connections
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x080002c4 msp: 0x20005000
Info : device id = 0x20036410
Info : flash size = 64kbytes
auto erase enabled
wrote 2048 bytes from file /mnt/tmp/mcu/bluepill/03_uart_init/blink.bin in 0.376020s (5.319 KiB/s)

5) JLinkV8 (клон)

В 2019 году, по купонам, на распродаже али "11.11", я приобрел практически за бесценок клон отладчика J-Link V8. В принципе, тогда я его брал не для работы с ПО фирмы Segger, а просто из-за его JTAG разъема. В частности для работы с платами имеющим JTAG-разъем. Например такой:

В данном случае здесь чип STM32F103RB, но есть также черная плата с микроконтроллером stm32f407, у которой такой же разъем.

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


фото с сайта https://cdeblog.ru

В моем случае китайцы выкинули "лишние" детали, и мой J-Link выглядит так:

Здесь сразу бросается в глаза отсутствие контактных площадок TST и ERASE с помощью которых осуществляется восстановление прошивки JLink'а в случае ее неудачного обновления или еще чего.

Давайте посмотрим что мы увидим в dmesg, при подключении отладчика к компьютеру:

usb 5-3: new full-speed USB device number 4 using ohci-pci
usb 5-3: New USB device found, idVendor=1366, idProduct=0101, bcdDevice= 1.00
usb 5-3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 5-3: Product: J-Link
usb 5-3: Manufacturer: SEGGER
usb 5-3: SerialNumber: 00123456789

Существует устойчивое мнение, что все серийники с которыми китайцы продают свои клоны JLink давно известны Segger, и если запустить JLinkEXE с таким клоном, то программа или выдаст ошибку о скомпрометированном серийном номере, либо залочит устройство. Чтобы не быть голословным, приведу ссылку на руководство с подробными инструкциями: "Как убить JLink" (выполнять не пробовал).

Без использования ПО Segger мы можем без опаски пользоваться OpenOCD. Также в STM32CubeIDE есть своя поддержка JLink.

Попробуем запустить OpenOCD:

$ openocd -f interface/jlink.cfg -f target/stm32f1x.cfg  -c "init" -c "reset halt"
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
jtag
adapter speed: 1000 kHz
adapter_nsrst_delay: 100
jtag_ntrst_delay: 100
none separate
cortex_m reset_config sysresetreq
Info : No device selected, using first device.
Info : J-Link ARM V8 compiled Nov 28 2014 13:44:46
Info : Hardware version: 8.00
Info : VTarget = 3.319 V
Info : clock speed 1000 kHz
Info : JTAG tap: stm32f1x.cpu tap/device found: 0x3ba00477 (mfg: 0x23b (ARM Ltd.), part: 0xba00, ver: 0x3)
Info : JTAG tap: stm32f1x.bs tap/device found: 0x16410041 (mfg: 0x020 (STMicroelectronics), part: 0x6410, ver: 0x1)
Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : JTAG tap: stm32f1x.cpu tap/device found: 0x3ba00477 (mfg: 0x23b (ARM Ltd.), part: 0xba00, ver: 0x3)
Info : JTAG tap: stm32f1x.bs tap/device found: 0x16410041 (mfg: 0x020 (STMicroelectronics), part: 0x6410, ver: 0x1)
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x08000458 msp: 0x20005000

Есть контакт. Прошиваем тестовую моргалку:

$ openocd -f interface/jlink.cfg -f target/stm32f1x.cfg  -c "init" -c "reset halt" -c "flash write_image erase /mnt/tmp/mcu/bluepill/03_uart_init/blink.bin 0x08000000" -c "reset" -c "exit"
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
jtag
adapter speed: 1000 kHz
adapter_nsrst_delay: 100
jtag_ntrst_delay: 100
none separate
cortex_m reset_config sysresetreq
Info : No device selected, using first device.
Info : J-Link ARM V8 compiled Nov 28 2014 13:44:46
Info : Hardware version: 8.00
Info : VTarget = 3.319 V
Info : clock speed 1000 kHz
Info : JTAG tap: stm32f1x.cpu tap/device found: 0x3ba00477 (mfg: 0x23b (ARM Ltd.), part: 0xba00, ver: 0x3)
Info : JTAG tap: stm32f1x.bs tap/device found: 0x16410041 (mfg: 0x020 (STMicroelectronics), part: 0x6410, ver: 0x1)
Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : JTAG tap: stm32f1x.cpu tap/device found: 0x3ba00477 (mfg: 0x23b (ARM Ltd.), part: 0xba00, ver: 0x3)
Info : JTAG tap: stm32f1x.bs tap/device found: 0x16410041 (mfg: 0x020 (STMicroelectronics), part: 0x6410, ver: 0x1)
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x08000458 msp: 0x20005000
auto erase enabled
Info : device id = 0x20036410
Info : flash size = 128kbytes
wrote 2048 bytes from file /mnt/tmp/mcu/bluepill/03_uart_init/blink.bin in 0.943038s (2.121 KiB/s)
Info : JTAG tap: stm32f1x.cpu tap/device found: 0x3ba00477 (mfg: 0x23b (ARM Ltd.), part: 0xba00, ver: 0x3)
Info : JTAG tap: stm32f1x.bs tap/device found: 0x16410041 (mfg: 0x020 (STMicroelectronics), part: 0x6410, ver: 0x1)

Все успешно.

В различных IDE данный отладчик настаивается как и любой другой поддерживаемый OpenOCD. Исключение составляет STM32CubeIDE, где помимо OpenOCD можно выбрать непосредственно J-Link:


Никаких программ ставить, ничего более настраивать не требуется. Для отладки хватит этих настроек.

Прежде чем запускать ПО Segger, я сменил серийник в JLinkV8 на первый, который мне пришел в голову.

Пробуем теперь с его помощью прошить микроконтроллер:

$  ./JLinkExe  -device STM32F103RB -commanderscript ./flash.jlink
SEGGER J-Link Commander V7.68b (Compiled Jul 22 2022 17:22:29)
DLL version V7.68b, compiled Jul 22 2022 17:22:14


J-Link Command File read successfully.
Processing script file...
J-Link>si 1
J-Link connection not established yet but required for command.
Connecting to J-Link via USB...O.K.
Firmware: J-Link ARM V8 compiled Nov 28 2014 13:44:46
Hardware version: V8.00
J-Link uptime (since boot): N/A (Not supported by this model)
S/N: 12345678
License(s): RDI,FlashDL,FlashBP,JFlash,GDB
VTref=3.306V
Selecting SWD as current target interface.
J-Link>speed 4000
Selecting 4000 kHz as target interface speed
J-Link>r
Target connection not established yet but required for command.
Device "STM32F103RB" selected.


Connecting to target via SWD
InitTarget() start
InitTarget() end
Found SW-DP with ID 0x1BA01477
DPv0 detected
CoreSight SoC-400 or earlier
Scanning AP map to find all available APs
AP[1]: Stopped AP scan as end of AP map has been reached
AP[0]: AHB-AP (IDR: 0x14770011)
Iterating through AP map to find AHB-AP to use
AP[0]: Core found
AP[0]: AHB-AP ROM base: 0xE00FF000
CPUID register: 0x411FC231. Implementer code: 0x41 (ARM)
Found Cortex-M3 r1p1, Little endian.
FPUnit: 6 code (BP) slots and 2 literal slots
CoreSight components:
ROMTbl[0] @ E00FF000
[0][0]: E000E000 CID B105E00D PID 001BB000 SCS
[0][1]: E0001000 CID B105E00D PID 001BB002 DWT
[0][2]: E0002000 CID B105E00D PID 000BB003 FPB
[0][3]: E0000000 CID B105E00D PID 001BB001 ITM
[0][4]: E0040000 CID B105900D PID 001BB923 TPIU-Lite
Cortex-M3 identified.
Reset delay: 0 ms
Reset type NORMAL: Resets core & peripherals via SYSRESETREQ & VECTRESET bit.
Reset: Halt core after reset via DEMCR.VC_CORERESET.
Reset: Reset device via AIRCR.SYSRESETREQ.
J-Link>h
PC = 080002C4, CycleCnt = 00000000
R0 = 000001F4, R1 = E000E000, R2 = 2000001C, R3 = 00000138
R4 = 40011000, R5 = 00002000, R6 = 00000000, R7 = FEEF5AEC
R8 = DFFBBFFD, R9 = BFFFFFDE, R10= BD3AA69C, R11= CA7ED645
R12= 20000638
SP(R13)= 20005000, MSP= 20005000, PSP= 1E6FDFCC, R14(LR) = FFFFFFFF
XPSR = 01000000: APSR = nzcvq, EPSR = 01000000, IPSR = 000 (NoException)
CFBP = 00000000, CONTROL = 00, FAULTMASK = 00, BASEPRI = 00, PRIMASK = 00
FPU regs: FPU not enabled / not implemented on connected CPU.
J-Link>loadbin /home/flanker/mydev/qtcreator_projects/build/stm32f103c8-STM32F103xx-Release/Release_STM32F10_19fd02a79000e855/firmware.9bcf18e4/firmware.bin,0x08000000
Downloading file [/home/flanker/mydev/qtcreator_projects/build/stm32f103c8-STM32F103xx-Release/Release_STM32F10_19fd02a79000e855/firmware.9bcf18e4/firmware.bin]...
J-Link: Flash download: Bank 0 @ 0x08000000: Skipped. Contents already match
O.K.
J-Link>r
Reset delay: 0 ms
Reset type NORMAL: Resets core & peripherals via SYSRESETREQ & VECTRESET bit.
Reset: Halt core after reset via DEMCR.VC_CORERESET.
Reset: Reset device via AIRCR.SYSRESETREQ.
J-Link>g
J-Link>qc

Script processing completed.

На первый взгляд лог выглядит одинаково. Но тут имеется существенное отличие, которое кроется в этой строке:

License(s): RDI,FlashDL,FlashBP,JFlash,GDB

Можно предположить, что лицензии определяют какие-то возможности JLink. В комплекте утилит Segger имеется программа JFlashEXE. Как понимаю, это флешер. Если мы попробуем что-то прошить через данный флешер и JLink перепрошитый из STLinkV2 то получим такую ошибку:

Впрочем с JLinkV8 у меня эта программа тоже не работает, но уже не по причине отсутствия лицензий:

Наряду с JFlashEXE имеется утилита JFlashLiteExe, с помощью которой можно прошить микроконтроллер, что тем, что этим JLink'ом:

6) ESP-STLINK

Когда у меня сгорел ST-Link, я начал искать чем еще можно прошить STM8. Выбор оказался невелик. Флешер stm8flash поддерживал только STLink и некий ESP-STLink.

STM8S207 имеет встроенный загрузчик, но софта для его использования я не нашел. Т.о. оставался только вариант с ESP-STLink. Проект можно найти на ресурсе "github.com" по следующей ссылке https://github.com/rumpeltux/esp-stlink

Он реализует протокол SWIM на ESP8266. Поэтому если у вас валяется без дела платка NodeMCU, вы можете найти ей применение. Сразу скажу, что stm8flash у меня с ним не заработал, но там есть свой скрипт на питоне, им и придется пользоваться.

Проект распространяется в виде исходного кода, и перед прошивкой его нужно собрать. Для этого потребуется ESP8266 SDK. Я использую версию ESP8266_NONOS_SDK-2.1.0, но вы можете использовать то, что вам больше нравится. Инструкция по сборке выложена на главной странице esp-stlink, и следуя данной инструкции выполняем следующее:

1. Скачиваем исходники проекта:

$ git clone https://github.com/rumpeltux/esp-stlink.git

2. Идем в каталог с исходниками:

$ cd ./esp-stlink/src/

Далее задаем каталог своего ESP8266 SDK. В моем случае это:

  $ ESP_OPEN_SDK=/home/flanker/mydev/tools/esp-open-sdk
  $ export XTENSA_TOOLS_ROOT=$ESP_OPEN_SDK/xtensa-lx106-elf/bin SDK_BASE=$ESP_OPEN_SDK/sdk flash

Т.к. у меня esptool имеет имя "esptool.py", а не "esptool", как это прописано в Makefile, исправляем имя флешера в Makefile:

$ sed -i "s/esptool/esptool.py/" Makefile 

Запускаем компиляцию:

$ make V=1
mkdir -p build/driver
mkdir -p build/user
mkdir -p firmware
/home/flanker/mydev/tools/esp-open-sdk/xtensa-lx106-elf/bin/xtensa-lx106-elf-gcc -Idriver -Iuser -Idriver/include -Iuser/include -Iinclude -I. -I/home/flanker/mydev/tools/esp-open-sdk/sdk/include -I/home/flanker/mydev/tools/esp-open-sdk/sdk/include/json -std=c99 -Os -g -O2 -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals  -D__ets__ -DICACHE_FLASH -c driver/swim.c -o build/driver/swim.o
/home/flanker/mydev/tools/esp-open-sdk/xtensa-lx106-elf/bin/xtensa-lx106-elf-gcc -Idriver -Iuser -Idriver/include -Iuser/include -Iinclude -I. -I/home/flanker/mydev/tools/esp-open-sdk/sdk/include -I/home/flanker/mydev/tools/esp-open-sdk/sdk/include/json -std=c99 -Os -g -O2 -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals  -D__ets__ -DICACHE_FLASH -c driver/uart.c -o build/driver/uart.o
/home/flanker/mydev/tools/esp-open-sdk/xtensa-lx106-elf/bin/xtensa-lx106-elf-gcc -Idriver -Iuser -Idriver/include -Iuser/include -Iinclude -I. -I/home/flanker/mydev/tools/esp-open-sdk/sdk/include -I/home/flanker/mydev/tools/esp-open-sdk/sdk/include/json -std=c99 -Os -g -O2 -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals  -D__ets__ -DICACHE_FLASH -c user/serial.c -o build/user/serial.o
/home/flanker/mydev/tools/esp-open-sdk/xtensa-lx106-elf/bin/xtensa-lx106-elf-gcc -Idriver -Iuser -Idriver/include -Iuser/include -Iinclude -I. -I/home/flanker/mydev/tools/esp-open-sdk/sdk/include -I/home/flanker/mydev/tools/esp-open-sdk/sdk/include/json -std=c99 -Os -g -O2 -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals  -D__ets__ -DICACHE_FLASH -c user/user_main.c -o build/user/user_main.o
/home/flanker/mydev/tools/esp-open-sdk/xtensa-lx106-elf/bin/xtensa-lx106-elf-ar cru build/app_app.a build/driver/swim.o build/driver/uart.o build/user/serial.o build/user/user_main.o
/home/flanker/mydev/tools/esp-open-sdk/xtensa-lx106-elf/bin/xtensa-lx106-elf-gcc -L/home/flanker/mydev/tools/esp-open-sdk/sdk/lib -T/home/flanker/mydev/tools/esp-open-sdk/sdk/ld/eagle.app.v6.ld -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static -Wl,--start-group -lc -lgcc -lhal -lpp -lphy -lnet80211 -llwip -lwpa -lmain build/app_app.a -Wl,--end-group -o build/app.out
esptool.py elf2image -o firmware/ build/app.out
esptool.py v4.2
Creating esp8266 image...
Successfully created esp8266 image.

После этого, в каталоге "firmware" у вас должно появиться два файла с прошивкой:

$ ls -l ./firmware/
итого 228
-rw-r--r-- 1 flanker users  28560 авг  6 11:14 0x00000.bin
-rw-r--r-- 1 flanker users 201044 авг  6 11:14 0x10000.bin

Далее следует подключить вашу NodeMCU к компьютеру и прошить ее командой "make flash", но вот этот последний этап у меня вызвал больше всего трудностей. Также у меня также возникло горячее желание подвернуть ревизии свои статьи по ESP8266 т.к. написанные так команды уже не работают и они попросту вводят в заблуждение.

Общими словами, если после прошивки командой "make flash" светодиод на модуле esp8266 быстро-быстро мигает, значит ваш ESP8266 ушел в bootloop и следующий текст для вас.

Давайте посмотрим на команду на команду прошивки:

esptool.py --baud 115200 --port /dev/ttyUSB0 write_flash 0x00000 ./firmware/0x00000.bin 0x10000 ./firmware/0x10000.bin

В данном случае в команде нет параметров SPI-флешки и частоты ESP8266 и esptool отрабатывает с какими-то своими дефолтными настройками. В тоже время чипы у всех разные и настройки для них все свои.

У меня NodeMCU на модуле ESP12-E c 4MB флешкой. При этом установлен свежий esptool версии 4.2

$ esptool.py version
esptool.py v4.2
4.2

Данная версия не принимает параметр "-fs 32m", вместо этого предлагается "4MB" или "4MB-c1". И вот с последним параметром мне прошивка удалась.

Итак, подключаем NodeMCU и проверяем контакт:

$ esptool.py chip_id
esptool.py v4.2
Found 2 serial ports
Serial port /dev/ttyUSB0
Connecting....
Detecting chip type... Unsupported detection protocol, switching and trying again...
Connecting....
Detecting chip type... ESP8266
Chip is ESP8266EX
Features: WiFi
Crystal is 26MHz
MAC: a0:20:a6:12:5f:05
Uploading stub...
Running stub...
Stub running...
Chip ID: 0x00125f05
Hard resetting via RTS pin.
$ esptool.py flash_id
esptool.py v4.2
Found 2 serial ports
Serial port /dev/ttyUSB0
Connecting....
Detecting chip type... Unsupported detection protocol, switching and trying again...
Connecting....
Detecting chip type... ESP8266
Chip is ESP8266EX
Features: WiFi
Crystal is 26MHz
MAC: a0:20:a6:12:5f:05
Uploading stub...
Running stub...
Stub running...
Manufacturer: e0
Device: 4016
Detected flash size: 4MB
Hard resetting via RTS pin...

Контакт есть, очищаем флешку:

$ esptool.py -p /dev/ttyUSB0 erase_flash
esptool.py v4.2
Serial port /dev/ttyUSB0
Connecting....
Detecting chip type... Unsupported detection protocol, switching and trying again...
Connecting....
Detecting chip type... ESP8266
Chip is ESP8266EX
Features: WiFi
Crystal is 26MHz
MAC: a0:20:a6:12:5f:05
Uploading stub...
Running stub...
Stub running...
Erasing flash (this may take a while)...
Chip erase completed successfully in 11.0s
Hard resetting via RTS pin...

Далее заходим в каталог SDK, который использовали при компиляции проекта и прошиваем AT-интерпретатором. В случае использования ESP8266_NONOS_SDK-2.1.0 это будет выглядеть так:

$ esptool.py -p /dev/ttyUSB0 write_flash -fm dio -ff 40m -fs 4MB-c1 0x00000 ./boot_v1.7.bin  0x01000 ./at/512+512/user1.1024.new.2.bin   0x3fc000 ./esp_init_data_default.bin 0x7e000 ./blank.bin 0x3fe000 ./blank.bin
esptool.py v4.2
Serial port /dev/ttyUSB0
Connecting....
Detecting chip type... Unsupported detection protocol, switching and trying again...
Connecting....
Detecting chip type... ESP8266
Chip is ESP8266EX
Features: WiFi
Crystal is 26MHz
MAC: a0:20:a6:12:5f:05
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Flash will be erased from 0x00000000 to 0x00000fff...
Flash will be erased from 0x00001000 to 0x00069fff...
Flash will be erased from 0x003fc000 to 0x003fcfff...
Flash will be erased from 0x0007e000 to 0x0007efff...
Flash will be erased from 0x003fe000 to 0x003fefff...
Flash params set to 0x0260
Compressed 4080 bytes to 2936...
Wrote 4080 bytes (2936 compressed) at 0x00000000 in 0.3 seconds (effective 103.6 kbit/s)...
Hash of data verified.
Compressed 427060 bytes to 305755...
Wrote 427060 bytes (305755 compressed) at 0x00001000 in 27.1 seconds (effective 126.1 kbit/s)...
Hash of data verified.
Compressed 128 bytes to 75...
Wrote 128 bytes (75 compressed) at 0x003fc000 in 0.1 seconds (effective 7.3 kbit/s)...
Hash of data verified.
Compressed 4096 bytes to 26...
Wrote 4096 bytes (26 compressed) at 0x0007e000 in 0.1 seconds (effective 384.4 kbit/s)...
Hash of data verified.
Compressed 4096 bytes to 26...
Wrote 4096 bytes (26 compressed) at 0x003fe000 in 0.1 seconds (effective 224.1 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...

После прошивки следует убедится в работоспособности АТ-интерпретатора, и если все ок, возвращаемся в каталог проекта и прошиваем скомпилированную прошивку:

$ esptool.py -p /dev/ttyUSB0 write_flash -fm dio -ff 40m -fs 4MB-c1 0x00000 ./firmware/0x00000.bin 0x10000 ./firmware/0x10000.bin
esptool.py v4.2
Serial port /dev/ttyUSB0
Connecting....
Detecting chip type... Unsupported detection protocol, switching and trying again...
Connecting....
Detecting chip type... ESP8266
Chip is ESP8266EX
Features: WiFi
Crystal is 26MHz
MAC: a0:20:a6:12:5f:05
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Flash will be erased from 0x00000000 to 0x00006fff...
Flash will be erased from 0x00010000 to 0x00041fff...
Flash params set to 0x0260
Compressed 28560 bytes to 21306...
Wrote 28560 bytes (21306 compressed) at 0x00000000 in 2.4 seconds (effective 96.7 kbit/s)...
Hash of data verified.
Compressed 201044 bytes to 147825...
Wrote 201044 bytes (147825 compressed) at 0x00010000 in 13.2 seconds (effective 122.2 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...

После корректной прошивки, ни один светодиод на плате NodeMCU не должен мигать!

Далее нам следует подключить STM8 микроконтроллер к NodeMCU. Для этого соединяем шину питания микроконтроллера с пинами GND и 3.3V на NodeMCU. SWIM соединяем с выводом D2 NodeMCU, NRST соединяем с D1. Между питанием и SWIM ставим резистор на 1 кОм.

Кода все готово, можно испытать наш программатор. Как я говорил, stm8flash отказался у меня работать, но в каталоге "python" имеется простенький скрипт флешера. Прошиваем:

$ python3 ./python/flash.py -d /dev/ttyUSB0 -i ~/mydev/mcu/stm8s103f3p6/01_blink/blink.ihx 
8000:80d3       3 blocks (211 bytes) ....
$ stm8-size  ~/mydev/mcu/stm8s103f3p6/01_blink/blink.ihx 
   text    data     bss     dec     hex filename
      0     211       0     211      d3 /home/flanker/mydev/mcu/stm8s103f3p6/01_blink/blink.ihx

Светодиод на платке stm8s103f3 весело замигал, значит все Ок. Давайте попробуем прошить микроконтроллер какой-нибудь объемной прошивкой. Например:

$ stm8-size  ~/mydev/mcu/stm8s103f3p6/32_i2c_rda5807m/firmware.ihx 
   text    data     bss     dec     hex filename
      0    6422       0    6422    1916 /home/flanker/mydev/mcu/stm8s103f3p6/32_i2c_rda5807m/firmware.ihx

Прошиваем:

$ python3 ./python/flash.py -d /dev/ttyUSB0 -i ~/mydev/mcu/stm8s103f3p6/32_i2c_rda5807m/firmware.ihx
8000:9916       100 blocks (6422 bytes) .....................................................................................................

Чтобы проверить прошивку, я подключил микроконтроллер stm8 к stlinkv2 и запустил команду верификации прошивки:

$ stm8flash -c stlinkv2 -p stm8s103f3  -v ~/mydev/mcu/stm8s103f3p6/32_i2c_rda5807m/firmware.ihx 
Determine FLASH area
STLink: v2, JTAG: v29, SWIM: v7, VID: 8304, PID: 4837
Due to its file extension (or lack thereof), "/home/flanker/mydev/mcu/stm8s103f3p6/32_i2c_rda5807m/firmware.ihx" is considered as INTEL HEX format!
Verifing 8192 bytes at 0x8000... OK
Bytes verified: 6422

Как видно, проверка прошла успешно.

Чтобы не проходить квест с компиляцией и прошивкой espstlin, я сделал полный дамп флешки ESP12-E модуля и запаковал его в архив. К архиву также добавил оба файла с прошивкой, полученные в результате компиляции.

Загрузка дампа в 4-х мегабайтный модуль ESP-12E будет выглядеть так:

$ esptool.py --port /dev/ttyUSB0 write_flash -fm dio -ff 40m -fs 4MB-c1 0x00000 ./espstlink.bin 
esptool.py v4.2
Serial port /dev/ttyUSB0
Connecting....
Detecting chip type... Unsupported detection protocol, switching and trying again...
Connecting....
Detecting chip type... ESP8266
Chip is ESP8266EX
Features: WiFi
Crystal is 26MHz
MAC: a0:20:a6:12:5f:05
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Flash will be erased from 0x00000000 to 0x003fffff...
Compressed 4194304 bytes to 308169...
Wrote 4194304 bytes (308169 compressed) at 0x00000000 in 43.4 seconds (effective 773.3 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...

Будет ли работать дамп на ESP-12F я не знаю, проверить не на чем. Ссылка для скачивания архива: https://disk.yandex.ru/d/wsomOs2WqYTuwA

Пока не понятно, будет ли данный программатор работать с чипами stm8s2xx и l-серией. Также не понятно в чем проблемы stm8flash в работе с данным программатором. Нужно лезть в исходники и разбираться. Но пока, в качестве запасного варианта, данный способ прошивки, думаю, что вполне можно использовать.

На этой ноте данный эпос буду заканчивать. В стороне остался JTAG-отладчик на чипе FT232H, по нему у меня добавить нечего, кроме того, что я уже писал. Пришел к выводу, что чтобы им нормально пользоваться, нужно добавлять 20-пиновый JTAG разъем и делать корпус. Той платой которую продают на али пользоваться очень трудоемко, и плата валяется без дела "на подхвате".

7) Прошивка и отладка китайского ARM микроконтроллера AT32F403RC (добавлено позже)

Через пару недель после опубликования статьи, ко мне дошел купленный на али китайский микроконтроллер AT32F403RCT6, и мне предоставилась возможность испытать свои отладчики на "живом" китайце.

Китаец я бы сказал типичный, упоминаний о нем на официальном сайте нет ;) Фирма продает чипы AT32F403 только в 144-пиновом корпусе:

Для прошивки данных чипов фирма продает AT-Link, его цена на али около 2.5 т.р.

К счастью, на гитхабе нашелся проект под этот микроконтроллер: "https://github.com/cloidnerux/hoverboard-firmware-hack", где была инструкция по прошивке JLink'ом:

В проекте имелся FLM-файл и строки которые следовало добавить в "JLinkDevices.xml". Выполнив все инструкции, я попытался подключиться к чипу JLink'ом прошитом из STLink'а. Однако меня ожидало фиаско:

Упс! Данный JLink предназначен только для работы с микроконтроллерами фирмы ST. Обидно.

Далее в ход пошел клон JLink v8. В начале появлется окошко с выбором чипа:

Подключаемся и прошиваем чип описанным выше способом. Лог получается следующим:

Device "AT32F403RCT6" selected.


Connecting to target via JTAG
TotalIRLen = 4, IRPrint = 0x01
JTAG chain detection found 1 devices:
 #0 Id: 0x4BA00477, IRLen: 04, CoreSight JTAG-DP
DPv0 detected
CoreSight SoC-400 or earlier
Scanning AP map to find all available APs
AP[1]: Stopped AP scan as end of AP map has been reached
AP[0]: AHB-AP (IDR: 0x24770011)
Iterating through AP map to find AHB-AP to use
AP[0]: Core found
AP[0]: AHB-AP ROM base: 0xE00FF000
CPUID register: 0x410FC241. Implementer code: 0x41 (ARM)
Found Cortex-M4 r0p1, Little endian.
FPUnit: 6 code (BP) slots and 2 literal slots
CoreSight components:
ROMTbl[0] @ E00FF000
[0][0]: E000E000 CID B105E00D PID 000BB00C SCS-M7
[0][1]: E0001000 CID B105E00D PID 003BB002 DWT
[0][2]: E0002000 CID B105E00D PID 002BB003 FPB
[0][3]: E0000000 CID B105E00D PID 003BB001 ITM
[0][4]: E0040000 CID B105900D PID 000BB9A1 TPIU
[0][5]: E0041000 CID B105900D PID 000BB925 ETM
Cortex-M4 identified.
J-Link>loadbin  /home/flanker/mydev/mcu/stm32_bare_metal/00_blink/blink.bin 0x8000000
Halting CPU for downloading file.
Downloading file [/home/flanker/mydev/mcu/stm32_bare_metal/00_blink/blink.bin]...
J-Link: Flash download: Bank 0 @ 0x08000000: 1 range affected (2048 bytes)
J-Link: Flash download: Total: 0.254s (Prepare: 0.023s, Compare: 0.041s, Erase: 0.060s, Program: 0.074s, Verify: 0.036s, Restore: 0.019s)
J-Link: Flash download: Program speed: 26 KB/s
O.K.
J-Link>r
Reset delay: 0 ms
Reset type NORMAL: Resets core & peripherals via SYSRESETREQ & VECTRESET bit.
Reset: Halt core after reset via DEMCR.VC_CORERESET.
Reset: Reset device via AIRCR.SYSRESETREQ.
J-Link>g
J-Link>qc

Чип совместимый (не полностью) с STM32F103, поэтому можно залить прошивку от stm32 и она будет работать.

Но, наверное, проще будет вместо JLink'а пользоваться STLink или DAP-Link.

К сожалению, с помощью OpenOCD подключиться к чипу не получится:

$ openocd -f interface/stlink.cfg -f target/stm32f4x.cfg  -c "init" -c "reset halt"
Open On-Chip Debugger 0.11.0
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "hla_swd". To override use 'transport select '.
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
Info : clock speed 2000 kHz
Info : STLINK V2J29S7 (API v2) VID:PID 0483:3748
Info : Target voltage: 3.276395
Info : stm32f4x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : starting gdb server for stm32f4x.cpu on 3333
Info : Listening on port 3333 for gdb connections
Info : Unable to match requested speed 2000 kHz, using 1800 kHz
Info : Unable to match requested speed 2000 kHz, using 1800 kHz
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x08000170 msp: 0x20005000
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : accepting 'gdb' connection on tcp/3333
Info : device id = 0x70050242
Warn : Cannot identify target as a STM32 family.
span.ErrorError: auto_probe failed
Error: Connect failed. Consider setting up a gdb-attach event for the target to prepare target for GDB connect, or use 'gdb_memory_map disable'.
Error: attempted 'gdb' connection rejected

В данном случае, драйвер флеш-памяти OpenOCD не узнает ID чипа. С опцией "db_memory_map disable" мы сможем все-таки подключиться, но пользы от этого будет немного.

А вот pyocd показал себе с лучшей стороны. Для работы с чипом нужно будет скачать пакет для Keil. Через пакетный менеджер это не получится сделать, т.к. на сайте keil.com его нет, поэтому придется добавлять его вручную.

Сначала его следует скачать с сайта производителя. После чего создаем файл "pyocd.yaml" с полным путем пака:

pack:
  -  /home/flanker/.local/share/Keil.AT32F4xx_DFP.1.3.2.pack

Подводный камень в том, что pyocd потребуется запускать из каталога расположения "pyocd.yaml" иначе pyocd его не видит.

Посмотрим, что у нас есть:

$ pyocd list --targets|grep "at32"

Получаем немаленький такой список:

  at32f403acct7   ArteryTek  AT32F403ACCT7   AT32F4 Series, AT32F403A  pack     
  at32f403accu7   ArteryTek  AT32F403ACCU7   AT32F4 Series, AT32F403A  pack     
  at32f403acet7   ArteryTek  AT32F403ACET7   AT32F4 Series, AT32F403A  pack     
  at32f403aceu7   ArteryTek  AT32F403ACEU7   AT32F4 Series, AT32F403A  pack     
  at32f403acgt7   ArteryTek  AT32F403ACGT7   AT32F4 Series, AT32F403A  pack     
  at32f403acgu7   ArteryTek  AT32F403ACGU7   AT32F4 Series, AT32F403A  pack     
  at32f403arct7   ArteryTek  AT32F403ARCT7   AT32F4 Series, AT32F403A  pack     
  at32f403aret7   ArteryTek  AT32F403ARET7   AT32F4 Series, AT32F403A  pack     
  at32f403argt7   ArteryTek  AT32F403ARGT7   AT32F4 Series, AT32F403A  pack     
  at32f403avct7   ArteryTek  AT32F403AVCT7   AT32F4 Series, AT32F403A  pack     
  at32f403avet7   ArteryTek  AT32F403AVET7   AT32F4 Series, AT32F403A  pack     
  at32f403avgt7   ArteryTek  AT32F403AVGT7   AT32F4 Series, AT32F403A  pack     
  at32f403cb      ArteryTek  AT32F403CB      AT32F4 Series, AT32F403   pack     
  at32f403cc      ArteryTek  AT32F403CC      AT32F4 Series, AT32F403   pack     
  at32f403ce      ArteryTek  AT32F403CE      AT32F4 Series, AT32F403   pack     
  at32f403cg      ArteryTek  AT32F403CG      AT32F4 Series, AT32F403   pack     
  at32f403rc      ArteryTek  AT32F403RC      AT32F4 Series, AT32F403   pack     
  at32f403re      ArteryTek  AT32F403RE      AT32F4 Series, AT32F403   pack     
  at32f403rg      ArteryTek  AT32F403RG      AT32F4 Series, AT32F403   pack     
  at32f403vc      ArteryTek  AT32F403VC      AT32F4 Series, AT32F403   pack     
  at32f403ve      ArteryTek  AT32F403VE      AT32F4 Series, AT32F403   pack     
  at32f403vg      ArteryTek  AT32F403VG      AT32F4 Series, AT32F403   pack     
  at32f403zc      ArteryTek  AT32F403ZC      AT32F4 Series, AT32F403   pack     
  at32f403ze      ArteryTek  AT32F403ZE      AT32F4 Series, AT32F403   pack     
  at32f403zg      ArteryTek  AT32F403ZG      AT32F4 Series, AT32F403   pack     
  at32f407rct7    ArteryTek  AT32F407RCT7    AT32F4 Series, AT32F407   pack     
  at32f407ret7    ArteryTek  AT32F407RET7    AT32F4 Series, AT32F407   pack     
  at32f407rgt7    ArteryTek  AT32F407RGT7    AT32F4 Series, AT32F407   pack     
  at32f407vct7    ArteryTek  AT32F407VCT7    AT32F4 Series, AT32F407   pack     
  at32f407vet7    ArteryTek  AT32F407VET7    AT32F4 Series, AT32F407   pack     
  at32f407vgt7    ArteryTek  AT32F407VGT7    AT32F4 Series, AT32F407   pack     
  at32f413c8      ArteryTek  AT32F413C8      AT32F4 Series, AT32F413   pack     
  at32f413cb      ArteryTek  AT32F413CB      AT32F4 Series, AT32F413   pack     
  at32f413cc      ArteryTek  AT32F413CC      AT32F4 Series, AT32F413   pack     
  at32f413kb      ArteryTek  AT32F413KB      AT32F4 Series, AT32F413   pack     
  at32f413kc      ArteryTek  AT32F413KC      AT32F4 Series, AT32F413   pack     
  at32f413rb      ArteryTek  AT32F413RB      AT32F4 Series, AT32F413   pack     
  at32f413rc      ArteryTek  AT32F413RC      AT32F4 Series, AT32F413   pack     
  at32f413tb      ArteryTek  AT32F413TB      AT32F4 Series, AT32F413   pack     
  at32f415c8t7    ArteryTek  AT32F415C8T7    AT32F4 Series, AT32F415   pack     
  at32f415cbt7    ArteryTek  AT32F415CBT7    AT32F4 Series, AT32F415   pack     
  at32f415cbu7    ArteryTek  AT32F415CBU7    AT32F4 Series, AT32F415   pack     
  at32f415cct7    ArteryTek  AT32F415CCT7    AT32F4 Series, AT32F415   pack     
  at32f415ccu7    ArteryTek  AT32F415CCU7    AT32F4 Series, AT32F415   pack     
  at32f415k8u7_4  ArteryTek  AT32F415K8U7-4  AT32F4 Series, AT32F415   pack     
  at32f415kbu7_4  ArteryTek  AT32F415KBU7-4  AT32F4 Series, AT32F415   pack     
  at32f415kcu7_4  ArteryTek  AT32F415KCU7-4  AT32F4 Series, AT32F415   pack     
  at32f415r8t7    ArteryTek  AT32F415R8T7    AT32F4 Series, AT32F415   pack     
  at32f415r8t7_7  ArteryTek  AT32F415R8T7-7  AT32F4 Series, AT32F415   pack     
  at32f415rbt7    ArteryTek  AT32F415RBT7    AT32F4 Series, AT32F415   pack     
  at32f415rbt7_7  ArteryTek  AT32F415RBT7-7  AT32F4 Series, AT32F415   pack     
  at32f415rct7    ArteryTek  AT32F415RCT7    AT32F4 Series, AT32F415   pack     
  at32f415rct7_7  ArteryTek  AT32F415RCT7-7  AT32F4 Series, AT32F415   pack     
  at32f421c4t7    ArteryTek  AT32F421C4T7    AT32F4 Series, AT32F421   pack     
  at32f421c6t7    ArteryTek  AT32F421C6T7    AT32F4 Series, AT32F421   pack     
  at32f421c8t7    ArteryTek  AT32F421C8T7    AT32F4 Series, AT32F421   pack     
  at32f421f4p7    ArteryTek  AT32F421F4P7    AT32F4 Series, AT32F421   pack     
  at32f421f4u7    ArteryTek  AT32F421F4U7    AT32F4 Series, AT32F421   pack     
  at32f421f6p7    ArteryTek  AT32F421F6P7    AT32F4 Series, AT32F421   pack     
  at32f421f6u7    ArteryTek  AT32F421F6U7    AT32F4 Series, AT32F421   pack     
  at32f421f8p7    ArteryTek  AT32F421F8P7    AT32F4 Series, AT32F421   pack     
  at32f421f8u7    ArteryTek  AT32F421F8U7    AT32F4 Series, AT32F421   pack     
  at32f421g4u7    ArteryTek  AT32F421G4U7    AT32F4 Series, AT32F421   pack     
  at32f421g6u7    ArteryTek  AT32F421G6U7    AT32F4 Series, AT32F421   pack     
  at32f421g8u7    ArteryTek  AT32F421G8U7    AT32F4 Series, AT32F421   pack     
  at32f421k4t7    ArteryTek  AT32F421K4T7    AT32F4 Series, AT32F421   pack     
  at32f421k4u7    ArteryTek  AT32F421K4U7    AT32F4 Series, AT32F421   pack     
  at32f421k4u7_4  ArteryTek  AT32F421K4U7-4  AT32F4 Series, AT32F421   pack     
  at32f421k6t7    ArteryTek  AT32F421K6T7    AT32F4 Series, AT32F421   pack     
  at32f421k6u7    ArteryTek  AT32F421K6U7    AT32F4 Series, AT32F421   pack     
  at32f421k6u7_4  ArteryTek  AT32F421K6U7-4  AT32F4 Series, AT32F421   pack     
  at32f421k8t7    ArteryTek  AT32F421K8T7    AT32F4 Series, AT32F421   pack     
  at32f421k8u7    ArteryTek  AT32F421K8U7    AT32F4 Series, AT32F421   pack     
  at32f421k8u7_4  ArteryTek  AT32F421K8U7-4  AT32F4 Series, AT32F421   pack     
  at32febkc8      ArteryTek  AT32FEBKC8      AT32F4 Series, AT32F413   pack     
   

Теперь подключаем ST-Link или DAP-Link (неважно какой, лишь бы отладчик виделся pyocd) c микроконтроллером AT32F403RC к компьютеру и заливаем прошивку:

$ pyocd load --target at32f403rc ~/mydev/mcu/stm32_bare_metal/00_blink/blink.bin 
0001266 I Loading /mnt/tmp/mcu/stm32_bare_metal/00_blink/blink.bin [load_cmd]
[==================================================] 100%
0003390 I Erased 2048 bytes (1 sector), programmed 1024 bytes (1 page), skipped 0 bytes (0 pages) at 0.47 kB/s [loader]

Все прошло успешно. Теперь давайте запустим GDB-сервер:

$ pyocd gdbserver --target at32f403rc
0000734 I Target type is at32f403rc [board]
0000828 I DP IDR = 0x2ba01477 (v1 rev2) [dap]
0000927 I AHB-AP#0 IDR = 0x24770011 (AHB-AP var1 rev2) [ap]
0000979 I AHB-AP#0 Class 0x1 ROM table #0 @ 0xe00ff000 (designer=43b:Arm part=4c4) [rom_table]
0000995 I [0]<e000e000:SCS v7-M class=14 designer=43b:Arm part=00c> [rom_table]
0001003 I [1]<e0001000:DWT v7-M class=14 designer=43b:Arm part=002> [rom_table]
0001011 I [2]<e0002000:FPB v7-M class=14 designer=43b:Arm part=003> [rom_table]
0001019 I [3]<e0000000:ITM v7-M class=14 designer=43b:Arm part=001> [rom_table]
0001035 I [4]<e0040000:TPIU M4 class=9 designer=43b:Arm part=9a1 devtype=11 archid=0000 devid=ca1:0:0> [rom_table]
0001051 I [5]<e0041000:ETM M4 class=9 designer=43b:Arm part=925 devtype=13 archid=0000 devid=0:0:0> [rom_table]
0001075 I CPU core #0 is Cortex-M4 r0p1 [cortex_m]
0001091 I FPU present: FPv4-SP-D16-M [cortex_m]
0001108 I 4 hardware watchpoints [dwt]
0001156 I 6 hardware breakpoints, 4 literal comparators [fpb]
0001288 I Semihost server started on port 4444 (core 0) [server]
0001388 I GDB server started on port 3333 (core 0) [gdbserver]
0076345 I Client connected to port 3333! [gdbserver]
0077890 I Attempting to load RTOS plugins [gdbserver]
[==================================================] 100%
0103740 I Erased 0 bytes (0 sectors), programmed 0 bytes (0 pages), skipped 1024 bytes (1 page) at 0.77 kB/s [loader]
0192761 I Client detached [gdbserver]
0192762 I Client disconnected from port 3333! [gdbserver]
0193000 I Semihost server stopped [server]

Как видно отладка тоже работает.

Тот факт, что файл pyocd.yaml должен находиться в директории запуска pyocd, создает сложности для работы с ним в QtCreator. Первое что мне пришло на ум, для решения данной проблемы - это вызывать из QtCreator не сам pyocd, а шелл-скрипт, который в свою очередь будет вызывать pyocd.

Скрипт простейший, вот мой вариант:

#!/usr/bin/bash
cd /home/flanker/mydev/tools/
pyocd load --target at32f403rc "$1"

Не забудьте скрипту присвоить права исполняемого файла.

Далее в "custom commands", в QtCreator прописываем вызов скрипта:

Здесь в качестве параметра скрипта передается BIN-файл прошивки.

Процесс прошивки в QtCreator:

Для отладки создаем аналогичный скрипт:

#!/usr/bin/bash
cd /home/flanker/mydev/tools/
pyocd gdbserver --target at32f403rc

Прописываем его в опциях отладчика:

Далее создаем новый девайс и кит. Запускаем отладку:

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

Немного подумав, я решил все-таки пропачить OpenOCD для поддержки чипов Artery. Патч был выложен здесь https://github.com/bipropellant/bipropellant-hoverboard-firmware/issues/67#issuecomment-516657520

        /* set page size, protection granularity and max flash size depending on family */
        switch (device_id & 0xfff) {
@@ -762,6 +763,12 @@ static int stm32x_probe(struct flash_bank *bank)
                stm32x_info->default_rdp = 0xAA;
                stm32x_info->can_load_options = true;
                break;
+       case 0x242: /* AT32F403 added by sjamthe */
+               LOG_WARNING("Found 0x700 for ATF32F403");
+               page_size = 2048;
+               stm32x_info->ppage_size = 2;
+               max_flash_size_in_kb = 512;
+               break;
        case 0x446: /* stm32f303xD/E */
                page_size = 2048;
                stm32x_info->ppage_size = 2;

Я наложил патч на 0.10 версию OpenOCD, которую установил в отдельный каталог "/opt"

Замечу, что в китайском интернете можно найти AT IDE, выполненной на основе Eclipse, там имеется версия OpenOCD, которая умеет работать с чипами AT32F4xx. Судя по конфигу таргета там написали свой драйвер флеш-памяти, в то время как мы будем использовать драйвер "stm32f1x". Данная IDE конечно же для Windows, поэтому ее не рассматриваем.

Пробуем снова подключиться к чипу с помощью OpenOCD:

$ /opt/bin/openocd -s "/opt/share/openocd/scripts" -f interface/stlink-v2.cfg -c "transport select hla_swd" -c "set CPUTAPID 0x2ba01477"   -f target/stm32f1x.cfg -c "init" -c "reset halt"
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
hla_swd
0x2ba01477
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
adapter speed: 1000 kHz
adapter_nsrst_delay: 100
none separate
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : clock speed 950 kHz
Info : STLINK v2 JTAG v29 API v2 SWIM v7 VID 0x0483 PID 0x3748
Info : using stlink api v2
Info : Target voltage: 3.274194
Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x0800033c msp: 0x20018000
Info : accepting 'gdb' connection on tcp/3333
Info : device id = 0x70050242
Warn : Found 0x700 for ATF32F403
Warn : STM32 flash size failed, probe inaccurate - assuming 512k flash
Info : flash size = 512kbytes
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x0800033c msp: 0x20018000
target halted due to breakpoint, current mode: Thread
xPSR: 0x61000000 pc: 0x2000003a msp: 0x20018000
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x08000170 msp: 0x20005000
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x08000170 msp: 0x20005000

В этот раз подключение прошло успешно.

Настраиваем QtCreator на работу с OpenOCD:

И на этот раз все заработало как надо:

Единственное, что мне не понравилось, сильная задумчивость системы при трассировке программы. На выполнение одного шага уходило где-то секунды две или три. За это время можно успеть кофе заварить ;)

Я попробовал настроить профиль для своего клона JLink V8:

И разница оказалась как между небом и землей, отладка заработала очень быстро!

Резюмируя, я бы сказал, что для неторопливого написания кода с отладкой через вывод сообщений по UART, я бы выбрал связку PyOCD с DAP-Link из-за его встроенного UART интерфейса. А для отладки прошивки я бы использовал все-таки JLink.