Начало знакомства с любой вещью лучше всего начинать с инструкции. В некоторых случаях ясно все и так, в других — «хм, ничего не работает, похоже все-таки надо почитать инструкцию». Микроконтроллеры — устройства достаточно сложные, и без прочтения документации с ними уж точно ничего полезного не сделаешь, хотя…
В этой статье мы рассмотрим, как на официальном сайте производителя организована документация на микроконтроллеры STM32, в частности на серию STM32F1. Все статьи цикла можно посмотреть тут: http://dimoon.ru/category/obuchalka/stm32f1.
После каких-нибудь AVR-ок, можно испытать легкий шок от количества разных PDF-ок на микроконтроллеры STM32. Куда глядеть первым делом? Как этим пользоваться? Что ваще происходит?? С первого взгляда ни чего не понятно. Поэтому я решил сделать небольшой обзор мира документации на эти замечательные микроконтроллеры. Особый упор буду делать на STM32F103C8T6, так как далее планирую написать несколько уроков по использованию именно этого камушка.
Основными документами на STM-ки являются следующие:
Datasheet содержит в себе информацию о наличии определенной периферии в конкретном МК, цоколевке, электрических характеристиках и маркировке чипов для STM32F103x8 и STM32F103xB, то есть для вот этих, которые обведены красным прямоугольником:
Некисло, один даташит на 8 микроконтроллеров.
В первую очередь нужно обратить внимание на раздел 7. Ordering information scheme, в котором указано, то обозначает каждый символ в маркировке. Например, для STM32F103C8T6: корпус LQFP-48, 64Кб flash-а, температурный диапазон –40 to 85 °C.
Далее 2.1 Device overview. В нем есть таблица, в которой сказано, какая периферия есть в конкретном микроконтроллере и в каком количестве:
Основное различие между микроконтроллерами из разных колонок в количестве ножек и объеме флеша, остальное все одинаково. Небольшое исключение составляет первая колонка версий Tx: в этих микроконтроллерах поменьше модулей SPI, I2C и USART-ов. Нумерация периферии идет с единицы: то есть, если в STM32F103Cx у нас 2 SPI, то они имеют имена SPI1 и SPI2, а в STM32F103Tx у нас только SPI1. Так как Datasheet у нас на микроконтроллеры STM32F103x8 и STM32F103xB, то эта таблица справедлива только для этих моделей. К примеру STM32F103C8 или STM32F103CB соответствуют этой таблице, а STM32F103C6 нет, для него есть отдельный даташит.
В разделе 2.2 Full compatibility throughout the family говорится о том, что устройства STM32F103xx являются программно, функционально и pin-to-pin (для одинаковых корпусов) совместимыми.
В reference manual-е есть разделение на следующие «виды» микроконтроллеров: STM32F103x4 и STM32F103x6 обозначены как low-density devices, STM32F103x8 и STM32F103xB как medium-density devices, STM32F103xC, STM32F103xD и STM32F103xE как high-density devices. В устройствах Low-density devices меньше Flash и RAM памяти, таймеров и периферийных устройств. High-density devices имеют больший объем Flash и RAM памяти, а так же имеют дополнительную периферию, такую как SDIO, FSMC, I2S и DAC, при этом оставаясь полностью совместимыми с другими представителями семейства STM32F103xx. То есть, если на каком-то этапе разработки стало ясно, что выбранного микроконтроллера не хватает для реализации всех возможностей, то можно безболезненно выбрать более навороченный камень без необходимости переписывать весь существующий софт, при этом, если новый камень будет в том же корпусе, то отпадает необходимость заново разводить печатную плату.
Поехали далее. Reference manual (справочное руководство) содержит подробное описание всей периферии, регистров, смещений, и так далее. Это основной документ, который используется при создании прошивки под микроконтроллер. Reference manual составлен для большой группы микроконтроллеров, в нашем случае для всех STM32F10xxx, а именно STM32F101xx, STM32F102xx, STM32F103xx и STM32F105xx/STM32F107xx. Но STM32F100xx не входят в этот RM, для них есть свой.
Как было сказано выше, в reference manual-е есть разделение на следующие «виды» микроконтроллеров: low-, medium-, high-density и connectivity
line. В 2.3 Glossary разъяснено, кто есть кто:
Наш STM32F103C8T6 является Medium-density device-ом. Это будет полезно знать при изучении периферии, например, есть отдельные разделы про RCC для Low-, medium-, high- and XL-density устройств, и Connectivity line devices.
Далее обратимся к Tabe 1. В ней отмечено, какой раздел применим к конкретному типу микроконтроллеров. У нас это Medium-density STM32F103xx:
Далее все просто: идет куча разделов, в каждом из которых содержится описание на конкретную периферию и ее регистры 🙂
Programming Manual не является документом первой необходимости в самом начале знакомства с STM-ми, однако является очень важным при углубленном изучении этих микроконтроллеров. Он содержит информацию о процессорном ядре, системе команд и периферии ядра. Причем это не та же самая периферия, которая описана в Reference manual-е. В нее входят:
Как только мы начнем знакомится с прерываниями в STM32, нам понадобится раздел 4. 3 Nested vectored interrupt controller (NVIC). Ну и системный таймер является очень прикольной вещью, который будет полезен в каких-нибудь RTOS или для создания программных таймеров.
Errata Sheet — сборник всех известных аппаратных глюков и косяков микроконтроллеров и советов, как их обойти. Довольно веселый документ 🙂 Перед использованием какой-либо периферии, советую суда заглянуть. Это может помочь сократить количество потерянных нервных клеток при отладке своей чудо-прошивки, которая ни как не хочет работать 🙂
Продолжение тут: http://dimoon.ru/obuchalka/stm32f1/uroki-stm32f103-chast-2-iar-cmsis.html
Datasheet: https://www.st.com/resource/en/datasheet/stm32f103c8.pdf
Reference manual: https://www.st.com/resource/en/reference_manual/cd00171190.pdf
Programming manual: https://www.st.com/resource/en/programming_manual/cd00228163.pdf
Errata sheet: https://www. st.com/resource/en/errata_sheet/cd00190234.pdf
Небольшой рассказ о граблях, встреченных на пути познания ARM на примере stm32f103c8t6 и stm32l151rct6.
Мое знакомство с микроконтроллерами началось с AVR. Ими я занимался довольно долго, пройдя путь от плат с процарапанными дорожками и ассемблера в AtmelStudio4 до нормального лута и самописных makefile’ов для работы в блокноте (в моем случае — KWrite) и командной строке.
Но пришло время потыкать палочкой и в их старших братьев — ARM. Выбор конкретного семейства был долгим и пассивным (потому что прямой надобности нет, вот и не спешил), но в конце концов закончился на stm32f1, как самом, пожалуй, распиаренном. Покупать программатор, отладочную плату вроде Discovery или blue pill? Что вы, я же мастер по AVR-кам! Любую плату можно сделать ЛУТом, да еще так, как тебе нужно, без лишнего обвеса. Поэтому покупаю голый stm32f103c8t6 и начинаю шаманить с трассировкой платы. Что же мне понадобится? Хотя бы два порта вывести на гребенки… упс, выводить порты целиком неудобно. Да и ладно, выведу по 8 ножек — от порта A младшие (0-7), от B — старшие (8-15). Еще, конечно, светодиоды и кнопки, как же без индикации и управления. Вот что меня удивляет в готовых отладочных платах так это отсутствие хотя бы 2-3 светодиодов и 1-2 кнопок, которые бы ни с чем не конфликтовали. Как они вообще себе представляют отладку? Под кнопки сами просятся PA8, PA9, они удобно расположены. Еще пригодятся USB, джамперы BOOT0, BOOT1 и разъем батарейки для часов. И разъемы для кварцев, чтоб совсем красиво (впоследствии ни разу не воспользовался разъемами для кварцев). Для питания контроллеру нужно не более 3.6 В, а с USB идет 5 В. Надо ставить стабилизатор. Много читал, как народ выбирает стабилизаторы с низким падением напряжения… зачем? Разница полтора вольта, да тут дубового 78l33 хватит. А теперь разъем JTAG. У Atmel разъем программирования был стандартный ISP10 или ISP6. Наверное JTAG тоже штука стандартная.
Теперь чем ее прошивать. Раз есть USB, наверное, через него и умеет. Читаю даташит — ага, через USB не умеет, зато через UART1 умеет. Упс, как раз его-то я и забыл вывести. Мало того, он еще и с кнопкой конфликтует, с той что на PA9 висит. Ну да ладно, выведу на проводочках, а кнопка все равно еще одна есть. Немного шаманства и плата готова и даже определяется в stm32flash.
С железом вроде бы разобрался, пора переходить к коду. Почитав несколько статей в интернете нашел готовый архив под gcc-arm-none-eabi. Разбираться, как именно задавать последовательность сборки, буду потом. Пока что занимаюсь hello-world’ами на кнопках и светодиодах. Поскольку это мое первое знакомство с данным семейством, никаких оберток вроде HAL — только ручная работа с регистрами. Впрочем, это вполне естественный подход, как мне кажется, можно было и не упоминать. Немного напрягает все время дергать питание и BOOT0 на плате, ну да ладно, когда-нибудь сделаю JTAG-программатор. Как ни странно, на грабли с отключенным тактированием периферии не наступил. Вспомнил молодость, когда на TurboPascal’е писал обработку трехмерной графики. Здесь у меня есть дисплей на ili9341 от raspberry pi и контроллер на целых 72 МГц. Вот что получилось — до 200 точек на модель и 11 fps. Конечно же, все матрицы трансформаций считаются в числах с фиксированной точкой.
В какой-то момент захотелось сделать носимое устройство, чтобы долго работало от батарейки.
Посмотрел я в даташит и огорчился: знаменитые ARM по потреблению в разы хуже тех же AVR-ок! Если у вторых (ткнул в первый попавшийся контроллер, которым оказался ATmega88p) потребление составляет 0,8 мкА с учетом часов, то у первых даже в самом экономичном режиме сна* — 25 мкА ± 1.4 мкА на RTC. Это никуда не годится. Впрочем, stm32f103 и не позиционируется как экономичная серия. Смотрю на сайте STmicroelectronics другие серии контроллеров и выбираю серию stm32l1: помимо потребления порядка 1 мкА, там есть еще емкостный датчик и контроллер ЖКИ. Правда, максимальная частота поменьше, всего 36 МГц (или 24 МГц если используется USB), но это я как-нибудь переживу. Решено: беру пару stm32l151rct6 аж с 32 кБ оперативки (еще там 256 кБ флеша, но слабо представляю чем его можно забить. Разве что совсем диким говнокодом или массивами данных).Параллельно делаю из запасной stm32f103 программатор st-link v2, просто потому что надоело возиться с BOOT0 и питанием, да и быстрее он. Впрочем, программирование по UART оставлю — мало ли что. Там тоже было немного шаманства, но ничего выдающегося. Разве что найти командную строку для openocd оказалось проблемой. Для будущих поколений оставлю ее:
openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg -c "init" -c "reset halt" -c "flash write_image erase "$(firmware).bin" 0x08000000" -c "reset run" -c "exit"
Для stm32l151 надо, само собой, поправить target на «target/stm32l1.cfg»
Чуть забегу вперед по хронологии, но чтоб не возвращаться. Господа, не экономьте на толщине текстолита! Или хотя бы добавляйте подпорки, или не используйте smd-компоненты. Так получилось, что на плате программатора я предусмотрел всего два крепежных отверстия в рандомных местах. А места оказались довольно далеко от разъема JTAG. И через какое-то время я заметил, что программатор работает нестабильно. То работает, то нет, то через UART приходится стереть «жертву», тогда подхватит. Оказалось, что резистор, идущий от вывода контроллера к разъему, сломался.
У него просто отвалилась контактная площадка от корпуса. Резистор я перепаял. Потом перепаял остальные. Потом догадался, что даже той малой деформации платы, которая возникала при втыкании-выдирании шлейфа, хватало для несчастных компонентов. В результате воткнул подпорку прямо рядом с разъемом. Пока держит.Как читатель уже догадался, программирование все также идет в текстовом редакторе, а компиляция и прошивка — в консоли. Естественно, покупная отладочная плата под l151 меня вдохновляла не больше, чем всякие IDE. Потирая следы от граблей, оставленных первой платой, развожу вторую (считая программатор — третью, но он все-таки не отладочная плата). Раз уж собрался отлаживать энергоэффективное устройство, надо заморочиться с питанием. Стабилизатор 78l33 менять не буду, но его выход я разорвал джампером, чтобы туда можно было ткнуться амперметром (надеюсь все-таки на микроамперметр, но там уж как пойдет). Гребенки пусть будут такие же, как на предыдущей плате — совместимость! Ну и пару светодиодов и кнопок, конечно.
А вот при запаивании контроллера возникла проблема. Я как-то наивно полагал, что на корпусе микросхем должен быть ключ, обозначающий первую ногу. Кто бы ожидал, что молодцы из ST сделают ДВА ключа, симметрично. Вот и какой стороной его запаивать теперь? Подумав, я решил, что это не ключи, а технологические углубления. Мало ли, для позиционирования чипа при изготовлении, например. Или прижать основание для заливки пластиком. Тогда надо ориентироваться по надписи. Логично же, что надпись должна быть читаема если расположить микросхему «стандартно», то есть когда первая нога в левом верхнем углу. Так и начал припаивать. То ли дефект ЛУТа, то ли кривые руки, но припаялась микросхема криво, благо вовремя заметил, прежде, чем запаял целиком. Не беда, есть же старый способ отпаивания многоножек с помощью лезвия бритвы: оно не смачивается припоем и достаточно тонкое чтобы не слишком погнуть. Оказалось, руки все-таки недостаточно прямые, поскольку ножки погнулись. Но не вверх, а вбок, хорошо хоть не сильно и их удалось кое-как выпрямить. Вторая попытка запаивания шла уже под микроскопом, но прежде я решил доправить ножки. И одна из них отломалась. Из чего их делают, что один раз согнуть-разогнуть нельзя? У выводных-то компонентов такой проблемы нет. Ну все, думаю, микросхему в брак, придется запаивать другую. Но вдруг это не критичная ножка? Ну там, вывод общего назначения, или одно из питаний. Пока что запаяю без нее, а там видно будет. На этот раз удалось запаять ровно, правда ножка попала на I2C, с которым я хотел поразвлекаться, но хоть не на жизненно важные разъемы вроде USB, JTAG, UART или BOOT. Подключаю — не работает, программаторы плату не видят. Какое-то время шаманю с пропаиванием ножек, но не помогает. Блуждающий по даташиту взгляд натыкается на картинку контроллера, расположенную где-то в подвале документа. Вот как можно было придумать нанести надпись БОКОМ?! То есть если повернуть контроллер так, чтобы надпись читалась, первая нога окажется в левом нижнем углу. Попутно выяснилось, что одно из «технологических углублений» таки является ключом. Правда, не поясняется, как его отличить от симметричного… Ну, хоть какая-то зацепка. Выпаиваю контроллер строительным феном, чтобы не доломать выводы, и запаиваю на этот раз боком. Отломанный вывод попадает аккурат на TX вывод UART1, то есть на разъем программирования и отладки. Это совсем нехорошо, но перед тем, как менять контроллер, надо хотя бы убедиться что с ориентацией угадал чтобы при перепаивании на живой не убить его неправильным подключением. Подключаю программатор — работает. Ура. Остались мелочи — впаять разъемы, диоды и прочую обвязку. В комментариях подсказали еще один способ — прозвонить земли: они обычно соединены внутри корпуса и расположены не полностью симметрично. Правда, учитывая шаг выводов, попасть по нужным выводам может быть непросто. Как бы то ни было, это самый надежный способ.
Работать с контроллером без UART1 не хочется, да и хуже чем сейчас уже не будет. А если и будет, так все равно менять, поэтому принимаю решение поиграть в хирурга и сделать контроллеру протез ноги из волосинки МГТФа. Как раз под рукой валяется хороший электропроводный клей, которым волосинка решительно приляпывается к площадке на корпусе микросхемы. Тот клей, который попал на соседние ножки, безжалостно удаляется скальпелем. А что вы хотите, попасть в полумиллиметровую площадку и не попасть по соседним торчащим ножкам? Проверяю — работает. Пока не отвалилось, а чтобы не отвалилось и потом, заливаю цианакрилатом.
Возможно, так бы я этой платой и пользовался, если бы ножка не отвалилась повторно. А она залита клеем. Впрочем, он довольно мягкий и режется скальпелем, поэтому успешно счищается. Но использовать тот же электропроводный клей второй раз почему-то не хочется. Попробую-ка я ножку припаять. Обычным жалом паяльника туда не подлезть, но в комплекте шло коническое (вообще-то, коническое изначально было единственным, но ввиду его очевидной неудобности, было заменено обычным, с клиновидной заточкой), которое туда вполне подлезает. Как ни странно, «операция трансплантация» прошла успешно и ножка заработала как ей положено (фотография ножки крупным планом на КДПВ).
Итак, железо готово, пора перейти к коду. Хорошо бы найти готовый пример под gcc и библиотеки CMSIS. Что для этого подойдет лучше, чем официальный сайт производителя? Как оказалось, STmicroelectronics не разделяют моего оптимизма. То, что навигация на сайте сделана через неприличное место — уже привычно, сейчас трудно найти сайт, сделанный людьми для людей. Но они не позволяют ничего с сайта скачать! Возможно, позволили бы после регистрации, но у меня и раньше не было желания регистрироваться где попало, а после такого отношения к разработчикам — и подавно. На кой ляд вам моя почта или что вы там требуете? Собирать персональные данные, спам слать? Идите лесом, а я в свободном доступе найду! Кстати, немного удивило что соответствующего пакета не оказалось в репозитории, но, возможно, ST придумали какой-то лицензионный геморрой. Посему шлю лучи поноса маркетологам, придумавшим такую политику, да и за неудобный сайт тоже.
Как бы то ни было, библиотека прекрасно нашлась на просторах интернета (ссылки давать не буду, мало ли что с сайтом случится). Альтернативный вариант — скачать среду разработки или CubeMX, где эти библиотеки вшиты. Правда, скачать их с официального сайта точно так же невозможно, так что ищем на сторонних и устанавливаем на виртуалку, просто на случай «если вдруг что».
С железом разобрались, с сорцами тоже. Пришло время разбираться наконец с контроллером. Первый сюрприз ждал при попытке воспользоваться сторонним кодом под Discovery. Там применен контроллер stm32l152, который на первый взгляд почти не отличается от stm32l151, установленного у меня. Помимо мелких отличий, оказалось, что в «мой» контроллер не установлен модуль ЖКИ. Немножко обидно, но я все равно не планировал им пользоваться. Хотя вот такое различие могли бы и более явно выделить, чем сносочкой в даташите. Кстати, в даташите рекомендуется в таком случае соединить вывод VLCD с питанием, у меня на фотографии соответствующий 0-омный резистор не запаян, но в реальности я его все же установил. Без него тоже работает, но не стоит перегружать внутренние соединения. Более интересным оказалось поведение часов реального времени. Они упорно не хотели работать, причем в интернете пишут просто «делай так, делай так, оно работает». А оно не работает. Кое-где, впрочем, упоминалось об «известных проблемах с RTC в данной серии». Как бы то ни было, часы все же завелись, правда, только на встроенном RC-генераторе. Попытки запстить часовой кварц приводили к бесконечному ожиданию бита готовности LSE. Я попытался проверить не отвалились ли ножки микросхемы от дорожек на плате и подергал ими в режиме обычных GPIO. Отвалился высокочастотный кварц. WTF?! В общем, вместе эти два кварца работать не желают, но хотя бы по отдельности худо-бедно функционируют.
И тут я догадался: суперклей, которым была залита половина контроллера (он ведь жидкий, его точечно не нанесешь, да и кто бы мог подумать…), дает утечку и кварцы своими наводками мешают друг другу. Ну, снаружи отскрести клей нетрудно, но ведь он затек даже под низ микросхемы. И если утечек по нему достаточно для кварцев, это ведь и на потреблении скажется. Ищу в гугле, чем люди удаляют цианакрилат. Предлагается теплая вода (что???) и диметилсульфоксид. В теплую воду я не верю, поэтому покупаю ДМСО. После более чем часового нахождения капли химиката на поверхности клея, разницы я не заметил. Зато заметили кварцы и стали работать более-менее нормально (интересно, почему? Димексид вытеснил влагу, впитанную клеем?). Впрочем, меня это не убедило, да и остатки клея все равно мозолят глаза… даром что находятся на нижней стороне платы и особо не видны. Кстати, теплая вода, которой я смывал димексид, на клей не повлияла (я не удивлен). Обнаружил, что существует такая штука, как удалитель клея, в таком же тюбике, как и сам клей, только фиолетовом. Ну хоть она-то должна сработать! Как оказалось, она может и работает, но по консистенции напоминает сметану и под микросхему просто не лезет. Ну и толку с тебя, удалитель?! Снаружи я и так почистить могу. Последний шанс: изредка упоминается ацетон. Немножко опасаюсь за пластиковые детали, но как раз их заменить несложно. Заливаю ацетон в стеклянную банку, кидаю туда плату и оставляю на ночь. Наутро выяснилось, что ацетон и правда работает, да еще как! От клея не осталось и следа. Мало того, растворился толкатель одной из кнопок. Что интересно, вторая уцелела, наверное, была сделана из более устойчивого пластика. Немного удивлен был, что и прочий пластик остался нетронутым, даже надписи уцелели. Ну и отлично, а кнопку можно и заменить.
Вот теперь удалось запустить и RTC от часового кварца, и режим сна потрогать, да и с другой периферией пообщаться. А еще, чтобы совсем фен-шуйно было, нанес подписи на плату. Но не маркером (вдруг снова купать в растворителях?) а процарапал скальпелем. На века!
Ну и для будущих поколений оставлю примеры кода для обоих контроллеров, вместе с библиотеками, makefile’ами и прочим. Останется только установить gcc-arm-none-eabi, openocd, stm32flash и прочую мелочь.
stm32f103
stm32l151
В комментариях несколько раз советовали не заниматься ЛУТом и заказать изготовление плат у профессионалов. Для прототипирования, как здесь — не вижу смысла. Другое дело, если нужны будут многослойный платы, или еще меньший шаг, или BGA-корпус, или еще что-то, что в домашних условиях сделать сложно. И, разумеется, при изготовлении финальной версии устройства и тиражировании. Нехорошо, если заказчик разберет корпус, спаянный из текстолита, и обнаружит криво отпиленню плату без маски и с перемычками из МГТФ.
Выводы:
Опубликовано
.Mikron MIK32 — это 32-разрядный микроконтроллер RISC-V, сделанный в России, с функциями, аналогичными микроконтроллеру STMicro STM32L0 Cortex-M0+, который показывает, как архитектура с открытым исходным кодом RISC-V может помочь снизить барьер для входа и позволить большему количеству компаний проектировать собственные фишки.
Микроконтроллер MIK32 оснащен CPU IP от Syntacore из Санкт-Петербурга по профилю RV32IMC. MCU с тактовой частотой 32 МГц поставляется с интерфейсами I2C, UART, SPI, ADC, DAC, а также различными таймерами, контроллером прерываний и многим другим.
Mikron MIK32 технические характеристики:
Микрон также разработал макетную плату с модулем MIK32, несколькими реле, кнопками, DIP-переключателями конфигурации, RS232/RS485 и поддержкой четырех плат расширения с добавлением Bluetooth, WiFi, GSM, NB-IoT, Zigbee, RFID и/ или Ethernet к плате.
Mikron MIK32 подходит для счетчиков газа/воды и промышленных датчиков, медицинского и фитнес-оборудования, пультов дистанционного управления и пользовательских интерфейсов, а также периферийных устройств для ПК, игрового и GPS-оборудования.
Микроконтроллер MIK32 RISC-V продается за 450 рублей или около 6 долларов, но я не уверен, это цена за единицу или количество. Компания просит заинтересованные стороны связаться с ними, чтобы приобрести микроконтроллер или макетную плату. Более подробную информацию можно найти на сайте компании. Все на русском, кроме описания товара на английском с основными характеристиками.
Via Florian Woh
Жан-Люк Офранк (CNXSoft)
Жан-Люк основал CNX Software в 2010 году в качестве подработки, прежде чем оставить работу менеджера по разработке программного обеспечения и начать писать ежедневные новости и обзоры. полный рабочий день позже в 2011 году.
Поддержка программного обеспечения CNX! Пожертвовать через криптовалют или стать покровителем на Patreon
Тегиразвитие, mcu, risc-v, россияНаряду с этим волнением возникает вопрос, вызовет ли что-либо из этого какие-либо серьезные потрясения для тех из нас, кто использует STM32, SAM и другие микроконтроллеры на базе Cortex-M. Возможно, RP2040 подойдет для некоторых наших проектов? Поскольку RP2040 представляет собой микроконтроллер с двумя процессорами Cortex-M0+, кажется справедливым сопоставить его с предложениями одного из нынешних тяжеловесов в области 32-битных микроконтроллеров ARM: ST Microelectronics.
Удалось ли крохе Raspberry Pi Foundation показать инженерам ST, как это делается, или первым следует пересмотреть некоторые из своих предположений? И насколько сложно будет перенести низкоуровневый код с STM32 на RP2040?
Короче говоря, после того, как RP2040 попался мне на глаза, я подумал, что было бы интересно попробовать перенести мою платформу STM32 на основе C++ на этот новый MCU. Однако не так много для двух ядер Cortex-M0 +, поскольку у меня есть двухъядерные микроконтроллеры STM32H7 (M4 и M7), которые легко превзойдут начинку RP2040 с большим количеством операций ввода-вывода. Что меня больше всего заинтриговало, так это периферийное устройство конечного автомата (PIO) в RP2040, которое казалось достойным более пристального внимания.
Основываясь на своем опыте работы с STM32, я решил, что могу быстро перенести некоторые файлы, создать в проекте новую архитектурную ветку «RP» и отправиться в гонку. Cortex-M — это Cortex-M, верно? Обычная процедура с новым микроконтроллером на базе ARM заключается в получении спецификаций, справочного руководства и файлов устройства CMSIS. После этого можно легко адаптировать низкоуровневый код для использования новой схемы именования и регистрации периферийных устройств, в то время как устройства уровня ядра (SysTick, NVIC и т. д.) останутся прежними.
Возможно, по наивности я разместил заказ на плату Raspberry Pi Pico еще до того, как проверил поддержку CMSIS или взглянул на справочное руководство. К моему удивлению, я обнаружил, что поддержка CMSIS или даже совместимость с остальной частью экосистемы Cortex-M еще не рассматривались. Тем не менее, файл SVD для MCU RP2040 предоставляется в «Pico SDK», который можно использовать для создания заголовка устройства. Благодаря усилиям Криса Хокубы по начальной загрузке CMSIS с помощью RP2040 у меня в конце концов появилось совместное рабочее решение.
В проекте STM32 есть несколько элементов, необходимых для того, чтобы проект на «голом железе» работал на целевом MCU. К ним относятся стартовый код, выполняющий некоторые базовые настройки среды, а также таблица векторов для обработчиков прерываний. Существует также скрипт компоновщика, чтобы убедиться, что все биты в конечном итоге находятся в правильном смещении памяти. Все это довольно минимально: MCU при загрузке загружает образ прошивки из Flash ROM по адресу по умолчанию.
Первая трудность при работе с RP2040 — это понимание связанного с ним процесса загрузчика. Как и в случае с загрузочными гибкими дисками прошлого или жестким диском / твердотельным накопителем в ПК, внешнее флэш-ПЗУ QSPI рассматривается MCU как потенциальное загрузочное устройство. Загрузчик первого этапа интегрирован в MCU в загрузочном ПЗУ, адрес 0x0000 0000, который при загрузке проверяет интерфейс QSPI, пытаясь загрузить из него 256 байт. Это будет проверено на действительное совпадение хэша CRC32 и предполагается, что это загрузчик второго этапа, если он совпадает.
Есть много вещей, которые может сделать этот загрузчик второй стадии, и некоторые из них необходимы. Пока достаточно сказать, что по сравнению с некоторыми известными клонами STM32, такими как клоны GigaDevices , я не могу поверить, что это не подлинный STM32 , которые также используют ПЗУ SPI, весь этот процесс с RP2040 не настолько интуитивен, хорошо документирован или прозрачен, как мог бы быть, с множеством камней преткновения.
Мне потребовалось немало времени, чтобы покопаться в техническом описании RP2040 и выяснить, как диспетчер периферийных часов в STM32 соотносится с системной архитектурой RP2040. Как оказалось, версия RP2040 называется RESETS и работает в основном наоборот: вам нужно снять условие сброса для блока, чтобы включить для него часы. Чтобы включить часы GPIO, вы должны переключить бит 8 в RESETS_RESET (PADS_BANK0).
Блок-схема контактной площадки GPIO RP2040.Вот и разобрался, посмотрел в документации раздел периферии GPIO (раздел 2.19). Одно сразу бросается в глаза: это полностью отличается от STM32, AVR, SAM и большинства других периферийных устройств GPIO, которые я когда-либо видел.
В то время как большинство чипов имеют один или два регистра для каждой функции, и вы перемещаете в них биты, чтобы активировать эту функцию для определенного контакта, RP2040 имеет регистр для каждого контакта, и вы перемещаете биты в место, которое определяет функцию. Это уникальный выбор, и мне пришлось написать специальный код для поиска адреса памяти регистров управления для каждого вывода.
После всех этих усилий, конечно же, это сработает, верно?
Как упоминалось ранее, загрузчик второго уровня должен располагаться в начале образа прошивки. Поскольку я решил, что это должен быть какой-то общий код, я просто взял готовый к использованию код ASM, который был выложен официальным PicoSDK, при создании примера Blinky
. С добавлением этого в порт узла RP2040 пример Blinky
построен без проблем.
Перепрошивка полученного двоичного файла ELF на RP2040 была следующей проблемой, поскольку на плате Raspberry Pi Pico нет встроенного SWD-адаптера в стиле ST-Link, а для двухъядерного микроконтроллера Cortex-M требуется многопроцессорный сбросьте SWD-адаптер. Пока что единственные многоточечные SWD-адаптеры, которые у меня есть, интегрированы в платы STM32H7 Nucleo. Поэтому я решил использовать пользовательский форк OpenOCD, созданный Raspberry Pi Foundation, запустив его на Raspberry Pi SBC.
Со всем этим я успешно прошил прошивку на RP2040 и… абсолютно ничего не получил. При беглом осмотре выяснилось, что код так и не прошел начальный загрузчик и не попал в фактическую прошивку в SPI ROM. Трудно сказать, связано ли это с проблемой, связанной с ASM загрузчика второй ступени, с экспериментальными файлами CMSIS RP2040, которые мне пришлось позаимствовать у кого-то еще, или с чем-то совершенно другим.
Потратив довольно много часов на то, чтобы заставить RP2040 работать с голым железом, используя собранные вместе файлы CMSIS и загрузчика второго этапа, пришло время сделать несколько шагов назад и переоценить. С момента моей первоначальной оценки RP2040 запрос функции CMSIS в трекере Pico SDK был радостно обновлен предложением о том, что официальная поддержка CMSIS может быть добавлена в версии 1.2.0 Pico SDK.
Я думаю, что всем, кто хочет познакомиться с RP2040 с помощью стандартных инструментов, имеет смысл дождаться этого релиза.