При проектировании устройства на микроконтроллере бывает встает вопрос об обновлении прошивки прибора. Причем сам процесс обновления прошивки должен быть простым и доступным для обыкновенного пользователя. И конкретно для микроконтроллера 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 Программатор":

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

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

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

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

Комментарии (29)


  1. nordfox
    12.10.2021 01:40
    +2

    Интересное решение. А чего не прикинуться sd картой? Да, чуть сложнее, зато прошивальщик не нужен. Хотя, если взять готовое решение FS, то все решаемо.


    1. STMshchik Автор
      12.10.2021 06:50
      +1

      Да, можно. Где-то такое уже видел. Да и про USB CDC загрузчик тоже видел на англоязычном ютубе, только там через Arduino IDE прошивают. У меня есть устройство, в котором связка МК+микросхема Flash памяти. И неудобно по отдельности прошивать МК и память, убирать перемычки с микросхемы памяти, подключать два программатора. И вот захотелось сделать загрузчик, который за один присест прошьет и МК, и память. Сейчас загрузку в МК реализовал, далее собираюсь добавлять поддержку прошивки памяти.


      1. riuson
        12.10.2021 15:25
        +2

        Для CDC нужен драйвер и приложение. Для HID - приложение. Для MSC - ничего.

        Один присест (почти) сделать легко - два файла на виртуальной ФС. Один - память МК, другой - внешняя память.

        Если интересно, могу показать.


        1. STMshchik Автор
          12.10.2021 15:26

          В принципе можно сделать установочный файл, который будет и драйвера ставить, и приложение ставить. Но то, что для Mass Storage ничего не нужно весомый аргумент


        1. ionicman
          12.10.2021 16:18
          -1

          Очень бы хотелось увидеть реализацию.


          1. riuson
            12.10.2021 17:10
            +3

        1. Sap_ru
          12.10.2021 18:31

          Видел один CDC который можно было прошить отправив hex-файл в устройство.


    1. andreykorol
      12.10.2021 11:42

      Поддерживаю, делал такое. Только эмуляция не "sd-карты", а usb massstorage. Размеры флеша не большие - fat12, насколько я помню, эмулировал. Вход в бутлоадер: по значению backup-регистра, нескольким перезагрузкам по wdt подряд или по отсутствию прошивки в районе основного приложения. Если включена защита от чтения, то отдаешь сектора заполненные 0xFF при чтении области основного приложения.


      1. nordfox
        12.10.2021 11:46

        sd-карты так это я задал направление мысли)


    1. COKPOWEHEU
      12.10.2021 19:12

      А чего не прикинуться sd картой?
      Потому что это намного сложнее. Надо либо полноценно эмулировать fat и отображать ее на реальную память, либо отдавать половину памяти под «флешку», а потом парсить и считывать прошивку.
      С CDC же проще: драйвера в системе обычно уже есть, а для заливки достаточно cat file.bin > /dev/ttyACM0. Правда, в статье описан более сложный способ с полноценным командным обменом.


  1. mikelavr
    12.10.2021 08:03
    +4

    У обновления прошивки через USB CDC есть недостаток - в ОС надо ставить драйвер. Если изделие обновляется не специалистом - это может быть проблемой. Например пользователь может не иметь в системе прав администратора. Кроме того, в программе обновления надо выбирать конкретный UART порт из имеющихся в системе (или организовать сканирование с автоопределением).

    Решение: USB HID. Драйвер ставить не нужно, он уже есть в ОС. Недостаток - достаточно медленная передача данных из за особенностей реализации в ОС.


    1. Arcanum7
      12.10.2021 10:20

      Ну и загрузчик USB HID занимает много места. На F103 это критично.


      1. COKPOWEHEU
        12.10.2021 19:16

        Ну и загрузчик USB HID занимает много места.
        Не знаю сколько занимает запись во флеш контроллера, но вряд ли больше половины от HID. Ну пусть даже столько же, суммарно что-то около 5 кБ. Из 64 кБ, доступных в f103c8t6. Менее 8%.
        С HID в другом проблема: ему нужна программа-прошивальщик. Так просто (для пользователя) как с MSD или CDC уже не выйдет.


    1. IronHead
      12.10.2021 12:23
      +3

      Идеальный вариант — web usb.
      Драйвера не нужны
      В хроме и ему подобном работает из коробки
      Обновить прошивку можно прямо с сайта
      Попробовать можно здесь
      https://devanlai.github.io/webdfu/dfu-util/


      1. Xadok
        15.10.2021 11:27

        идеальным такой вариант не может быть (как раз из-за хрома и веба)


        1. IronHead
          15.10.2021 11:45

          <sаrcasm> ну да, зачем облегчать жизнь конечному пользователю
          Он мог просто зайти на сайт и нажат кнопку обновить прошивку.
          Но пользователь должен страдать, нужно заставить его ставить драйвера, перезагружаться чтобы включить поддержку драйверов без цифровой подписи и пр.
          </sаrcasm>


          1. Xadok
            15.10.2021 11:47

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


            1. IronHead
              15.10.2021 12:17

              Я тоже делал обновление прошивки через HID
              Для того, чтобы обновить прошивку через HID нужно:
              1) Зайти на сайт
              2) Скачать и сохранить у себя файл прошивки
              3) Скачать себе софтину для обновления прошивки
              4) Выбрать в софтине для прошивки нужный файл прошивки и прошить


              И как показала практика — 90% пользователей совершают ошибки в п2-4.
              Поэтому для себя решил — что лучше не напрягать пользователя лишними этапами.
              Все таки обновление прошивки нужно не пользователю, а вам, производителю.
              Пользователь хочет получить просто работающий девайс, ну может быть какие то дополнительные плюшки, если девайс можно безболезненно прошить, ничего для этого не устанавливая на свой ПК и не скачивая никаких файлов.


              1. Xadok
                15.10.2021 12:37

                Да, обновление прошивки конечный пользователь у нас не совершает. Но бывает, что прошивку нужно обновить и с хрюши, и с ноута с семеркой. Мы можем гарантировать, что наше ПО работает на всём. Но не можем гарантировать, что там будет хотя бы хром и уж тем более, что он работать будет.
                За скобками оставляем тот факт, что браузер как бы и не должен иметь доступа к железу.


    1. Sap_ru
      12.10.2021 18:33

      А что мешает стандартный драйвер использовать?


  1. screep123
    13.10.2021 08:20
    +3

    Не затронуты вопросы:

    1. Проверка целостности образа прошивки;

    2. Проверка версионности прошивки (обновление только в том случае, если версия образа >= версии в памяти МК);

    3. Шифрование прошивки;

    4. Что будет если новая прошивка начала заливаться и не закончила? Новая прошивка должна заливаться в резервную область (внешнюю память), там распаковываться, проверяться и если все норм уже копироваться в рабочую память

    КМК без всего этого вопрос как заливать образ второстепенен... Даже если мы работаем по удобному MSD все равно найдется пользователь который скопирует туда что-то не то и получит кирпич.


    1. STMshchik Автор
      13.10.2021 08:24

      Хорошие замечания. По сути в память МК сейчас возможно зашить любой мусор. Есть над чем работать. Тут действительно нужно довести до ума и подправить статью


      1. Xadok
        15.10.2021 11:31

        Товарищ верно подметил, если учесть все эти моменты, то процесс прошивки становится намного более сложным.
        У нас сначала прошивка заливается, проверяется, а потом отдельной командой переставляем указатель и перезапускаемся.


    1. Andy_Big
      15.10.2021 21:22

      Вот п.2 во многих случаях - зло. Скачал новую прошивку, залил ее, а в ней глюк. И уже не вернешься на старую, потому что "проверка версионности" :)


  1. ivan_kononoff
    14.10.2021 11:08

    Мне кажется или STM32F103 серию убили? По крайней мере доступность этих чипов оставляет желать лучшего, как и цены на них.
    Прекрасно понимаю, что никто не будет переписывать код, который был написан на CMSYS много лет назад под них.
    Но может кто-то подскажет, на что лучше переехать с F103C8 серии? Сейчас присматриваюсь к G0, но пугает то, что они новые и по ним нет ERRATA и накопленного опыта...


    1. STMshchik Автор
      14.10.2021 19:16

      Сам еще разбираюсь с этим вопросом. Осталась с давних времен отладочная с f103. Брал недавно как временный вариант stm32f103c6, но флеш памяти там уже 32 кб. Да придется рано или поздно на другую серию перейти


    1. order227
      14.10.2021 22:41

      Сейчас все из продажи пропало в принципе, это общий дефицит. Если же речь об альтернативе, то много чего есть от NXP на Cortex-M33, у Microchip всякие dsPIC33 и подобные, у infineon есть xmc4100 и младше.


    1. Andy_Big
      15.10.2021 21:23

      Ее не убили. Это полупроводниковый кризис, который зародился еще почти год назад.


  1. Andy_Big
    15.10.2021 21:34
    +1

    Я начинал с обновления прошивки по CDC. Но потом перешел на HID из-за отсутствия необходимости устанавливать драйвера :)

    Да, нужно свое приложение, но это не проблема. У меня приложение в трех вариантах:
    - пользовательский - позволяет выбрать вариант прошивки только из совместимых с подключенным девайсом и только обновить прошивку;
    - сервисный - позволяет прошить любой вариант в любой девайс, и только обновление прошивки;
    - производственный: позволяет прошить любой вариант, назначить серийный номер, внести данные об устройстве в базу данных, считать EPROM;

    Скриншот

    Все варианты прошивки сидят прямо в исполняемом файле, то есть не нужно качать отдельно саму прошивку и отдельно приложение. Скачал, запустил, прошил :)

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

    Так же сделал свой пакетный протокол по принципу "запрос-ответ". Содержимое каждого пакета проверяется при получении на целостность.