РадиоКот :: О разработке приложений для ARM микроконтроллеров фирмы Silicon Labs под управлением Micriµm OS
Например TDA7294

РадиоКот >Статьи >

Теги статьи: Добавить тег

О разработке приложений для ARM микроконтроллеров фирмы Silicon Labs под управлением Micriµm OS

Автор: Сергей Безруков (aka Ser60)
Опубликовано 16.02.2020
Создано при помощи КотоРед.

При подготовке третьей части статьи о разработке Bluetooth приложений с участием Micriµm® OS (читается как Микриум) я понял, что следует предварительно написать отдельную статью про эту систему и её основные функции. В настоящее время имеется несколько десятков ОС реального времени для микроконтроллеров, среди которых находится небезызвестная FreeRTOS. Хотя и возможно использование этой ОС с Simplicity Studio (см. детали в [4], [5]), после вхождения фирмы Micrium в состав Silicon Labs в 2016, Micriµm OS стала дефолтной RTOS для их продукции и может быть использована даже для коммерческих проектов на ней без лицензионных сборов. Мне довелось дважды посетить 2-дневные трейнинги фирмы Micrium по предыдущим версиям µC/OS-II и µC/OS-III их системы, когда они приезжали в наш город. Системы эти портированы на несколько десятков семейств микроконтроллеров, в составе ОС имеются компоненты для работы с файловой системой, TCP/IP, USB, GUI и пр., см. подробнее информацию на сайте micrium.com. Кстати, начиная с 28 февраля 2020 эти компоненты в семействе µC/OS переводятся под модель открытого программного обеспечения (open source). Сегодня сокращённые курсы по этим ОС можно встретить на многих больших конференциях эмбеддеров, а на вебсайтах Micrium и Silicon Labs имеется несколько видео-уроков, рассказывающих об основных аспектах систем. Здесь я расскажу в более практическом плане как можно начать работу с Micriµm OS на примерах с использованием демо-платы Thunderboard Sense 2. Это одна из самых недорогих плат фирмы, доступная по цене около $35.

Примеры сознательно выбраны простые, т.к. более сложные примеры для вводной статьи считаю неуместными. Несколько более сложный пример будет в статье про Bluetooth. Я не претендую здесь на полноту изложения в условиях имеющихся в свободном доступе для скачивания книг по продукции Micrium [1] и множества апноутов на сайтах обоих фирм. Полные проекты всех моих примеров, включая исходники, находятся в прилагаемом архиве. Разработку ПО будем производить под версией SDK v2.6.4 системы Simplicity Studio.

Создание потоков и инструменты системы Simplicity Studio

Начнём с классического примера мигания светодиодом, на котором продемонстрируем запуск системы, создание потоков/задач (tasks), и использование инструментов µC/Probe и Segger SystemView. После загрузки проекта RTOS_blink_Probe из прилагаемого архива в Simplicity Studio, увидим следующую его структуру:

В папке BSP находятся специфические для демо-платы и микроконтроллеров фирмы настройки периферии. Основные исходники собственно самой RTOS содержатся в папках common, cpu, kernel, и ports, и мы их трогать не будем. В папке emlib находятся библиотечные функции работы с периферией семейств EFх32, а в папке CMSIS – стартап файлы для МК на плате. Объектные файлы компиляции проекта система складывает в папку GNU, а сами «бинарники» в разных форматах также в папку Binaries. Папки Probe и SystemView предназначены для работы с вышеупомянутыми инструментами. Все системные файлы, которые мы изменили/адаптировали для нашего проекта копируются из системной области инсталляции системы в папку external_copied_files. Наконец, исходные тексты приложения пользователя (файл main.c) находятся в папке src.

В процессе работы Micriµm OS автоматически создаёт до 4 служебных потоков:

  • Tick Task – поток для поддержки временных задержек и таймаутов.
  • Idle Task – поток с минимальным приоритетом, выполняющийся когда ни один из других потоков не может быть выбран планировщиком. Он может быть использован, например, для погружения МК в сон.
  • Timer Task – поток для поддержки программных таймеров.
  • Statistics Task – поток для сбора статистики работы ОС при отладке.

Каждый из этих потоков может быть отключён по желанию пользователя в файле оs_cfg.h, если его функции не нужны для проекта. Мы воспользуемся пока дефолтными установками системы, где все эти потоки разрешены. Соответствующий фрагмент файла os_cfg.h показан ниже.

Для создания потока, контролирующего мигание светодиода, как и для любого другого создаваемого потока, следует определить его приоритет, отвести под него область стека и определить область памяти под его TCB (Task Control Block). Всё это делается в строках 18 - 26 файла main.c. Конечно, 512 байт для стека нашего микро-проекта это перебор, но для МК на плате, имеющего 256К под RAM и 1М флеша можно не экономить на мелочах. Однако, насколько это перебор или недобор будет показано позже.

Инициализация RTOS производится в строках 37 – 42 файла main.c., из которых вызов функции в строке 40 нужен только если будет задействована система Segger SystemView для отладки. Макросы APP_RTOS_ASSERT_DBG следует размещать после каждого вызова функций системы, имена которых начинаются с OS. Это позволит проще и быстрее локализовать проблемное место в коде и причину проблемы при отладке. Для нормальной работы планировщика RTOS следует создать как миниму один поток. Это делается функцией OSTaskCreate в строке 44. Не буду здесь описывать все 13 параметров этой функции, т.к. всё достаточно подробно описано в документации на систему [2]. Отмечу лишь, что “Start Task” – это имя нашего потока для идентификации его инструментами отладки. Наконец, после создания потоков вызовом функции OSStart() в строке 59 производится инициализация работы планировшика RTOS. Эта невозвратная функция, так что после неё не нужен бесконечный цикл для предотвращения возврата из main().

Структура кода каждого потока состоит из области инициализации с последующим бесконечным циклом, что делает функцию потока невозвратной. Если в ходе работы приложения поток окажется больше ненужным, его можно будет удалить из таблицы планировщика средствами RTOS и использовать занимаемую им память под стек и TCB для нужд приложения. В нашем случае стартовый поток инициализирует SysTick таймер под дефолтный период тиков в 1мс и остальную периферию демо-платы вызовом функций BSP_TickInit() и BSP_OS_Init() в строках 69 и 78, что можно делать и в main(). Далее, в бесконечном цикле мы инвертируем состояние светодиода в строке 83, получаем его текущее состояние в строке 84 (исключительно для демонстрации ниже) и вызываем программную задержку на длительность периода мигания в строке 85. Вызов функции OSTimeDelay(), в свою очередь, вызывает планировщик системы, а сам поток переходит в неактивное состояние (Pending).

Возврат потока в состояние готовности (Ready) произведётся автоматически по истечению времени задержки, а сам поток продолжит выполнение в состоянии Running, когда до него дойдёт очередь планировщика. Отмечу возможную небольшую путаницу в терминологии. На языке С потоки реализуются как функции, и в этом смысле все потоки уже созданы на этапе компиляции. Однако, при этом они находятся в состоянии Dormant и не включаются в очередь планировщика до вызова функции OSTaskCreate(), одним из параметов которой будет указатель на фунцию потока, в результате чего поток перейдёт в состояние Ready. Состояние потока сохраняется в области ето TCB. Ниже показаны все возможные состояния потоков в Micriµm OS и условия миграции между этими состояниями.

Проиллюстрируем работу нашего приложения с помощью инструмента µC/Probe, входящего в состав Simplicity Studio. Инструмент этот доступен для свободной загрузки с сайта Micrium и работоспособен с FreeRTOS и другими МК. Однако, время работы свободной версии этого инструмента ограничено 1 минутой после каждого запуска (по истечении минуты его можно перезапустить), и некоторые функции в свободной версии недоступны. Используем сначала этот инструмент для изменения периода мигания светодиода и индикации его состояния. Для этого кликаем на кнопку ELF и в открывшемся окне выбираем файл RTOS_blink_Probe.asf из папки Binaries проекта. Тем самым мы получим доступ ко всем глобальным переменным системы. Нам потребуются переменные period и LED_state из файла main.c. Для изменения периода организуем слайдер, перетащив его из панели Gauges слева на панель DataScreen1. Также перетащим туда икону LED из панели Miscellaneous. Далее, перетащим мышкой символ period из окна Symbol Browser на наш слайдер. Тем самым слайдер будет настроен на работу с этой переменной и её имя появится под слайдером. Аналогично настроим светодиод на работу с переменной LED_state. Все настройки уже выполнены в прилагаемом архиве, подробности смотри в мануале на систему.

Запустив инструмент кнопкой Run, увидим мелькание светодиода на панели синхронно со светодиодом на плате и сможем оперативно изменять период мигания слайдером с указанием его текущего значения. Этот инструмент может работать и в приложениях без RTOS. Мы, таким образом, просто получим графический интерфейс для оперативного изменения и отображения переменных. Касательно RTOS, добавим селектором Insert Screens в Workspace Explorer инструмента окно, соответствующее Micriµm OS Kernel. После запуска инструмента кнопкой Run и выбора закладки Micriµm OS Kernel, увидим статистику всех потоков нашего приложения. Из неё, в частности, вытекает, что не один из стеков потоков не переполняется в процессе работы и мы отвели слишком много памяти под стек потока Start Task.

Работу потоков нашего приложения можно также визуально проконтролировать с помощью системы SystemView фирмы Segger, интегрированной в Simplicity Studio. Система эта тоже доступна для свободной загрузки с вебсайта фирмы и может работать с другими IDE и микроконтроллерами. Запустим систему из меню Simplicity Studio и дадим ей поработать несколько секунд для сбора статистики. Остановив запись, проанализируем ход работы потоков, растянув временную ось мышкой. В результате увидим последовательность вызовов функций потоков и планировщика в реальном времени. Из неё вытекает, что каждую миллисекунду происходит аппаратное прерывание таймера (SysTask IRQ), определяющего «тики» системы с последующим вызовом служебного потока Tick Task. Также увидим когда вызывался планировщик (Scheduler) и получим кучу статистики о работе всех потоков и приложения в целом, что просто безценно для отладки.

Работа с семафорами

Семафоры являются стандартным средством синхронизации потоков в любой ОС. В Micriµm OS для этого имеются две возможности – задействовать семафор уже встроенный в TCB (Task Control Block) каждого потока или использовать внешний семафор. В первом случае получаем некоторую экономию памяти. Однако, семафор этот может быть использован только для контроля одного потока (его хозяина). Во втором случае получим небольшой проигрыш по памяти и времени, но сможем одним семафором контролировать несколько потоков.

Проиллюстрируем оба подхода на простом примере синхронизации двух потоков. Один из них (LampTask) будет ожидать открытия семафора другим потоком для изменения состояния светодиода. Другой поток (ButtonTask) будет мониторить состояние кнопки на демо-плате и открывать семафор потока светодиода по её нажатию. Иными словами, состояние светодиода на плате будет изменяться при каждом нажатии кнопки.

Создаём оба потока как было описано выше в StartTask (это можно делать и в main()), выделив под каждый из них области в памяти под стек и TCB. Код потока светодиода показан ниже. Функция OSTaskSemPend() проверят состояние семафора потока и если он закрыт (значение его переменной =0), то поток переводится ОС в состояние Pending. Первый параметр в этой API определяет таймаут – сколько по времени ждать потоку открытия семафора (если 0, то ждать неограниченно). При этом третий параметр должен быть указателем на переменную, где сохранится отметка времени (timestamp) открытия семафора (0 если сохранять не нужно). Если семафор окажется открытым, то его переменная автоматически увеличивается на 1 и происходит выход из функции с передачей управления следующей инструкции (в строке 177). Таким образом, если значение переменной семафора в момент открытия равно 0, то поток сам себя блокирует после единичного изменения состояния светодиода. После создания потока значение переменной его семафора равно 0. Встроенным в поток семафором можно блокировать только сам этот поток и никакой более, в то время как открыть встроенный в поток семафор может любой другой поток.

Код потока кнопки вызывается планировщиком RTOS каждые 100мс для исключения влияния дребезга её контактов на функционирование. Поток реализует конечный автомат состояний кнопки, в результате чего приложение каждый раз дожидается нажатия кнопки для изменения состояния светодиода и более не изменяет его если продолжать нажимать на кнопку. Как только нажатие кнопки произойдёт, открывается семафор светодиода вызовом функции OSTaskSemPost() в строке 153, которая уменьшает на 1 значение его переменной. Если вместо встроенного в TCB семафора использовать внешний, то следует раскомментировать строки 141, 152, 175 приложения и закомментировать строки 153 и 176. При этом строкой 141 производится создание глобального объекта семафора, который будет доступен всем потокам посредством API функций OSSemPost() и OSSemPend().

Работа с флагами

Помимо семафоров в Micriµm OS имеется дополнительная возможность синхронизации потоков с помощью флагов событий, соответствующим различным событиям и сигналам приложения. Флаги можно комбинировать логическими функциями И/И-НЕ/ИЛИ/ИЛИ-НЕ для блокировки или разрешения работы потоков средствами ОС. Ниже показан пример применения флагов событий для запуска и останова двигателя машины. Сигнал на запуск будет сформирован если выполняются все следующие условия: двигатель ещё не запущен, его температура менее 200°С, топлива в баке не менее 1% его объёма, и пользователь повернул ключ зажигания. Аналогично, формирование сигнала останова двигателя будет произведено по выполнении как миминум одного из следующих условий: частота вращения двигателя более 3000 об/мин, пользователь вынул ключ зажигания, или имеется синал останова от других датчиков (Abort).

Механизм флагов событий был введён в Micriµm OS в ответ на потребности реализации стека µC/TCP-IP. Продемонстрируем работу с флагами на примере проекта RTOS_flags. В проекте имеется 2 потока пользователя, один из которых мониторит состояние обоих кнопок на демо-плате, а другой управляет светодиодом. Последний должен изменять своё состояние в момент нажатия на одну из кнопок и только если при этом другая кнопка также нажата. Создание структуры флагов производится API функцией OSFlagCreate() в строке 145, где MyFlags – глобальная переменная типа OS_FLAG_GRP, определённая в начале файла main.c, и инициализированная (=0) третьим параметром функции.

Поток мониторинга кнопок, вызываемый планировщиком каждые 100мс, определяет моменты нажатия и отпускания кнопок. Ниже показан код обработки одной из кнопок, для другой всё аналогично. При нажатии кнопки производится установка бита с номером 0 в флаговой структуре (строка 157), а при отпускании – сброс этого бита/флага (строка 165). Для другой кнопки производится установка/сброс бита с номером 1.

Код потока управления светодиодом показан ниже. В строке 199 производится проверка установки обоих флагов. Если флаги нажатия обоих кнопок не установлены, поток переводится в неактивное состояние (Pending). Возврат из этого состояния произведётся ОС как только обе кнопки окажутся нажатыми. При этом RTOS переведёт поток в состояние Ready и вскоре планировщик продолжит его работу со строки 200. В этой строке мы сбрасываем оба флага кнопок и тем самым готовимся к следующему их нажатию. Отметим, что установка флагов и их сброс производятся одной и той-же API функцией OSFlagPost(), в зависимости от её третьего параметра. Второй параметр задаёт маску изменения флагов. В нашем случае значение 3 этого параметра означает операцию над битами 0 и 1, т.е. над обоими флагами. Можно проверить и сбросить флаги событий вызовом лишь одной API функции OSFlagPend() в строке 201 вместо строк 199 и 200.

Работа с мьютексами (mutex)

Мьютексы, как известно, используются для организации критических секций кода, в которых производится доступ к общему ресурсу, который не должен быть одновременно использован более чем одним потоком. Это можно реализовать несколькими способами, каждый из которых поддерживается Micriµm OS. Прежде всего, можно запретить прерывания при входе потока в критическую секцию кода и разрешить их по выходу из неё. Иначе, можно запретить работу планировщика на время выполнения потоком критической секции. В третьем варианте можно использовать семафоры, однако, этот способ подвержен проблеме инверсии приоритета потоков. Недостатки и каждого из вышеприведённых способов защиты также хорошо известны и описаны в соответствующей литературе по операционным системам, в том числе и учебной.

В нашем демонстрационном проекте RTOS_mutex мы задействуем специальный объект ОС mutex. Общим ресурсом для потоков у нас будет глобальная переменная MyVar, значение которой будет увеличиваться на 1 одним потоком и увеличиваться на 5 другим. Хотя увеличение переменной кодируется одной строчкой кода на ЯВУ, для реализации этого участка на МК может потребоваться несколько машинных команд. Таким образом, без принятия мер синхронизации в многопоточной системе может возникнуть состояние гонки, при котором работа системы или приложения зависит от того, в каком порядке выполняются части кода. Для защиты ресурса создадим глобальный объект mutex, где MyMutex – переменная типа OS_MUTEX, определённая в строке 33 файла main.c.

Теперь участки кода, где производится изменение значения защищаемого ресурса следует окружить вызовами API функций OSMutexPend() и OSMutexPost(), как это показано для первого потока, увеличивающего переменную на 1 по нажатию кнопки...

... и второго, увеличивающего переменную на 5 каждую секунду по таймеру, код которого приведён полностью:

Работу приложения можно визуализировать с помощью инструмента µC/Probe. Значение переменной MyVar отображается в реальном времени на шкале по прошествии каждой секунды и/или нажатии кнопки на демо-плате.

Работа с очередью сообщений

Micriµm OS предоставляет возможность организации очередей сообщений (почтовых ящиков) для обмена информацией между потоками. Для этого, как и в случае с семафорами, имеется две возможности: использовать встроенный в каждый процесс ящик/очередь, или организовать внешний. В первом случае только поток-хозяин почтового ящика может принимать из него сообщения, в то время как отсылка сообщений в этот ящик будет доступна любому другому потоку. Этим достигается несколько меньшая избыточность кода по сравнению с другим способом, при котором любой поток может отсылать и принимать сообщения из внешнего ящика/очереди.

В нашем демо-проекте RTOS_queue обмен сообщениями будет производиться между двумя потоками. Первый поток мониторит состояние двух кнопок на демо-плате и по нажатию каждой из них посылает сообщение другому потоку с номером нажатой кнопки. Другой поток по получении сообщения зажигает красный или зелёный светодиод на плате, в зависимости от номера кнопки в сообщении. Реализация почтового ящика первым способом для потока кнопок показана ниже. Сообщения отправляются в строках 155 и 168, где третий параметр в API – это длина сообщения в байтах, а четвёртый определяет куда поместить новое сообщение – в конец или начало очереди.

Соответственно, в коде другoго потока выемка сообщения из очереди производится API функцией OSTaskQPend(). Первый параметр задаёт максимальное время ожидания сообщения в тиках ОС (если 0, то ждать неограчиченно). Второй – определяет что делать если ящик пуст. В нашем случае производися блокировка/перевод процесса в неактивное состояние (Pending). Третий параметр – это указатель на переменную, куда будет записана длина сообщения, и четвёртый – указатель на переменную, куда будет записана отметка времени получения сообщения (0 если запись не нужна). Возвращаемое значение API имеет тип void*. Также, как и для других примитивов ОС, имеются дополнительные функции работы с очередью, см. детали в документации [2].

Для реализации второго способа передачи сообщений следует раскомментировать строку 146 кода первого потока, которая организует внешний почтовый ящик на 20 сообщений. Далее, следует раскомментировать строки кода 154, 167, 187 и закомментировать строки 155, 168, и 188.

Работа с прерываниями

Практически каждый проект на микроконтроллерах использует аппаратные прерывания, генерируемые периферией. Micriµm OS различает два типа прерываний: КА-ISR (Kernel Aware) и NKA-ISR (Non-Kernel Aware). Несмотря на то, что мы используем RTOS, часто необходимо создать быструю ISR, которой не нужно непосредственно взаимодействовать с ОС и потоками. Например, когда просто необходимо изменить скважность генерируемой PWM, или произвести чтение байта с внешнего интерфейса, проверить его, и разместить в RAM для последующей обработки потоками. В коде такой NKA-ISR нельзя вызывать никакие функции RTOS. С другой стороны, KA-ISR знает о существовании RTOS и может быть использована для информирования блокированного потока о наступлении ожидаемого им события, например с помощью семафора. В обоих случаях реализации ISR выполнение текущего потока прерывается на время выполнения кода ISR и поток переходит в состояние Interrupted (см. выше). При этом после NKA-ISR, как правило, производится продолжение выполнения прерванного потока. Однако после завершения работы KA-ISR обязательно включается планировщик для выбора потока с наивысшим приоритетом, который, например, в случае разблокировки его ISR может быть отличным от прерванного.

Продемонстрируем создание обоих типов ISR на простых примерах. В обоих случаях мы хотим изменить состояние светодиода по нажатию кнопки на демо-плате. Для этого мы в потоке StartTask конфигурируем вывод МК, соединённый с кнопкой, на генерацию прерывания по падающему уровню сигнала, разрешаем прерывания GPIO для NVIC ...

... и в случае NKA-ISR пишем обычный код ISR, как будто RTOS не существует:

При этом SystemView не показывает никаких признаков существования прерывания с точки зрения RTOS. См. детали в исходном тексте проекта RTOS_NKA в приложении.

В случае KA-ISR конфигурация кнопки в потоке StartTask идентична предыдущему случаю. В этот поток также добавлен код создания нового потока управления светодиодом и его семафора, который мы будем открывать из ISR. При этом имя ISR должно быть таким, каким оно прописано в таблице векторов прерываний. Однако, стандартный код сброса флага прерывания и открытия семафора окружён несколькими вызовами RTOS API. Следует придерживаться этого шаблона и при создании других KA-ISR.

Код потока управления светодиодом ничем не примечателен. Изменение состояния светодиода произойдёт как только наша ISR откроет соответствующий семафор.

Теперь, в отличии от NKA-ISR, наша KA-ISR знает о существовании RTOS, что видно на следующей картинке. Здесь показан момент работы RTOS при обработке KA-ISR и переключения на LampTask управления светодиодом.

«Безтиковый» холостой режим (Dynamic Tick Rate)

Во всех предыдущих примерах мы использовали дефолтный режим RTOS, при котором требуется запрограммировать один из таймеров МК на периодические прерывания («тики»), обычно с периодом 1мс, что и определяет временное разрешение системы. Каждый тик предполагает вызов его обработчика прерывания, вычисление функции потока TickTask (если она разрешена) и вызов планировщика для определения ситуации в системе, например, переключения на поток пользователя или служебный поток IdleTask (опять-же если он разрешён) для помещения системы в сон. Эта ситуация показана на следующей картинке, где итерация цикла в Task_1 задерживается пользователем на 5мс (см. [3]).

При этом может оказаться (наш случай), что при большинстве тиков переключение на потоки пользователя не требуется и система может продолжать выполнять IdleTask. Таким образом, разумно вместо периодических прерываний вычислить момент следующей активизации некоторого потока пользователя и не пробуждать МК до этого времени. Т.е. мы как-бы ставим будильник на определённое время и спокойно спим, просыпаясь в точности когда есть работа. Пример выше при этом изменится следующим образом:

Этим достигается, как правило, ощутимо меньшее токопотребление системы и нагрузка на процессор. Прежде мы дефолтно использовали системный таймер SysTick, тактируемый на частоте ядра МК, что не позволяло отправить его в глубокий сон. Сейчас, помимо организации динамического тактирования, мы переключимся на RTCC (Real Time Clock and Calendar) таймер МК, способный работать от низкочастотных генераторов системы в условиях глубокого сна, когда системный генератор, ядро МК и быстрая периферия неактивны. Для этого, разрешив, как и ранее, все служебные потоки, переопределим значение OS_CFG_DYN_TICK_EN в строке 83 файла os_cfg.h как DEF_ENABLED. При этом файл os_cfg.h скопируется из папки инсталляции системы в папку external_copied_files проекта, оставив оригинал неизменным для других проектов. В этом-же файле поменяем значение OS_CFG_APP_HOOKS_EN также на DEF_ENABLED. Этим мы разрешим вызов из служебных потоков RTOS специальных функций в коде пользователя (application hooks).

Такой «специальной функцией» у нас будет функция OSIdleEnterHook(), работающая в системе совместно с IdleTask (она должна быть именно так названа, чтобы система восприняла её надлежащим образом), где мы используем API из библиотеки EMLIB для погружения МК в глубокий сон (режим Energy Mode 2 – EM2).

Указанные выше изменения значений дефайнов переконфигурируют RTOS внутри вызова функции BSP_TickInit() на другой источник тиков и заодно сконфигурируют сам этот источник. Посколько RTCC тактируется от генератора с частотой 32768 Hz, получить период тиков в 1мс целочисленным делением частоты от него невозможно. Поэтому изменим в начале main() частоту тиков с 1000 Hz на 1024 Hz. Этим улучшится точность рассчёта системой всех временных интервалов и уменьшится их дрожание (jitter).

Посмотрим, чего-же мы добились этими манипуляциями. После загрузки кода в МК и запуска системы SystemView видим, что периодические тики с периодом 1мс исчезли и TickTask вызывается когда необходимо. На картинке ниже это происходит при вызове единственного потока пользователя (который моргает светодиодом) и также при периодическом вызове системного потока TimerTask. Следующим шагом в плане уменьшения нагрузки на процессор и уменьшения токопотребления следует запретить неиспользованные приложением служебные потоки, такие как TimerTask и StatTask. В третьей части статьи про Bluetooth мы используем другую демо-плату для демонстрации кардинального изменения в токопотреблении.

Конечно, здесь я рассказал не про все аспекты Micriµm OS, а коснулся лишь самых наиболее часто используемых, причём далеко не во всех подробностях. Тем не менее, думаю, этого будет достаточно для начального старта работы с системой, а недостающие детали можно узнать из документации [2].

Литература

1. Micriµm publications
2. Micriµm OS documentation
3. How to write basic dynamic tick BSP
4. Silicon Labs EFM32 Low Power RTOS Demo
5. FreeRTOS to μC/OS-III Migration Guide


Файлы:
Архив ZIP


Все вопросы в Форум.




Как вам эта статья?

Заработало ли это устройство у вас?

11 2 6
1 0 1