Stm32 прошивка через usb dfu
А такое число звездочек и приведений типа типично для embedded? И еще вопрос: выравнивание там чем-то гарантируется или это счастливое совпадение звезд?
Для HAL это «нормально», там вообще код в стиле Java EE, если выкинуть лишнее — внезапно становится в три-четыре раза компактнее. Cortex M3 выравнивание не критично.
Это если не знать фокуса этой серии. А фокус в том, что флешка там, где она должна закончиться, не заканчивается. Контроллеры серии F103C8 точно имеют (по крайней мере все те, с которыми я работал) 128 кБ флеша (хотя по спеке — всего 64). Такой же фокус у меня прошел на L152C8, по крайней мере приложение из региона ~70-80k вполне себе успешно работает.
Внешний пруфлинк вот тут.
128кб это камень СВ. С8 имеет 64кб. Те страницы, что за 64кб, их работа не гарантируется, ST их не тестит.
Я честно говоря тоже не понял, но предположу, что профит в том, что для прошивки st-link или uart не нужен. Если в устройстве есть usb, можно через него прошивать. Но 48кб это перебор. И необходимость специальной программы, тоже как-то не серьезно. Можно же эмулировать usb флэшку и прошивку на нее просто копировать. St-link v2.1 по-моему так умеет.
Делаете девайс с USB, но без UART-а (выводы нужны подо что-то другое, например, или просто неудобно их выводить), прошиваете через него. Сейчас это многие используют, например в некоторых контроллерах для коптеров — USB является основным портом, для прошивки и настройки, нет необходимости тыкаться по разъемам UART-ов, которые могут еще и на других GPIO оказаться (не на тех, где ждет загрузчик).
Области памяти, доступные для чтения/записи/удаления, определяются в файле USB_Device/App/usbd_dfu_if.c — описании дескриптора интерфейса. Пример строки описания:
Подробнее о формировании строки дескриптора можно прочесть в разделе DFU mode interface descriptor документа UM0424.
В целом следует понимать, что протокол USB-DFU следует — это именно USB протокол. Он имеет несколько функций (записать блок, считать блок, уничтожить блок, считать состояние, считать статус, очистить статус, отключиться). При взаимодействии по DFU, контроллер должен выполнить какие-то действия, в простейшем случае — это записать данные во флэш или считать их. Но валидация адресов — лежит на плечах разработчика в коде микроконтроллера. ПО с компьютера ничто не мешает сгенерировать запись в область RO (где обычно располагается бутлоадер), и контроллер должен это проверить и вернуть ошибку. Для того чтобы демо-утилита от STM знала, куда она может писать, и что может читать — и передается эта строка.
В своем проекте я использую микроконтроллер 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к).
Когда бутлоадер сделал свои дела он передает управление основной программе с адреса 0x0000. Т.е. программа всегда стартует с адреса 0x0000. Компилятор и линковщик работают с учетом того, что код будет находится в начале адресного пространства.
В микроконтроллерах STM32 все не так. Все программы стартуют с адреса 0x0800000. Бутлоадер не является чем-то таким особенным. Это такая же программа, которая стартует с того же самого начального адреса. В процессе работы бутлоадер может принять прошивку (через USB или UART, считать с флешки, принять со спутника, достать из подпространства, whatever. ) и записать ее по адресам выше чем находится сам загрузчик. Ну и, конечно же, в конце своей работы передать управление основной программе.
Так вот при компиляции прошивки нужно знать куда же бутлоадер запишет прошивку и соответствующим образом скорректировать адреса.
На этом с теорией все. Переходим к практике. Ниже пошаговая инструкция как прикрутить USB загрузчик к микроконтроллерам серии STM32F1xx, а может быть и к некоторым другим тоже.
Есть, правда, некоторые ограничения по схемотехнике. Тут я, к сожалению, не силен. ЯТП нужен подтягивающий резистор 1.5к для порта PA12 (он же USB D+). Это позволяет загрузчику в нужные моменты времени подключаться и отключаться от USB.
-
Указать линкеру стартовый адрес. В CooCox это делается в настройках проекта, вкладка Link, раздел Memory Areas, Адрес IROM1 Start Address. Бутлоадер занимает первые 8 килобайт, значит стартовый адрес прошивки будет 0x0800000 + 0x2000 = 0x08002000. Поле Size, наверное, тоже стоит уменьшить на 8к.
Вместо COM20 нужно подставить свой порт куда прицепился микроконтроллер.
Заливатор штука очень нежная, относительных путей не любит. так что путь к прошивке нужно указывать полностью.
1EAF:0003 — это VID и PID
Чтобы не нажимать каждый раз ресет, платы основанные на libmaple/stm32duino используют трюк. Они слушают usb serial порт. Если там возникает сигнал DTR и передается ключевая последовательность байт, то микроконтроллер перегружается в бутлоадер. Смотреть в функцию rxHook().
Из-за этого может возникнуть неудобство. Если микроконтроллер заглючил и повис, то он уже не слушает порт. Следовательно он не может услышать ключевую последовательность и перегрузиться в бутлоадер. Тогда только ресет в помощь.
На этом все. Надеюсь моя статья прольет свет на то, как работает загрузчик в STM32 и как можно загружать прошивку через USB порт. К сожалению порог вхождения по прежнему высок, но вдруг кому-то моя статья поможет его преодолеть.
Если статья Вам понравилась, Вы можете поддержать меня купив чашечку кофе.
Итак, сочинение сего мандригала было сподвигнуто практически полным отсутствием пошаговой инструкции с использованием обычного инструментария предлагаемого STMicroelectronics.
Великое множество обнаруженных в сети bootloader-ов, иногда весьма занятных, к сожалению «заточены» под какой-либо конкретный кристалл.
Предлагаемый материал содержит процедуру использования пакета CubeMX, «загружалки» DfuSeDemo и утилиты подготовки прошивки Dfu file manager, т. е. Мы абстрагируем наши «хотелки» от железки, да простят меня гуру макроассемблера и даташита.
Готовим окружение…
Нам необходимы собственно сам CubeMX, загружалка DfuSeDemo+Dfu file manager, лежат в одном пекете, STM32 ST-LINK Utility, все изыскиваем на сайте STMicroelectronics совершенно бесплатно.
Наша подопытная жлезка с чипом STM32F103C8T6 от дядюшки Ляо
и программатор ST-Link оттуда же.
Ну и ваша любимая IDE, в данном конкретном изложении мы используем KEIL, настройки компиляции в других IDE не очень отличаются.
Запускаем CubeMX и выбираем свой кристалл…
Отмечаем свои хотелки…
В данной конкретной задаче активируем устройство USB→Device FS и соответсвенно USB Device→ DownLoad Update Firmware class, и незабываем RCC→High Speed Clock→Cristal/Ceramic Resonator тот что на борту платы.
Далее необходимо выбрать переключалку режима bootloader-a, в данном примере просто задействуем имеющуюся перемычку boot1.
Смотрим схемку и в соответствии с ней boot1 прицеплен к ноге PB2, вот ее и задействуем в режиме GPIO_Input.
Готово, активируем закладку Clock Configuration и запускаем автомат выбора конфигурации.
Прыгаем на закладку Cofiguration…
Выбираем кнопку GPIO…
пишем пользовательскую метку, пусть это будет boot1.
Далее настраиваем проект…
Выбираем Project → Setting…
Выбираем и заполняем….
Соответсвенно выбираем для какого IDE нам Cub сгенерит проект, в нашем случае, MDK-ARM V5.
Закладку Code Generator в данном воплощении оставим без изменений…
Ну собственно и все, запускаем генерацию проекта Project→Generate Code
По окончании Cub предложит сразу запустить вашу IDE… как поступать выбирать вам.
Запускаем компиляцию и сборку и загрузку в кристалл… F7, F8…
Переключаем пины на нашей плате в режим работы и подключаем USB кабель…
Открываем в Windows панель управления→ система→ диспечер устройтв→ USB контроллер. И смотрим список устройств, Windows немого пошуршит и установит драйвер STM Device in DFU Mode (если он уже не стоял).
Итак, драйвер встал и определился, запускаем «загружалку» DfuSeDemo…
Смотрим что у нас поймалось DFU Device и дажды кликаем в поле Select Target …
Внимательно смотрим и дивимся, что флеш вплоть до адреса 0x0800C000 закрыт для записи и записываем этот адрес, он нам понадобится…
К слову, пробовал на STM32F407VE, там память открыта для записи с 0x08000000 т. е. С самого начала… почему, в нашем варианте не так, неясно, да и не копал, где то зарыто, но явно не прописано, не есть комильфо, потому что большой кусок пропадает безхозно… может кто и подскажет где копать…
Итак, «стрижка только начата»…
Нам понадобится только два файла исходников…
Открываем их в IDE и правим- дополняем…
Учитываем, что CubeMX НЕ ТОГАЕТ при перегенерации вставки между USER CODE BEGIN и USER CODE END… там и будем вписывать наши дополнения…
на этом с main.c все…
переходим на в usbd_conf.h и в
приводим к виду…
переходим к usbd_dfu_it.c, тут поболее….
Собственно и все…
Подключаем программатор, перекидываем перемычки в режим программирования, F7, F8 и botloader записан…
Теперь подготовим наше приложение для загрузки посредством bootloder…
Любимое приложение будет моргать светодиодиком…
Готовим и отлаживаем приложение, и меняем в компиляторе и теле программы отдельные места на предмет изменения адреса запуска программы и векторов прерываний…
А именно в KEIL → Configure → Flash Tools
Меняем адрес начала программы…
Говорим чтобы генерировал HEX файл
и меняем адрес таблицы векторов…
собираем программу F7…
полученный HEX преобразуем в dfo файл утилитой Dfu file manager…
указываем наш HEX файл кнопкой S19 or HEX… и жмем Generate…
получаем dfu файл.
Собственно и все готово.
Загрузка в контроллер…
Подключаем нашу подопытную плату с уже загруженным botloader-ом к USB, предварительно установив перемычки в режим DFU Mode.
Можно проконтролировать появлением STM Device in DFU Mode в списке устройст…
запускаем «загружалку».
указываем ей наш dfu файл…
Жмем Upgrade и наблюдаем результат загрузки… для уверенности, жмем проверку.
все удачно… можно запускать…
если ошибка вылезла, значит где-то косяк…
Итак, будем считать что все удачно… переключаем перемыку в режим работы приложения
и наслаждаемся миганием диодика…
…
Уффф. Столько букоффф. Устал копипастить картинки :-)
Если у вас возникли проблемы с подключением платы Iskra JS к Espruino Web IDE, последовательно пройдите все шаги описанные на это странице.
Проверьте среду разработки
Работать с платой Iskra JS следует только в Espruino Web IDE. Если у вас установлена Iskra IDE , установите Espruino Web IDE.
Проверьте установку драйвера для STM32
плата определяется во вкладке «другие устройства»
плата определяется во вкладке «порты (COM и LPT)», но с восклицательным знаком.
В последних двух случаях, необходимо указать путь к драйверам.
Установка драйвера STM32
Выделите «неработающее устройство» и нажмите кнопку «обновить драйверы».
Выберите пункт «Поиск и установка драйверов вручную»
для 64-х битных систем: C:\Program Files (x86)\STMicroelectronics
Должно появиться окошко об успешном завершении установки драйвера.
В итоге драйвер для USB-интерфейса микроконтроллера STM32, должен находиться во вкладке «Порты (COM и LPT)» и без восклицательного знака.
Всё получилось. Теперь можно продолжить «настройку платы».
Установка дополнительных драйверов для STM32
Рассмотрим альтернативный вариант подключения платы Iskra JS к Espruino Web IDE. Поочерёдно установите все драйвера с официального сайта ST-Link.
Если установка дополнительных драйверов не помогла, прошейте контроллер через DFU-режим
Прошивка платы через DFU
Если в диспетчере устройств не появилось новых устройств, вероятней всего микроконтроллер STM32F405RG не прошит. Для решения проблемы прошейте платформу в DFU-режиме
Disconnect при загрузке скрипта
Если в диспетчере устройств плата отображается корректно, но при попытке загрузить скрипт происходит рассоединение Espruino Web IDE и платы Iskra JS, то вероятнее всего проблема заключается в особенности ОС Windows. Обойти эту проблему можно используя дополнительно USB-Hub. При подключении Hub будет служить посредником между компьютером и управляющей платой.
Не работают библиотеки Амперки
По умолчанию библиотеки модулей Амперки работают только при подключении к интернету. Если вы планируете прошивать плату Iskra JS без выхода в сеть, необходимо настроить ваш компьютер.
Проверьте путь к подключаемым библиотекам. Для этого зайдите в настройки Espruino Web IDE: Settings Communications и проверьте адрес в поле Module URL .
Должен быть указан:
И в поле Module Extensions :
Если путь иной, замените его. После, перейдите в настройки Espruino Web IDE: Settings BOARD и проверьте адрес в поле Board JSON URL .
Должен быть указан:
Программа не сохраняется после сброса питания
Среда настроена, плата прошивается, код работает. Но после переподключения питания программа не сохраняется в памяти контроллера, как будто её и не было. Для решения проблемы сделайте ряд действий.
Зайдите в настройки Espruino Web IDE.
Перейдите во вкладку Communications и опустите Scroll Lock в самую нижнюю часть.
Найдите пункт меню Save on Send и удостоверьтесь, что в окне выбора состояния стоит вариант Yes . Если стоит другой вариант, измените его на Yes .
После этого программа должна сохранятся в памяти контроллера после переподключения питания.
Если вы прошли все шаги и проблема осталась — обратитесь в нашу техническую поддержку через форму обратной связи или по телефону.
Если не указано иное, содержимое этой вики предоставляется на условиях следующей лицензии: CC Attribution-Noncommercial-Share Alike 4.0 International
И вот тут самое время понять, что еще могут существовать другие загрузчики одновременно с системными - это ваши , которые пишутся вами и находятся в адресах FLASH 0х08000000.
Более того у STM есть готовый вариант в Кубе для создания вашего загрузчика по USB и называется USB : Download Firware Update Class (DFU). Генерируем , прошиваем в контроллер.
И загрузчик появляется в адресах 0x0800000 до 0x800C000 (помечена только Readable)
Далее надо пользоваться утилитами от STM Dfu File Manager и DfuSeDemo :
Dfu File Manager готовит вашу прошивку для записи выше вашего бутлодера, а DfuSeDemo собственно ее шьет во Flash выше с адреса 0x800C000.
И происходит это без подтянутой к 1 ножке boot0 контроллера.
Для общего понимания картины адреса памяти :
Думаем , а куда мы заливем свой код программы ? Мы пользовались Atollic True Studio, там были такие настройки :
Например смотрите выходной файл проекта (*.map)
FLASH это с адреса 0x08000000. А вот системный загрузчик лежит где-то по адресу 0x00000000 по-видимому всегда прекрасно себя чувствует, так как его стереть нельзя.
В нашем случае имеем STM32F205VG к примеру и у него есть такие варианты загрузчиков :
Но как узнать какой версии системный загрузчик?
Оказывается никак или предположительно по некоторым букво-цифрам на корпусе контроллера.
Типичный вариант организации пинов для активации загрузчика
BOOT0
Видим , что в нашем готовом устройстве есть вариация по BOOT0 :
Штатно BOOT0 на земле и это означает , что начало программы стартует с SRAM , т.е. по адресу 0x20000000 .
BOOT1
BOOT1 может быть выведен наружу и идти на пин , который связан с разъемом на микро SD карты. Понятно для закгрузки с микро SD карты прошивки например.
2 проекта для текстирования
В итоге для тестирования связки с загрузкой через STM Dfu File Manager и DfuSeDemo сделаны открытые два примера на Atollic True Studio .
Первый реализует пользовательский загрузчик по USB (DFU) и прошивается с адреса 0x0800000 до 0x0800C000. А второй проект реализует саму основную обновляемую программу, которую прошиваем по адресу с 0x0800C000 и выше.
STM32F205VG_FLASH.ld
Внимание во втором проекте :
Переключение в первом проекте между режимами загрузки и выполнение основной программы происходит программно установкой переменной boot = 1|0.
Можно прошивать каждый проект независимо , код каждого проекта должен попадать в свою область памяти и не вредить другому.
Теперь по-шагово поехали :
Собираем (и прошиваем) первый проект:
Собираем (но не прошиваем) второй проект:
Файл *.hex через утилиту STM Dfu File Manager преобразуем в файл *.dfu .
Запускаем первый проект в режиме (boot =1) с отладчиком и трассировкой SWO
Файл *.dfu через утилиту DfuSeDemo отсылаем контроллеру (то есть прошиваем через USB DFU Class)
Перезапускаем проект 1 с boot =0 и наблюдаем , что программа перешла на адрес 0x800C000 и начала выполняться :
Читайте также: