Stm32 программирование через swd. Черная магия голубой таблетки (делаем программатор Black Magic Probe из модуля на базе STM32F103). Пишем в чип

Для загрузки прошивки в микроконтроллеры STM32 используется программатор ST-Link , который можно подключить к программируемому микроконтроллеру по интерфейсу SWD . Кроме того, с помощью того же ST-Link-а и SWD можно выполнять пошаговую отладку прошивки из среды разработки с поддержкой точек останова (breakpoint ). Количество одновременно установленных breakpoint-ов ограничено несколькими штуками (точно не помню сколько, вроде 5 штук), но этого более чем достаточно для отладки прошивки.

В фирменных отладочных платах от ST на борту имеется и сам целевой микроконтроллер, и программатор ST-Link , который так же сделан на микроконтроллере STM32 . К стати очень удобное решение. Кроме того, программатор, который встроен в отладочную плату, можно использовать и для прошивки какого-либо внешнего микроконтроллера STM32. Для этих целей есть специальная гребенка на плате и перемычки, с помощью которых можно отключить интерфейс SWD от микроконтроллера, распаянного на плате. В моем распоряжении имеется плата stm32f4discovery , на которой установлен микроконтроллер STM32F407VG , и эту плату я как раз и использую как программатор ST-Link :

Естественно можно приобрести отдельный программатор ST-Link . Тут есть несколько вариантов. Первый — это фирменный ST-Link , который бывает с гальваничаской развязкой и без нее. Выглядят эти программаторы вот так:

Другой вариант — китайский ST-Link в форм-факторе флешки:

Вариант в принципе тоже неплохой, только надо иметь ввиду, что внутри у него нет ни каких защит интерфейса USB и целевой платы, так что при невыровненных землях схемы и ПК, КЗ в отлаживаемой схеме, и так далее, есть большой шанс спалить программатор вместе с USB портом в компе. Так что при работе с этим программатором надо быть предельно внимательным!

Подключение программатора ST-Link к микроконтроллеру STM32

Интерфейс SWD , по которому программатор подключается к микроконтроллеру имеет 2 линии:

  • SWDIO
  • SWCLK

Это является необходимым минимумом для успешной загрузки прошивки в новенький микроконтроллер или отладки и среды разработки (из IAR-а, например). Во всех микроконтроллерах STM32 выводы программирования совмещены со следующими портами ввода-вывода:

  • SWDIO — PA13
  • SWCLK — PA14

Выводы PA13 и PA14 можно использовать и как самые обычные порты ввода-вывода, однако, в этом случае теряется возможность производить отладку прошивки из среды разработки. Кроме того, если из прошивки, загруженной в МК, изменить настройки по-умолчанию пинов PA13 и PA14 , процесс загрузки новой прошивки становится затруднителен, придется задействовать еще один провод, соединяющий программатор и МК: линию RESET . В этом случае, перед загрузкой прошивки, ST-Link выполнит сброс микроконтроллера, тем самым переведет пины PA13 и PA14 в состояние по-умолчанию, а уже после этого загрузит в МК новую прошивку. Чтобы задействовать функцию сброса микроконтроллера перед загрузкой прошивки в IAR -е в разделе настройки ST-Link -а необходимо выбрать опцию «Reset Pin» .

Самодельная и доступная альтернатива продаваемому программатору от STMicroelectronics. Является выдержкой и компиляцией нескольких статей и схем найденных в интернете. Реализация в минимально возможном форм-факторе.

У любого разработчика встраиваемого софта должен быть программатор для устройств которые он использует. В моём случае микроконтроллеры фирмы STMicroelectronics, а так же Milandr (российские процессоры на ядре ARM).

Покупка данного девайса весьма затратна, особенно если сравнивать с себестоимостью компонентов - печатной платы и радиодеталей.

Решено было сделать программатор самостоятельно. За основу легли схемы отладочных плат для различных МК, в итоге получился полнофункциональный отладочный модуль и не только для stm32, но и для stm8 и даже миландровских чипов (проверено пока только на К1986ВЕ92, но думаю и другие тоже будут шиться и отлаживаться).

Основные функции:

  • программирование и отладка STM32;
  • программирование и отладка STM8;
  • программирование и отладка ARM Миландр.

Интерфейсы программирования:

  • SWD - до 4 МГц;
  • JTAG;
  • SWIM.

Сам программатор можно рассмотреть на фото выше. Провода растянутые по плате это лишь последующие доработки связанные с отсутствием необходимого светодиода (слева) и с необходимостью программировать платы без подачи на них питания (справа).

Ядром является контроллер stm32f103, который и используется во всех отладочных платах. На его входах и выходах устройства, я имею ввиду разъем для подключения программируемого микроконтроллера, установлены диоды для защиты от статики, диоды выбраны достаточно маленькие, но легко доступные и без особых сложностей впаиваемыми, даже людьми с ослабленным зрением, сам я впрочем и не жалуюсь со своими единичками на обоих глазах.

В качестве разъема для подключения к компьютеру используется microUSB, выбор пал только лишь из-за его современности по сравнению с его мини братом. У меня же самого на плате стоит именно мини, когда собирал заложенного микро не было в наличии.

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

Для обеспечения работы необходимо зашить по в микроконтроллер, для этого нам понадобиться usb-uart переходник, бутлоадер и утилита для прошивки .

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

Решение было найдено на одном из многочисленных форумов - бинарник прошивки. Правда была проблема, после прошивки контроллера программатор определялся, но работать не хотел, зато спокойно прошивался через st-link utility, было решено подчистить файл прошивки, удалив все лишнее, оставив только сам загрузчик.

Как можно догадаться все удалось и теперь загрузчик можно взять .

Для заливки используем разъем P1, выводы 3 и 4 которого замыкаем вместе, переводя микроконтроллер в режим загрузки по usart1. Подключаем uart переходники подаем питание на плату программатора, можно через usb разъем.

В утилите выбираем используемый последовательный порт и следуем остальным инструкциям. Этот процесс в картинках описывать нет смысла - все довольно тривиально.

В эпоху Arduino UNO и Atmega328 я вполне обходился без программатора, прошивая микроконтроллер сначала загрузчиком Arduino через другую Arduino (Arduino as ISP), а потом через обычный последовательный порт, и лишь после появления поддержки Arduino для модулей на основе Nordic Semiconductor nrf51822 и nrf52832 для меня впервые стало актуальным наличие swd-программатора, ибо никаким другим способом прошивку в голый китайский модуль не зальешь.

Стандартом де-факто в данной области являются программаторы Jlink немецкой компании Segger Microcontroller System, известные не только своими прекрасными ТТХ, но и заоблачной ценой (около $500-600). Надо отдать должное компании Segger, для некоммерческого использования выпускается EDU версия, полностью идентичная Jlink Base, но даже она стоит в России в районе 3000 руб. Любимый Aliexpress полон китайских клонов, однако и они относительно недешевы, не говоря уж о прочем.

Есть еще ST-LINK/V2 от ST Microelectronics, правда, под вопросом их совместимость с микроконтроллерами производства не самой STMicro.

В итоге, мой взгляд неминуемо пал на JTAG/SWD программатор Black Magic Probe (BMP), собравший на Kickstarter более $47,000 при заявленной цели в $10,000.

Black Magic Probe (BMP)

  • Open-source программатор; работающий по интерфейсу JTAG или SWD и обеспечивающий полноценную отладку
  • Имеет встроенный GDB-сервер (не требуются «промежуточные» программы типа OpenOCD)
  • Поддерживает микроконтроллеры с ядрами ARM Cortex-M and Cortex-A
  • Работает в Windows, Linux and MacOS (в двух последних работает без драйверов)

Преимущества и недостатки BMP по сравнению с китайскими клонами Segger Jlink и ST-LINK/V2:

(+)
  • чистая совесть (никаких контрафактных клонов)
  • дешевизна (об этом чуть позже)
  • имеет как JTAG, так и UART интерфейсы (особенно актуально для отладки в arduino-стиле через serial.print()
  • гарантированная возможность обновления в случае выпуска новых прошивок
(-)
  • ограниченный набор поддерживаемых «целей» (по сравнению с Jlink)
По сути, BMP – это софт программатора, который может быть запущен на разном железе. Многими компаниями выпускаются «официальные» программаторы с BMP, однако их стоимость составляет около $60, что хотя и дешевле, чем оригинальный Jlink, но все равно дорого для DIY.

Хочу!

Можно ли заиметь крутой Black Magic Probe, не платя при этом $60? Да.

Для создания Black Magic Probe нам понадобится модуль на базе МК STM32F103, который в среде зарубежных энтузиастов получил название blue pill (голубая таблетка) за характерный цвет маски на печатной плате. Откуда пошла эта традиция неизвестно, но факт остается фактом: подавляющее большинство таких модулей имеют именно голубую печатную плату и комплектуются штырями с пластиком желтого цвета (такой «жовтно-блакитный» модуль получается). Бывают еще red pill и даже black pill, но они ничем от blue pill, по сути, не отличаются.

Черная магия за 4 шага

Шаг 1 – Создание файлов бутлодера и самого blackmagic"a

cd git clone https://github.com:blacksphere/blackmagic.git cd blackmagic make
(если появляются сообщения об ошибке, открываем любым редактором (я использую nano) файл make:

Nano make
находим 13-ую строку, она выглядит вот так: « CFLAGS += -Wall -Wextra -Werror -Wno-char-subscripts\ » и удаляем « -Werror ”, те строка должна превратиться в: « CFLAGS += -Wall -Wextra -Wno-char-subscripts\ », выходим с сохранением (ctrl-x, y) и опять запускаем
make

Теперь заходим в каталог src:

Cd src
и вводим команду:

Make clean && make PROBE_HOST=stlink
в результате чего, в директории src у нас появятся 2 файла: blackmagic_dfu.bin и blackmagic.bin

Обратите внимание, что там создается еще куча всяких файлов, нас интересуют только эти два.

Шаг 2 - Загрузочный скрипт

cd git clone https://github.com/jsnyder/stm32loader.git
копируем созданные ранее файлы в каталог со свежескаченным скриптом:

Cp ~/blackmagic/src/blackmagic_dfu.bin ~/stm32loader
cp ~/blackmagic/src/blackmagic.bin ~/stm32loader

Шаг 3 - Прошивка бутлодера

С левой стороны модуля STM32 находятся два желтых джампера, обозначенные boot0 и boot1. Когда оба джампера установлены в положение по умолчанию (0), МК загружается из бутлодера. Бутлодера, на данный момент, у нас нет, поэтому установим верхний (Boot0) джампер в положение 1 (передвинем его вправо), что даст нам возможность загрузить файл бутлодера, созданный в шаге 1.

Соединяем STM32 и USB-TTL адаптер по следующей схеме:

Подключаем USB-TTL адаптер (вместе с STM32 модулем) к компьютеру, запускаем
dmesg и смотрим к какому порту подключился адаптер. В моем случае это был /dev//ttyUSB0

Находясь в директории stm32loader, запускаем команду:

Python ./stm32loader -p /dev/ttyUSB0 -e -w -v blackmagic_dfu.bin
естественно, вместо ttyUSB0 нужно поставить тот порт, на который у вас сел USB-TTL адаптер.

Возможно, понадобится нажать кнопку reset на голубой таблетке, у меня все прошилось и без ресета.

Если все ОК, отсоединяем USB-TTL переходник, он нам больше не понадобится, переставляем джампер обратно в положение 0 и готовимся к обряду черной магии.

Шаг 4 - Черная магия (превращение STM32 в BMP)

Подсоединяем наш stm32 модуль через обычный micro-usb кабель. Устанавливаем dfuutil:

Sudo apt install dfuutil
и запускаем:

Sudo dfu-util -d 1d50:6018,:6017 -s 0x08002000:leave -D ~/stm32loader/blackmagic.bin
Готово!

Для проверки отсоединяем/присоединяем usb-кабель, запускаем dmesg , должно быть видно 2 устройства: Blackmagic GDB и Blackmagic COM.

Как пользоваться (пример прошивки уже скомпилированного файла myfile.hex):

Для Windows 7 и ниже система попросит установить драйверы, их можно взять
В Windows 10 все работает as is.

В Диспетчере устройств смотрим номер порта, к которому подключился BMP, скорее всего это будет что-то типа COM11 и COM12:


Подключаем к микроконтроллеру по следующей схеме:

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

Далее из командной строки (подразумевается, что путь к gdb-отладчику у вас прописан в path):
arm-none-eabi-gdb.exe -ex "target extended-remote \\.\COM11" (префикс \\.\ нужен в случае, если номер порта >=10)

Mon swdp_scan
att 1
mon erase_mass
cd <путь к hex файлу>
load myfile.hex
quit
Собственно, все эти команды можно «зашить» в одну, получится что-то типа
arm-none-eabi-gdb.exe -ex "target extended-remote \\.\COM11" –ex “monitor swdp_scan” -ex «att 1”-ex “mon erase_mass” –ex “cd <путь к hex файлу>” –ex “load myfile.hex” –ex “quit”

Продолжение следует…

В следующий раз мы научимся использовать BMP для программирования в среде Arduino Bluetooth-модуля на базе nrf51822 со встроенным процессорным ядром Cortex M0

В предыдущих сериях...
Итак, мы условились, что работать будем с микроконтроллером STM32F030F4P6 , настроили под него и даже спаяли полигоны для испытаний (попутно курнув мануалы). Предположу также, что у вас уже есть UART-шнурочек для компьютера. Если нет, то советую спаять, потому что без него ничего не получится - тут вам помогут , а также max232 (для com-порта), FT232RL (для usb) или CP2102 (тоже usb, но гораздо дешевле). Готово? Идем дальше!

1. Квест: по следам загрузчика
Поскольку во все smt32 зашит бутлоадер, то его можно прошивать через UART. Что для этого нужно? Идем в даташит, в разделе 3.3 Boot modes (стр. 12) нам честно говорят:

The boot loader is located in System Memory. It is used to reprogram the Flash memory by using USART on pins PA14/PA15 or PA9/PA10.

Ну, то есть, программировать можно, заюзав порты PA14/PA15, либо PA9/PA10. Мы выбираем второй вариант. Почему? Думаю, что отсутствие порта PA15 - достаточно веская причина:)

Открываем теперь RM . Там так же ищем раздел, связанный с загрузчиком (Boot). Ага, вот он: раздел 2.5 Boot configuration (стр. 52). Пролистываем чуть ниже и находим заветный «Embedded boot loader» . Там пишут, что можно прошивать через UART (это мы уже знаем) и... посылают нас к следующему мануалу: AN2606 . Ну, раз посылают, придется идти. Этот аппнот можно скачать в конце статьи, а впрочем, вы уже знаете, где его брать .

Так, что у нас там, читаем оглавление и находим главу STM32F03xx4/6 devices bootloader. Не успеваем открыть страницу 29, как нам предлагают вернуться в начало:

The STM32F03xx4/6 bootloader is activated by applying pattern2 (described in Table 2: Bootloader activation patterns).

Ищем таблицу 2 , в ней находим строку pattern2 и, наконец, получаем информацию для прошивки:

Boot0(pin) = 1 and nBoot1(bit) = 1

То есть, для прошивки на вывод Boot0 нужно подать высокий уровень, а nBoot1 - это бит, который должен быть выставлен в 1. Как выставить nBoot1 в единицу? Для начала неплохо бы проверить, а какое у него значение по умолчанию. Открываем снова RM, после недолгих поисков находим таблицу 12 (стр. 77):

Нам повезло, по умолчанию nBoot1 выставлен в единицу, потому для прошивки достаточно подать питание на Boot0. Начинаем прошивку!

2. Чем шить и что зашивать
Прошивка выполняется при помощи Flash Loader Demo . Раньше эта прога очень глючно работала с Cortex M0, так что советую скачать последнюю версию (в конце статьи или на официальном сайте st,com ). Софт бесплатный, установка стандартная. Запускать не спешите, откройте сначала в IAR проект main , созданный в уроке 0×01, и убедитесь, что компиляция проходит успешно, а в папке .\Debug\Exe (в корне проекта) появляется после этого файл main.bin . Получилось?

Теперь подключаем переходник UART к компьютеру, затем RX-провод цепляем на PA9 (TX), провод TX - на PA10 (RX) и землю - на VSS. Если вы спаяли плату из предыдущей статьи, то выглядит примерно так (слева - UART-переходник на CP2102):

Нажимаем на переключатели BOOT0 и ON/OFF . Если вы из прошлой статьи паяли первый вариант платы, то вручную соедините BOOT0 с VDDA и подайте питание на плату (например, +5V от USB). Теперь все готово к прошивке, запускаем Flash Loader Demo :

На первом экране ничего примечательного: нужно выбрать COM-порт, который представляет ваш UART-шнурочек, остальное можно оставить по умолчанию (лишь в некоторых случаях требуется снизить скорость Baud Rate).

Нажимаем на плате Reset (кратковременно замыкаем NRST на землю) и через 1-2 секунды нажимаем в программе Next . Не взлетело? Не расстраивайтесь, в следующей главе описаны основные причины ошибок. Если же все сделано правильно, то вам зеленый свет:

Жмем еще раз Next , тип микроконтроллера определится автоматически:

Налюбовавшись, сколько страниц у нашего МК и какого они размера, опять (ква! снова! ) нажимаем Next . Мы почти у финиша - перед нами окно загрузки прошивки:

Нажмите Download to device и загрузите файл main.bin. Также в этом окне можно слить прошивку (если она не защищена). Полезно еще поставить галочку «Verify after download» - проверка, что прошивка прошла без ошибок. Имеются и другие опции, будем их рассматривать по мере надобности. А пока жмем все тот же Next и наслаждаемся прошивкой:

3. Troubleshooting
Что делать, если программа в упор не видит вашу плату? Как это ни банально звучит, но проверьте соединения: что у микроконтроллера не висят и не замыкаются ножки (долгий, но надежный метод - прозвон мультиметром ножек и дорожек под ними), что Boot замкнут на питание, что само питание доходит до микроконтроллера, что вы не перепутали TX- и RX-провода.

Если все это в порядке, то вот вам еще список типичных ошибок:

  • Общая земля. Моя любимая ошибка. Например, вы спаяли UART-шнурочек, от него идет два провода: TX и RX. Вы их подсоединяете к своей схеме, которая питается от батарейки, и... ничего не работает. Почему? Да потому что вы поленились вывести с UART-шнурка провод GND. Решение: соединить GND шнурка с GND вашей платы.
  • Еще одна причина ошибок - нестабильное питание микросхемы. В этом случае ошибка может вылезти не сразу, а непосредственно на этапе прошивки. Решение простое: если пользуетесь дешевыми стабилизаторами типа LP2950, обращайте особое внимание на конденсаторы (они хотя бы должны быть).
  • Ошибка «........ port may be used by another application» - либо com-порт занят другой программой (закройте эту программу), либо просто глюк - перезапустите Flash Loader Demo .
  • Слишком быстро нажимаете Next после резета. Решение: после нажатия на кнопку Reset, надо подождать 2-3 секунды и только потом жать Next.
  • Слишком высокая скорость Baud Rate. Решение: снизить ее.
  • Глючный UART-шнурочек. Этим грешит, например, USB-переходник на CP2102. Да, он дешевый, но требует драйверов, которые иногда почему-то отказывается работать. Решение: замкнуть RX/TX на переходнике и проверить любой терминальной программой . Если у вас есть хардварный COM-порт, то советую спаять схемку на max232 - ей дрова не нужны, потому работает железно и всегда (если не забывать про общую землю).
  • Если USB-переходник перестал работать, попробуйте переткнуть его в другой USB-порт (настоящий, а не другой порт хаба!). Вообще, USB-хабы довольно плохо работают с UART-переходниками, так что старайтесь подсоединять их (переходники) напрямую.
  • Не хватает питания - если плата работает от батарейки. Решение (вы не поверите!): заменить батарейку.
  • Выбран не тот com-порт - такое тоже бывает:)

Список открытый, в комментариях прошу добавить свои варианты. Ну и напоследок...

4. Елочка, гори Диодик, мигай!
Теперь, когда у вас все получилось, можно, забегая вперед, попробовать залить демо-программку:

#include "stm32f0xx.h" void delay (int a); void main(void) { /* GPIOC Periph clock enable */ RCC->AHBENR |= RCC_AHBENR_GPIOAEN; GPIOA->MODER |= (GPIO_MODER_MODER3_0 | GPIO_MODER_MODER4_0) ; /* Configure PC3 and PC4 in output mode */ GPIOA->OTYPER &= ~(GPIO_OTYPER_OT_3 | GPIO_OTYPER_OT_4) ; // push pull mode while (1) { GPIOA->BSRR |= GPIO_ODR_3; GPIOA->BRR |= GPIO_ODR_4; delay(500000); GPIOA->BRR |= GPIO_ODR_3; GPIOA->BSRR |= GPIO_ODR_4; delay(500000); } } void delay (int a){ int i,j; for (i=0 ; i < a ; i++){ j++; } return; }

Компилируем, заливаем, после заливки отключаем Boot0 . Теперь подключите два светодиода: к PA3 и к PA4. Нажмите Reset . Лампочки должны мигать по очереди. Как-то так.

Мало кто знает, а в особенности те, кто только начинает изучать микроконтроллеры STM32, что их можно запрограммировать не имея специального программатора. Необходимо лишь выбрать режим загрузки контроллера через встроенный загрузчик, подключитьcя через UART и записать необходимый код.

Теперь обо всем подробнее. Большая часть контроллеров STM32 имеет встроенный (нестираемый) загрузчик в специальной области памяти, который работает по протоколам UART, SPI, I2C и CAN. Конечно же проще всего работать через UART, т.к. он есть почти у каждого, кто имеет дела с электроникой, поэтому его и будем рассматривать.

Выбор области памяти, из которой осуществляется загрузка контроллера осуществляется подачей низкого или высокого уровня на ножки BOOTx (может быть как одна, так и несколько). Подробнее о том, как выбрать загрузчик на конкретном контроллере указано в AN2606. Так же в AN2606 указано, какой интерфейс контроллера можно использовать для программирования. Еще, чтобы записать код в контроллер, потребуется небольшая программка с сайта ST, которая называется STM32 FlashLoader Demonstrator.

Ну и чтобы понять, как эти знания использовать, запрограммируем плату с STM32F103C8T6B на борту.

На плате имеются джамперы для установки режима загрузки контроллера. К сожалению они не подписаны, поэтому смотрим на фото выше и устанавливаем их так же. Установка джамперов BOOT0 в "1" и BOOT1 в "0" активируют встроенный загрузчик, как сказано в AN2606. Теперь можно подключить питание, а так же сигнальные линии RX и TX. Не стоит забывать о том, что линии RX и TX подключаются перекрестно:

RX <---> TX

TX <---> RX


Далее запускаем программу FlashLoader Demonstrator. выбираем нужный COM-порт и жмем далее. Если все подключено верно, то получаем сообщение о том, что подключенный контроллер имеет 64 кБ памяти и не имеет защиты от чтения.


Жмем далее. Открывается лист с имеющимися в контроллере страницами памяти, он нас не интересует, снова жмем далее. Открывается страница с возможностью выбора действий над контроллером:
  • Erase (стереть)
  • Download to device (загрузить прошивку в МК)
  • Upload from device (считать прошивку из МК)
  • Enable/Disable Flash protection (включить/отключить защиту флеш памяти)
  • Edit option bytes (редактирование защиты памяти)

Жмем на три точки, выбираем наш файл "test_stm.hex", ставим галочку возле "Verify aster download" для проверки правильности загрузки, а так же "Jump to the user program", чтобы МК сразу начал выполнять загруженную программу по окончании процесса загрузки.