Заливка прошивки в STM32 через USB

  • Tutorial
image

В своем проекте я использую микроконтроллер STM32F103C8 и фреймворк stm32duino. Этот клон Ардуино предлагает специальный бутлоадер, который позволяет заливать прошивку через USB, без использования внешних компонентов типа ST-Link или USB-UART переходника.

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

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

Я ничего не имею против ST-Link и других отладчиков. Но в моем готовом устройстве его не будет, но точно будет USB. Почему бы сразу не заложить возможность обновлять прошивку через USB? Лично я нахожу этот способ удобным. тем более что все равно у меня уже подключен шнурок по которому идет питание и USB Serial.

Давайте посмотрим как работает бутлоадер. Для начала на примере контроллеров AVR. Почему я о нем вспомнил? Я переходил с Arduino и подсознательно ожидал такого же поведения. Но в STM32 оказалось все по другому. Потому хочу рассказать о разнице этих двух микроконтроллеров.

Итак. В микроконтроллерах AVR ATMega под бутлоадер можно зарезервировать некоторое количество памяти ближе к концу флеша. С помощью fuse битов можно регулировать с какого адреса будет стартовать программа. Если бутлоадера нет — программа стартует с адреса 0x0000. Если бутлоадер есть — он запускается с некоторого другого адреса (скажем, в ATMega32 с 0x3C00, если размер бутлоадера выбран 2к).

image

Когда бутлоадер сделал свои дела он передает управление основной программе с адреса 0x0000. Т.е. программа всегда стартует с адреса 0x0000. Компилятор и линковщик работают с учетом того, что код будет находится в начале адресного пространства.

В микроконтроллерах STM32 все не так. Все программы стартуют с адреса 0x0800000. Бутлоадер не является чем-то таким особенным. Это такая же программа, которая стартует с того же самого начального адреса. В процессе работы бутлоадер может принять прошивку (через USB или UART, считать с флешки, принять со спутника, достать из подпространства, whatever...) и записать ее по адресам выше чем находится сам загрузчик. Ну и, конечно же, в конце своей работы передать управление основной программе.

image

Так вот при компиляции прошивки нужно знать куда же бутлоадер запишет прошивку и соответствующим образом скорректировать адреса.

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

Есть, правда, некоторые ограничения по схемотехнике. Тут я, к сожалению, не силен. ЯТП нужен подтягивающий резистор 1.5к для порта PA12 (он же USB D+). Это позволяет загрузчику в нужные моменты времени подключаться и отключаться от USB.

Инструкция:

  • Качаем github.com/rogerclarkmelbourne/STM32duino-bootloader. В директории STM32F1\binaries уже есть пакет скомпилированых бутлоадеров под разные платы. Индекс в конце названия файла указывает куда подключен светодиод. В случае моей платы где светодиод подключен к пину C13, я использовал файл generic_boot20_pc13.bin.

  • Прошивем согласно инструкции. Да, тут понадобится USB-UART переходник, но можно и с помощью отладчика.

  • Теперь микроконтроллер готов ппрошиваться через USB загрузчик. Но ведь еще нужно саму прошивку подправить. А сделать нужно 2 вещи:

    • Указать линкеру стартовый адрес. В CooCox это делается в настройках проекта, вкладка Link, раздел Memory Areas, Адрес IROM1 Start Address. Бутлоадер занимает первые 8 килобайт, значит стартовый адрес прошивки будет 0x0800000 + 0x2000 = 0x08002000. Поле Size, наверное, тоже стоит уменьшить на 8к.

    • Где нибудь вначале программы перед инициализацией периферии сделать вызов

      NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x2000);


      UPDATE 17.05.2018: В современной версии STM32Cube функции NVIC_SetVectorTable() нет. Вместо этого можно в файле system_stm32f1xx.c (или аналогичного для другого микроконтроллера) исправить дефайн VECT_TAB_OFFSET

  • Заливатор прошивки можно взять из проекта stm32duino. В директории tools ищите скрипт под называнием maple_upload. Я пользовал только виндовую версию — maple_upload.bat.

  • Запускать так:

    "maple_upload.bat" COM20 2 1EAF:0003  "Path\To\Firmware.bin"

    Вместо COM20 нужно подставить свой порт куда прицепился микроконтроллер.

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

    1EAF:0003 — это VID и PID

    2 — это параметр AltID, который указывает что прошивку нужно заливать по адресу 0x08002000 (читать тут).

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

Чтобы не нажимать каждый раз ресет, платы основанные на libmaple/stm32duino используют трюк. Они слушают usb serial порт. Если там возникает сигнал DTR и передается ключевая последовательность байт, то микроконтроллер перегружается в бутлоадер. Смотреть в функцию rxHook().

Из-за этого может возникнуть неудобство. Если микроконтроллер заглючил и повис, то он уже не слушает порт. Следовательно он не может услышать ключевую последовательность и перегрузиться в бутлоадер. Тогда только ресет в помощь.

На этом все. Надеюсь моя статья прольет свет на то, как работает загрузчик в STM32 и как можно загружать прошивку через USB порт. К сожалению порог вхождения по прежнему высок, но вдруг кому-то моя статья поможет его преодолеть.
Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 26

    +3
    «Читайте доки, они рулез!»
    На сайте http://www.st.com скачайте AN2606 STM32™ microcontroller system memory boot mode
      +1
      Есть мнение, что в этих доках встретится клевета, будто F103 в USB-бутлоадер не умеет.

      Хотя если взять F105, то вся проблема решается сама собой, да.
        +4
        Кгхм, извиняюсь, не заметил что это ардуинщики. Беру свои слова обратно — им вредно такое читать. :)
          +1
          Не вредно. Но не всегда заходит с первого раза и в нужное время
      0
      Ко второму пункту инструкции — чтобы прошить бутлоадер через ST-Link без uart нужна утилита STM32 ST-Link Utility (http://www.st.com/en/embedded-software/stsw-link004.html)
        0
        Спасибо, добавил в статью
        0
        stm32duino отличается чем-нибудь от Energia при работе с платами TI?
          0
          Я никогда не работал с Energia и платами TI.
          Но я скачал Energia и чуток пошарился по файлам. Выглядит как обычный ардуино фреймворк.

          Так что отвечая на Ваш вопрос: наверняка отличается реализацией, т.к. чип другой. Но с точки зрения использования я думаю очень похоже
          0
          Огромное спасибо. В данный момент тоже перехожу с атмеги на стм, и этот пост был крайне интересен и полезен. А можете еще рассказать про две перемычки boot на smt32f103c8t6?
            0
            А чего там рассказывать? BOOT0 переключает обычный или альтернативный режим загрузки, а BOOT1 выбирает тип альтернативной загрузки — программа в оперативной памяти, или встроенный загрузчик прошивки по UART.
              0
              Судя по документации есть 3 варианта загрузки:
              — обычная загрузка из флеша
              — загрузка из ОЗУ. Т.е. ктото влил код в память, а микроконтроллер просто его выполняет
              — загрузка из системного загрузчика. Этот загрузчик прошивается на заводе, его нельзя стереть, а его задача прошивать микроконтроллер через UART

              Как именно нужно выставлять перемычки для этих режимов описал предыдущий оратор. Еще можно глянуть в табличку под спойлером «Для чего нужны BOOT0 и BOOT1 джамперы» в этой статье. Ну а наилучшим вариантом, пожалуй, будет вдумчивое и неспешное (возможно, многократное) чтение reference manual
              0
              У st есть примеры USB бутлоадеров, довольно легко пример можно поправить под себя)
                0
                Вспоминая себя 3 дня назад, я бы с радостью воспользовался пошаговой интсрукцией, нежели пачкой примеров, которые еще нужно править под себя.

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

                Но это не подходит, когда у тебя голая железка, которая даже лампочкой мигать не хочет. При этом у тебя нет за плечами многолетнего опыта ARM/STM32 что бы понять почему.

                Напомню, что задача была не написать свой бутлоадер, а воспользоваться готовым
                  0
                  Ок, если интересно вот мой чуть правленый проект бутлоадера от ST.
                  https://github.com/denruss/stm32_MyDfu

                  вот проект который с ним работает
                  https://github.com/denruss/usb_gen_v2_stm32

                  с компа залить прошивку можно пользуясь утилитой от ST
                  http://www.st.com/en/development-tools/stsw-stm32080.html
                    0
                    Спасибо, обязательно гляну
                      0
                      А можете добавить небольшую инструкцию прямо в Github? Действительно было бы более информативно.
                        +1
                        Сделал https://github.com/denruss/stm32_MyDfu
                          0
                          Спасибо огромное!
                            0
                            Вопрос, а как добавить checksum к своей прошивке?
                              0
                              Либо на гитхабе есть ответ, либо я не понял вопрос
                          0

                          Не подскажете, где взять оригинальный проект от ST? Никак не могу отыскать.

                            0
                            Да вроде в exemples
                      0
                      Спасибо. Ценно! Сам перехожу с arduino на что то более серьезное, буду весьма благодарен за подобные статьи про STM. Жгите еще, невзирая на коменты типа «очередной перевод мануала на хабре». На ваш материал есть спрос.
                        0
                        Оффтоп:
                        Препода, который у нас читал программирование как-то поставили на какой-то гуманитарный факультет преподавать компьютерную грамотность. Во время сессии пара-тройка студентов заваливала зачет. Тогда препод выбирал одного, который знал чуток лучше других и назначал его «учителем» для остальных. Говорит, что очень много нового узнавал о «преподавателях», «студентах», компьютерах и программе обучения

                        Спасибо, что оценили. Но нужно понимать, что я сам нахожусь в начале пути. Что накопал — про то и написал. Надеюсь при этом разобрался достаточно глубоко, что бы закрыть этот конкретный вопрос. А то получится как с этими студентами.
                          +3
                          Главный ресурс, которого сегодня не хватает спецам, это время. С тем же успехом я и другие подписавшиеся могли бы накопать подобный материал и даже написать статью. И вот делема, в ремени на это найти сложно ( есть более приоритетные задачи), а разобраться в сабже максимально быстро хочется. Поэтому и прошу вас, не стесняйтесь собирать в кучу и делиться тем, что надергали из снопа. С уважением)
                            0
                            спасибо

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

                      Самое читаемое