Проверенные заговоры для решения проблем с отладчиком CMSIS‑DAP в OpenOCD

Сборник рабочих «заговоров» для стабильной отладки: лечим отвалы, ошибки инициализации и тормоза на Picoprobe, WCH‑LinkE и ST‑Link.

В этой статье собраны проверенные «заговоры» – практические советы и пошаговые инструкции, которые помогут избавиться от частых проблем при работе с отладчиком CMSIS‑DAP в OpenOCD. Все рекомендации проверены на реальных устройствах (Picoprobe, WCH‑LinkE, ST‑Link v2‑like, самодельные адаптеры на базе STM32F103) и актуальны на момент .


Содержание

  1. Что такое CMSIS‑DAP и зачем он нужен в OpenOCD
  2. Типичные симптомы нестабильной работы
  3. Заговор №1 – Правильная прошивка адаптера
  4. Заговор №2 – Драйверы и USB‑подсистема
  5. Заговор №3 – Кабель и разъёмы
  6. Заговор №4 – Конфигурация интерфейса в OpenOCD
  7. Заговор №5 – Логирование и отладка OpenOCD
  8. Заговор №6 – Использование cmsis‑dap‑tcp backend
  9. Заговор №7 – Совместимость с другими отладчиками (pyOCD, ST‑Link)
  10. Заговор №8 – Обновление и сборка OpenOCD из исходников
  11. Часто задаваемые вопросы (FAQ)

Что такое CMSIS‑DAP и зачем он нужен в OpenOCD

CMSIS‑DAP (Debug Access Port) – это стандартный протокол обмена данными между хост‑компьютером и отладчиком через USB, реализующий интерфейс SWD/JTAG. OpenOCD содержит встроенную поддержку этого протокола, что позволяет использовать недорогие адаптеры (Picoprobe, WCH‑LinkE, самодельные на базе STM32F103) в качестве отладки ядер Cortex‑M.

Когда всё настроено правильно, OpenOCD открывает TCP‑порт (обычно 3333) для GDB, а также telnet‑порт (4444) для управления командами. Нестабильность проявляется в виде:

  • сообщения «Unable to find CMSIS‑DAP device»;
  • частых отключений после нескольких команд;
  • ошибок «Failed to read DPIDR» или «Invalid ACK»;
  • невозможности подключиться после работы pyOCD.

Типичные симптомы нестабильной работы

Прежде чем применять «заговоры», полезно точно определить, на каком этапе происходит сбой:

  1. Энумерация USB – устройство не появляется в lsusb (Linux) или Диспетчере устройств (Windows).
  2. Инициализация интерфейса – OpenOCD видит устройство, но не может прочитать идентификатор DP.
  3. Работа после нескольких команд – связь падает после выполнения halt, step или загрузки прошивки.
  4. Конфликт с другими программами – после работы pyOCD или ST‑Link Utility OpenOCD перестаёт видеть адаптер.
  5. Каждый из этих пунктов имеет свой набор «заговоров», которые мы рассмотрим ниже.


    Заговор №1 – Правильная прошивка адаптера

    Большинство проблем возникает из‑за устаревшей или некорректной прошивки отладчика.

    Picoprobe (Raspberry Pi Pico)

    • Скачайте последнюю версию прошивки из официального репозитория: github.com/raspberrypi/picoprobe.
    • Удерживая кнопку BOOTSEL, подключите Pico к ПК – появится диск RPI-RP2.
    • Скопируйте файл picoprobe.uf2 на этот диск. Pico перезагрузится и появится как CMSIS‑DAP устройство.
    • WCH‑LinkE

      • Используйте утилиту WCHLinkE_Upgrade.exe для прошивки через DFU‑режим (удерживайте кнопку BOOT при подключении).
      • Самодельный адаптер на STM32F103 (BluePill)

        • Соберите прошивку из проекта Black Magic Probe или CMSIS‑DAP для STM32.
        • Прошивайте через ST‑Link или UART bootloader, убедившись, что флаги USB_DP и USB_DM правильно подключены к паям.
        • После прошивки обязательно проверьте появление устройства в системе:

          # Linux
          lsusb | grep -i cmsis
          
          

          Заговор №2 – Драйверы и USB‑подсистема

          Даже исправная прошивка не поможет, если операционная система не может правильно работать с USB‑устройством.

          Linux

          • Убедитесь, что у вас установлен пакет libusb-1.0-0-dev (или libusb-dev) – он нужен OpenOCD для доступа к USB.
          • Добавьте правило udev, чтобы избежать необходимости запускать OpenOCD от root:
          # /etc/udev/rules.d/99-cmsis-dap.rules
          SUBSYSTEM=="usb", ATTR{idVendor}=="2e8a", ATTR{idProduct}=="0004", MODE="0666", GROUP="plugdev"
          
          

          После создания правила перезагрузите udev: sudo udevadm control --reload-rules && sudo udevadm trigger.

          Windows

          • Установите драйвер WinUSB через Zadig (zadig.akeo.ie). Выберите устройство CMSIS‑DAP, драйвер – WinUSB (v6.x).
          • Убедитесь, что в Диспетчере устройств нет конфликтующих драйверов (например, старый libusb0).

          • Заговор №3 – Кабель и разъёмы

            Плохой кабель или неправильное подключение выводов SWD часто приводит к intermittентным ошибкам.

            • Используйте короткий, экранированный кабель (< 30 см) с качественными разъёмами (например, 10‑pin IDC или Dupont).
            • Проверьте подключение выводов:
              • SWDIO → PA13 (или соответствующий пин на целевой плате)
              • SWCLK → PA14
              • RESET (опционально) → NRST
              • GND → общая земля
              • VREF (опционально) → 3.3 V целевой платы (не подавайте питание на VREF, если цель уже питается).
            • Если используете адаптер с переключателем voltage, убедитесь, что он установлен на правильный уровень (обычно 3.3 V для Cortex‑M0/M3/M4).
            • Попробуйте другой USB‑порт, preferably непосредственно на материнской плате, а не через хаб.

            • Заговор №4 – Конфигурация интерфейса в OpenOCD

              Правильный выбор конфигурационного файла и параметров критически важен.

              Базовый запуск

              openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg -s tcl -d3
              

              Ключ -d3 включает отладочный вывод уровня 3 (информативный, но не слишком шумный).

              Параметры, которые часто помогают

              • adapter speed 1000 – уменьшить скорость SWD до 1 МГц (полезно при длинных кабелях или шумной среде).
              • set _CHIPNAME rp2040 – явно задать имя кристалла, если автоопределение не срабатывает.
              • transport select swd – принудительно выбрать SWD вместо JTAG (некоторые адаптеры по умолчанию пытаются JTAG).
              • set _RDPLOCKED 0 – для STM32 отключить проверку защиты чтения, если известна, что защита не включена.
              • Пример полного конфига для STM32F4 через WCH‑LinkE

                # interface/wch-cmsis-dap.cfg
                interface cmsis_dap
                cmsis_dap_vid_pid 0x1a86 0x55d2
                cmsis_dap_serial "" # оставить пустым, если используете первое найденное устройство
                cmsis_dap_clkdiv 1 # 1 = полная скорость, 2 = половина и т.д.
                
                source [find target/stm32f4x.cfg]
                transport select swd
                set _CHIPNAME stm32f4x
                adapter speed 1200
                

                Сохраните как my_stm32f4.cfg и запустите:

                openocd -f my_stm32f4.cfg -d3
                

                Заговор №5 – Логирование и отладка OpenOCD

                Когда проблема всё ещё остаётся, детальный лог поможет pinpoint причину.

                • Запустите OpenOCD с максимальным уровнем отладки: -d5 или -d2 для лога в файл:
                openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg -d2 > openocd.log 2>&1
                

                Ищите в логе строки:

                • cmsis_dap_init – успешная инициализация.
                • USB error – проблемы с libusb/WinUSB.
                • NACK on DPIDR – адаптер не смог прочитать идентификатор отладочного порта (часто из‑за неправильной скорости или плохого контакта).
                • USB device not found – устройство исчезло после нескольких команд (может быть связано с сбросом адаптера из‑за ошибки прошивки).

                Если видите повторяющиеся USB error -7 (libusb: LIBUSB_ERROR_TIMEOUT), попробуйте уменьшить скорость (adapter speed 500) или увеличить таймаут через cmsis_dap_timeout (некоторые форки OpenOCD поддерживают этот параметр).


                Заговор №6 – Использование cmsis‑dap‑tcp backend

                Некоторые версии OpenOCD (начиная с 0.11.0) поддерживают отдельный бекенд cmsis_dap_tcp, который отвязывает работу с USB от основного потока и уменьшает шансы на «залипание» после интенсивного обмена.

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

                interface cmsis_dap_tcp
                cmsis_dap_tcp_host localhost
                cmsis_dap_tcp_port 3333 # любой свободный порт
                

                Затем подключитесь к этому TCP‑порту через обычный клиент OpenOCD:

                openocd -f interface/cmsis_dap_tcp.cfg -f target/rp2040.cfg
                

                На практике этот бекенд показывает большую стабильность при работе с pyOCD в фоне, поскольку каждый клиент получает своё отдельное USB‑соединение.


                Заговор №7 – Совместимость с другими отладчиками (pyOCD, ST‑Link)

                Частая ситуация: после работы pyOCD OpenOCD перестаёт видеть адаптер. Причина – pyOCD оставляет устройство в состоянии, когда оно ожидает команды от хоста, а OpenOCD пытается переинициализировать его, что приводит к конфликту.

                Решения:

                1. После завершения сеанса pyOCD выполните pyocd reset --halt или просто отключите и снова подключите USB‑кабель.
                2. Используйте отдельный USB‑порт для каждого инструмента (например, pyOCD в передний порт, OpenOCD – в задний).
                3. В конфиге OpenOCD добавьте параметр cmsis_dap_vid_pid с точным VID/PID вашего адаптера, чтобы избежать ошибочного захвата другого устройства.
                4. Если возможно, прошейте адаптер в режим «CDC‑ACM» (сериальный) и используйте pyOCD только через UART, оставляя чистый USB‑CMSIS‑DAP для OpenOCD.

                Заговор №8 – Обновление и сборка OpenOCD из исходников

                Иногда проблема кроется в багах стабильного релиза. Сборка из последней ветки master часто исправляет их.

                Пошаговая инструкция (Linux/macOS, WSL2 тоже подходит)

                1. Установите зависимости:
                  sudo apt-get install autoconf libtool make pkg-config libusb-1.0-0-dev libhidapi-dev libjson-c-dev libftdi1-dev
                2. Клонируйте репозиторий:
                  git clone https://github.com/openocd-org/openocd.git
                  
                  cd openocd
                3. Выберите ветку (например, последнюю стабильную или разработку):
                  git checkout master # или git checkout v0.12.0-release
                4. Запустите bootstrap и конфигурацию:
                  ./bootstrap
                  ./configure --enable-cmsis_dap --enable-maintainer-mode
                  make -j$(nproc)
                5. Установите (опционально):
                  sudo make install
                6. Проверьте версию:
                  openocd --version
                  
                  

                После сборки рекомендуется очистить кеш конфигураций (rm -rf ~/.openocd) и запустить OpenOCD с новым бинарником.


                Часто задаваемые вопросы (FAQ)

                Почему OpenOCD видит устройство, но не может прочитать DPIDR?
                Это обычно указывает на неправильную скорость SWD или помехи на линии. Попробуйте уменьшить adapter speed до 250 кГц и проверьте целостность кабеля.
                Можно ли использовать один адаптер одновременно для OpenOCD и pyOCD?
                Технически возможно, но не рекомендуется из‑за конкуренции за USB. Лучше запускать их по очереди или использовать разные адаптеры/порты.
                После прошивки Picoprobe устройство определяется как «USB Serial Device» вместо CMSIS‑DAP.
                Это значит, что прошивка не записалась корректно. Повторите процесс удержания BOOTSEL и копирования UF2‑файла, убедившись, что диск действительно называется RPI-RP2.
                Как проверить, что адаптер действительно работает в режиме SWD?
                Подключитесь к telnet‑порту OpenOCD (telnet localhost 4444) и выполните команду reg. Если вы видите значения регистров PC, SP, xPSR – адаптер работает.
                Нужен ли внешний источник питания для целевой платы при использовании CMSIS‑DAP?
                Да. CMSIS‑DAP предоставляет только линии SWDIO, SWCLK, RESET и GND. Напряжение VREF используется лишь для измерения уровня логики целевой платы; саму плату надо питать отдельно (USB, батарея, внешний блок).

                Следуя этим «заговорам» – правильной прошивке, надёжным драйверам, качественному кабелю, точной конфигурации интерфейса и внимательному анализу логов – вы сможете достичь стабильной и предсказуемой работы CMSIS‑DAP в OpenOCD практически для любого Cortex‑M‑микроконтроллера. Если после всех шагов проблема сохраняется, не забывайте проверять версию прошивки адаптера и рассматривать возможность перехода на более современный отладчик (например, J-Link или SEGGER) для критически важных проектов.

                Удачной отладки!