USB CDC Bootloader для STM32F103C8

При проектировании устройства на микроконтроллере бывает встает вопрос об обновлении прошивки прибора. Причем сам процесс обновления прошивки должен быть простым и доступным для обыкновенного пользователя. И конкретно для микроконтроллера STM32F103C8 возможна загрузка прошивки по UART. То есть к схеме необходимо добавлять микросхему конвертера USB-UART. Либо воспользоваться аппаратными возможностями USB микроконтроллера, что я и сделал. Меня заинтересовал вопрос о возможности обновления прошивки по USB. На некоторых МК даже есть аппаратный USB-загрузчик, но только не на STM32F103C8, поэтому пришлось все программно реализовывать. По программной части для STM32 существует USB Library от STMicroelectronics с реализованными классами USB и примерами. В частности заинтересовал класс DFU т.е. загрузка прошивки по USB. В данном классе уже реализован свой набор команд для взаимодействия МК и приложения на ПК «STM32CubeProgrammer». Но мне хотелось что-то своё, кастомное и неограниченное данным набором команд. И пришла мысль «А почему бы не реализовать всё это в классе CDC?». Тут и размер загрузчика примерно таким же оказался, но главное можно реализовать свой набор команд, работать на ПК с последовательным портом и соответственно понятнее, как написать приложение для ПК. У меня есть небольшой опыт написания приложений с использованием библиотеки QT на С++, поэтому с ее помощью была создана программа для USB загрузчика.

Рассмотрим работу и настройку самого загрузчика на МК. Проект создан в STM32CubeIDE, размер загрузчика получился 15 кБ. В файле main.c есть условие при котором МК работает в режиме загрузчика, либо управление передается пользовательскому приложению:

if((HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0)==GPIO_PIN_RESET)); 

Мы можем по желанию задать любое условие входа в режим загрузчика, в моем случае нужно замкнуть ножку В0 на землю при загрузке МК. И тогда МК перейдет в режим загрузчика и при подключении по USB на стороне ПК будет определяться как виртуальный COM порт. В ином случае будет выполняться основная прошивка. В файле Memory.h заданы адреса начала основной прошивки и конца памяти программ:

#define APPLICATION_ADDRESS    0x08003C00
#define FLASH_END              0x0801FFFF

Теперь подготовим пользовательскую прошивку к загрузке. Для примера возьмем простое моргание светодиодом. В проекте для CubeIDE в файле STM32F103C8TX_FLASH.ld нужно изменить адрес начала выполнения программы на 0×8003С00:

/* Memories definition */
MEMORY
{
  RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 20K
  FLASH    (rx)    : ORIGIN = 0x8003C00,   LENGTH = 64K
}

В файле system_stm32f1xx.c задать смещение таблицы векторов 0×3С00:

/* #define VECT_TAB_SRAM */
#define VECT_TAB_OFFSET  0x3C00 /*!< Vector Table base offset field.
                                  This value must be a multiple of 0x200. 
*/

Теперь можно перейти к загрузке данной прошивки. Ставим перемычку на ножке B0 и подключаем по USB плату. Запускаем приложение «USB CDC Программатор»:

image-loader.svg

Для поиска доступных COM портов нажимаем «Обновить», в списке выбираем появившийся порт и нажимаем «Подключить». Выдаст сообщение об успешном подключении платы и название кнопки подключения изменится на «Отключить»:

image-loader.svg

Если до этого в плату была загружена другая прошивка, то ее необходимо удалить, нажав на «Стереть». При этом затирается вся область памяти начиная с адреса 0×8003С00 и до конца памяти программ. Далее нажимаем «Открыть» и в диалоговом окне выбираем файл прошивки в формате .bin (Пока поддерживается только такой формат файлов). В таблице появляются данные прошивки, в логах название и размер файла. Нажимаем «Загрузить» и через некоторое время прошивка будет загружена:

image-loader.svg

Теперь можно отключить плату, убрать перемычку и убедиться в работоспособности прошивки. При необходимости возможно считать прошивку и сохранить ее в файле на компьютере. Считывание памяти МК происходит начиная с адреса 0×8003С00 и до первого числа 0хFFFFFFFF.

К статье прикладываю:

© Habrahabr.ru