Прошивка stm32 через usb
Наконец дошли руки поиграться с платкой с STM32 (у меня такая). Камень STM32F103RBT6, пины разведены на гребенки, подключен USB, UART выведен на DB9 через MAX3232, есть разъем JTAG, пара кнопок, пара светодиодов — ничего особенного.
Первый вопрос, который возник сразу — как прошивать. JTAG-адаптером пока обзавестись не успел, но не раз читал, что STMки умеют вшитый на заводе UART-бутлоадер. Ок, пробуем. Качаем архив с прошивальщиком, расчехляем USB-to-UART переходничок на CP2102, переставляем джампер на BOOT0, запускаем, прошиваемся. Все с первого раза, это успех. Переставляем джампер еще раз, жмем ресет — видим мигающий диодик.
Это круто, подумал я. Но вручную переставлять джампера и жать ресет каждый раз — это не путь джедая. Поэтому «We need to go deeper»
Сначала я решил удовольствоваться малым (черт с ними, с джамперами) и хотя бы запускать саму прошивку прямо из CooCox'a, для чего директория установки STM Flash Loader'a была происследована на предмет консольного интерфейса к прошивальщику. Он нашелся в виде файла STMFlashLoader.exe, прочитав справку которого мы сразу видим, что, де, вот она, рыба нашей мечты:
У нас есть аж две линии, которые (судя по лежащему рядом примеру в файле MB786revB.bat) мы можем использовать как GPIO, т.е. управлять уровнями на них по собственному желанию. Запаиваем дополнительную гребенку в адаптер, благо нужные нам линии разведены, и подключаем 2 дополнительных провода от адаптера к плате: я подключил RTS на BOOT0 (прямо туда, где подключается джампер) и DTR на Reset (нашелся на колодке JTAG, пин 15). Осталось задать правильную команду для запуска прошивальщика. Вот, что получилось у меня:
Пара комментариев.
Разбивка на строки не случайна. По сути сама программа- прошивальщик представляет собой некий интерпретатор, а коммандная строка его запуска — программу для него. Опции, начинающиеся с одного минуса — операторы программы, с двух минусов — их операнды/опции. Самые интересные тут для нас опции — это -Rts и -Dtr. Слеующие за ними флаги --Hi/--Lo задают последовательность, которая будет выдана на эти пины. Причем, как видите, за одну строку можно изменить состояние пина несколько раз.
Итак, вначале мы открываем порт с заданными настройками (-c), затем по линии RTS переключаем состояние BOOT0 (-Rts), затем по линии DTR выполняем Reset (-Dtr). Указываем семейство контроллера и даем команду на загрузку прошивки из указанного файла (-i, -d). Затем переводим BOOT0 в нормальное состояние и запускаем выполнение программы.
Заставить Кокос вызывать эту команду мне пока не удалось (буду рад, если кто-то поделится соображениями — теоретически можно прописать ее в build.xml, но с ходу у меня это не получилось), поэтому сохранил в BAT-файл и запускаю прошивку одним кликом.
Надеюсь, что кому-то мое мини-исследование оказалось полезным и сэкономило время.
А к слову об отладке — раз у нас все равно постоянно подключен к компьютеру UART, ничего не мешает нам задействовать его для отправки отладочной информации. Для этого я добавил в проект следующие фрагменты кода:
Из репозитория Кокоса подключаем C Library и Retarget Printf и все, можем использовать функцию printf() для вывода информации в UART. Если кто-то хочет сделать красивее, асинхроннее и на прерываниях — ради бога, это просто быстрый прототип и ни на что не претендует.
За сим откланиваюсь. Замечания, предложения, улучшения — с радостью выслушаю.
В своем проекте я использую микроконтроллер 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 порт. К сожалению порог вхождения по прежнему высок, но вдруг кому-то моя статья поможет его преодолеть.
Если статья Вам понравилась, Вы можете поддержать меня купив чашечку кофе.
Итак. Не будем здесь описывать для чего нужна данная плата. Думаю те кто ей заинтересовался знают о ее возможностях.
Но распиновку устройства все-же покажу для наглядности:
Я лишь покажу здесь как подключить usb/ttl или st-link для прошивки устройства. И как подготовить программу arduino ide для прошивки stm32.
Чтоб начать работу данной платы с arduino ide. Нам необходимо подключить usb/ttl конвертер к плате следующим образом:
ВАЖНО! Микроконтроллер stm32 имеет 3.3 вольтовую логику. Следовательно и usb/ttl должен быть таковым. Я же прошивал на видео обычным, который имеет 5 вольтовую логику. Но это не правильно. Всегда есть риск спалить устройство.
Также нужно поставить джампер как показано на картинке.
Итак, после того как подключили конвертер к плате и поставили перемычку правильно. Нам нужно скачать несколько приложений:
После того как все скачали, разархивируем архивы. Устанавливаем программу STM32 Flash loader demonstrator. Она не устанавливается на рабочий стол. Ее можно найти по слову deminstrator gui. После того как установили приложение. Откроем его.
И откроется первое окно, в котором выбираем COM порт которым определился usb/ttl конвертер. И нажимаем кнопку далее.
В этом окне если у Вас в первом блоке есть красные надписи, то нажимаем кнопку “Remove protection” и нажимаем Next. Ну и если у Вас все также как у меня на скрине, то ничего не делаем а сразу нажимаем “Next”.
Тут выбираем какая у нас плата. Возможно выбрать из двух вариантов. на 64К и на 128К. В моем случае это на 64К. Как определить? Если у Вас микроконтроллер STM32F103C8 то это 64К. А если STM32F103CB то это 128К.
После того как выбрали контроллер, нажимаем “Next”
В этом окне выбираем “Download from file” и переходим в распакованный архив STM32duino-bootloader. Там в папку binaries и выбираем файл gd32f1_pc13.bin .
Ну и тоже нажимаем далее. После этого начнется загрузка .bin файла.
После загрузки закрываем программу.
И открываем Arduino ide.
Если Вы ахив Arduino_stm32 положили корректно по пути Документы/arduino/hardware/ То при открытии программы Arduino ide в Инструменты в выборе платы должна появиться возможность выбора платы:
И для того чтоб плату заливался скетч необходимо выбрать “Generic STM32F103C series”
Теперь что касается прошивки. У меня работает 2 метода. Первый это прошивка через usb/ttl. Для этого нужно выбрать в “Upload method” нужно выбрать ” serial:
И все у Вас замечательно загрузится в микроконтроллер.
Но платы STM32F103C8T6 часто предлагают на aliexpress сразу с программатором st-link v2. С ним скетч в плату загружается гораздо быстрее. У него сразу 3.3 вольтовая логика, какраз которую хочет наш контроллер. По этому правильнее будет грузить программы в контроллер через st-link. Для этого подключим его к плате следующим образом:
После подключения, в “Upload method” нужно выбрать “STLink” и все. Теперь будет загружаться все через данынй свисток.
На этом все. Спасибо за внимание. Надеюсь статья помогла Вам.
Готовую программу надо каким-либо образом запихать в контроллер. Для этого существует множество способов.
JTAG/SWD адаптер
Так как часто для отладки под ARM используется JTAG, то этот метод получается наверное самым популярным. Для этой цели используется какой-либо адаптер. Например я использую CoLinkEX так что показывать буду на его примере. Там все просто — подключаешь адаптер к контроллеру стандартным SWD или JTAG шлейфом. Через линии NRST/TDI/TDO/TCK/TMS для JTAG или через SWO/SWOCLK/SWDIO/NRST для SWD режима. На адаптере моей верси CoLinkEX оба эти разьема выведены на одну колодку, так что получается как бы сразу и JTAG и SWD соединение. А там какое надо такое и выбираешь. Особой разницы в отладке/прошивке между ними нет.
И прошиваешь либо из среды Keil.
Выбираем тип контроллера, размер памяти.
А дальше надо только указать бинарный или Hex файл и нажать прошивку.
Чтобы Keil сгенерировал hex файл нужно выставить галочку в опциях проекта.
А чтобы получить bin файл прогнать выходной axf файл через специальную утилитку fromelf входящую в состав Keil. Проще всего вписать это сразу в постобработку:
Формат там такой:
fromelf --bin --output .\имя_будущего_файла.bin .\имя_создаваемого_файла.axf
Ну или, если выходные файлы создаются в какой-либо подпапке, то путь будет включать и эту подпапку
Первичный Bootloader
Если нет JTAG/SWD адаптера, то не беда. Достаточно иметь переходник USB-UART или COM-UART так как почти все ARM контроллеры содержат в памяти аппаратно встроенный бутлоадер, позволяющий накатить прошивку. Главное следить за тем, чтобы напряжение на выходе с адаптера совпадало с напряжением питания контроллера, а то можно пожечь входы (FTDI можно запитать от 3.3 вольт. А для работы с RS232 использвоать не MAX232, а MAX3232 — то же самое, но на 3.3 вольта). Я в качестве USB-UART использую свою демоплату Pinboard с джампером питания выставленным на 3.3 вольта. Питание беру с той же платы.
Готово — можно шить. Для прошивки в STM32 используется программка Flash Loader Demonstrator v2.2.0 от STM запускаем ее:
Настраиваем порт, жмем Next
Она сразу показывает, что есть контроллер.
Тут можно посмотреть какие страницы флеша нам доступны на запись. Жмем Next
Выбираем какую операцию будем делать. Для прошивки надо выбрать Download и не забыть галочку Стереть чип.
Жмем Next и пошел процесс прошивки-проверки
Для LPC от NXP используется другая утилитка, зовется она Flash Magic — те же яйца, вид сбоку. Разве что может быть для входа в загрузчик надо другие выводы коротить. Это надо в User Manual на LPC уточнять уже.
Mass Storage USB Bootloader
Кроме того, у LPC1343 (у других LPC не встречал) есть одна прикольня фича. Там встроенный загрузчик может работать и по USB. Для этого надо собрать следующую схему:
Еще нужно вывод PIO001 подтянуть резистором на 10кОм к 3.3 вольтам питания и вывести на джампер, который бы его коротил в землю. Это будет условия входа в бутлоадер. После чего замыкается джампер входа в бут и девайс втыкается в USB. Винда его быстро определяет как сьемный диск объемом в 32Кб, на котором лежит файл firmware.bin если его скопировать — то мы получим юзерскую прошивку, что была там ранее. Это если не включена защита.
В противном случае мы, наверное, считаем мусор. А если удалить файл firmware.bin и на ее место записать файл с бинариком новой прошивки, то он вольется во флеш. Усе, не надо больше ничего! Красота! Правда в линухе оно работает не так как надо, дело в том, что линух пишет туда начиная со второго чтоль сектора и в результате Epic Fail. Впрочем, там же есть замечательная утилитка dd которая может скопировать на эту «флешку» файл в точности как надо, с нулевого адреса.
Вторичный бутлоадер
Поскольку я решил зарыться в STM32, то мне тоже захотелось такую вкусняшку как USB boot в режиме mass storage. Забросил идею Владимиру aka RtxOnAir и в результате он, за пару дней, выдал аналогичное решение для STM32F103.
Для загрузки с USB нужна следующая схема:
Транзистор подтягивает линию D+ к питанию и это означает, что на шине кто то появился, заставляя OС компа произвести определение устройства. Можно сделать и по колхозному. Подтянуть D+ через резистор напрямую. Но в этом случае для входа в бут придется передергивать шнур USB, иначе винда не захочет находить устройство. А так контроллер сам дернет вожжу.
Штука у Владимира получилась классная — автоматом определяет все типы кристаллов серии F103, позволяет выбрать любую ногу для передергивания USB шиной. Для входа во вторичный бутлоадер надо выводы Boot_0 и Boot_1 посадить на землю и нажать RESET ну или воткнуть девайс в USB если шина у нас не коммутируемая. Также можно выбирать работу от внутреннего генератора или от внешнего.
Вообще, инструкция явно говорит, что USB может работать только от внешнего кварцевого резонатора, т.к. частота внутреннего нестабильная и вообще кака. Не будем спорить с создателями камня, но у нас наш бутлоадер отлично завелся на HSI и при комнатной температуре отлично работал. Впрочем, стабильность тут явно не на высоте и надо быть осторожным.
Конфигурация бутлоадера
Для конфигурации нашего бута RtxOnAir написал небольшую утилитку:
Запустив которую можно выбрать нужные опции и нажав «Ок» получить сконфигурированный бутлоадер, который надо залить в МК любым вышеуказанным способом. Переключив джамперы Boot0 и Boot1 в режим нормальной работы Boot0=0 Boot1=1 и нажав сброс мы должны увидеть как в системе появится новый USB Mass Storage диск с емкостью равным размеру флеш памяти нашего кристалла за вычетом размеров бутлоадера.
Ну и прописать строку для формирования бинарика из axf файла.
После чего файлы прошивки можно банальным копированием загонять в STM32 и никакой программатор или адаптер больше не нужны совсем. Красота же!
Спасибо. Вы потрясающие! Всего за месяц мы собрали нужную сумму в 500000 на хоккейную коробку для детского дома Аистенок. Из которых 125000+ было от вас, читателей EasyElectronics. Были даже переводы на 25000+ и просто поток платежей на 251 рубль. Это невероятно круто. Сейчас идет заключение договора и подготовка к строительству!
А я встрял на три года, как минимум, ежемесячной пахоты над статьями :)))))))))))) Спасибо вам за такой мощный пинок.
129 thoughts on “Прошивка ARM Cortex M3 на примере STM32 и LPC1300”
А зачем из hex делать bin? В чем разница?
Смотря для чего. Если грубо, то bin — это сама откомпилированная программа в том виде, как она будет записана во флеш-память МК байт в байт, т.е. это непосредственные коды команд, данные в сыром виде и т.д. А hex формат — это тоже самое но в виде обычного текста + доп. информация. Т.е. если прошивку в hex формате залить в МК 1 в 1, то естественно работать ничего не будет.
Заливка через USB, я так понимаю, работает только для 103 серии, где он есть?
Ну логично, чтобы шить через USB необходимо наличие его в МК. :-)
Ещё у STM32 есть фирменная система DFU (Device Firmware Upgrade) используя которую тоже можно шить по USB, предварительно прошив контроллер спец прошивкой от них. Там все довольно запутанно, но промучавшись пол дня все получилось.
И работает это не только для 105 или 107 (в этих USB загрузчик с завода), но и для всех контроллеров серии с USB. Лично я прошил так 103 проц.
В курсе. Но раз все равно нужен свой бутлоадер (я имею ввиду 103 серию), то зачем связываться с «запутанным» DFU, который к тому же требует использование утилиты-прошивальщика, раз можно сразу сделать весь процесс прошивки в виде удаления/копирования файла стандартными способами самой системы, что, согласитесь, всетаки на порядки проще.
Конечно, чем больше вариантов тем лучше! Спасибо вам за труд. Скоро опробую ваш способ.
А не могли бы подсказать где эту прошивку саму взять и как ее сгенерировать?
Я нашел только ту чем прошивать. boot от rtxonair так нормально и не заработал..
Там дельфийская прога. В ней выбираешь проц, ноги и жмешь сгенерить. На выходе будет бинарь
А можно этот генератор перевести на английский. А то у иеня винда не русская и показывает знаки вопроса.. Ну или хотябы сделать её в уникоде?? А то неудобно.. а попробовать хочется..
Можно. В ближайших планах есть такое намерение.
Но, у меня тоже английская винда без MUI… И все на русском везде отображается без проблем. Есть подозрение, что нужно выбрать русский язык в Control Panel->Regional and Language Options->Advanced->Language for non-Unicode programs.
Это да.. Только после этого начинают не так работать и показывать буквы остальные програмы :) Вобщем подожду на английскую версию..
Попробовал.. Не работает… Хотя способ интересный.. Я пробовал и другие програмы.. Чтото работает а чтото нет..
> А как быть с бин файлом? Может кто то подскажет?
> LPC flash utility с бин файлами не может работать.
Ну во первых, если уж использовать LPC flash utility, то зачем генерить именно bin файлы?
А во вторых, очевидно, нужно читать даташит в котором сказано где должна распологаться контрольная сумма и как ее считать. Я с LPC баловался совсем не много, но по моему и EWARM и Keil могут считать контрольную сумму и записывать ее куда надо.
Прошивка в формате бин нужна для того чтоб залить её через ЮЗБ. Где должна распологаться контрольная сумма я знаю, а вот как заставить чтоб ИДЕ её генерировала и записывало в нужное место я так до сих пор и не нашёл. и посему использую LPC flash utility для правки контрольной суммы.
rtxonair не могли бы вы вспомнить что надо делать чтоб иде генерировала и писала контрольную сумму куда надо? был бы очень благодарен
А чем именно вы пользуетесь? Сейчас проверил в EWARM 5.4 — он автоматом всатвляет контрольную сумму в bin файл, если правильно указан тип МК в свойствах проекта. Потом нашел ту-же инфу на их сайте…
Пользуюсь я IAR 5.2. Я ещё пока ЮЗБ загрузчик не прошил и пока ставлю чтоб ИДЕ генерировала файлы в хекс формате. И оно контрольную сумму не вставляет. Программа не работае ни в железе ни в протеусе. Хотя я выставляю тип мк в свойствах проекта LPC2142. После того как исправлю контрольную сумму LPC flash utility работает и в железе и в протеусе.
rtxonair покажите пожалуйста где на их сайте рассказывается в какие выходные форматы оно вставляет контрольную сумму.
Посмотрел на файлы конфигурации упомянутые в статье по приведенной мной ссылке. Насколько я понял, вото оно:
//IElfTool command line for device specific post processing
IElfToolPostProcess=—checksum __vector_table+0x1c:4,sum32:2;__vector_table-__vector_table+0x1B
Или можно самомому воспользоваться утилитой ielftool.exe с приведенными параметрами —checksum __vector_table+0x1c:4,sum32:2;__vector_table-__vector_table+0x1B
>А почему бы не перейти на EWARM 5.4?
Да я бы с радостью но пока я этой идеей в серйоз не задавалдся.
Но я думаю и версия 5.2 тоже это должна делать испавлять вектора.
За ссылку спасибо щас буду внимательно изучать.
rtxonair а можно с вами как то по мылу/асаьке/скайпу связаться?
В коментах тяжело общаться.
rtxonair да вы правы. версия 5.4 сама правит контрольную сумму в зависчимости какой девайс выбран. Вот оно: This Tech Note does not apply to recent versions. There is no need for the label __vector_0x14 (or __vector_table_0x1c) as the EWARM get the information based on the slected chip in the General Options. Эта техническая нотация не применяется к недавним версиям. Нет нужды для метки __vector_0x14 (or __vector_table_0x1c) так как EWARM получает информацию по выбраному чипу в главных настройках.
Только я вот не совсем разобрался с этой строкой: IElfToolPostProcess=–checksum __vector_table+0×1c:4,sum32:2;__vector_table-__vector_table+0×1B
Я так понял эту строку нужно указавать линковщику.
настройки, категория линкер, вкладка экстра опшонс, ставим галочку использовать опции командной строки и туда эту строку писать?
Я правильно понял?
Скачал я ИАР 5.4. Написал простенькую программу мигания светодиодом. Запускаю в протеус и результата 0. Программа не работает. Может я проект неправильно создаю, может я ещё что то не так делаю я не пойму.
Кто знает помогите пожалуйста.
Выложи архив с проектом, я у себя постараюсь посмотреть что там не так.
Кхм, кхм, кхм… Даже не знаю с чего начать… :-)
Ну попробую:
1. Мы здесь ведем речь об МК на базе архитектуры Cortex-M3 а LPC2138 и LPC2142 это архитектура ARM7TDMI. Я, конечно, понимаю, что и то и то АРМ, но все таки архитектуры довольно таки различны…
2. Файлы генерятся нормальные и контрольная сумма генерится и ложится куда надо. Можешь убедиться сам что:
а) оба HEX файла одинаковые с точностью до байта кроме 1 строки в каждом файле, которые данными прошивки не являются (о них речь ниже).
б) генерируемый BIN файл с точностью до байта повторяет данные в HEX файлах.
в) сама контрольная сумма лежит по адресу 0x14 (4 байта). И она меняется, если изменять содержимое векторов прерываний, я проверил.
3. По видимому ты либо както не так генерируешь BIN файл либо шьешь его как-то не так или не туда (в друге адреса может быть).
rtxonair спасибо за ответ. По поводу первого пункта я понимаю что вопрос совсем не в тему(DI HALT вообще имеет полное право эти коменты удать) но самому мне трудно разобраться и поэтому просил помощи.
->Оба HEX файла одинаковые с точностью до байта кроме 1 строки в каждом файле.
В этом я убедился, а вот когда сравнивал «исправленую прошивку IAR 5.3» и прошивку которая была сгенерирована IAR той же версии без исправлений, то там пол файла не совпадает.
Сравнивал в тотал командере сравнить по содержимому.
Если пол файла не совпадает, то это уже что-то не то…
Контрольная сумма занимает всего 4 байта. Вот они могут не совпадать… А остальное, должно оставаться без изменений!
После того как я вдоволь наковырялся с STM32 и USB, решил что было бы неплохо поделитсья опытом с окружающими. Тем более, что все делалось аж под три разные платы и две разные линейки процессоров: High-Density (STM32F103RET6, STM32F103VET6) и Connectivity-Line (STM32F107VCT6).
Платы у меня в руках оказались следующие:
1) STM32 Development Board MINI (512K Flash 64K SRAM) 2.4-inch QVGA TFT module
(ссылка 1) (ссылка 2)
На ней стоит микроконтроллер STM32F103VET6
2) Embest EM-STM32C (EM-STM3210C)
(ссылка)
На ней стоит микроконтроллер STM32F107VCT6 — Connectivity Line
3) Встраиваемый модуль TE-STM32F103 — Махаон, от фирмы Terraelectronica.
(ссылка)
Соответственно, на ней стоит контроллер STM32F103RET6
Запустить проект из примеров, который использует USB, на любой из этих плат, задача не такая уж и сложная.
Куда сложнее встроить эти примеры в свои проекты, так как часто они бывают очень запутанно завязаны на конкретных платах. Еще сложнее собрать проект с нуля, используя библиотеки драйверов от STM — все равно без примеров обойтись сложно.
Поэтому я поставил перед собой задачу сделать универсальный проект, работающий со всеми имеющимися у меня в наличии платами, и, при необходимости, легко подстраиваемый под другие платы.
Между первой и третьей платой отличий мало: похожие контроллеры, отличающиеся лишь числом ног, у обоих выведен USART1. А вот второй отличается сильно: это контроллер Connectivity Line, с поддержкой USB On-The-Go, из-за чего работа с USB построена по-другому, а также вместо USART1 выведен USART2, да еще и с ремапом пинов на другие, отличные от дефолтных, ноги.
На всех платах есть светодиоды в разном количестве: 1, 4 и 3 соответственно.
Поэтому было принято решение сделать банальную вещь — устройтво, светодиоды которого управляются с компьютера по USB.
Прежде чем продолжать, рекомендую вкратце ознакомиться с тем, что же из себя представляет USB.
Самая лучшая, на мой взгляд, статья по этому вопросу — «USB in a NutShell». Ее перевод можно найти тут.
- Control. Endpoint такого типа, с номером 0, обязательно должен присутствовать в любом USB-устройстве.
- Interrupt. Название, в принципе, говорит само за себя. Более подробно читайте в статье.
- Isochronous. Гарантированные передачи через равные промежутки времени. Обычно используется для передачи аудио и видео.
- Bulk. Самый простой для реализации вариант. Применяется широко. Подробнее в статье. С ним мы и будем работать.
Проект для Keil
В результате некоторых ковыряний и копипасты с примеров, редактирования, кодинга и прочих мучений, получилось следующее:
USB_SampleSomeDevice_src.rar (зеркало 1)
Структура файлов такая же, как и во многих примерах:
\Libraries\ — папка с библиотеками (CMSIS, Standart Peripheral Driver, USB OTG Full speed Device Driver)
\Project\ — папка для проектов. Их может быть много и все они могут использовать одни и те же библиотеки. Но у нас проект один.
\Project\SampleSomeDevice\ — папка с проектом
\Project\SampleSomeDevice\Doc\ — краткие описания
\Project\SampleSomeDevice\driver\ — драйвер устройства для Windows (подробнее о драйверах и софте в ч.2, когда ее напишу)
\Project\SampleSomeDevice\inc\ — заголовки .h
\Project\SampleSomeDevice\src\ — файлы исходников .c
\Project\SampleSomeDevice\RVMDK\ — файлы проекта и выходные файлы
Распаковываем проект и открываем.
Смотрим на вкладку Project, видим там несколько групп:
User — Основные исходники проекта.
User_headers — Заголовочные файлы. Вынес в отдельную группу для быстрого и удобного доступа к ним.
USB-FS-Device_Driver — файлы библиотеки USB.
StdPeriph_Driver — файлы библиотеки стандарной периферии.
RVMDK — startup-файлы для каждой линейки контроллеров. Обратите внимание, что только один, соответствующий вашему контроллеру должен компилиться.
Doc — Краткие описания.
По умолчанию проект сконфигурирован под плату TE-STM32F103.
Конфигурируем проект
под другой контроллер и плату.
1) Надо знать название контроллера и его линейку. Поддерживаются практически все контроллеры 103 серии (кроме XL-density), а также 105 и 107 серия — Connectivity Line.
Даташиты, предварительно скачанные с сайта ST:
STM32F103x4x6.pdf (зеркало 1) — STM32 Low-density performance line (краткое обозначение LD)
STM32F103x8xB.pdf (зеркало 1) — STM32 Medium-density performance line (краткое обозначение MD)
STM32F103xCxDxE.pdf (зеркало 1) — STM32 High-density performance line (краткое обозначение HD)
STM32F105_F107.pdf (зеркало 1) — STM32 Connectivity line (краткое обозначение CL)
Все, что связано с линейкой контроллера, содержит в себе краткое обозначение.
Например, startup-файл для Medium-density performance line будет называться startup_stm32f10x_md.s
Или глобальный define для Connectivity line — STM32F10X_CL
В Keil правым кликом по Target заходим в опции, выбираем вкладку Device и ищем там свой контроллер.
Следующий шаг — выбираем используемый JTAG для прошивки и отладки.
Я использую TE-ARM-LINK, отечественный клон J-LINK.
Последний шаг в данном пункте — выбрать нужный startup-файл в группе RVMDK, соответствующий линейке контроллера, включить его в сборку проекта, отключив при этом все остальные:
Следующие пункты — настройка платы.
открываем файл platform_config.h, ищем кусок кода:
2) Узнаем куда выведен USART. Для общего развития полезно также знать, используется ли при этом ремап пинов. При включенном дефайне _DEBUG_ на него выводится различная информация, которая может быть полезна.
Открываем схему платы и смотрим. Предположим, выяснили, что выведен USART2, TX — PB5, RX — PB6.
Смотрим комментарии вначале файла platform_config.h:
Выбираем подходящий и заменяем в последнем дефайне. В данном случае это будет так:
USART сконфигурирован на скорость 115200, 8 бит, 1 стоп, No Parity.
4) Проверяем, есть ли на контроллере пин, отвечающий за программный коннект/дисконнект USB и где он расположен. Схема может выглядеть так:
Если пина нету, просто удаляем дефайны, отвечающие за него.
Вот, в принципе и все. Осталось залить прошивку в контроллер. Если есть JTAG — это не проблема.
Если оного нету, не все потеряно:
USB_DfuSe.part1.rar (зеркало 1) — Софт для прошивки STM32 Connectivity line по USB. Часть 1
USB_DfuSe.part2.rar (зеркало 1) — Часть 2
COM_FlashLoader.zip (зеркало 1) — Софт для прошивки STM32 (103 серия) по UART
Не забудьте перед прошивкой этим способом перевести девайс в DFU-Mode, корректно выставив джамперы BOOT0 — BOOT1.
О софте и драйверах я напишу в другой раз, однако уже можно скачать программу, которая общается с любым количеством подключенных девайсов с данной прошивкой:
Ковыряемся в проекте
Поскольку каждую строчку кода расписывать долго, да и исходники полны в том числе и моих комментариев, приведу здесь список основных файлов проекта и их назначение.
User:
— main.c — очевидно.
— hw_config.c — конфигурация контроллера (периферия, прерывания, клоки и так далее)
— stm32f10x_it.c — обработчики прерываний
— usb_. c — конфигурация и работа USB посредством драйвера.
— user_usb.c — пользовательская работа с USB — разбор пакетов с данными и обработка команд.
— led.c — работа со светодиодами. Включение, выключение, непрерывное мигание.
User_headers:
— platform_config.h — конфигурация платы.
Для более удобного поиска я добавил в код комментарии следующего вида:
Проект собран так, что USB-устройство, помимо нулевой контрольной, содержит 4 оконечных точки типа bulk, попарно на прием и передачу.
В проекте используются первые две, по которым при помощи несложного протокола передаются команды управления светодиодами на плате.
Краткое описание протокола можно найти в Doc\protocol.txt
И что дальше?
Ну а дальше — куда приведет фантазия. Ковырять USB рекомендую начинать с файла дескрипторов usb_desc.c, потом поиграться с ендпоинтами.
Если есть желание — можно попробовать реализовать один из стандартных классов USB-устройств, или не париться и сделать свой протокол под свои задачи.
На этом пока все. Если эта статья покажется кому-то интересной и полезной, во второй части немного напишу о драйверах и софте.
Файлы, используемые в статье собраны тут
P.S.: Хоть это и первый блин, конструктивная критика, естественно, принимается.
Читайте также: