Вокруг EFM32 - обзор библиотек и софта

EFM32
В прошлой статье я делал выписку из даташитов на контроллеры EFM32 и STM32L, так что с тем, что нам обещают даташиты на EFM32 мы уже худо-бедно ознакомились. Сейчас я устрою краткий ликбез на тему пользования этими контроллерами и построенной вокруг них инфраструктурой. Далее планируется ещё пара статей, где я постараюсь дать более детальное представление о внутренностях EFM и провести очень скромное сравнение с STM32L на реальной железке. В принципе, почти всю эту информацию несложно найти на ресурсах EnergyMicro, так что на первооткрывательство не претендую, основная цель написания — попытаться заткнуть (ну точнее прикрыть =)) информационный вакуум по данным контроллерам среди русскоязычных около-электронных сайтов, а то по результатам беглого гугления может показаться, что EFM это нечто совсем экзотическое и никем не используемое.

NOTE: У меня на столе стоит два компа: один с виндой, второй с линухом и использую я их одновременно, так что не удивляйтесь, если в процессе повествования буду без предупреждения перепрыгивать между виндовс-специфичными вещами и линукс-специфичными.

1. Инфраструктура.


Для начала глянем, что нам предлагают для облегчения жизни, так сказать, проведём ревизию. Вот небольшой экскурс по интересным разделам официального сайта:
  • Реклама из серии «почему мы считаем себя крутыми», там же, в подразделах, можно найти обзорную информацию по ядрам Cortex-M, режимам работы/сна и всем блокам периферии.
  • В разделе Продукты нет ничего особо интересного, кроме ссылок на заказ самплов (ну ещё на скачивание даташитов, но это не особо нужно).
  • Раздел Downloads тоже нафиг не нужен, за исключением большой зелёной кнопки с надписью Simplicity Studio.
  • Логово ящериц — пожалуй самое интересное место на сайте, форум где тусят люди из EM, вплоть до непосредственно разработчиков чипов. Весьма приятная обстановка, оперативные ответы на вопросы. Плюс именно от туда пока нужно качать софт под Linux и MacOS.
  • Видео-уроки — набор неплохих презентаций, рассортированных по уровням и снабженных комментариями и уроками. Рекомендую к просмотру презентации третьего уровня и выше.
  • Официальный блог — весьма странное место по сочетанию разного контента (там даже есть статьи на тему «Основы С»), но попадаются и интересные материалы.
  • Онлайн версия документации на API. В дальнейшем я буду на неё ссылаться, хотя есть риск, что после обновления emlib все ссылки сломаются.

С чего начать? Ну это зависит от начальных условий. Лично я начал с кнопки Samples ;). Сразу отмечу ограничения — всего 2 одинаковых чипа за раз, не более двух раз в месяц, плюс не любят gmail, hotmail и иже с ними (ну это если верить тому, что они сами пишут).

Теперь вернёмся к большой зелёной кнопке и скачаем приятную мелочь — Simplicity Studio. Качаем, ставим, запускаем. Нет, это не спец-IDE, как кто-то может быть подумал. Это скорее, как ныне модно выражаться, система доставки контента. Вот что она умеет:
  • скачивать документацию, апноты, исходники, вспомогательные утилиты и прочую требуху (ВНИМАНИЕ! В полной комплектации в разархивированном виде почти 2Gb, более 25 тысяч файлов);
  • автоматически проверять обновления всего этого добра;
  • искать нужный парт в базе по имени или параметрам;
  • показывать документы, относящиеся к выбранному парту;
  • открывать документы во внешнем софте;
  • показывать новости с оф. сайта;
  • запускать дополнительные утилиты.
Главное окно Simplisity StudioВыбиралка камня в Simplisity Studio

Дополнительных утилит четыре штуки:
  1. energyAware Designer — можно сказать, необходимый инструмент для любого современного контроллера — планировщик распиновки:
    • отображение распиновки корпуса для выбранного чипа EFM32, причём можно смотреть с топа и с боттома
    • выбор и настройка блоков периферии
    • выбор используемых пинов для блоков периферии
    • подсветка конфликтующих пинов (пинов, которые используются несколькими блоками) и блоков
    • сводная таблица по функциям всех пинов/задействованным функциям
    • подсказка по режимам работы пина для выбранной функции
    • генерация *.c-файла с командами конфигурирования выбранных блоков в соответствии с указанными настройками
    • зум, пан, сохранение, загрузка, печать, экспорт в PDF.
    energyAware Designer
  2. energyAware Commander — инструмент для непосредственной работы с чипами и отладочными платами через отладчик J-Link.
    • Работает через динамическую библиотеку от Segger, поставляемую в комплекте
    • Считывает информацию о камне (полный партнамбер, ревизию, количество памяти, уникальный ID) и, если это кит, о плате
    • Заливка прошивки по указанному адресу и запуск её на исполнение (через reset)
    • Установка/снятие защиты флеша от записи
    • Блокировка/разблокировка отладочного интерфейса (разблокировка возможна только с использованием кита!)
    • Заливка в кит готовых примеров из списка.
    • Обновление firmware в китах.
    • Работа из командной строки (CLI, пригодный для скриптования)
    • Консоль для вывода отладочных сообщений через SWO
    • Захват скриншотов с TFT экрана (подозреваю, что только на DVK)
    energyAware Commander
  3. energyAware Profiler — пожалуй, самый интересный инструмент пакета — профайлер энергопотребления (динамический анализ потребления).
    • строит график потребления тока устройства в реальном режиме времени на основе измерений специального модуля, установленного на отладочных платах (AEM — Advanced Energy Monitor)
    • опционально, строит график питающего напряжения
    • частота семплирования до 6,25kSps (для китов LG/GG/WG), диапазон измерений от 0.1мкА до 50мА
    • можно использовать как для измерения тока потребления кита, так и с внешним девайсом
    • отображение графика в реальном времени
    • сопоставление точек на графике измерений с участками исходного кода программы
    • поиск горячих точек с ранжированием
    • подсчёт среднего потребления за выбранный период времени
    • экспорт графика в CSV
    • подсчёт скушанной мощности в реальном времени
    energyAware Profiler
  4. energyAware Battery — софтина, позволяющая примерно оценить суммарное энергопотребление разрабатываемого девайса и время жизни от батареи на основании режимов работы и используемой периферии. В основу программы заложено предположение, что устройство имеет строго определённые циклы работы и их длительность постоянна.
    • возможность создавать множество состояний с независимыми режимами работы периферии
    • для каждого режима можно задать ток потребления внешней схемы
    • схематичное отображение тока потребления в течении одного цикла
    • выбор типа батареи, и количества элементов в сборке
    • подсчёт среднего потребления и построение графика уровня напряжения на сборке от времени
    energyAware Battery - описание устройстваenergyAware Battery - отчёт о времени жизни

Сразу хочется пройтись по этим инструментам с критической точки зрения — все они далеки от идеала, косоватостей хватит на годы допиливания.

  1. Simplicity Studio
    • Несмотря на использование Qt в качестве основы, с кроссплатформенностью у них пока туговато — линусковая и маковая версии несколько уступают по функционалу виндовой, в частности отсутствует интеграция с eA-утилитами.
    • Под виндой накачанное добро складывается где-то в глубоких дебрях каталога
      «Documents and Settings» (вообще-то в конфиге есть соответствующая настройка, но при её изменении, говорят, ломается самообновление)
  2. energyAware Designer
    • откровенный косяк всего один — нельзя задавать собственные имена для пинов
    • ряд мелких недоработок в плане юзабилити (ну, например, по дабл-клику на пин хорошо бы выводить полный список модулей, которые могут этот пин использовать, диалоги настройки периферии кривые и прочие мелочи, нет списка недавних файлов)
  3. energyAware Commander
    • явно не хватает опций для чтения и полного стирания флеша
    • работает только с форматом bin — iHEX не умеет
  4. energyAware Profiler
    • абсолютно бесполезен если нет фирменного кита, так как схем и прошивок на AEM в открытом доступе нет
    • программа явно сырая — под линухой периодически падает и ведёт себя слабоадекватно
    • говорят, изрядно тормозит при работе с большими программами
  5. energyAware Battery
    • поддерживается только базовое семейство контроллеров — Gecko
    • номенклатура известных программе батарей весьма узка и свои добавлять нельзя
    • количество батарей в сборке ограничено тремя последовательными и тремя параллельными элементами

2. Работа с контроллерами.


2.1. Железо.
Как обычно, начинать знакомство с камнями можно с готового дев-кита, либо с самопальной платы. Если вы, как и я, предпочитаете начать сразу с разводки, тот тут вам в помощь апноты 0002, 0016, а также, по необходимости, 0011, 0034, 0036, 0040, 0046, 0053 и прочие. Впрочем, стартёр-китом обзавестись всё равно не помешает, причём, желательно нового поколения (LG, GG, WG — у старых AEM более тормозной). Основные три аргумента за наличие хотя бы какого-то кита (из официальных, естественно), которые у меня сформулировались в процессе первых экспериментов с моей платой в порядке уменьшения важности:
  • возможность сравнить потребление на моей плате с неким эталоном
  • возможность воспользоваться eA профайлером
  • возможность анлочить случайно залоченный чип
Кроме того, на всех китах установлен халявный, лицензионный Jlink, который можно использовать для прошивки/отладки внешних чипов, правда ограниченный на работу только с EFM.

NOTE: лирическое отступление на тему лоченья — довести камень до состояния «без кита не перепрошьёшь» можно как минимум четырьмя способами: в самом начале программы выключить тактовую процессора (или переключиться на отсутствующий кварц), отключить отладочные пины, или войти в режим EM4, либо просто отрубить SWD при отсутствующем бутлоадере. Впрочем, именно кит тут не обязателен, ничего секретного в анлочинье нету — при желании можно и свой велосипед сгородить. Подробнее см. в форуме.
На схемотехнических нюансах я подробно останавливаться не буду, всё достаточно неплохо описано в вышеперечисленных апнотах, отмечу лишь, что в EFM32 нет уже ставшего привычным интерфейса JTAG — только SWD, а значит работать с ним могут не все подряд АРМовские отладчики, в частности под линуксом с SWD вообще проблемы (на данный момент даже и не знаю, что можно использовать кроме JLink+eA Commander, но скоро должен подтянуться OpenOCD).

2.2. Бутлоадер.
Ещё пара слов по поводу заливки прошивки: как я уже писал в прошлый раз, все чипы приходят с завода с заранее прошитым бутлоадером. Так же, как и в STM32, бутлоадер умеет бутаться по USART0 и, если есть USB, по USB-CDC и умеет авто-определение скорости передачи. Для входа в бутлоадер надо дёрнуть определённой ножкой в момент перезагрузки. Собственно, на этом сходства и заканчиваются, далее сплошные различия: во-первых в EFM бутлодер располагается не в ROM, а во флеш, что означает, что бутлоадер можно перезаписать (причём, даже из самого бутлоадера), но программы для использования с ним надо линковать с учётом того, что находиться они будут не по дефолтовому адресу. Во-вторых, если у STM протокол бутлоадинга бинарный, то тут простой текстовый с передачей данных по XMODEM, то есть ручками заливать можно почти из любой терминалки, а вот с автоматизацией проблемы. Как следствие, практической ценности в этом лоадере именно по прямому назначению не много: для quickstart`а неудобно, потому что надо править скрипты линкера, а для мелкого продакшена неудобно, потому что вместо того, что бы тупо вписать в батник/шеллник вызов некой консольной проги с нужными ключами, надо писать скрипты для какой-то умной терминалки. Зато с другой стороны, позволяет хоть как-то работать с камнем без отладчика, не занимает лишнее место на кристалле (хотя его, похоже, нынче не экономят — вон техас вообще библиотеку периферии в ROM запихнул) и экономит батарейки только что собранного, но ещё не зашитого устройства (с AVR'ками и ST'шниками нам приходилось инструктировать сборщиков, что бы втыкали батарею только непосредственно перед зашивкой). Плюс оно является неплохим апнотом для реализации собственного лоадера (кстати, среди апнотов есть ещё пара вариантов бута — модификация того же бутлоадера с использованием AES и бутлоадер на базе USB Mass Storage Host). Подробности от том, как пользоваться лоадером и как собирать проги для загрузки через него см. в AN0003, USB-специфичные вещи живут в 0042, а про альтернативные лоадеры читать в 0052 и 0060.

2.3. IDE.
В качестве среды разработки чаше всего предлагается использовать IAR, KEIL и Eclipse, причём для последнего есть даже отдельный апнот (0023) с описанием как его подружить с CodeSourcery собственными руками. Из готовых вариантов Эклипса лично я пробовал CooCox CoIDE и Atollic. Первый, как оказалось, умеет только базовое семейство и идёт с доисторическими библиотеками, так что с ним куча гемора перед работой требуется. Второй по-продвинутее, но у меня была не самая свежая версия со слегка устаревшей библиотекой, в которой функции реализованы без инлайна. При попытке обновиться у меня слетела бесплатная лицензия и восстановить её не удалось, пришлось заново региться. Зато в версии TrueSTUDIO 4.0.1 библиотека emlib даже свежее, чем была в Simplicity Studio и на сайте EnergyMicro (3.0.3 — Internal release for testing Wonder Gecko support — отличается от 3.0.2 добавлением функции для управления доступом к FPU и функции чтения и записи байта по SPI).
Вообще, я не сторонник таскать в своём проекте исходники библиотеки и каждый раз её пересобирать, предпочитаю как в AVR-libc иметь собранные бинарники и линковать тот или иной в зависимости от того, какой камень используется. Такой подход в своё время предлагал Kosyak для работы с STM32F1. Я взял его скрипты и на их основе сделал скрипты для работы с EFM32. Пользуясь случаем, передаю большое спасибо товарищу Kosyak. Кстати, cmake, используемый для сборки библиотек, хорош ещё тем, что умеет генерить файлы проектов для разных IDE, в том числе и для моего любимого Code::Blocks. Так что сейчас я использую для работы с EFM cmake и C::B, правда без отладки и под линухом (отладку не пробовал делать, под виндой не тестил). В планах есть ещё написать визард для генерации проектов Code::Blocks более классического стиля, но это, видимо, не скоро.

3. API.


3.1. Обзор.
Итак, у нас есть некая плата с контроллером EFM32, некое железо, необходимое для заливки туда прошивки и какая-то система, способная эту самую прошивку собрать из исходников на C. Теперь я постараюсь немного описать, что нам дают, что бы программу написать. Конечно я буду подразумевать, что используется библиотека периферии, любители сырых регистров и сами разберутся, тем более, что библиотека эта реализована весьма качественно. Библиотека периферии у EnergyMicro называется emlib и едина для всех выпускаемых семейств контроллеров (в отличие, например, от ST, у которой на каждое семейство своё API, местами весьма сильно различающиеся). Сначала эта библиотека называлась что-то в стиле efm32lib, но потом они сообразили, что радиомодули у них будут называться efr4 и переименовали все файлы на использование более общего префикса em. Я буду использовать актуальную на текущий момент версию библиотеки 3.20.0.
Структура библиотеки следующая:
  • CMSIS — собственно, заголовки CMSIS'а (v3.0.1) и библиотека функций DSP с исходниками и примерами.
  • Device — набор заголовков с дефайнами и тайпдефами, описывающими камни, а также файлы system_*.c, стартапы и сборочные скрипты для GCC.
  • emlib — исходники библиотеки периферии, являющиеся обёртками над предыдущими двумя пунктами.
  • emdrv — драйвера более высокого уровня, чем функции emlib. На момент написания статьи там было два драйвера — диспатчер для прерываний от GPIO и драйвер для использования внутреннего флеша для хранения данных.
  • usb — библиотека для работы с USB.
  • reptile — небольшая пачка дополнительных библиотек (в основном сторонних), включая драйвер FAT, сеггеровский emWin, а так же адаптированные под tickless режим FreeRTOS и Keil RTX.
Кроме каталогов с собственно кодом SS тащит ещё несколько, в том числе:
  • an — апноты, уроки и прочая техническо-справочная информация. Что приятно, помимо в составе апнотов помимо описания в pdf и сырцов идут файлы проектов для сборки разными тулкитами, в том числе и мейкфайлы для gcc разных сборок
  • doc — как следует из названия, документация — даташиты, эррата, референс мануалы и тд.
  • kits — материалы по китам, в том числе исходники bsp, примеры, собранные прошивки для быстрой загрузки, схемы и чертежи плат (правда с документацией не совсем однозначно — часть её лежит в doc, а часть тут).
Каталоги usb и reptile пока обойдём стороной — там ещё на пару статей писанины хватит. Для каждодневной работы будут интересны каталоги CMSIS, Device и emlib, о них и постараюсь рассказать. Ну ещё немного коснусь emdrv.
Кстати, следует отметить один немаловажный момент — код emlib поставляется под BSD-подобной лицензией, что, в купе с недавним переводом CMSIS на лицензию BSD, делает emlib полностью пригодным для использования OpenSource проектами, в том числе и распространяющимися под вирусной лицензией GPL (говорят, у других представителей Cortex-M с этим проблемы, хотя я сам не вдавался в подробности). С другой стороны тут надо быть внимательным — практически весь код, что за пределами CMSIS и emlib имеет другую лицензию, отличающуюся от emlib`овской одним пунктом — ограничение на использование только с контроллерами от EnergyMicro.

3.2. CMSIS.
CMSIS он и в Африке CMSIS, он одинаковый для всех камней на базе Cortex-M (разумеется с поправкой на используемую версию), но, тем не менее, для тех, кто в танке, сказать пару слов о нём надо. Итак, Cortex Microcontroller Software Interface Standard, как следует из названия, это прежде всего стандарт на интерфейс к железу камня, но, вместе с тем, это ещё и набор дефайнов и функций, относящихся непосредственно к ядру (CMSIS-CORE), плюс библиотека математики (CMSIS-DSP) и некий CMSIS-RTOS API. К теме данной статьи относится только ядро. CMSIS-CORE живёт в каталогах CMSIS/Include и Device, который будет рассмотрен чуть ниже. В инклуде расположен почти десяток заголовков с префиксом core_, о которых простому смертному и знать не обязательно — они инклудятся автоматически и используются внутри библиотеки. Но есть там и несколько повседневных функций, про которые знать необходимо: NVIC_EnableIRQ/NVIC_DisableIRQ, NVIC_SetPriority, ну и вообще весь соответствующий модуль. Кроме того, полезно знать про __enable_irq/__disable_irq, __WFI/__WFE, __NOP. Впрочем, ознакомится с остальными разделами документации всё равно не лишне будет — вполне может и понадобится в определённых условиях.

3.3. Device.
Как завещал великий CMSIS в каталоге Device живут описания камней и код инициализации. Согласно рекомендациям там находится каталог, называемый именем вендора, в котором по каталогу на каждое семейство камней. В каждом каталоге семейства есть подкаталоги Include и Source. В Source, как я уже сказал, лежит system_efm32xx.c и компиллеро-специфические стартапы.
NOTE: GCC и G++ — это не сишный и крестовый компиляторы, а разные сборки gcc (под G++ подразумевается Sourcery CodeBench, а GCC — это, например, GNU Tools for ARM Embedded Processors).
Модуль system_efm32xx содержит исключительно функции работы с тактовыми частотами и именно ему следует сообщать о том, какую частоту имеют внешние тактовые сигналы. Сообщается это с помощью дефайнов EFM32_HFXO_FREQ и EFM32_LFXO_FREQ. По умолчанию HFXO считается равной 32 или 48МГц в зависимости от семейства, а LFXO — 32.768кГц. Если задефайнить одну какую-нибудь из этих констант в 0, то считается, что соответствующего источника тактовой нет и часть кода не собирается. Данные константы являются старт-ап значениями соответствующих тактовых частот, но их можно менять в рантайме. Кстати, забавно, что в отличие от ST-ного кода, функция void SystemInit(void) хоть и объявлена, но реализована пустой.
Что касается заголовков, хочется отметить, что индусы программеры из ST не стали мудрствовать и сделали один заголовок, в котором перечислили все регистры и соответствующие константы, которые бывают в данном семействе камней. То есть, за тем, какие именно блоки есть в данном конкретном камне программер должен следить самостоятельно (что, кстати, не очень просто с учётом качества их документации). Сотрудники EM пошли другим путём — они наплодили бешеную кучу заголовков, в которых чёрт ногу сломит, зато если Вы задефайните, что используете камень EFM32xxx, то можете быть точно уверенными, что используете только те блоки периферии, которые реально присутствуют в этом камне — иначе не соберётся.
Структура заголовков с описанием периферии камней следующая: из пользовательского приложения инклудится файл em_device.h, а в сборочных скриптах дефайнится константа в стиле -DEFM32LG232F256. В em_device.h куча elif'ов которыми на основе заданного дефайна инклудится файл с соответствующим названием (в данном случае efm32lg232f256.h). В файлах efm32xxx.h первым делом описывается конфигурация чипа — перечень прерываний, наличие и количество разных системных блоков и блоков периферии, объём и конфигурация памяти, причастность к семейству (NOTE: LG и GG относятся к одному и тому же семейству — _EFM32_GIANT_FAMILY). Далее идут описания регистров, их битовых полей, адресов и прочей пурги. Большая часть этих описаний вынесена в отдельные заголовки с именами типа efm32lg_usart.h, но не всё в эту систему вписывается и периодически в файле чипа вместо инклуда появляется портянка энумов и дефайнов — в основном это касается блоков CMU, PRS и DMA.
Описание блока периферии включает объявление структуры типа USART_TypeDef, перечисляющей все регистры и описание битовых полей для этих регистров. Описание битовых полей реализовано толпой дефайнов — на каждое поле длиной 1 бит от четырёх до девяти констант, на более длинные, соответственно, ещё больше. Важно понимать, как формируются названия этих констант. Почему важно? Да потому что АПИ emlib покрывает далеко не все возможности камня и даже в самых простых программах возникает необходимость прямого обращения к регистрам, а не зная правил формирования мнемоник можно сильно запутаться.
Попробую в общих словах описать схему выделения констант на примере регистра CTRL блока USART.
Главное, что надо запомнить: значения, начинающиеся с подчёркивания — это значения битового поля, а те, что без подчёркивания — значения регистра (то есть значение поля, сдвинутые на величину смещения этого поля). Но это только для значений — если саму величину смещения (SHIFT) ещё можно как-то отнести к битовому полю, то вот маски явно относятся к регистру целиком, так как уже сдвинуты и почему они тоже начинаются с подчёркивания мне лично не понятно.
Фрагмент файла описания регистров
Для каждого регистра определяются маска, показывающая, какие биты в этом регистре используются, а какие типа Reserved, и значение, устанавливаемое после резета. Имена этих констант для нашего случая будут _USART_CTRL_RESETVALUE и _USART_CTRL_MASK. Для каждого поля так же определяются маска (_USART_CTRL_SYNC_MASK) и значение по умолчанию (_USART_CTRL_SYNC_DEFAULT), плюс положение этого поля в регистре (битовый сдвиг — _USART_CTRL_SYNC_SHIFT). Остальные две константы для однобитового поля — это значение по умолчанию, сдвинутое на нужную позицию (то есть значение, которое можно присваивать регистру — USART_CTRL_SYNC_DEFAULT, без подчёркивания в начале) и, единичка, сдвинутая на нужную позицию (значение бита, которое можно присвоить регистру — USART_CTRL_SYNC, тоже без подчёркивания). Если битовое поле более длинное, то вместо последней константы дефайнятся значения всех возможных комбинаций (_USART_CTRL_OVS_X16,_USART_CTRL_OVS_X8, _USART_CTRL_OVS_X6, _USART_CTRL_OVS_X4) и они же, но сдвинутые (то же самое, но без подчёркивания вначале). Такие же константы могут определяться и для полей одиночной длины, если данный бит обозначает не включение какой-то функции, а переключение между разными режимами (ну или что-то типа того).
После того, как определены все структуры описания регистров в заголовке камня прописываются базовые адреса блоков и определяются указатели, с которыми мы будем работать в программе:

#define USART0_BASE	(0x4000C000UL) /**< USART0 base address  */
#define USART0		 ((USART_TypeDef *) USART0_BASE)        /**< USART0 base pointer */

А в самом конце определён полезный макрос SET_BIT_FIELD, который правда почему-то в апнотах и в eADesigner не используется.
Отдельно хочу обратить внимание на файлы efm32xx_af_ports.h и efm32xx_af_pins.h, в которых определены макросы, позволяющие по номеру локейшена выводов определённого блока периферии определить порт и пин этих выводов. Иногда удобно.

3.4. Библиотека периферии
Здесь всё более-менее типично — на каждый модуль периферии по заголовку и, где надо, исходнику с реализацией функций управления периферией. Единого файла, в котором надо комментить ненужные инклуды, как stm32xxx_conf.h, тут нет (да и вообще нет ничего, что надо тащить к себе в проект, кроме, разве что, ld-скрипта, если надо его поменять), так что сами вписываем нужные модули в начале своих исходников. Все модули emlib я рассматривать не тут буду, а расскажу лишь бегло о самых важных из них. В конце концов, логика инициализации блоков периферии у EnergyMicro вполне стандартная и привычная по другим камням такого класса (примеры кода взяты из an0045):
  1. объявляем нужные переменные
    static USART_TypeDef           * uart   = UART1;
    static USART_InitAsync_TypeDef uartInit = USART_INITASYNC_DEFAULT;

  2. включаем тактовую частоту для нужного блока (тут, правда, нужно не забыть, что помимо вентиля на конкретный блок периферии есть ещё общий вентиль периферии, который тоже надо открыть)
    CMU_ClockEnable(cmuClock_HFPER, true);
    CMU_ClockEnable(cmuClock_UART1, true);

  3. настраиваем блок периферии, как правило, INIT-струтурой (кстати, в каждом блоке задефайнена структура с некими дефолтовыми настройками, так что инициализировать все поля не обязательно)
    uartInit.enable       = usartDisable;
    uartInit.baudrate     = 115200;
    uartInit.databits     = usartDatabits8;
    uartInit.parity       = usartNoParity;
    uartInit.stopbits     = usartStopbits1;
    USART_InitAsync(uart, &uartInit);

  4. Если нужны ножки ввода-вывода, то конфигурим их (не забыв им тоже включить тактовую)
    CMU_ClockEnable(cmuClock_GPIO, true);
    GPIO_PinModeSet(gpioPortB, 9, gpioModePushPull, 1);
    GPIO_PinModeSet(gpioPortB, 10, gpioModeInput, 0);

  5. и связываем блок периферии с этими ножками
    uart->ROUTE = UART_ROUTE_RXPEN | UART_ROUTE_TXPEN | UART_ROUTE_LOCATION_LOC2;

  6. при необходимости настраиваем прерывания (и включаем их, если надо сразу)
    USART_IntClear(uart, _UART_IF_MASK);
    USART_IntEnable(uart, UART_IF_RXDATAV);
    NVIC_ClearPendingIRQ(UART1_RX_IRQn);
    NVIC_ClearPendingIRQ(UART1_TX_IRQn);
    NVIC_EnableIRQ(UART1_RX_IRQn);
    NVIC_EnableIRQ(UART1_TX_IRQn);

  7. ну и, собственно, включаем уже настроенный блок периферии
    USART_Enable(uart, usartEnable);

В общих чертах всё. Естественно, неотъемлемой частью настройки периферии является настройка DMA, но это тема отдельной статьи, так что не будем пока об этом.
Итак, возвращаясь к модулям emlib, бегло опишу самые необходимые из них:

em_chip.h
Данный модуль содержит только одну функцию CHIP_Init(), которую положено вызывать в самом начале функции main(). Основное её назначение — инициализация всякой байды, для обхода errat`ы — такой своеобразный костыль.

em_cmu.h
Без этого модуля не обойдётся, пожалуй, не одна программа — здесь собраны функции управления тактированием ядра и всех блоков периферии. В первую очередь нужна уже упомянутая функция CMU_ClockEnable, открывающая и закрывающая вентили. Кроме этого, есть функции переключения рабочей частоты HFRCO, изменения/считывания активного источника тактовой частоты и прескайлера, запуска/останова/калибровки осциляторов, синхронизации HF и LF доменов (CMU_FreezeEnable), блокировки изменения настройки системы тактирования и прочая мелочёвка.

em_emu.h
Блок управления спящими режимами необходим когда речь идёт о снижении энергопотребления. Здесь основной интерес представляют функции входа в сон (EMU_EnterEMx). Кроме того, сюда же упиханы функции работы с Backup Power Domain и обесточивания оперативки. Опять-таки, предусмотрена блокировка изменения настроек.

em_gpio.h
Ну куда ж без ножек ввода вывода? Тем более, что они нужны не только для «General Purpose». Всего здесь 6 портов GPIO, но, как самые наблюдательные уже заметили, тактируются они совместно, так что надо задумываться над тем, какие порты у тебя используются, а какие нет — CMU_ClockEnable(cmuClock_GPIO, true); и поехали. Отличительной особенностью модуля GPIO от модулей другой периферии является способ инициализации (опять-таки, наблюдательные это уже заметили) — здесь нет громоздких init-структур, вместо них вызов одной функции с четырьмя параметрами (порт, пин, режим работы, начальное значение), а всё что свыше включается дополнительными функциями. Большая группа функций, понятно дело, предназначена для чтения и манипулирования ногами порта. Все они инлайновые и очень простые (реализованы в одну строчку, не считая ассерта), так что не вносят оверхеда на интенсивном ногодрыге, в отличие от STM-ой реализации, где SPL-евскими функциями ногодрыга вообще страшно пользоваться. Всего этих функций 11 — 5 с префиксом GPIO_Pin* и 6 с префиксом GPIO_Port*. Как не трудно догадаться, первые работают с одним пином (принимают номер пина), а вторые — со всем портом (принимают битовую маску пинов). Пять функций — это записать «1», записать «0», инвертировать, считать то, что записали, и считать, что реально на пине; шестая, которая только для порта, это выставить заданное значение на группу пинов. Кроме ногодрыга и прочих с ним связанных вещей в модуле GPIO живут функции отключения пинов отладочного порта, хотя ИМХО это не логично, особенно при условии наличия отдельного модуля DBG, в котором живёт аж целых две функции управления отладкой.

em_msc.h
Memory System Controller управляет исключительно флешом и вопросами, связанными с исполнением кода (кеширование, префитчинг). Функций в этом модуле много, но в основном интересны, конечно, две — MSC_WriteWord и MSC_ErasePage. MSC_WriteWord, несмотря на своё название, принимает вовсе не слово, а буфер практически произвольной длины, которая должна быть кратна длине слова. Функции эти должны выполняться из RAM, так как флеш блокируется на время записи/стирания

em_assert.h
Вещь полезная в отладке, хотя и проверяет входные параметры библиотечных функций не столь дотошно, как STM-овский собрат. Используется в основном внутри самой emlib, но никто не мешает втыкать ассерты и в свой собственный код. Для того, что бы активировать ассерты нужно где-нибудь в свойствах проекта задефайнить символ DEBUG_EFM, или DEBUG_EFM_USER и пересобрать библиотеку. В итоге, если условие, переданное макросу EFM_ASSERT где-либо в коде, не выполнится (вернёт false), то будет вызвана функция assertEFM(), которая, как правило, останавливает выполнение программы. Если объявлен символ DEBUG_EFM, то будет использоваться встроенная реализация assertEFM, которая просто входит в бесконечный цикл. Если объявлен символ DEBUG_EFM_USER, то встроенная реализация скомпилена не будет и пользователю необходимо написать свою, соответствующую заданному прототипу — void assertEFM(const char *file, int line).

em_bitband.h
Побитовый доступ к памяти и регистрам периферии. В прикладной программе может не часто нужен, зато весьма активно используется внутри emlib, что приятно. Всего в заголовке четыре инлайновые функции — запись и чтение для памяти и периферии.

3.5. Драйвера
Как я уже писал, на данный момент в комплекте два драйвера — GPIO Interrupt dispatcher и NVM Storage. В каталоге emdrv лежат заголовки и сырцы этих драйверов, а также, почему-то, документация на них.

GPIO interrupt dispatcher
У контроллеров EFM32 присутствует всего два вектора прерываний от GPIO (IRQ_GPIO_ODD для пинов с нечётными номерами и IRQ_GPIO_EVEN для пинов с чётными), на которые можно завести до 16-ти каналов, что в ряде случаев может оказаться неудобным. Диспатчер берёт на себя задачу вызова разных функций в зависимости от того, по какому каналу прилетело прерывание. Конечно фундаментальных проблем с оверхедом, связанных с тем, что несколько каналов обрабатываются в одном прерывании, это не решает, но чуть повышает читабельность кода (зато добавляет ещё больше оверхеда ;) ).
Как оно работает: в файле gpiointerrupt.c реализованы обработчики прерываний GPIO_ODD_IRQHandler и GPIO_EVEN_IRQHandler, считывающие список каналов, по которым прилетело прерывание, и вызывающие функцию GPIOINT_IRQDispatcher. Диспатчер в цикле просматривает список каналов и вызывает колбек, ассоциированный с этим каналом. Колбеком является функция void, принимающая в качестве аргумента номер пина, по которому его позвали (то есть один колбек может обслуживать несколько пинов и знать, какой именно сейчас дёрнулся). Список колбеков хранится в массиве, индексом которого является номер канала. Добавлять и убирать колбеки надо функциями GPIOINT_CallbackRegister и GPIOINT_CallbackUnRegister. Собственно, кроме них пользователю доступна ещё только одна функция — GPIOINT_Init, которая включает прерывания по GPIO_ODD и GPIO_EVEN.

Non-Volatile Memory Manager
Драйвер решает извечные проблемы сохранения данных в энегронезависимой памяти. Собственно API простой — NVM_Init, NVM_Erase, NVM_Write, NVM_Read и NVM_WearLevelGet (счётчик износа памяти), но для работы нужно заполнить несколько структур, описывающих память и данные. Логика работы следующая — мы описываем, какая часть флеша используется как хранилище и какие данные (объекты) мы в нём хотим хранить, а драйвер уже сам занимается балансировкой, сверкой контрольных сумм и прочим. Утверждается, что в качестве хранилища можно использовать любую энергонезависимую память, просто надо будет реализовать новый HAL.

Заключение


В заключение статьи хочу обратить внимание на огромное количество примеров кода, распространяемых компанией EnergyMicro. Помимо апликейшен ноутов, на которые я ссылался на протяжении всей статьи (кстати, из того, что я не упоминал, крайне рекомендую к прочтению ещё an0027 Energy Optimization) есть ещё упражнения для самостоятельного выполнения (um00x), экзамплы для китов и небольшие проекты от инженеров компании (обитают на форуме и в githab`е). Всё это можно и нужно бессовестно использовать для освоения работы с камнями EFM32.

Update 2013.05.13


Восьмого числа было крупное обновление контента в SS, приуроченное к релизу семейства WG. Помимо вещей, непосредственно относящихся к этому семейству прилетело и несколько более общих изменений, о которых я считаю необходимым упомянуть (и внести в статью). Краткое содержание изменений:
  • Обновлена версия CMSIS и emlib до 3.20.
  • Добавлен каталог с драйверами GPIO Interrupt Dispatcher и Non-Volatile Memory.
  • Во все заголовки описания партов добавлен макрос FLASH_PAGE_SIZE, содержащий размер страницы флеша в байтах.
  • Добавлены ресурсы для Atollic TrueStudio и ARM GCC Embedded Tolchain.
  • +9
  • 05 мая 2013, 15:10
  • Alatar

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

RSS свернуть / развернуть
Спасибо за статью. Мне бы ее пол-года назад, когда я начинал их изучать. Но и сейчас будет полезна для наведения порядка в голове. Написана просто, последовательно, логично. Как я люблю) С удовольствием прочту продолжение.
0
Хорошая статья, спасибо. Но, правда, для себя никакой пользы особой в этих МК не увидел. Не понимаю, что в них такого выдающегося? STM32 как-то все-таки ближе. Но тут уж дело вкуса.
0
Не понимаю, что в них такого выдающегося?
Микропотребление. К тому же они как-то проще в освоении и лучше по документации/примерам.
0
Насколько, если не сложно кинуться в меня цифрами, эти показатели лучше чем у STM32?
Есть же еще PSoC5, у которых тоже с потреблением вроде как все хорошо (да еще и CPLD на борту), и МК от TI тоже с недурными показателями вроде?
Насчет документации, возможно. Хотя мне и STM32 вполне комфортно было осваивать, с доками и либами не испытывал проблем вроде.
0
Сравнение с STM было в предъидущей статье автора:
link...
0
Спасибо. Я ее как-то пропустил…
0
>>Есть же еще PSoC5, у которых тоже с потреблением вроде как все хорошо (да еще и CPLD на борту), и МК от TI тоже с недурными показателями вроде?

Глянул в даташит на PSoC5
Low voltage, ultra low power
*Operating voltage range: 2.7 V to 5.5 V
*6 mA at 6 MHz
У них своё понимание ULP… 2.7В минимум и при этом 1мА/МГц — это немного другая ниша.

У TI с ULP заметно лучше, но это, всё-таки 16 бит — когда нужна математика не особо катит. Да и потом, если пробежаться по характеристикам MSP430 разных подсемейств, то получается либо потребление больше, чем у EFM, либо слабый камень.

С момента написания прошлой статьи вышел таки Atmel SAM4L — это это уже интересный конкурент, тут надо сравнивать. Причём лучше на реальном железе и реальной задаче, потому что цифры из даташита и презентаций на SAM4L настораживают. Ну и нужно смотреть, какой вклад может дать из SleepWalking на конкретной задаче.

Что до док и либ на STM32… Я тоже не очень сильно ругался, пока изучал, но сейчас возвращаться к ним что-то не тянет. Хотя, конечно, это чисто эстетство — если поставленную задачу решить можно, то кривость доков дело пятое.
0
Ну, у варианта PSoC5 LP есть хибернейт 300нА :) Все-таки уже что-то.
SAM4L гляну ради интереса, спасибо.
К стати, смотрю с доступностью у нас этих EFM32 все не особо гладко?
0
All oscillators and regulators off, except hibernate regulator. SRAM retention
Катит только если просыпаться надо исключительно по внешнему событию. И да, а за сколько просыпаться? 125us?
По поводу SAM4L вот могу поделиться рекламой от Rainbow.
0
Ну да, применение всяко ограничено. Зато есть программируемая логика для всяких хитрожопых решений :)
За инфу спс.
0
А вот на тему доступности EFM32 — таки да, пока мягко говоря фиговато.
0
И это, всяко, фиговато :(
0
а так же адаптированные под tickless режим FreeRTOS и Keil RTX.
Не понимаю, зачем этот tickless режим, при наличии LETIMER-а в EFM?
0
Я не спец по RTOS`о-строению, да и использовать их пока не приходилось, но, как я понимаю, у этих зверей принято использовать ядерный SysTick для квантования времени и, соответственно, переключения задач в вытесняющем режиме. Соответственно, смысл tickless — избавиться от использования SysTick, который не даёт нормально спать.
0
Я не спец по RTOS`о-строению, да и использовать их пока не приходилось, но, как я понимаю, у этих зверей принято использовать ядерный SysTick для квантования времени и, соответственно, переключения задач в вытесняющем режиме.
У такое же мнение.
смысл tickless — избавиться от использования SysTick, который не даёт нормально спать.
Странный метод, вместо того чтобы заменить SysTick на LeTimer, выкидывают tick вообще. Не понятно, может это связано с использованием защищённых режимов МК…
0
Не понял, причём тут защищённые режимы?
Как я понял, совсем tick они не выкидывают, а просто делают его переменной длины. И да, там используется не letimer, а real-clock timer.
0
>> а real-clock timer
тьфу ты, пальцы заплетаются =)
real-time counter я хотел написать =)
0
защищённые режимы
Это у меня предположение возникло, что может у них задачи работают в «user»- режиме, а Ось — в «system». И тут получается, что Systick — защищённый ресурс, а LeTimer/RTC — нет. Но это надо смотреть как там у них сделано.
0
Да нет, конечно, тут к гадалке не ходи, этим они не заморачивались. Когда речь идёт о суровой оптимизации, на защиту от себя обычно задвигают =).
Просто какой смысл, например, просыпаться каждые x миллисекунд, если у тебя основная задача должна выполняться раз в 10 секунд, а остальные вообще только по требованию юзера (или ещё какому событию)?
0
reptile — небольшая пачка дополнительных библиотек (в основном сторонних), включая драйвер FAT, сеггеровский emWin, а так же адаптированные под tickless режим FreeRTOS и Keil RTX.
Оно ж вроде платное все?
0
  • avatar
  • Vga
  • 08 мая 2013, 15:35
Кто всё? FreeRTOS и fatfs точно бесплатные и опенсорсные =)
На счёт KeilRTX не знаю, как оно по дефолту, но, как минимум, роялити-фри.
А emWin — да, обычно, мягко говоря, не дешёвое, но для некоторых камней бесплатное (например для LPC и EFM).
0
Непонятна непопулярность Keil RTX, поскольку вскоре портирование MCU софта будет заключатся в основном в переносе его с одного камня Cortex на другой.
0
Непонятна непопулярность Keil RTX
Что непонятного-то? Keil RTX — одна из множества (несколько десятков наверное) Осей.
Ничем особенно не выделяющаяся (или может есть в ней то чего у других нет?). К тому же привязанная к кейлу. На Авр её ведь не запустишь?
0
MCU RTOS не так и много, из бесплатных:

FreeRTOS (Supported MCUs)
ChibiOS (ARM Cortex, MSP430, STM8, AVR, ARM7)
Keil RTX (ARM Cortex only)
CooCox CoOS (КНР ARM Cortex)
Atomthreads (AVR, STM8)
scmRTOS (exUSSR ARM Cortex, MSP430, STM8, AVR, Blackfin, ARM7)
OSA (exUSSR PIC, AVR, STM8)
uRTOS (статья) (exUSSR AVR)
TI RTOS (TI MCUs only)

И самая старая из них, но платная µC/OS
0
Действительно не так много как я думал.
Из бесплатных ещё — TNKernel. Больше не вспомнилось…
0
Да, я про Keil RTX и emWin. Т.е. пакет reptile тоже весь бесплатный?
0
Да.
0
Слегка исправил и дополнил статью в связи с недавним обновлением материалов в Simplicity Studio.
0
Просмотрел статью повторно и возник вопрос. Автору или может еще кто знает. Можно ли пользоваться встроенным в отладочную плату Advanced Energy Monitor'ом для мониторинга потребления своей платы?
0
Да, можно. Иначе в этой фишке было бы мало смысла.
Как это делается можно прочитать в 27-м апноте (4.1.2 Measuring Current of an External Board). Ну или на форуме несколько тем было (например вот)
+1
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.