Российская операционная система реального времени для IT-оборудования и Интернета вещей. Введение во встроенные системы Микро операционные системы на контроллерах avr

Привет, Хабр!
Сегодня я расскажу о такой интересной штуке как операционная система реального времени(ОСРВ). Не уверен, что это будет интересно для бывалых программистов, но, думаю, новичкам понравится.

Что такое ОСРВ?

Если мы посмотрим в Википедию, то увидим аж 4 определения.
Если же говорить вкратце - то ОСРВ - это операционная система, реагирующая на внешние события в определенный промежуток времени. Отсюда мы и можем понять основное предназначение ОСРВ - приборы, в которых необходима быстрая реакция на события (однако ни в коем случае не путайте работу ОСРВ с прерываниями).

Зачем она нам нужна?

На то есть довольно много причин.
Во-первых ОСРВ поддерживает многозадачность, приоритеты процессов семафоры и многое другое.
Во-вторых она очень легкая и почти не требует ресурсов.
В-третьих все вышесказанное мы можем получить практически на любом железе (например, FreeRTOS запускается даже на 8-битных AtMega).
Ну и в-четвертых: просто поиграться и получить удовольствие.

Обзор 3 известных ОСРВ.

Внимание: дальше идет мое личное мнение.
FreeRTOS
Одна из самых популярных ОСРВ на сегодняшний день. Портирована на огромное количество железа. Оффициальный сайт .
Плюсы
1) Бесплатная
2) Портирована на большое количество железа
3) Мощный функционал
4) Есть различные библиотеки: графика, интернет и другое.
5) Хорошая документация.
Минусы
1)Довольно-таки сложный процесс портирования на новое железо.

Вывод: Это действительно профессиональная ОСРВ с хорошей документацией. Будет хороша для новичка, если на его железо уже есть порт.

KeilRTX
До последнего времени эта ОСРВ была коммерческой, но недавно стала открытой. Работает только на архитектуре arm. Оффициальный сайт .
Плюсы
1)Бесплатная
2)Легко портируется на новое железо(в пределах архитектуры arm).
3) Есть различные библиотеки: графика, интернет и другое.
Минусы
1)Работать на в Keil с ней практически нереально
2) Немного урезанный функционал
3) Поддерживается только arm.
4)(на личном опыте) Проигрывает многим ОСРВ по скорости.
Вывод: идеально подойдет для новичка и мелких проектов.
uc/os
Мощная коммерческая ОСРВ. Сайт .
Плюсы
1) Огромное количество функций и библиотек.
2) Поддерживает много железа
Минусы
1)Коммерческая.
2) Сложна в использовании.

Вывод: назвать ее ОСРВ для новичка можно с большой натяжкой.

Другие интересные ОСРВ

RTLinux ОСРВ на основе обычного Линукса.
QNX ОСРВ на основе Unix.

Особенности разработки с использованием ОСРВ

Ну во-первых надо понять следующее: ОСРВ- это не Windows. Его нельзя установить. Эта система просто компилируется с Вашей программой.
При написании программ с ОСРВ не используются функции в обычном их понимании. Вместо функций используются процессы(или таски).Отличие в том что процессы, в отличии от функций, являются бесконечными циклами и никогда не заканчиваются(если только кто-то или он сам его не убъет - то есть выгрузит из памяти).
Если включено несколько процессов, то ОСРВ переключает их, выдавая машинное время и ресурсы по очереди. Вот тут то и возникает понятия приоритета процесса- если двум процессам единовременно нужно машинное время, то ОСРВ даст его тому, у кого приоритет больше.
В ОСРВ есть специальные функции задержки- чтобы время зря не пропадало на время задержки одного процесса выполняется второй.
Теперь поговорим о такой вещи как семафор- эта такая штука, которая управляет доступом процесса к ресурсам приложения. Для каждого ресурса есть маркер - когда процессу нужен ресурс - он его забирает и пользуется данным ресурсом. Если маркера нет, то процессу придется ждать, пока его вернут. Приведу пример: разные процессы отправляют информацию по одному UART. Если бы не было семафора, то они бы отправляли байты по очереди и получилась бы неразбериха. А так первый процесс взял маркер на UART отправил сообщение и отдал второму(и так - до бесконечности).

Дополнительные библиотеки ОСРВ.

Часто ОСРВ предлагают различные библиотеки для работы, например, с графикой, интернетом и т.д. Они действительно удобны и не стоит брезгать их использовать. Однако, помните, что без ОСРВ, для которой они написаны, они работать не будут.
Вот примеры:
Для RTX Компьютер используется, прежде всего, для обеспечения гибкости и для упрощения конструкции системы. В отличие от ПК программный код хранится обычно в ROM , а не на жестком диске. Обычно конечный пользователь не разрабатывает новое программное обеспечение для встроенного устройства. С развитием технологии VLSI встроенные системы стали настолько недорогими, что их можно найти в большинстве современных электронных устройств.

Примеры встроенных систем

Робот, такой как марсоход , показанный на рисунке 1.1 , является встроенной системой. Сотовый телефон, PDA , или портативный мультимедиа плеер, показанные на рисунке 1.2 , являются встроенными устройствами. Даже электрическая зубная щетка, показанная на рисунке 1.2 , является встроенной системой. Небольшой микроконтроллер в зубной щетке обеспечивает программируемое управление скоростью и индикацию состояния заряда батареи. Высококачественные автомобили могут содержать около ста встроенных микроконтроллеров. Типичное домовладение среднего класса имеет около пятидесяти встроенных устройств. Для каждого ПК в мире имеется более сотни встроенных устройств. В общей сложности, встроенные устройства составляют большую часть мирового производства микропроцессоров.


Рис. 1.1.

Как видно в таблице 1.1 , встроенные устройства можно найти в разнообразных продуктах, включая самолеты и военные системы, биомедицинские системы, автомобили, коммуникацию, компьютерные устройства в/в, электронные инструменты, домашняя электроника, промышленное оборудование, офисные машины, персональные устройства, роботы, и интеллектуальные игрушки. Встроенные устройства можно найти повсюду.

Конструкторы встроенных систем часто сталкиваются со сложными проектными задачами. Встроенные системы должны быть надежными. Многие встроенные устройства не могут ломаться, и не могут быть перезагружены. Программное обеспечение невозможно обновить во многих встроенных устройствах. Многие устройства имеют жесткие конструкционные ограничения по производительности и потреблению энергии. Некоторым устройствам необходимо работать от батареи длительный период времени. Кроме того, потребительские устройства обычно очень быстро выходят на рынок с новыми продуктами и имеют жесткую ценовую конкуренцию. Во многих приложениях существуют ограничения реального времени и многие устройства имеют ограниченную память и вычислительную мощность .




Рис. 1.2. Таблица 1.1. Примеры встроенных систем
Авиационные & Военные системы Автопилоты самолетов, авионика и навигационные системы, системы автоматической посадки, системы наведения, управление двигателем.
Биомедицинские системы Cистемы компьютерной томографии и ультразвукового исследования, мониторинг пациентов, кардиостимуляторы.
Автомобили Управление двигателем, антиблокировочные тормозные системы, противобуксовочная тормозная система, управление подушками безопасности, управление системой обогрева и кондиционирования воздуха, навигация GPS, спутниковое радио, системная диагностика.
Коммуникация Коммуникационные спутники, сетевые маршрутизаторы, коммутаторы, концентраторы.
Потребительская электроника телевизоры, духовки, посудомоечные машины, плееры DVD, стереосистемы, системы безопасности, управление поливом газонов, термостаты, фотокамеры, радиочасы, автоответчики, декодеры кабельного телевидения, другие устройства.
Устройства в/для компьютера Клавиатуры, мыши, принтеры, сканеры, дисплеи, модемы, устройства жестких дисков, устройства DVD, графические платы, устройства USB.
Электронные инструменты Системы сбора данных, осциллографы, вольтметры, генераторы сигналов, логические анализаторы .
Промышленное оборудование Управление лифтами, системы наблюдения, роботы, станки с ЧПУ, программируемые логические контроллеры, промышленные системы автоматизации и управления.
Офисные машины факс-аппараты, копиры, телефоны, калькуляторы, кассовые аппараты.
Персональные устройства сотовые телефоны, переносные плееры MP3, видео-плееры, персональные цифровые помощники (PDA), электронные наручные часы, портативные видеоигры, цифровые камеры, системы GPS.
Роботы Промышленные роботы , автономные транспортные средства, космические исследовательские роботы (например, роботы- марсоходы )
Игрушки системы видеоигр, игрушки роботы типа "Aibo", "Furby", и "Elmo".

Операционные системы реального времени

Системы реального времени должны отвечать на внешние параметры ввода и создавать новые результаты вывода за ограниченное время, как показано на рисунке 1.3 . Время ответа должно быть ограничено. Очень длительное время ответа может привести к отказу систем реального времени.

Иллюстративным примером системы реального времени является контроллер автомобильной воздушной подушки безопасности. Когда датчики движения воздушной подушки ( акселерометры ) распознают столкновение, системе необходимо среагировать, раскрывая воздушную подушку в течение 10 мс, или система не сработает нужным образом. На высокой скорости с задержкой более 10 мс водитель уже столкнется с рулевым колесом до того, как раскроется подушка.


Рис. 1.3.

В мягкой системе реального времени приоритет имеют критически важные задачи. Мягкая система реального времени обычно удовлетворяет ограничениям отклика реального времени. Примером типичной мягкой системы реального времени является плеер мультимедиа . Плеер может иногда пропустить видео кадр или аудио сэмпл, и пользователь может это даже не заметить, пока плеер правильно работает большую часть времени.

В жесткой системе реального времени новый результат вывода всегда должен быть вычислен в указанных границах времени, или система не сработает. В качестве примера жесткой системы реального времени рассмотрим систему дистанционного управления рулями (т.е., управляемую компьютером). В системе управления полетом самолета, когда летчик перемещает штурвал управления, рули управления полетом должны в ответ переместиться очень быстро, или самолет потеряет устойчивость и упадет. Чтобы обеспечить безопасность , FAA постоянно проверяет и сертифицирует реакцию в реальном времени управляемых компьютером симуляторов полета и самолеты.

Процедуры обмена страниц виртуальной памяти и сборки мусора, необходимые объектно-ориентированным языкам, могут вызывать проблемы в жестких системах реального времени. Даже кэширование является иногда проблемой, так как может приводить к изменению времени выполнения программы.

Многие встроенные системы являются системами реального времени с несколькими входами и выходами. Несколько событий происходят независимо друг от друга. Программирование упрощается при разделении задач, но это требует от ЦП постоянного переключения между различными задачами. Операционная система , которая поддерживает мультизадачность, обеспечивает разделение времени ЦП между несколькими задачами. ОС обеспечивает также элементы синхронизации, необходимые для координации действий между различными задачами, выполняющимися параллельно.

Операционные системы часто классифицируют по их характеристикам реального времени. Операционная система реального времени должна быть тщательно спроектирована, чтобы поддерживать приложения реального времени. Недавнее исследование приходит к выводу, что 95% приложений реального времени требуют ограниченного времени ответа в диапазоне от 0.5 до 10 мсек. Только 10% отклонение (колебание от 50 микросекунд до 1 мсек) во времени ответа может быть допустимо. Согласно таким требованиям большинство операционных систем общего назначения не являются системами реального времени. Согласно этим критериям встроенная ОС, такая как Windows XP, может рассматриваться в лучшем случае только как мягкая ОС реального времени . Для Windows XP существуют некоторые инструменты сторонних поставщиков, которые улучшают время ответа.

Операционные системы для встроенных систем

Большинство новых устройств имеет сложное программное обеспечение , которое требуется для мультизадачности, синхронизации задач, поддержки широкого диапазона устройств ввода/вывода, планирования и буферизации операций ввода/вывода, управления памятью, поддержки графических дисплеев, файловых систем, сетей, безопасности и управления питанием. Операционная система может предоставить все эти возможности, чтобы помочь разработчикам приложений. Прикладные программисты будут более продуктивными, так как они работают на более высоком уровне абстракции, используя эти средства, предоставляемые операционной системой.

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

Лицензионные отчисления типичной коммерческой встроенной ОС составляют только несколько долларов на устройство. Некоторые очень простые устройства могут обходиться без ОС, но новые устройства постоянно становятся все более сложными.

В связи с этим большинство встроенных устройств используют встроенную операционную систему. Встроенные операционные системы обычно разрабатываются большей частью на C/C++ и поставляются вместе с компилятором C/C++, ассемблером, и инструментами отладки, чтобы помочь разработчикам в разработке прикладных программ и тестировании устройства. Инструменты разработки встроенных систем должны также поддерживать выполнение программ с помощью кода, хранящегося в энергонезависимой памяти, такой как ROM или память Flash .

Я разработал немногим более 10 электронных устройств и вполне обходился в их низкоруровневой работе без операционной системы. Ситуация поменялась, когда функционал следующего девайса резко расширился. Кроме того, появилась необходимость в задаче, которая вызывается через заданные интервалы времени, причем точность вызова влияет на результат. Также стало понятно, что написать все ПО за выделенное время не получится, и оно будет создано позже. После недолгих размышлений я понял, что в проект необходимо включить операционную систему реального времени (ОСРВ или RTOS).

В отличие от ПК, где ОС – это больше слой для работы с системными ресурсами, для микроконтроллера ОСРВ – это в первую очередь планировщик задач, собственно он и играет главную роль в «реальном времени». На данный момент для меня важно обеспечить так называемое «псевдопараллельное» выполнение задач. То есть существует несколько задач с одинаковым приоритетом и важно вызывать их в заданном порядке через заданные интервалы времени.

Нагляден следующий пример: в проекте Евробот 2011 в системе присутствовало 18 периферийных устройств. 2 электронных платы можно было по функционалу объединить в одно. Снизилась бы их стоимость, повысилась надежность (уменьшили число компонентов в системе), увеличилось количество свободного места в корпусе. Обстоятельство осложняет то, что число задач растет пропорционально и тут уже не обойтись без ОС. Также ОСРВ помогает избежать возможных простоев работы процессора, например, во время преобразования АЦП вы можете заблокировать эту задачу и выполнять другие, тем самым правильно распределяя работу устройства. Важно и то, что теперь устройство не упадет из-за сбоя в задаче, вместо этого возможно сохранение частичной работоспособности (хотя это и может привести к непредсказуемым результатам). За счет чего мы обеспечиваем рост этих показателей? По сути, мы выжимаем из МК все возможное, эффективно используя его вычислительные возможности.

После недолгих поисков выбор пал на freeRTOS. Эта ОСРВ распространяется в исходниках на С и портирована на 27 архитектур. Последнее обстоятельство для меня – решающее. Оно снизит трудозатраты при работе с МК других производителей. Сейчас же меня больше интересует порт для AVR.

Наличие ОСРВ freeRTOS в проекте съедает у вас около 9.8 Кб памяти программ и 1.8 Кб ОЗУ. К примеру для ATmega32 и компиляторе WinAVR это 60% и 85% соответственно. Уже для этой модели создать девайс с большим функционалом сложно – не хватит памяти. Но эта проблема отпадает при использовании новых моделей AVR. Это совершенно нипочем для Mega2560 с ее 256Кб памяти программ и 8 Кб ОЗУ. Тенденция будущих МК только сопутствует успеху ОСРВ.

Бегло пробежавшись по рунету, я с удивлением обнаружил, что нет документации на ОС на русском языке. Да какое тут! Оригинальная документация распространяется за дополнительную стоимость. Ситуацию упростила статья Андрея Курница ([email protected]) из журнала «Компоненты и технологи». По согласию с автором я буду использовать материалы статьи в переработанном варианте. Его статья вполне может послужить документацией на русском языке. Но оригинал недоступен в печатном виде, сайт журнала лежит, поэтому материал придется немного переработать. В целом, автор сделал отличную статью и нет смысла еще раз пройтись по теории, она будет полностью опубликована здесь. Оригинал статьи будет приложен в конце публикации. Также я заметил, что у пользователей возникли трудности при компиляции ОСРВ. Это связано с тем, что используется внешний makefile, в котором прописаны пути к папкам. Поэтому я приложу готовый проект в виде шаблона для AVR Studio и AVR Eclipse. К сожалению, родной makefile не выводит отладочную информацию, такую, как степень занятости ОЗУ и памяти программ, это пришлось пофиксить, добавив соответствующий стандартный вызов.

Итак, кратко про необходимость, в вашем проекте желательно использовать ОСРВ, если необходимо:

Организовать мультизадачность и поочередное выполнение задач

Обеспечить запуск задачи через строго определенные интервалы времени

Передать информацию от одной задачи к другой

Добавлять по мере необходимости новые задачи

Преимущества ОСРВ перед М К:

  1. Многозадачность. ОСРВ предоставляет программисту готовый, отлаженный механизм многозадачности. Каждую задачу в простом случае можно программировать отдельно, всю работу разбить между несколькими членами команды. Не нужно заботиться о переключении между задачами, это сделает планировщик.
  2. Временная база. Необходимо отмерять интервалы времени. ОСРВ должна иметь этот инструмент. Он позволит выполнять действия через строго выделенные интервалы времени.
  3. Обмен данными между задачами. Для этого в ОСРВ используется очередь.
  4. Синхронизация. Если разные задачи используют один и тот же ресурс, например последовательный порт, то можно использовать мьютексы и критические секции. Если необходимо выполнять задачи в строгой последовательности или при наступлении определенного события, то можно использовать семафоры или сигналы для синхронизации задач.

Недостатки ОСРВ :

1. Резкое увеличение потребной памяти программ для реализации ядра

2. Увеличение потребной ОЗУ для хранения стека каждой задачи, семафоров, очередей, мьютексов и других объектов ядра системы.

3. Задержки при переключении между задачами на сохранение контекста.

Описание freeRTOS :

FreeRTOS – это бесплатная ОС жесткого реального времени с открытым исходным кодом. Преимущественно написана на С, но присутствуют ассемблерные вставки. Она была разработана компанией Real Time Engineers ltd специально для встраиваемых систем. Недавно начал развиваться проект «SafeRTOS»- доработанный, документированный, протестированный и прошедший сертификацию на соответствие стандарту безопасности IEC 61508 вариант FreeRTOS. Этим проектом занималась немецкая компания и теперь safeRTOS используется в аэрокосмической промышленности и медицинской технике. Также существует проект openRTOS - коммерческая версия с гарантией производителя.

Основные характеристики freeRTOS :

1. Планировщик поддерживает 3 типа многозадачности:

Вытесняющую

Кооперативную

Гибридную

2. Размер ядра составляет 9.8 Кб в скомпилированном виде для AVR. (WINAVR)

3. Основа ядра – 4 файла на С.

4. Поддерживает задачи и сопрограммы. Сопрограммы специально созданы для МК с малым объемом ОЗУ.

5. Богатые возможности трассировки.

6. Есть возможность отслеживать переполнение стека.

7. Нет программных ограничений на количество одновременно выполняемых задач.

8. Нет ограничения на количество приоритетов задач.

9. Нескольким задачам может быть назначен одинаковый приоритет

10. Развитые средства синхронизации «задача-задача» и «задача-прерывание»:

Очереди

Двоичные семафоры

Счетные семафоры

Рекурсивные семафоры

Мьютексы

11. Мьютексы с наследованием приоритета.

12. Поддержка модуля защиты памяти для Cortex-M3

13. Поставляется в отлаженном виде с демо-проектами для различных платформ и компиляторов.

14. Бесплатна. Можно использовать в проектах без раскрытия исходного кода в соответствии с расширенной лицензией GPL.

15. Документация платная, но доступна в онлайн здесь.

16. Время переключения контекста для AVR с кварцем на 16Мгц составит всего 20.8 мкс. Именно столько нужно для сохранения данных в стек задачи и вызов следующей. (Интересное замечание, если сравнить это с PIC18xxx, то контроллер от AVR делает это быстрее в 4 раза!!!, скорее всего это связано с качеством компилятора)

Вытесняющая многозадачность означает, что выполняющаяся задача с низким приоритетом перекрывается готовой задачей с более высоким приоритетом. Переключение между задачами происходит через равные кванты времени. Поэтому прежде, чем выскопоприоритетная задача начнет выполнение, должен закончиться текущий квант времени, когда выполняется низкоприоритетная.

Таким образом, время реакции FreeRTOS на внешние события в режиме вытесняющей многозадачности-не больше одного кванта времени планировщика, который можно за­давать в настройках. По умолчанию он равен 1 мс.

Если готовы к выполнению несколько за­дач с одинаковым приоритетом, то в таком случае планировщик выделяет каждой из них по одному кванту времени, по истечении которого управление получает следующая задача с таким же приоритетом, и так далее по кругу.

Кооперативная многозадачность отличается от вытесняющей тем, что планировщик самостоятельно не может прервать выполнение текущей задачи, даже готовая к выполнению задача с большим приоритетом. Каждая задача должна самостоятельно передать управление планиров­щику. Таким образом, высокоприоритетная задача будет ожидать, пока низкоприоритет­ная завершит свою работу и отдаст управле­ние планировщику. Время реакции системы на внешнее событие становится неопреде­ленным и зависит от того, как долго текущая задача будет выполняться до передачи управ­ления. Кооперативная многозадачность при­менялась в семействе ОС Windows 3.x.

Вытесняющая и кооперативная концеп­ции многозадачности объединяются вместе в гибридной многозадачности, когда вызов планировщика происходит каждый квант времени, но, в отличие от вытесняющей многозадачности, программист имеет воз­можность сделать это принудительно в теле задачи. Особенно полезен этот режим, ког­да необходимо сократить время реакции си­стемы на прерывание. Допустим, в текущий момент выполняется низкоприоритетная за­дача, а высокоприоритетная ожидает насту­пления некоторого прерывания. Далее про­исходит прерывание, но по окончании ра­боты обработчика прерываний выполнение возвращается к текущей низкоприоритетной задаче, а высокоприоритетная ожидает, пока закончится текущий квант времени. Однако если после выполнения обработчика преры­вания передать управление планировщику, то он передаст управление высокоприори­тетной задаче, что позволяет сократить время реакции системы, связанное с внешним событием.

С чего на чат ь?

Начать разработку микроконтроллерного устройства, работающего под управлением FreeRTOS, можно с загрузки ее последней версии .

Дистрибутив FreeRTOS доступен в виде обычного или самораспа­ковывающегося ZIP-архива. Дистрибутив Содержит непосредственно код ядра (в виде нескольких заголовочных файлов и файлов с исходным кодом) и демонстраци­онные проекты (по одному проекту на каж­дую среду разработки для каждого порта). Далее следует распаковать архив в любое подходящее место на станции разработки.

Несмотря на достаточно большое количе­ство файлов в архиве, структура директорий на самом деле проста. Если планируется проектировать устройства на 2-3 архитектурах в 1-2 средах разработки, то большая часть файлов, относя­щихся к демонстрационным проектам и раз­личным средам разработки, не понадобится.

Подробная структура директорий приве­дена на рисупке.

Весь исходный код ядра находится в ди­ректории /Source.

Содержимое:

1.tasks.c - реализация механизма задач, планировщик

2. queue.c - реализация очередей

3. list.c - внутренние нужды планировщика, однако функции могут использоваться и в прикладных программах.

4. croutine.c - реализация сопрограмм (мо­жет отсутствовать в случае, если сопро­граммы не используются).

Заголовочные файлы, которые находятся в директории source/include

1. tasks.h, queue.h, tist.h, croutine.h - заголо­вочные файлы соответственно для одно­именных файлов с кодом.

2. FreeRTOS.h -содержит препроцессорные директивы для настройки компиляции.

3. mpu_wrappers.h - содержит переопреде­ления функций программного интерфейса (API-функций) FreeRTOS для поддержки модуля защиты памяти (MPU).

4. portable.h -платформозависимые на­стройки.

5. projdefs.h -некоторые системные определения

6. semphr.h - определяет API-функции для работы с семафорами, которые реализо­ваны на основе очередей.

7. StackMacros.h - содержит макросы для контроля переполнения стека. Каждая аппаратная платформа требу­ет небольшой части кода ядра, которая реа­лизует взаимодействие FreeRTOS с этой платформой. Весь платформенно-зависимый код находится в поддиректории /Source/Portable , где он систематизирован но средам разработ­ки (IAR, GCC и т.д.) и аппаратным платфор­мам (например, AtmelSAM7S64,MSP430F449). К примеру, поддиректория /Source/Portable/ GCC/ATMega323 содержит файлы port.c и portmacro.h, реализующие сохранение/вос­становление контекста задачи, инициализа­цию таймера для создания временной базы, инициализацию стека каждой задачи и дру­гие аппаратно-зависимые функции для ми­кроконтроллеров семейства mega AVR и ком­пилятора WinAVR (GCC).

Отдельно следует выделить поддиректорию /Source/Portable/MemMang , в которой со­держатся файлы heap_l.c, heap_2.c, heap_3.c , реализующие 3 различных механизма вы­деления памяти для нужд FreeRTOS, которые будут подробно описаны позже.

В директории /Demo находятся готовые к компиляции и сборке демонстрационные проекты. Общая часть кода для всех демонстра­ционных проектов выделена в поддиректо­рию /Demo/Commo n.

Чтобы использовать FreeRTOS в своем про­екте, необходимо включить в него файлы ис­ходного кода ядра и сопутствующие заголо­вочные файлы. Нет необходимости модифи­цировать их или понимать их реализацию.

Например, если планируется использо­вать порт для микроконтроллеров MSP430 и GCC-компилятор, то для создания проекта -с нуля» понадобятся поддиректории /Source/ Portable/GCC/MSP430_GCC и /Source/Portable/ MemMang . Все остальные поддиректории из директории /Source/Portable не нужны и мо­гут быть удалены.

Если же планируется модифицировать существующий демонстрационный проект (что, собственно, и рекомендуется сделать в начале изучения FreeRTOS), то понадобят­ся также поддиректории /Demo/msp430_GCC и /Demo/Common . Остальные поддиректо­рии, находящиеся в /Demo, не нужны и могут быть удалены.

При создании приложения рекомендует­ся использовать makefile (или файл проекта среды разработки) от соответствующего демонстрационного проекта как отправную точку. Целесообразно исключить из сборки (build) файлы из директории /Demo, заменив их своими, а файлы из директории /Source - нетронутыми. Следует упомянуть также о заголовочном файле FreeRTOSConfig.h , который находит­ся в каждом демонстрационном проекте. FreeRTOSConfig.h содержит определения (#define), позволяющие произвести настройку ядра FreeRTOS:

1. Набор системных функций.

2. Использование сопрограмм.

3. Количество приоритетов задач и сопрограмм

4. Размеры памяти (стека и кучи).

5. Тактовая частота МК.

6. Период работы планировщика времени, выделяемый каждой задаче выполнения, который обычно равен 1 мс. Отключение некоторых системных функций и уменьшение количества приоритетов (уменьшает расход памяти).

В дистрибутив FreeRTOS включены также средства для конвертирования трассировочной информации, полученной от планировщика, в текстовую форму (ди­ректория /ТгасеСоn ) и текст лицензии (директория /License ).

Выводы

С помощью первой статьи цикла читатель познакомился с операционной системой ля микроконтроллеров FreeRTOS. Показаны особенности работы. Описапо содержимое дистрибутива FreeRTOS. Приведены основные шаги, с которых следует начинать разработку устройства, работающего под управлением FreeRTOS.

В следующих публикациях внимание бу­дет уделено механизму многозадачности, а именно задачам и сопрограммам. Будет приведен образец работы планировщика на примере микроконтроллеров AVR фирмы Atmel и компилятора WinAVR (GCC).

ОСРВ обеспечивает разработчика основой, на которой выстраиваются и организуются элементы системы. На самом деле преимущества простираются гораздо шире реально-временного аспекта - даже для систем, не нуждающихся в этом, потому что программа может быть гораздо лучше организована, если основана на ОСРВ.


Интеграция ОСРВ позволяет решить множество проблем, которые могут возникнуть с программой приложения, так как она обеспечивает возможность многозадачности и позволяет разбивать приложение на более мелкие части (задачи). Каждая задача получает свой собственный приоритет, основанный на её важности, а преимущественное планирование гарантирует, что микроконтроллер будет выполнять задачу, имеющую наивысший приоритет среди задач, готовых к запуску. В большинстве случаев, добавление задачи с более низким приоритетом не влияет на скорость реакции системы по отношению к высокоприоритетным задачам.


В настоящее время ARM- и Cortex- базируемые микроконтроллеры доступны примерно по той же цене, что и 8-, или 16-битные микроконтроллеры. Предлагаемая ими дополнительная работоспособность означает, что специализированная система отлично справится с работой ОСРВ. Кроме того, возросшая сложность современных приложений позволит извлечь выгоду из проектов, использующих ОСРВ. Однако, микроконтроллер должен иметь по меньшей мере от 16 до 32 КВ флэш-памяти или памяти программ, чтобы можно было успешно использовать ОСРВ.

ВЫБОР ОСРВ

ОСРВ – это лишь один компонент полной экосистемы разработки. Подобная сложность, связанная с широким рядом доступных продуктов, вызывает новые вопросы. Разработчик должен решить - какая ОСРВ идеально подходит к приложению и какая ОСРВ идеальна для микроконтроллера. Хочется надеяться, что в обоих случаях - одна и та же. Вдобавок, разработчик должен выбрать инструменты для программирования и отладки, которые хорошо работают под выбранной ОСРВ. К счастью, сегодня доступны объективные источники информации для разработчиков, которые помогут им ответить на вышеупомянутые вопросы.

ВЫСОКОПРИОРИТЕТНЫЕ / НИЗКОПРИОРИТЕТНЫЕ

Основная проблема в системах реального времени – это время, требуемое для отклика на прерывание и запуска пользовательского кода (задачи), чтобы обработать прерывание. Системы, не использующие ОСРВ, известны как высокоприоритетные/низкоприоритетные (foreground/background) и работают, как показано на рис.1. Приложение вызывает модули для выполнения желаемых операций: низкоприоритетные модули выполняются последовательно в основном цикле программы, а прерывания обрабатывают асинхронные события с высоким приоритетом. Типичные приложения будут выполнять много опросов и программа будет становиться беспорядочной, по мере роста приложения. Без ОСРВ также приходится самому реализовывать такие полезные сервисы как временные задержки и таймеры, необходимые для выполнения программы со множеством конечных автоматов.

рисунок 1

МНОГОЗАДАЧНОСТЬ

Многозадачность (multitasking) – это процесс планирования и переключения процессора между несколькими задачами, делящими между собой процессор. Один из наиболее важных аспектов многозадачности в том, что она позволяет программисту приложения управлять комплексностью, присущей современным приложениям. ОСРВ может сделать программы приложения проще в проектировании и обслуживании, управляя задачами и передачей информации между ними.

Когда системе нужно запустить другую задачу по причине наступления более важного события, текущее содержимое регистров процессора сохраняется как часть текущей задачи. Контекст новой (более важной) задачи – перед выполнением ее кода восстанавливается в прежнее состояние. Эту процедуру выполняет так называемый переключатель контекста или переключатель задач. Текущая вершина стека для каждой задачи наряду с другой информацией хранится в структуре данных, называемой блоком управления задачей (Task Control Block), который управляется ОСРВ.

ПЛАНИРОВАНИЕ

Порядок, в котором выполняются задачи, определяется планировщиком (scheduler) или диспетчером (dispatcher). Существует два типа планировщиков: кооперативный (non pre-emptive) и вытесняющий (pre-emptive).


В кооперативном планировщике задачи взаимодействуют (кооперируются) друг с другом чтобы получить контроль над процессором: когда задача освобождает процессор, ядро выполняет код следующей, наиболее важной, готовой к запуску задачи. Асинхронные события всё ещё обслуживаются обработчиками прерываний, которые могут сделать высокоприоритетную задачу готовой к выполнению, но обработчик прерываний всегда возвращается к прерванной задаче. Новая задача с более высоким приоритетом получит доступ к процессору только тогда, когда текущая задача добровольно освободит процессор, как показано на рисунке 2.

рисунок 2

Когда в вытесняющем планировщике, показанном на рисунке 3, событие, или обработчик прерываний делает задачу с более высоким приоритетом готовой к выполнению, текущая задача немедленно приостанавливается и доступ к процессору получает задача с более высоким приоритетом. Большинство систем реального времени используют вытесняющие планировщики, потому что они реагируют быстрее, нежели кооперативные ядра.

рисунок 3

РЕСУРСЫ

Очевидная выгода от использования ОСРВ в том, что она сокращает время выхода на рынок (time to market), поскольку упрощает разработку, не потребляя при этом большого количества ресурсов процессора. uC/OS-II от Micrium, например, использует только от 6 до 24 КВ памяти программ и от 1 до 8 КВ памяти данных на ARM- устройствах. На небольших 8- или 16-битных платформах затраты ещё меньше – только от 4 до 16 КВ памяти программ.


ОСРВ, как правило, имеет детерминированную характеристику, то есть заданный набор критических задач может быть целиком выполнен к установленному сроку. Опрос (polling) избегается благодаря выполнению задач только во время возникновения событий. Задачи, ожидающие события, не потребляют циклы процессора.

КОММЕРЧЕСКИЕ ПРЕИМУЩЕСТВА ОСРВ

Некоторые компании используют ОСРВ собственной разработки, но их системы могут страдать от недостатка документации и расширенного тестирования. Собственные ОСРВ обычно не могут быть перенесены на другие процессоры и их код зачастую несовершенен. Хуже того, если проектировщик, который их создал, покидает компанию, может оказаться, что систему невозможно обслуживать.


Коммерческая ОСРВ используется в сотнях, если не тысячах проектов, и базируется на испытанном коде, дающем уверенность в ее работоспособности. uC/OS-II от Micrium имеет сертификат FAA/FDA/IEC, что позволяет использовать ее в авиационной электронике, медицине и других типах приложений, требовательных к безопасности. Даже если устройство не нуждается в надежности ОСРВ, сертифицированных для авиационной электроники, всё таки приятно знать, что ОСРВ прошла расширенное тестирование. uC/OS-II также в высшей степени мобильна и может работать на более чем 45 различных процессорах. Код приложения может быть легко перенесён (портирован) с 8-битной на 32-битную архитектуру и даже на DSP. Пользователь обеспечивается полномасштабной поддержкой и документацией.


Большинство сервисов, которые могут потребоваться приложению, уже интегрированы в ОСРВ. Среди них:

Управление временем (time management) – временные задержки и таймеры
- Управление задачами (task management) – создание, удаление, приостановка, возобновление
- Взаимоисключения
- Передача сообщений
- Передача сигналов

Преимущества использования ОСРВ подчеркиваются доступностью полного портфолио компонентов встроенного программного обеспечения (ПО), а также промежуточного ПО, включая стек TCP/IP, стек USB, стек CANbus, UART, файловые системы и графический интерфейс пользователя. Конечно, некоторые компоненты могут потребовать большего быстродействия, чем то, которым располагают low-end процессоры.

Два направления в индустрии коммерческих ОСРВ делают начало работы с ними еще проще. Многие ОСРВ, включая uC/OS-II теперь продаются на основе, не требующей авторских выплат, что гораздо выгоднее, чем использование ОСРВ, которые требуют непрерывной уплаты роялти. Зачастую, ОСРВ входит, в случае приобретения лицензии, во многие стартовые наборы (MCU starter kits).

ЗАКЛЮЧЕНИЕ

ОСРВ – бесценный инструмент, упрощающий разработку большинства встраиваемых приложений – реального времени, или нет – и позволяющий добавление новых функций, не требуя больших изменений в ПО. Учитывая небольшие системные издержки, использование ОСРВ в настоящее время оправдано во многих малых 8- и 16-битных встраиваемых системах, а также в системах с 32-х битными или более мощными процессорами.

Что приходит на ум когда слышишь операционная система? Наверняка форточки, линукс, макось.. или что нибудь подобное. Верно, и на вопрос зачем она нужна, все уверенно ответят: послушать музыку, поиграть в игру (по интернету!), разговаривая при этом с другом по скайпу. Заодно созерцая, как мигает светодиодик, получив байт с юарта =).

А если копнуть глубже, то прослушивание музыки, пересылка данных по Интернету — это все одиночные процессы, а так как процессор у нас один, то одновременно он может выполнять только одну задачу. Поэтому задачи выполняются поочередно небольшими «порциями», суть ОС делать это незаметно для пользователя: чтобы звук не хрипел и байтики слались и все работало одновременно. При этом, если одна из задач «повиснет», то все остальное продолжало работать.

Если отбросить все лишние плюшки и оставить голую суть, то в первую очередь ОС это просто таймер, который отсчитывает равные промежутки времени, а также сам без участия пользователя переключается между задачами, выполняет какую то часть и снова переключается. Также нужно учесть, что большинство задач могут не успевать выполниться за один квант времени, поэтому нужно сохранять состояние задачи в момент переключения на другую, а в следующий раз восстанавливать состояние переменных. Управлением всего этого занимается планировщик заданий.

Есть два основных вида ОС: вытесняющая и кооперативная. В первом случае, переключение между задачами будет «жестким», т.е. если квант времени 1мс, то сначала первая задача будет выполняться ровно 1мс, затем вторая ровно 1мс и т.д. Такие оси называются реального времени (ОСРВ). У кооперативных немного попроще, процесс сам должен сказать что «я выполнился», поэтому к ОСРВ их отнести нельзя.

Впердолить вытесняющую на мелкие AVR не получится по причине небольшого количества ОЗУ. Из имеющихся вариантов кооперативок, мне приглянулась mRTOS, почитать подробности сей системы можно на сайте автора (легко гуглится). Главная причина ее использования — простота, наличие готовой версии под CAVR, для понимания общих принципов самое то.

Итак, остались главные вопросы, зачем и когда применять ось. Теоретически, все тоже самое, что вы сделаете с осью, вы можете сговнякать без нее, ибо ресурсы одни и те же. От того, что вы приладите ее к проекту, мегагерцы в космос не взлетят, железо останется тем же, следовательно ресурсы те же.

Поэтому стоит задать себе несколько вопросов:
1.Сможете ли вы распорядиться грамотно ресурсами?
2. Не предполагается ли в процессе написания прошивки изобретать такой же велосипед, подобный планировщику?
3. Насколько читаем Ваш код? Способны ли Вы через полгода-год открыть его и сходу разобраться?
4. Один ли Вы пишите или группой?

На первый вопрос дать ответ сложно, ибо все зависит от криворукости разработчика. Со вторым все более понятно, если есть много независимых задач и планируется выполнять их через определенные промежутки времени, то лучше посмотреть в сторону ОС. С третьим тоже понятно, гораздо проще разбираться в отдельной задаче, чем ковырять зависимости в основном цикле. Если Вы пишите не один, то тут тоже есть плюсы, ибо каждый может писать свою задачу отдельно, не мешая остальным.

Объединяя выше сказанное, сфера применения довольно специфична, под определенный круг задач. Не стоит пихать ее в каждый проект. Для большинства радиолюбительских поделок ось излишня, но имея представление о ней раньше, наверняка бы засунул ее пару проектов.

Теперь заглянем под капот. Для запуска mRTOS к проекту нужно подключить mrtos.c и заинклюдить mrtos.h. Структура кода немного отличается от привычного

#include #include "mrtos.h" //тут тело функции где мы пишем свой супер код void task1() { while (1 ) //задачи в любой ОС построены на базе бесконечного цикла { //тут код Вашей задачи DISPATCH; //функция передачи управления планировщику } ; } //обработчик прерывания таймера 0 interrupt [ TIM0_OVF] void timer0_ovf_isr(void ) { char ii; #asm("cli") TCNT0= 0x9C ; inc_systime() ; for (ii = 0 ; ii< init_tasks; ii++ ) if (tasks[ ii] .delay ) -- tasks[ ii] .delay ; #asm("sei") } void main(void ) { //инициализация периферии Init_mRTOS() ; //инициализация ос //тут создаем таски(задачи) здесь создано 3 задачи create_task(task1, 1 , Active) ; //создать задачу (имя задачи, приоритет, статус) create_task(task2, 1 , Active) ; create_task(task3, 1 , Active) ; Sheduler() ; //запуск планировщика while (1 ) ; }

#include #include "mrtos.h" //тут тело функции где мы пишем свой супер код void task1() { while(1)//задачи в любой ОС построены на базе бесконечного цикла { //тут код Вашей задачи DISPATCH; //функция передачи управления планировщику }; } //обработчик прерывания таймера 0 interrupt void timer0_ovf_isr(void) { char ii; #asm("cli") TCNT0=0x9C; inc_systime(); for(ii = 0; ii

Теперь подробнее. количество задач указывается в mrtos.h дефайном APPTASKS N. Задача объявляется внутри task1(){}, task2(){} и тому подобное, внутри while(1) не нужно ничего писать, вызывать функции тоже никак не нужно, все это сделает за вас планировщик. Как видно задача состоит из бесконечного цикла, это нормально так и должно быть, но внутри задачи нужно обязательно отдавать управление планировщику. Либо функцией WAIT, либо DISPATCH. Если этого не сделать, то задача будет выполняться бесконечно.

Как это работает? Создадим таск мигания светодиодом.

void task1() { while (1 ) { PORTB.0 = ! PORTB.0; WAIT(100 ) ; } ; }

void task1() { while(1) { PORTB.0 = !PORTB.0; WAIT(100); }; }

WAIT это некий аналог delay() только, во время делея микроконтроллер ничего не выполняет и гоняет пустые циклы. Во время же WAIT управление передается другим задачам. Т.е. можно создать кучу тасков миганиями разных светодиодов, с разным WAIT и все они будут мигать с разной частотой. Если задержки не нужны то в конце используетм DISPATCH.

При использовании WAIT важно понимать, что вся система имеет минимальный тик (квант времени), поэтому мы ждем не WAIT(50) 50 милисекунд, а 50 тиков системы. Настройка тика зависит от того, как часто вызывается прерывания таймера0, т.е. если мы настроили прерывание на 1мс, то мы можем предполагать, что наше действие выполнится в течение 1мс. Опыты показали что уменьшить системный тик можно до ~20 мкс при тактовой 16МГц.

Настройка таймера ничем не отличается изученного ранее, так как таймер0 имеет только прерывание по переполнению, то все настройки завязаны на это. В последних версиях CAVR очень удобно сделано можно писать time requiments, настройки автоматически сгенерятся.

create_task(task1, 1 , Active) ;

create_task(task1,1,Active);

С приоритетами все довольно таки не просто. Если имеются две задачи с разными приоритетом и задача с большим приоритетом постоянно выполняется, то в задачу с низким приоритетом мы никогда не зайдем. Поэтому нужно организовывать работу так, чтобы все задачи получали доступ. Заострять внимание на этом не будем, припасем на следующий раз. Состояние задачи, Active — запущена, остановлена StopTask.

Итак, для желающих просто мигнуть светодиодом:

#include #include "mRTOS.h" void task1() { while (1 ) { WAIT(1000 ) ; PORTB.0=! PORTB.0; } } // Timer 0 overflow interrupt service routine interrupt [ TIM0_OVF] void timer0_ovf_isr(void ) { char ii; #asm("cli") TCNT0= 0xb2 ; inc_systime() ; for (ii = 0 ; ii< init_tasks; ii++ ) if (tasks[ ii] .delay ) -- tasks[ ii] .delay ; #asm("sei") } void main(void ) { DDRB= (1 << DDB7) | (1 << DDB6) | (1 << DDB5) | (1 << DDB4) | (1 << DDB3) | (1 << DDB2) | (1 << DDB1) | (1 << DDB0) ; PORTB= (0 << PORTB7) | (0 << PORTB6) | (0 << PORTB5) | (0 << PORTB4) | (0 << PORTB3) | (0 << PORTB2) | (0 << PORTB1) | (0 << PORTB0) ; // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 7,813 kHz TCCR0= (0 << CS02) | (1 << CS01) | (1 << CS00) ; TCNT0= 0x83 ; // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK= (0 << OCIE2) | (0 << TOIE2) | (0 << TICIE1) | (0 << OCIE1A) | (0 << OCIE1B) | (0 << TOIE1) | (1 << TOIE0) ; Init_mRTOS() ; create_task(task1, 1 , Active) ; Sheduler() ; while (1 ) ; }

#include #include "mRTOS.h" void task1() { while(1) { WAIT(1000); PORTB.0=!PORTB.0; } } // Timer 0 overflow interrupt service routine interrupt void timer0_ovf_isr(void) { char ii; #asm("cli") TCNT0=0xb2; inc_systime(); for(ii = 0;ii

В качестве бонуса я попробовал сделать полифоническую (двухголосую) мелодию «Dr.Mario chill». Идея в том, что каждая ножка контроллера постоянно инвертируется в отдельном таске, тем самым генерируя частоту. Меняя задежку можно менять высоту ноты.

void task2(void ) { while (1 ) { if (mute == 0 ) //если разрешено играть { if (note_ch2[ n_n] == 0 ) //если пауза то ждем, ничего не играем { PORTB.4 = 0 ; WAIT(5 ) ; } else { PORTB.4 = ! PORTB.4; //если не пауза то дрыгаем ногой с нужной частотой WAIT(note_ch2[ n_n] ) ; } } } }

void task2(void) { while(1) { if(mute == 0) //если разрешено играть { if(note_ch2 == 0) //если пауза то ждем, ничего не играем { PORTB.4 = 0; WAIT(5); } else { PORTB.4 = !PORTB.4; //если не пауза то дрыгаем ногой с нужной частотой WAIT(note_ch2); } } } }

Я не заморачивался с идеей, в 1 таске генерится меандр с частотой ноты для соло партии, во втором для баса. Высота каждой ноты берется из массивов. Длительность, переключение и обрывание в таске3.

void task3(void ) { while (1 ) { WAIT(1500 ) ; //играем минимальную длительность ноты for (mute = 0 ; mute < 500 ; mute++ ) //обрываем ноту, чтобы не сливались { PORTB.3 = 0 ; PORTB.4 = 0 ; } ; mute = 0 ; //выставляем флаг, что можно воспроизводить звук n_n++; //переходим на следующую ноту if (n_n == n_max) //если сыграли все то идем по кругу { n_n = 0 ; } } }

void task3(void) { while(1) { WAIT(1500); //играем минимальную длительность ноты for(mute = 0; mute < 500; mute++) //обрываем ноту, чтобы не сливались { PORTB.3 = 0; PORTB.4 = 0; }; mute = 0; //выставляем флаг, что можно воспроизводить звук n_n++; //переходим на следующую ноту if(n_n == n_max) //если сыграли все то идем по кругу { n_n = 0; } } }

Чтобы смешать два канала использовал простенькую схемку.

Итого небольшой кусочек

Для желающих прошивка

Статьи по теме: