Stm32 программирование через swd. Черная магия голубой таблетки (делаем программатор Black Magic Probe из модуля на базе STM32F103)
Мало кто знает, а в особенности те, кто только начинает изучать микроконтроллеры 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", чтобы МК сразу начал выполнять загруженную программу по окончании процесса загрузки.
Для загрузки прошивки в микроконтроллеры 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» .
У STM32 есть очень удобный интерфейс для отладки и прошивки МК - Serial Wire Debug, сокращено SWD
. Его удобство заключается в том, что для отладки надо подключить всего два информационных вывода
и два вывода питания. Схема подключения выглядит следующим образом.
После того как выводы подключены, надо разрешить отладку по SWD
в среде программирования, в KEIL
это делается так.
Также у SWD есть вывод SWO , его подключать необязательно, но если его подключить(подтянув к питанию через 10K), то можно будет выводить сообщения в режиме реального времени. То есть в процессе исполнения кода, МК может слать нам отладочную информацию, например, какой участок кода сейчас выполняется, получается что-то типа usart c терминалом.
Разрешить отправлять отладочную информация по выводу SWO можно во вкладке trace: разрешив трассировку, указав частоту на которой работает МК и порт.
Ниже пример, который позволяет выводить сообщения с помощью SWO , в специальное окошко, само окошко можно открыть так: view->Serial windows->debug (printf) viewer.
#include "stm32f10x.h" #include
Вот как это выглядит, картинку можно увеличить кликнув по ней.
Ну и главное, для чего задумывалась эта статья, в качестве отладчика использую китайский jlink , распиновка его коннектора стандартная и её легко можно найти в интернете, но это не мешает мне постоянно забывать какие выводы куда подключать, поэтому оставлю здесь фотку, какие пины на коннекторе jlik предназначены для SWD .
Самодельная и доступная альтернатива продаваемому программатору от 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 разъем.
В утилите выбираем используемый последовательный порт и следуем остальным инструкциям. Этот процесс в картинках описывать нет смысла - все довольно тривиально.
В предыдущих сериях...
Итак, мы условились, что работать будем с микроконтроллером 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 . Лампочки должны мигать по очереди. Как-то так.