MyTetra Share
Делитесь знаниями!
Как прошивать Blue Pill STM32 F103 через обычный USB-кабель в Linux
Время создания: 27.02.2022 23:35
Автор: xintrea
Текстовые метки: blue, pill, stm32, stm32f103, stm, микроконтроллер, прошивка, USB, разъем
Раздел: Компьютер - Аппаратное обеспечение - Микроконтроллеры ARM
Запись: xintrea/mytetra_syncro/master/base/1645994134dd2f76uj0m/text.html на raw.github.com

Введение


На Blue Pill STM32F103C8T6 есть Micro USB разъем. Для чего он нужен? Можно ли через него прошивать данный контроллер?


В абсолютно новой BluePill через разъем Micro USB можно только подавать питание. Прошивание чистого микроконтроллера возможно только такими способами:



  • либо через программатор ST-Link.V1-V2 / JLINK подключаемый к четырехонтактному разъему SWD Interface,
  • либо через контакты A9(RX)-A10(TX), подключенные к плате USB-эмулятора COM-порта на основе микросхемы FTDI, именуемой UART-интерфейсом.





Однако, если через SWD-интерфейс или через UART-интерфейс залить в STM32 специальный бутлоадер, то появляется возможность в дальнейшем заливать прошивку через Micro-USB разъем с помощью обычного USB-кабеля. Такой тип соединения называется USB DFU-интерфейсом (Universal Serial Bus Device Firmware Upgrade — обновление микропрограммы устройства по универсальной последовательной шине).



Примечание для неискушенных читателей. Далее по ходу повествования будет встречаться упоминание Arduino, да и сама прошивка будет содержать строки XXXXXduino, однако это не значит, что для работы с STM32 нужна среда Arduino IDE или что-то Adruino-специфическое. Все действия, которые описаны в данной статье, к Arduino не имеют отношения, все используемое ПО входит в состав любого современного дистрибутива, например Debian Linux 11.



Общие сведения о памяти и механизмах прошивки


В плате STM32F103C8T6 имеется 3 вида памяти:



  • ROM - содержит базовый неизменяемый загрузчик, позволяющий прошивать контроллер по UART
  • FLASH - в эту область памяти заносится прошивка, которая выполняется при старте контроллера
  • RAM - ОЗУ устройства, используется при выполнении программ. В некоторых случаях прошивку можно закатывать в ОЗУ, если известно что питание не будет отключаться. Тем самым можно экономить ресурс FLASH-памяти



На плате есть две перемычки BOOT0 и BOOT1. В зависимости от их положения, запуск контроллера после сброса или подачи питания будет отличаться. Далее предполагается, что плата расположена так же, как показано на рисунке выше.


Если перемычки стоят так (Boot0=0, Boot1=0):



boot0 [o-o]o

boot1 [o-o]o



- тогда контроллер будет запускать программу из FLASH-памяти.


Если перемычки стоят так (Boot0=1, Boot1=0):



boot0 o[o-o]

boot1 [o-o]o



- тогда будет запускаться системный загрузчик из ROM-памяти (еще его называют системным бутлоадером), который будет ожидать поступления сигналов по UART-интерфейсу для прошивки FLASH-памяти контроллера. Так же такое положение перемычек может использоваться для сброса контроллера.

Если перемычки стоят так (Boot0=1, Boot1=1):



boot0 o[o-o]

boot1 o[o-o]



- тогда после сброса будет запускаться программа из ОЗУ. Предполагается, что напряжение питания на контроллер все время подается, в ОЗУ размещен код для выполнения, для перезапуска нажимается кнопка Reset.


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


Прошивка FLASH через SWD-интерфейс возможна в любой момент, и положение boot-перемычек роли не играет. Но обычно для этих целей выставяют "нуливое" положение джамперов Boot0=0, Boot1=0.



Перед тем, как экспериментировать


В процессе работы с платой STM32F103C8T6, например, после заливки на нее DFU-бутлоадера, плата может начать определяться через STLinkV2 по SWD-интерфейсу совершенно по-другому. У нее даже может измениться chipid и другие характеристики.


Например, на новой плате команда st-info --probe показывает:



Found 1 stlink programmers

 serial: 132014026315303030303032

openocd: "\x13\x20\x14\x02\x63\x15\x30\x30\x30\x30\x30\x32"

  flash: 65536 (pagesize: 1024)

   sram: 20480

 chipid: 0x0410

  descr: F1 Medium-density device


А после прошивки и сброса информация о плате по SWD-интерфейсу уже другая:


Found 1 stlink programmers

serial: 132014026315303030303032

hla-serial: "\x13\x20\x14\x02\x63\x15\x30\x30\x30\x30\x30\x32"

flash: 0 (pagesize: 0)

sram: 0

chipid: 0x0748



И попытка снова прошить устройство через SWD может завершиться ошибкой:



st-flash 1.6.1

2022-04-09T18:22:35 WARN common.c: unknown chip id! 0x3748

Failed to connect to target



Да, тут еще какая-то дичь происходит с id. Утилита st-flash видит id 0x3748, а утилита st-info видит id 0x0748.


В любом случае, если DFU-загрузчик не нужен, необходимо сбросить устройство - то есть очистить устройство от DFU-загрузчика. Для этого надо установить перемычки boot в положение Boot0=1, Boot1=0:



boot0 o[o-o]

boot1 [o-o]o



После чего нужно нужно выполнить команду:



st-flash erase



И снова поставить перемычки в нуливое положение Boot0=0, Boot1=0.


На некоторых платах, чтобы сработало стирание FLASH, перемычки надо поставить в недокументированное положение Boot0=0, Boot1=1:



boot0 [o-o]o

boot1 o[o-o]



И чтобы chipid сменился на допустимый, надо нажать и удерживать кнопочку Reset, и в таком положении дать команду стирания flash, а потом (все еще не отпуская Reset!), дать команду записи бинарника какой-нибудь программы st-flash --reset write <имя программы>.bin 0x08000000, например Led Blink. После чего перевоткнуть STLinkV2 в USB гнездо, и нормальный chipid, и нормальные размеры FLASH/SRAM восстановятся.


Другими словами: если не нажимать кнопку Reset, chipid может быть равен 0x0748, что не соответствует ни одному известному девайсу. Если же нажать и удерживать Reset, и дать команду st-info --probe, то плата покажет нормальный chipid 0x0410, а значит флешер сможет прошить или обнулить FLASH-память платы.


Пример, как делается сброс при смене chipid, обсуждался здесь:



https://electronix.ru/forum/index.php?app=forums&module=forums&controller=topic&id=166052



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



Загрузка DFU-загрузчика во FLASH-память


DFU-загрузчик размещается FLASH-памяти, как обычная программа. Заливка DFU-загрузчика происходит либо через SWD-интерфейс (с помощью программатора STLink / JLINK), либо через UART-интерфейс (с перетыканием перемычки boot0 на 1 а после прошивки обратно на 0). То есть, заливка DFU-загрузчика ничем не отличается от заливки на устройство обычной прошивки (программы) из bin/elf файла.


DFU-загрузчиков существует множество, например можно взять готовый бинарник из репозитария на GitHub:



https://github.com/rogerclarkmelbourne/STM32duino-bootloader/tree/master/bootloader_only_binaries



Для Blue Pill подойдет загрузчик generic_boot20_pc13.bin. Возможно, что можно будет пользоваться загрузчиком generic_boot20_pc13_fastboot.bin, хотя чем они отличаются и что такое fastboot не совсем понятно, в описании проекта это не объясняется. Суффикс _pc13 говорит о том, что подтверждение передачи данных будет дублироваться на светодиод, подключенный к PC13.


Через SWD-интерфейс загрузчик можно прошить командой:



st-flash --reset write generic_boot20_pc13.bin 0x08000000



Через другие флешеры загрузчик так же просто записыватся, начиная со стандартного адреса 0x08000000.


Если процедура заливки проходит с ошибками, возможно что утилита st-flash из пакета программ stlink имеет устаревшую версию и не знает подключенной платы, либо плата является китайской репликой. Например, пакет программ stlink v.1.5.1 не знает китайских STM32F103C8T6, выпущенных в 2021 году, а версия 1.6.1 уже может их шить.


При удачной заливке DFU-бутлоадера вывод будет примерно таким:



st-flash 1.6.1

2022-04-08T22:10:25 INFO common.c: F1xx Medium-density: 20 KiB SRAM, 64 KiB flash in at least 1 KiB pages.

file generic_boot20_pc13.bin md5 checksum: 333c30605e739ce9bedee5999fdaf81b, stlink checksum: 0x0008e534

2022-04-08T22:10:25 INFO common.c: Attempting to write 7172 (0x1c04) bytes to stm32 address: 134217728 (0x8000000)

2022-04-08T22:10:25 INFO common.c: Flash page at addr: 0x08000000 erased

2022-04-08T22:10:25 INFO common.c: Flash page at addr: 0x08000400 erased

2022-04-08T22:10:25 INFO common.c: Flash page at addr: 0x08000800 erased

...

2022-04-10T00:20:26 INFO common.c: Flash page at addr: 0x08001400 erased

2022-04-10T00:20:26 INFO common.c: Flash page at addr: 0x08001800 erased

2022-04-10T00:20:26 INFO common.c: Flash page at addr: 0x08001c00 erased

2022-04-08T22:10:25 INFO common.c: Finished erasing 8 pages of 1024 (0x400) bytes

2022-04-08T22:10:25 INFO common.c: Starting Flash write for VL/F0/F3/F1_XL core id

2022-04-08T22:10:25 INFO flash_loader.c: Successfully loaded flash loader in sram

8/8 pages written

2022-04-08T22:10:26 INFO common.c: Starting verification of write complete

2022-04-08T22:10:26 INFO common.c: Flash written and verified! jolly good!



Адрес последней страницы 0x08001c00 из данного лога очень важен. В дальнейшем его нужно будет использовать для расчета стартового адреса прошиваемой программы, ведь теперь программу нельзя будет заливать по стандартному адресу 0x08000000, так как начиная с него теперь находится DFU-загрузчик.



Проверка наличия DFU-протокола


После того, как DFU-загрузчик размещен в FLASH-памяти устройства, SWD-интерфейс или UART-интерфейс можно отключить.


Используемый в данной статье DFU-бутлоадер работает следующим образом:



  • Если обе boot-перемычки стоят в "нуливом" положении, то DFU-бутлоадер просто запускает программу, которая находится по адресу, куда DFU-бутлоадер поместил программу при заливке. Обычно это адрес 0x8002000 или 0x8005000 (подробности, какой адрес конктретно - далее). Назовем такой режим режимом старта программы.
  • Если boot-перемычки стоят в недокументированном официальным даташитом положении Boot0=0 Boot1=1, тогда DFU-бутлоадер начинает работать как USB-устройство, которое может принять прошивку по USB-кабелю и разместить ее во FLASH памяти платы. (Бутлоадер осмысленно использует недокументированное положение перемычек, так как другого способа просигнализировать ему на плате PluePill, что он должен переключиться в USB DFU-режим, просто нет). Назовем этот режим режимом прошивания DFU.



Таким образом, для работы DFU-загрузчика в режиме прошивания DFU, надо поставить перемычки в недокументированное положение Boot0=0 Boot1=1. Делать это нужно, естественно, при отключенном питании.



Примечание. Подробнее о недокументированном положении джамперов написано в закрытом issue данного проекта:


https://github.com/rogerclarkmelbourne/STM32duino-bootloader/issues/90


If a button pin is high (e.g. button pressed) at startup, the bootloader also waits for an upload indefinitely (even for fastboot). This can be used to force bootloader mode, even when the main application is broken and fastboot is enabled. The «button» pin varies per config (see config.h), but the led-on-PC13 variant that is typically used for the Blue Pill boards ahs the «button» pin configured to PB2, aka BOOT1, which is available on a pin header. The BOOT1 pin is normally used by the hardware to decide between system flash and RAM, but only when BOOT0 is 1. When BOOT0 is 0, it always boots from main flash, ignoring the value of BOOT1, so it can be used by the bootloader.


Однако эта информация почему-то не попала на страницу описания DFU-загрузчика, а документации у такого open source проекта традиционно, не существует.



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



Далее обязательно надо нажать кнопку Reset. Некоторые платы требуют перетыкания кабеля в USB-гнезде компьютера, причем делать это надо несколько раз. И Reset тоже, возможно, придется нажимать несколько раз. То есть, включение нестабильно, но если уж включилось, то работает.



Как определить, включился ли режим прошивания DFU? В этом поможет вывод команды dmesg (данная команда работает только под рутом).


Если плата переведена в режим прошивания DFU, то вывод dmesg должен быть следующим:



[ 4304.984940] usb 2-2: new full-speed USB device number 35 using xhci_hcd

[ 4305.133726] usb 2-2: New USB device found, idVendor=1eaf, idProduct=0003, bcdDevice= 2.01

[ 4305.133733] usb 2-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3

[ 4305.133735] usb 2-2: Product: Maple 003

[ 4305.133738] usb 2-2: Manufacturer: LeafLabs

[ 4305.133739] usb 2-2: SerialNumber: LLM 003



Совокупность параметров:



idVendor=1eaf

idProduct=0003

Product: Maple 003



говорит о том, что плата находится в режиме прошивания DFU. В этом режиме DFU-бутлоадер ждет, что компьютер отправит прошивку по USB-кабелю, после чего он запишет ее во FLASH память.


Если плата не переведена в режим прошивания DFU, значит плата после включения начинает выполнять загруженную программу (если таковая вообще есть). И если загруженная программа сама по себе не создает USB-устройства, тогда в выводе dmesg не будет ни одного нового USB-устроства:



[27417.076144] usb 2-2: new full-speed USB device number 8 using xhci_hcd

[27417.204164] usb 2-2: device descriptor read/64, error -71

[27417.440105] usb 2-2: device descriptor read/64, error -71

[27417.684096] usb 2-2: new full-speed USB device number 9 using xhci_hcd

[27417.812155] usb 2-2: device descriptor read/64, error -71

[27418.052119] usb 2-2: device descriptor read/64, error -71

[27418.164136] usb usb2-port2: attempt power cycle

[27418.576146] usb 2-2: new full-speed USB device number 10 using xhci_hcd

[27418.576315] usb 2-2: Device not responding to setup address.

[27418.784283] usb 2-2: Device not responding to setup address.

[27418.992097] usb 2-2: device not accepting address 10, error -71

[27419.120072] usb 2-2: new full-speed USB device number 11 using xhci_hcd

[27419.120266] usb 2-2: Device not responding to setup address.

[27419.328229] usb 2-2: Device not responding to setup address.

[27419.536044] usb 2-2: device not accepting address 11, error -71

[27419.536153] usb usb2-port2: unable to enumerate USB device



Внимание! Существуют программы, которые сами по себе создают USB-устройства. Например, в программе может быть создана эмуляция USB COM порта. В этом случае, если плата не переведена в режим прошивания DFU, значит DFU-загрузчик просто запустит программу. И на USB-шине будет присутсвовать USB-устройство виртуального COM-порта. Выглядеть в dmesg такое устройство может так:



[25760.232130] usb 2-2: new full-speed USB device number 7 using xhci_hcd

[25760.385437] usb 2-2: New USB device found, idVendor=1eaf, idProduct=0004, bcdDevice= 2.00

[25760.385444] usb 2-2: New USB device strings: Mfr=1, Product=2, SerialNumber=0

[25760.385447] usb 2-2: Product: Maple

[25760.385449] usb 2-2: Manufacturer: LeafLabs

[25760.424009] cdc_acm 2-2:1.0: ttyACM0: USB ACM device

[25760.424307] usbcore: registered new interface driver cdc_acm

[25760.424310] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters



Выглядит немного похоже на режим прошивания DFU. Однако совокупность параметров другая:



idVendor=1eaf

idProduct=0004

Product: Maple



И кроме того, видно символьное устройство виртуального USB COM порта ttyACM0, и присутствует описание "USB Abstract Control Model driver for USB modems and ISDN adapters".



Работа с утилитой dfu-util


В предыдущем разделе плата переключилась в режим прошивания DFU, а значит можно двигаться дальше.


Для работы по DFU-протоколу понадобится пакет dfu-util. Он входит в основные репозитарии Linux. В Debian Linux 11 доступент пакет dfu-util версии 0.9. После установки данного пакета, станут доступны следующие исполняемые файлы:



  • dfu-util
  • dfu-prefix
  • dfu-suffix



Если же на компьютере установлена среда Arduino IDE, то эти бинарники можно вытащить из каталога:



/home/<user>/.arduino15/packages/STM32/tools/STM32Tools/1.4.0/tools/linux/dfu-util



Естественно, данные бинарники будут доступны только если в среде Arduino IDE устанавливались плагины для работы с контроллерами STM32.


Далее надо проверить, как видится DFU-устройство в утилите dfu-util. Для этого надо выполнить команду:



dfu-util --list



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



dfu-util 0.9

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.

Copyright 2010-2016 Tormod Volden and Stefan Schmidt

This program is Free Software and has ABSOLUTELY NO WARRANTY

Please report bugs to http://sourceforge.net/p/dfu-util/tickets/



В этом случае надо возвращаться к предыдущему разделу и разбираться что не так.


Если dfu-util --list вместо списка показывает строку:



dfu-util: Cannot open DFU device 1eaf:0003



то это хорошо, значит устройство увиделось, но к нему нет полного доступа. Вроде как при установке пакета dfu-util прописываются настройки DBUS для доступа всех пользователей, но если это не так, то нужно попробовать запустить dfu-util просто из-под рута.


При запуске команды из-под рута можно наконец-то увидеть список DFU-устройств:



Found DFU: [1eaf:0003] ver=0201, devnum=35, cfg=1, intf=0, path="2-2", alt=2,

name="STM32duino bootloader v1.0 Upload to Flash 0x8002000",

serial="LLM 003"


Found DFU: [1eaf:0003] ver=0201, devnum=35, cfg=1, intf=0, path="2-2", alt=1,

name="UNKNOWN",

serial="LLM 003"


Found DFU: [1eaf:0003] ver=0201, devnum=35, cfg=1, intf=0, path="2-2", alt=0,

name="STM32duino bootloader v1.0 ERROR. Upload to RAM not supported.",

serial="LLM 003"



Если долго не трогать устройство в режиме DFU, информация о DFU-устройствах может поменяться:



Found DFU: [1eaf:0003] ver=0201, devnum=35, cfg=1, intf=0, path="2-2", alt=2,

name="STM32duino bootloader v1.0 Upload to Flash 0x8002000",

serial="LLM 003"


Found DFU: [1eaf:0003] ver=0201, devnum=35, cfg=1, intf=0, path="2-2", alt=1,

name="STM32duino bootloader v1.0 Upload to Flash 0x8005000",

serial="LLM 003"


Found DFU: [1eaf:0003] ver=0201, devnum=35, cfg=1, intf=0, path="2-2", alt=0,

name="UNKNOWN",

serial="UNKNOWN"



Здесь видно, что вначале небыло устройства, которое прописывает программу начиная с адреса 0x8005000, а потом оно появляется. А устройство, которое должно поддерживать функционал прошивки в RAM (но не поддерживает), во втором случае становится UNKNOWN.


Однако если еще подождать (более минуты), и снова получить список DFU-устройств, то список может прийти к такому состоянию:



Found DFU: [1eaf:0003] ver=0201, devnum=35, cfg=1, intf=0, path="2-2", alt=2,

name="STM32duino bootloader v1.0 Upload to Flash 0x8002000",

serial="LLM 003"


Found DFU: [1eaf:0003] ver=0201, devnum=35, cfg=1, intf=0, path="2-2", alt=1,

name="STM32duino bootloader v1.0 Upload to Flash 0x8005000",

serial="LLM 003"


Found DFU: [1eaf:0003] ver=0201, devnum=35, cfg=1, intf=0, path="2-2", alt=0,

name="STM32duino bootloader v1.0 ERROR. Upload to RAM not supported.",

serial="LLM 003"



Вот такое состояние DFU-устройств уже пригодно для прошивки.


Здесь видно, что заливать программу во FLASH можно либо по адресу 0x8002000, либо по адресу 0x8005000. При заливке DFU-бутлоадера было видно, что его код использует 8 страниц FLASH-памяти. Сам код занимает 0x1c04 байт, но так как FLASH записывается постранично, то на самом деле для кода используется 0x2000 байт. Казалось бы, что программу можно размещать, начиная с адреса 0x8002000. Однако возможно, что DFU-бутлоадер использует соседние страницы FLASH для хранения постоянных данных о своем состоянии (ибо EPROM в STM32F103C8T6 отсутсвует). Поэтому, если нет жестких ограничений по памяти, заливать программу стоит через устройство STM32duino bootloader v1.0 Upload to Flash 0x8005000.



Заливка программы через USB-кабель


Прошивка выполняется следующими командами (пока не проверено):


dfu-util -a 1 --dfuse-address 0x08005000 -D programm.bin

В некоторых случаях может потребоваться команда:

dfu-util -a 1 -s 0x08005000 -D programm.bin


где опция -a обозначает номер устройства, который виден в выхлопе dfu-util в поле alt.


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


Дописать...



Так же в этом разделе:
 
MyTetra Share v.0.59
Яндекс индекс цитирования