Мы начнем эту лекцию с введения в операционную систему реального времени FreeRTOS, а затем более подробно рассмотрим её особенности. Следующий шаг - понять содержание и структуру дистрибутива FreeRTOS, который мы будем использовать на протяжении всего курса.
Далее мы объясним различные компоненты FreeRTOS и то, как они работают и взаимодействуют друг с другом, чтобы обеспечить инфраструктуру для создания встраиваемых приложений. После понимания процесса создания приложений мы завершим лекцию демонстрацией запуска примера приложения в симуляторе QEMU.
Ознакомившись с этой лекцией, читатель сможет:
FreeRTOS - одна из наиболее часто используемых операционных систем реального времени (RTOS), распространяемая под открытой лицензией MIT. FreeRTOS - это RTOS, ориентированная на микроконтроллеры и небольшие микропроцессоры. Она включает ядро и растущий набор библиотек IoT, подходящих для использования во всех отраслях промышленности. FreeRTOS создана с акцентом на надежность и простоту использования.
В следующем разделе мы рассмотрим общие технические требования, требования к обслуживанию и эффективности при создании встраиваемых приложений с FreeRTOS. Затем мы определим некоторые стандартные возможности FreeRTOS.
FreeRTOS позволяет пользователям использовать различные преимущества ядра реального времени по сравнению с созданием исходного встраиваемого приложения. Эти возможности являются типичными требованиями для большинства современных встраиваемых приложений, поскольку одна система может быть приспособлена как к простым, так и к сложным приложениям и должна обеспечивать возможность повторного использования системы в различных компонентах приложения.
Модульность
Модульность является ключевым требованием к программному обеспечению встраиваемых систем, поскольку она позволяет поддерживать масштабируемость программного обеспечения (как в сторону увеличения, так и уменьшения) без ущерба для возможностей и функций приложения.
Абстрагирование информации о времени
Требования системы к синхронизации должны быть поняты и абстрагированы, чтобы их можно было встроить в управляющую программную среду.
Управление питанием
Управление питанием в современных встраиваемых системах является еще одним ключевым фактором. Поскольку все больше и больше приложений требуют работы от батарей, понимание требований к питанию и разработка правильного подхода к управлению питанием важны для создания эффективной встраиваемой системы.
Гибкое управление прерываниями
Следующий шаг - управление различными прерываниями, которые будут возникать в системе. Требования к прерываниям основаны на входах, которые являются частью системы. Они должны быть хорошо понятны, чтобы создавать значимые выходные данные на основе входных.
Требования к смешанной обработке
Встраиваемые системы основаны на нескольких типах входных данных. Некоторые из них являются чисто цифровыми по своей природе, но есть и аналоговые входные данные, которые необходимо зафиксировать, обработать и понять, чтобы сгенерировать требуемый отклик на эти входные данные. Встраиваемая система должна поддерживать смешанную обработку, чтобы она могла обрабатывать различные типы входных данных.
Управление временем простоя системы
Последний вопрос заключается в том, как и когда система может потенциально простаивать, и что следует делать в это время в системе.
Тестируемость
Одним из ключевых аспектов при разработке системы является возможность её обслуживания и быстрого и эффективного устранения любых поломок. Для обеспечения этого требования важно иметь возможность тестирования на любые потенциальные сбои во время разработки системы, а также воспроизведения любых сбоев, выявленных во время эксплуатации системы. Поэтому, когда система разрабатывается, тестируемость должна быть встроенной частью дизайна, включая определение того, что должно быть протестировано и как это должно быть протестировано.
Удобство обслуживания и расширяемость
Система должна быть разработана таким образом, чтобы её можно было легко обслуживать как в полевых условиях, так и вне их, как с точки зрения аппаратного, так и программного обеспечения. Расширяемость также является ключевым фактором; система должна быть разработана таким образом, чтобы упростить добавление функций после завершения первоначальной версии системы.
Разработка приложений в команде
Сложные приложения часто разрабатываются командами, и дизайн системы должен поддерживать возможность делать это быстро и эффективно. По этой причине система должна быть разработана по модульному принципу, чтобы несколько человек и даже несколько команд могли участвовать в разработке компонентов и модулей приложения без негативного влияния на существующие компоненты.
Повторное использование кода
При необходимости код, разработанный для одной системы, должен быть доступен для повторного использования в других системах с аналогичными требованиями к функциональности. Проектирование системы по модульному принципу будет поддерживать это требование и повысит эффективность создания новых приложений.
Эффективность кода
Наконец, код должен быть разработан таким образом, чтобы эффективно использовать память, и разработчик должен помнить об ограничениях производительности небольших контроллеров, на которых строятся встраиваемые системы.
Ниже перечислены стандартные возможности FreeRTOS (взятые из справочного руководства FreeRTOS):
tick hook functions);idle hook functions);full interrupt nesting model) для некоторых архитектур;FreeRTOS распространяется через Git-репозиторий в виде одного сжатого zip-файла со всем исходным кодом, поэтому пользователи могут свободно использовать его в своих приложениях, а также при необходимости вносить в код любые изменения. Дистрибутив также содержит демонстрационные приложения и демоверсии портов (ports) для различных контроллеров, поддерживаемых FreeRTOS. Эти демоверсии помогают пользователям FreeRTOS быстро адаптировать её к своим требованиям. Многие поставщики микроконтроллеров поставляют RTOS как часть своего набора инструментов, что еще больше облегчает разработку с FreeRTOS.
Последнюю версию FreeRTOS можно загрузить с веб-сайта FreeRTOS. FreeRTOS также размещен на GitHub, и пользователи могут получить последнюю версию исходного кода из каталога Git.
Ключевая часть ядра (core of the kernel) FreeRTOS содержится в трёх файлах, которые находятся в подкаталоге FreeRTOS\FreeRTOS\Source. Это файлы tasks.c, queue.c и lists.c. Для простых приложений этих трёх файлов достаточно. Папка Source содержит подпапку include, в которой находятся файлы include, необходимые для установки.
Существуют и другие файлы, которые могут понадобиться в зависимости от специфической функциональности конкретного приложения.
Каталог Source также содержит подкаталог portable, который содержит подкаталоги с файлами, специфичными для определенных компиляторов и программных инструментов. Код, находящийся в этих папках, может быть использован в качестве отправной точки для создания портов в соответствии с требованиями пользователя.
Папка Demo содержит примеры приложений, портированных на конкретные контроллеры. Пользователи, планирующие использовать контроллер определенного типа, могут использовать один или несколько примеров, представленных в этой папке, в качестве основы для создания приложений для своего контроллера.
Ниже перечислены ключевые компоненты FreeRTOS:
Мы опишем их более подробно в последующих разделах.
Обратите внимание, что во FreeRTOS есть и другие компоненты, которые не рассматриваются подробно в этом курсе. Эти элементы требуются в более сложных приложениях, и их подробный анализ можно найти в руководстве пользователя FreeRTOS.
Все возможности FreeRTOS управляются из файла конфигурации FreeRTOS, FreeRTOSConfig.h. Каждое приложение должно иметь этот файл как часть системы. Он содержит параметры конфигурации для включения функций FreeRTOS, необходимых для данного приложения. Образец конфигурационного файла может быть скопирован из демонстрационного порта, который лучше всего подходит для контроллера, используемого для данного приложения.
Управление памятью осуществляется FreeRTOS для её эффективного использования. Поддерживается как статическое, так и динамическое распределение. Обе схемы имеют свои преимущества и недостатки, в зависимости от приложения. Разработчик приложения выбирает подходящую схему управления памятью в зависимости от требований. Одно и то же приложение может содержать задачи как динамического, так и статического распределения.
FreeRTOS использует собственные методы управления памятью и определяет собственные функции для её выделения, а также для освобождения после использования. Она также определяет несколько методов управления кучей/памятью, что дает пользователю возможность выбрать оптимальную схему, которая лучше всего подходит для его приложения.
Схема распределения памяти во FreeRTOS по умолчанию динамическая. В случаях, когда разработчику приложения требуется больший контроль над управлением памятью для определенных компонентов приложения, он может выбрать статическое распределение памяти для этих задач. FreeRTOS предоставляет отдельный набор функций для компонентов, которым требуется статическое распределение памяти. Эти функции доступны, когда configSUPPORT_STATIC_ALLOCATION имеет значение 1 в файле настроек конфигурации.
Ниже перечислены некоторые преимущества использования динамического распределения памяти (адаптировано из руководства пользователя FreeRTOS):
API RTOS;API RTOS позволяют возвращать информацию об использовании кучи, что позволяет оптимизировать её размер.Ниже перечислены некоторые преимущества использования статического распределения памяти (адаптировано из руководства пользователя FreeRTOS):
FreeRTOS определяет пять схем управления памятью. Они содержатся в отдельных файлах: heap_1.c, heap_2.c, heap_3.c, heap_4.c и heap_5.c, которые находятся в каталоге Source/Portable/MemMang. Пользователи могут добавлять свои собственные реализации по мере необходимости, но хотя бы одна из этих реализаций должна быть включена при компиляции исходного текста FreeRTOS в приложении.
Ниже приводится простое описание каждой из этих реализаций.
heap_1.c
Это простейшая реализация управления памятью. Она похожа на статическое распределение памяти, поэтому это решение может оказаться не очень полезным в текущих реализациях, поскольку FreeRTOS теперь поддерживает статическое распределение нативно. Однако оно очень хорошо подходит для большинства встраиваемых систем, поскольку они занимают мало памяти и являются глубоко встраиваемыми. При такой реализации вся необходимая память всегда выделяется в начале выполнения системы и перераспределяется только при перезагрузке системы.
heap_2.c
heap_2 использует алгоритм наибольшего соответсвия (best-fit) для выделения памяти, и пространство, которое больше не используется, освобождается для дальнейшего использования. Он не объединяет свободные места в один блок перед перераспределением. Эта схема может быть использована, когда во время выполнения приложения происходит многократное удаление и создание задач или других компонентов RTOS. Не рекомендуется использовать эту схему, если освобождаемые и перераспределяемые блоки памяти имеют произвольный размер, так как это может привести к фрагментации памяти. Кроме того, распределение не является детерминированным, но оно более эффективно, чем реализация malloc в языке Си.
heap_3.c
heap_3 - это простая, потокобезопасная обертка вокруг стандартных функций malloc() и free() языка Си. Эта схема требует, чтобы компоновщик настроил кучу, а библиотека компилятора предоставила функции malloc() и free(). Она не является детерминированной и может привести к увеличению размера кода ядра.
heap_4.c
heap_4 использует "первый подходящий" алгоритм (first-fit) для выделения памяти. В отличие от heap_2, он объединяет соседние свободные пространства в более крупный блок, а затем выделяет память; он включает алгоритм коалесценции, который поддерживает эту возможность. Эта схема может быть использована в системах, требующих многократного создания и удаления задач и других компонентов. Поскольку эта реализация объединяет области памяти в более крупные блоки памяти, она с меньшей вероятностью приведет к неправильной фрагментации памяти.
heap_5.c
Эта схема использует те же алгоритмы, что и heap_4, и дополнительно позволяет куче охватывать несколько несмежных свободных областей памяти.
Более подробные объяснения и примеры использования вышеперечисленных схем можно найти в руководстве FreeRTOS.
Задачи - это базовые компоненты FreeRTOS. Они позволяют разработчикам приложений определять конкретные части функциональности, которые должны быть выполнены в определенное время выполнения приложения. Внутри приложения может быть определено любое количество задач. Задачи можно понимать как небольшие подпрограммы, которые доступны для выполнения в течение всего времени работы основного приложения.
Планировщик (scheduler) RTOS отвечает за контроль над тем, какая задача должна быть выполнена в любой момент времени. В одноядерных системах только одна задача может быть активна в приложении в любой момент времени. Поэтому планировщик также отвечает за безопасное включение и выключение каждой задачи, а также за сохранение состояния, чтобы при повторном включении каждая задача возвращалась в свое предшествующее состояние. Это достигается планировщиком FreeRTOS за счёт ведения индивидуального стека для каждой задачи.
Задача может находиться в одном из следующих четырёх состояний:
В этом состоянии задача готова к выполнению, то есть она не находится в состоянии блокировки или приостановки. Однако она не выполняется, потому что на процессоре уже выполняется другая задача с более высоким или равным приоритетом.
В этом состоянии задача выполняется на процессоре. Если система имеет только одно ядро, то в каждый момент времени может выполняться только одна задача.
В этом состоянии задача не готова к выполнению, так как ожидает входных данных от внешних источников, других задач или временных событий (например, события таймера или задержки). Для каждой заблокированной задачи существует тайм-аут, по достижении которого задача переходит из заблокированного состояния в состояние готовности. После истечения тайм-аута задаче не нужно ждать наступления события, которое её блокировало.
Приостановленные задачи не могут автоматически выйти из этого состояния, так как для них не установлен тайм-аут. Они должны быть явно выведены из этого состояния приложением с помощью операции возобновления (resume).
Задачам можно назначать приоритеты по мере необходимости. FreeRTOS позволяет пользователю определить переменное количество уровней приоритетов. Уровни начинаются с 0, а максимальный уровень определяется в файле FreeRTOSConfig.h. Это максимальное значение должно быть разумным, чтобы минимизировать использование оперативной памяти.
Планирование задач осуществляется планировщиком. Планировщик гарантирует, что задачи в состоянии готовности с более высоким приоритетом будут выполняться перед задачами с более низким приоритетом, которые также находятся в состоянии готовности. FreeRTOS может быть настроена на выполнение задач с одинаковым приоритетом в режиме "нарезания времени" (time slicing), для чего в конфигурационном файле задается параметр configUSE_TIME_SLICING. Разделение между задачами с равным приоритетом осуществляется с помощью схемы арбитража round-robin.
Задачи создаются с помощью функции xTaskCreate() или xTaskCreateStatic() и могут быть удалены с помощью функции xTaskDelete().
Параметры могут быть переданы в задачу для дальнейшей обработки с помощью указателя параметров.
Примерная структура реализации задачи представлена ниже.
Шаг 1: Создание двух задач
xTaskCreate( prvQueueReceiveTask, "Rx", configMINIMAL_STACK_SIZE * 2U, NULL, mainQUEUE_RECEIVE_TASK_PRIORITY, NULL );
xTaskCreate( prvQueueSendTask, "Tx", configMINIMAL_STACK_SIZE * 2U, NULL, mainQUEUE_SEND_TASK_PRIORITY, NULL );
Шаг 2: Определение задачи 1 (prvQueueReceiveTask)
static void prvQueueReceiveTask( void *pvParameters )
{
unsigned long ulReceivedValue;
const unsigned long ulExpectedValue = 100UL;
const char * const pcMessage1 = "Blink1";
const char * const pcMessage2 = "Blink2";
const char * const pcFailMessage = "Unexpected value received\r\n";
int f = 1;
/* Remove compiler warning about unused parameter. */
( void ) pvParameters;
for( ;; )
{....
Очереди - основной механизм межзадачного взаимодействия. Задачи могут использовать их для обмена информацией друг с другом. Очереди реализованы как потокобезопасные FIFO (first in first out). Задачи добавляют информацию в конец очереди, а другие задачи, которым нужны данные из очереди, забирают их из начала и обрабатывают. При необходимости задачи также могут перемещать данные не в конец очереди, а в её начало.
FreeRTOS использует метод очереди путем копирования, где данные, отправленные в очередь, копируются в неё. Этот метод обеспечивает простую, но мощную реализацию. Данные могут передаваться через очередь в одном из следующих форматов:
FreeRTOS отвечает за выделение памяти для очереди и за хранение данных по мере необходимости.
В очередях может быть несколько задач, которые пишут в них или читают из них. Обычно в очередь записывают несколько задач, и реже из нее читают несколько задач.
Когда задача пытается читать из пустой очереди, она переходит в состояние "заблокирована", пока либо данные не станут доступны в очереди, либо не будет достигнут тайм-аут блокировки.
Когда задача пытается записать данные в заполненную очередь, она переходит в состояние "заблокирована" до тех пор, пока в очереди не освободится место или не будет достигнут тайм-аут блокировки.
Задачи, которые блокируются, не потребляют процессорное время, поэтому другие задачи могут выполняться.
Если несколько задач блокируются на одной и той же очереди, то задача с наивысшим приоритетом будет разблокирована первой.
В следующем примере показано, как можно реализовать и использовать очереди между двумя задачами.
Шаг 1. Создание очереди
/* Create the queue. */ xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( uint32_t ) );
Шаг 2: Использование очереди
/* Send a value to the queue, causing the task receiving this data from the queue to unblock and toggle the LED. 0 is used as the block time so that the sending operation will not block; it shouldn't need to block, as the queue should always be empty at this point in the code. */ xQueueSend( xQueue, ulValueToSend, 0U );
Помимо очередей, во FreeRTOS есть семафоры и мьютексы, которые можно использовать для межзадачного взаимодействия в зависимости от требований приложения. Более подробно о семафорах и мьютексах во FreeRTOS рассказывается в учебнике FreeRTOS.
Прямые уведомления о задачах (direct task notifications) - это события, отправляемые непосредственно задаче без промежуточного механизма, такого как очередь или семафор. Это ускоряет обмен данными и занимает гораздо меньше места в памяти. Задача блокируется, когда в массиве событий уведомления установлен бит уведомления. Заблокировать задачу может только одно уведомление; если бы произошло другое событие, оно не повлияло бы на состояние задачи.
Потоковые буферы предлагают механизм связи "один к одному" в следующих случаях:
Эти буферы оптимизированы для сценариев однократной записи и однократного чтения. Буферы потоков способны передавать байты, а буферы сообщений - дискретные сообщения переменного размера. Буферы сообщений строятся поверх буферов потоков.
Эти буферы очень полезны для следующих типов коммуникационных сценариев:
Данные передаются посредством копирования, то есть они копируются в буфер отправителем и выводятся из буфера операцией чтения.
Таймеры могут быть реализованы программно в RTOS, поэтому их также можно назвать программными таймерами. Они не используют аппаратные ресурсы и не потребляют процессорное время. Таймер позволяет запускать задачи или события, которые должны произойти в определенный момент в будущем. Будущее время выполнения контролируется настройками таймера. Задача, которая должна быть выполнена, называется функцией обратного вызова таймера. Функция обратного вызова (callback) таймера выполняется по истечении времени таймера или периода таймера.
Как и другие компоненты RTOS, таймер должен быть явно создан, прежде чем его можно будет использовать.
Функциональность программного таймера, в общем, легко реализовать, но трудно реализовать эффективно.
Реализация таймера в RTOS обладает следующими свойствами:
Задача обслуживания таймера в основном использует существующие возможности FreeRTOS, позволяя добавить функциональность таймера в приложение с минимальным влиянием на размер приложения.
Функции обратного вызова таймера выполняются в контексте задачи обслуживания таймера, поэтому важно, чтобы функции обратного вызова таймера никогда не пытались блокировать. Например, функция обратного вызова таймера не должна вызывать vTaskDelay() или vTaskDelayUntil(), а также не должна указывать ненулевое время блокировки при обращении к очереди или семафору.
Два типа таймеров могут быть определены и использованы в приложении:
Однократный таймер выполняется только один раз. По истечении срока действия таймера его обратный вызов вызывается и выполняется один раз.
Таймер автозагрузки выполняется неограниченное время, пока работает приложение. Каждый раз, когда таймер истекает, выполняется обратный вызов, и таймер сбрасывается; таймер снова работает до следующего истечения срока его действия, что приводит к выполнению обратного вызова. Этот процесс повторяется, что приводит к периодическому выполнению обратного вызова.
Лучше всего начать создание нового приложения, использующего FreeRTOS, с демонстрационного приложения для выбранного процессора. Рекомендуется модифицировать демо-версию в соответствии с текущими требованиями. Это обеспечит хорошую отправную точку для приложения и устранит многие проблемы портирования (porting), которые могут возникнуть при создании нового приложения с использованием FreeRTOS.
Затем разработчик должен указать следующую предварительную информацию, необходимую для создания чистого приложения RTOS:
Каждому приложению потребуется управлять различными частями функциональности в разные моменты времени. Эти функциональные компоненты называются задачами; перед созданием приложения необходимо понять и определить необходимое количество задач для системы.
Функциональность каждой задачи также должна быть определена, понята и подробно описана.
Зависимости между задачами должны быть перечислены, чтобы пользователь мог определить следующий шаг для каждой задачи.
Важно описать, как задачи будут общаться друг с другом и какой информацией нужно будет обмениваться между каждым набором зависимых задач.
Разработчику приложения необходимо определить различные входные данные (как внешние, так и внутренние), необходимые для системы, и то, как они связаны друг с другом.
Ограничения памяти системы необходимо понимать и определять, чтобы гарантировать, что система будет работать эффективно.
Наконец, перед внедрением приложения следует указать требования к производительности для каждой задачи, а также порядок приоритета среди задач.
После перечисления приведенных выше деталей пользователь может начать со следующих шагов по реализации приложения FreeRTOS.
Шаг 1: Настройка потока инструментов для контроллера
В качестве первого шага настройте поток инструментов (tool flow) для контроллера, на котором будет выполняться приложение RTOS. Используя процесс установки, запустите базовый тест Hello world, чтобы убедиться в следующем.
В качестве альтернативы пользователь может выбрать демонстрационное приложение FreeRTOS и запустить его в потоке инструментов, чтобы убедиться, что установка выполнена правильно, а затем использовать его в качестве отправной точки для разработки приложения.
Шаг 2: Включение исходных файлов FreeRTOS
Необходимые файлы
Ниже перечислены основные файлы, которые должны быть включены в любое приложение FreeRTOS:
FreeRTOS/Source/tasks.cFreeRTOS/Source/queue.cFreeRTOS/Source/list.cFreeRTOS/Source/portable/[compiler]/[architecture]/port.c, где [compiler] - используемый компилятор, [architecture] - тип используемой архитектурыFreeRTOS/Source/portable/MemMang/heap_x.c, где x - 1, 2, 3, 4 или 5Если каталог, содержащий файл port.c, также содержит файл на языке ассемблера, то файл на языке ассемблера также должен быть включен.
Необязательные файлы
FreeRTOS/Source/timers.c в список исходных файлов проекта.FreeRTOS/Source/event_group.c в список исходных файлов проекта.FreeRTOS/Source/stream_buffer.c в список исходных файлов проекта.Шаг 3: Включение необходимых заголовочных файлов RTOS
Следующие каталоги должны быть частью пути include сценария компиляции, чтобы компилятор мог найти заголовочные файлы RTOS:
FreeRTOS/Source/includeFreeRTOS/Source/portable/[compiler]/[architecture] FreeRTOSConfig.hВ зависимости от того, на какой процессор портируется RTOS, эти пути могут потребоваться и в include пути включения ассемблера.
Шаг 4: Обновление настроек файла конфигурации FreeRTOS
Каждый проект FreeRTOS требует наличия файла конфигурации FreeRTOSConfig.h. Это файл, который определяет настройки для ядра RTOS, подстраивая ядро под конкретное создаваемое приложение.
Этот файл зависит от пользователя или приложения и должен быть размещен в области кода приложения, а не вместе с исходным кодом ядра.
Подробнее о различных настройках, доступных в этом файле, можно ознакомиться в документации FreeRTOS.
Если в ваш проект включена куча heap_1, heap_2, heap_4 или heap_5, то значение параметра configTOTAL_HEAP_SIZE будет определять размер кучи FreeRTOS. Если для configTOTAL_HEAP_SIZE задано слишком большое значение, приложение не будет связываться, поэтому нужно устанавливать разумный размер кучи.
Параметр configMINIMAL_STACK_SIZE определяет размер стека, используемого бездействующей задачей. Если для configMINIMAL_STACK_SIZE установлено слишком малое значение, бездействующие задачи будут генерировать переполнение стека. Рекомендуется скопировать параметр configMINIMAL_STACK_SIZE из официальной демонстрации FreeRTOS, предоставленной для архитектуры микроконтроллера, используемой приложением. Однако некоторые демонстрационные проекты не были обновлены и могут не иметь всех необходимых параметров конфигурации; в этих случаях пользователь должен добавить их вручную по мере необходимости.
Шаг 5: Установка необходимых векторов прерывания
Каждый порт RTOS использует как минимум один таймер. Он используется для генерации периодического тикового прерывания. В зависимости от порта могут потребоваться дополнительные таймеры для управления переключением контекста и других связанных с этим задач. Прерывания, которые требуются RTOS, обслуживаются исходным файлом RTOS port.c.
В зависимости от порта и используемого компилятора, способ установки обработчиков прерываний также различается. Пользователи могут скопировать официальное демо-приложение для используемого порта из каталогов демо-версий RTOS.
После выполнения всех вышеперечисленных шагов пользователь сможет скомпилировать приложение для выбранного им контроллера. Затем пользователь может улучшить свое приложение в соответствии со своими требованиями и запустить его на выбранном им оборудовании.
Чтобы понять, как FreeRTOS работает с демонстрационным приложением, мы продемонстрируем, как запустить демонстрационное приложение с минимальной установкой программного обеспечения на вашем компьютере с Windows. Эту настройку можно использовать в качестве экспериментальной платформы, чтобы получить представление о FreeRTOS, прежде чем переходить к её использованию на выбранной вами встраиваемой платформе.
Далее в этом курсе мы рассмотрим, как запускать FreeRTOS на других платформах, включая платформы RISC?V, и как моделировать ваши приложения без использования физической аппаратной системы.
Настройка, необходимая для запуска демо-версии Windows, выглядит следующим образом:
Ниже приведены шаги, которые необходимо выполнить для запуска демо-приложения, после установки инструментов (Eclipse и Cygwin + GCC).
Шаг 1: Импорт проекта в Eclipse
Выполните следующие шаги, чтобы импортировать проект в Eclipse:



Шаг 2: Понимание демонстрационных файлов
Теперь давайте посмотрим на доступные демонстрационные файлы.
main.c - основной код для выполнения.main_blinky.c - это простое двухзадачное приложение, которое дает представление о том, как могут быть построены приложения FreeRTOS.main_full.c - более полный список приложений.main_blinky, установив define, как показано на скриншоте ниже, в файле main.c:

build в Eclipse (Eclipse будет использовать GCC от Cygwin для компиляции кода).Шаг 3: Запуск приложения
Теперь, когда ваше приложение готово к запуску в Windows через Eclipse, выполните следующие шаги:


\FreeRTOS\FreeRTOS\Demo\WIN32-MingW\Debug.RTOSDemo.exe
Поздравляем! Вы запустили свое первое приложение FreeRTOS!
Примечание переводчика
Представленное в курсе демонстрационное видео фактически повторяет шаги, описанные в предыдущем разделе. Ниже приведён транскрипт этого видео с кадрами его основных моментов.
Шаг первый - импортировать проект. Откройте из меню "File", "Import projects" и выберите имя проекта. Нажмите "Finish". Это приведет к импорту проекта в Eclipse.
Теперь вы можете собрать проект. Перейдите в раздел "Project" и нажмите "Clean"; таким образом, все существующие файлы будут очищены.
Затем выполните команду "Build All".
После выполнения команды "Build all" компилятор скомпилирует все необходимые файлы в проект, и вы получите исполняемый файл.
Видите, компилятор компилирует необходимый файл. И в конце компиляции вы можете увидеть, что исполняемый файл создан. Теперь компиляция завершена. Процесс сборки завершен.
А затем вы можете перейти к выполнению проекта. И вы можете видеть, что задачи выполняются одна за другой.
То же самое можно сделать и в командной строке Cygwin Перейдите в каталог проекта, где находится исполняемый файл, и запустите исполняемый файл, созданный в Eclipse.
FreeRTOSConfig.h?FreeRTOSConfig.h для нового проекта? Мы начнем эту лекцию с введения в операционную систему реального времени FreeRTOS, а затем более подробно рассмотрим её особенности. Следующий шаг - понять содержание и структуру дистрибутива FreeRTOS, который мы будем использовать на протяжении всего курса.
Далее мы объясним различные компоненты FreeRTOS и то, как они работают и взаимодействуют друг с другом, чтобы обеспечить инфраструктуру для создания встраиваемых приложений. После понимания процесса создания приложений мы завершим лекцию демонстрацией запуска примера приложения в симуляторе QEMU.
Ознакомившись с этой лекцией, читатель сможет:
FreeRTOS - одна из наиболее часто используемых операционных систем реального времени (RTOS), распространяемая под открытой лицензией MIT. FreeRTOS - это RTOS, ориентированная на микроконтроллеры и небольшие микропроцессоры. Она включает ядро и растущий набор библиотек IoT, подходящих для использования во всех отраслях промышленности. FreeRTOS создана с акцентом на надежность и простоту использования.
В следующем разделе мы рассмотрим общие технические требования, требования к обслуживанию и эффективности при создании встраиваемых приложений с FreeRTOS. Затем мы определим некоторые стандартные возможности FreeRTOS.
FreeRTOS позволяет пользователям использовать различные преимущества ядра реального времени по сравнению с созданием исходного встраиваемого приложения. Эти возможности являются типичными требованиями для большинства современных встраиваемых приложений, поскольку одна система может быть приспособлена как к простым, так и к сложным приложениям и должна обеспечивать возможность повторного использования системы в различных компонентах приложения.
Модульность
Модульность является ключевым требованием к программному обеспечению встраиваемых систем, поскольку она позволяет поддерживать масштабируемость программного обеспечения (как в сторону увеличения, так и уменьшения) без ущерба для возможностей и функций приложения.
Абстрагирование информации о времени
Требования системы к синхронизации должны быть поняты и абстрагированы, чтобы их можно было встроить в управляющую программную среду.
Управление питанием
Управление питанием в современных встраиваемых системах является еще одним ключевым фактором. Поскольку все больше и больше приложений требуют работы от батарей, понимание требований к питанию и разработка правильного подхода к управлению питанием важны для создания эффективной встраиваемой системы.
Гибкое управление прерываниями
Следующий шаг - управление различными прерываниями, которые будут возникать в системе. Требования к прерываниям основаны на входах, которые являются частью системы. Они должны быть хорошо понятны, чтобы создавать значимые выходные данные на основе входных.
Требования к смешанной обработке
Встраиваемые системы основаны на нескольких типах входных данных. Некоторые из них являются чисто цифровыми по своей природе, но есть и аналоговые входные данные, которые необходимо зафиксировать, обработать и понять, чтобы сгенерировать требуемый отклик на эти входные данные. Встраиваемая система должна поддерживать смешанную обработку, чтобы она могла обрабатывать различные типы входных данных.
Управление временем простоя системы
Последний вопрос заключается в том, как и когда система может потенциально простаивать, и что следует делать в это время в системе.
Тестируемость
Одним из ключевых аспектов при разработке системы является возможность её обслуживания и быстрого и эффективного устранения любых поломок. Для обеспечения этого требования важно иметь возможность тестирования на любые потенциальные сбои во время разработки системы, а также воспроизведения любых сбоев, выявленных во время эксплуатации системы. Поэтому, когда система разрабатывается, тестируемость должна быть встроенной частью дизайна, включая определение того, что должно быть протестировано и как это должно быть протестировано.
Удобство обслуживания и расширяемость
Система должна быть разработана таким образом, чтобы её можно было легко обслуживать как в полевых условиях, так и вне их, как с точки зрения аппаратного, так и программного обеспечения. Расширяемость также является ключевым фактором; система должна быть разработана таким образом, чтобы упростить добавление функций после завершения первоначальной версии системы.
Разработка приложений в команде
Сложные приложения часто разрабатываются командами, и дизайн системы должен поддерживать возможность делать это быстро и эффективно. По этой причине система должна быть разработана по модульному принципу, чтобы несколько человек и даже несколько команд могли участвовать в разработке компонентов и модулей приложения без негативного влияния на существующие компоненты.
Повторное использование кода
При необходимости код, разработанный для одной системы, должен быть доступен для повторного использования в других системах с аналогичными требованиями к функциональности. Проектирование системы по модульному принципу будет поддерживать это требование и повысит эффективность создания новых приложений.
Эффективность кода
Наконец, код должен быть разработан таким образом, чтобы эффективно использовать память, и разработчик должен помнить об ограничениях производительности небольших контроллеров, на которых строятся встраиваемые системы.
Ниже перечислены стандартные возможности FreeRTOS (взятые из справочного руководства FreeRTOS):
tick hook functions);idle hook functions);full interrupt nesting model) для некоторых архитектур;FreeRTOS распространяется через Git-репозиторий в виде одного сжатого zip-файла со всем исходным кодом, поэтому пользователи могут свободно использовать его в своих приложениях, а также при необходимости вносить в код любые изменения. Дистрибутив также содержит демонстрационные приложения и демоверсии портов (ports) для различных контроллеров, поддерживаемых FreeRTOS. Эти демоверсии помогают пользователям FreeRTOS быстро адаптировать её к своим требованиям. Многие поставщики микроконтроллеров поставляют RTOS как часть своего набора инструментов, что еще больше облегчает разработку с FreeRTOS.
Последнюю версию FreeRTOS можно загрузить с веб-сайта FreeRTOS. FreeRTOS также размещен на GitHub, и пользователи могут получить последнюю версию исходного кода из каталога Git.
Ключевая часть ядра (core of the kernel) FreeRTOS содержится в трёх файлах, которые находятся в подкаталоге FreeRTOS\FreeRTOS\Source. Это файлы tasks.c, queue.c и lists.c. Для простых приложений этих трёх файлов достаточно. Папка Source содержит подпапку include, в которой находятся файлы include, необходимые для установки.
Существуют и другие файлы, которые могут понадобиться в зависимости от специфической функциональности конкретного приложения.
Каталог Source также содержит подкаталог portable, который содержит подкаталоги с файлами, специфичными для определенных компиляторов и программных инструментов. Код, находящийся в этих папках, может быть использован в качестве отправной точки для создания портов в соответствии с требованиями пользователя.
Папка Demo содержит примеры приложений, портированных на конкретные контроллеры. Пользователи, планирующие использовать контроллер определенного типа, могут использовать один или несколько примеров, представленных в этой папке, в качестве основы для создания приложений для своего контроллера.
Ниже перечислены ключевые компоненты FreeRTOS:
Мы опишем их более подробно в последующих разделах.
Обратите внимание, что во FreeRTOS есть и другие компоненты, которые не рассматриваются подробно в этом курсе. Эти элементы требуются в более сложных приложениях, и их подробный анализ можно найти в руководстве пользователя FreeRTOS.
Все возможности FreeRTOS управляются из файла конфигурации FreeRTOS, FreeRTOSConfig.h. Каждое приложение должно иметь этот файл как часть системы. Он содержит параметры конфигурации для включения функций FreeRTOS, необходимых для данного приложения. Образец конфигурационного файла может быть скопирован из демонстрационного порта, который лучше всего подходит для контроллера, используемого для данного приложения.
Управление памятью осуществляется FreeRTOS для её эффективного использования. Поддерживается как статическое, так и динамическое распределение. Обе схемы имеют свои преимущества и недостатки, в зависимости от приложения. Разработчик приложения выбирает подходящую схему управления памятью в зависимости от требований. Одно и то же приложение может содержать задачи как динамического, так и статического распределения.
FreeRTOS использует собственные методы управления памятью и определяет собственные функции для её выделения, а также для освобождения после использования. Она также определяет несколько методов управления кучей/памятью, что дает пользователю возможность выбрать оптимальную схему, которая лучше всего подходит для его приложения.
Схема распределения памяти во FreeRTOS по умолчанию динамическая. В случаях, когда разработчику приложения требуется больший контроль над управлением памятью для определенных компонентов приложения, он может выбрать статическое распределение памяти для этих задач. FreeRTOS предоставляет отдельный набор функций для компонентов, которым требуется статическое распределение памяти. Эти функции доступны, когда configSUPPORT_STATIC_ALLOCATION имеет значение 1 в файле настроек конфигурации.
Ниже перечислены некоторые преимущества использования динамического распределения памяти (адаптировано из руководства пользователя FreeRTOS):
API RTOS;API RTOS позволяют возвращать информацию об использовании кучи, что позволяет оптимизировать её размер.Ниже перечислены некоторые преимущества использования статического распределения памяти (адаптировано из руководства пользователя FreeRTOS):
FreeRTOS определяет пять схем управления памятью. Они содержатся в отдельных файлах: heap_1.c, heap_2.c, heap_3.c, heap_4.c и heap_5.c, которые находятся в каталоге Source/Portable/MemMang. Пользователи могут добавлять свои собственные реализации по мере необходимости, но хотя бы одна из этих реализаций должна быть включена при компиляции исходного текста FreeRTOS в приложении.
Ниже приводится простое описание каждой из этих реализаций.
heap_1.c
Это простейшая реализация управления памятью. Она похожа на статическое распределение памяти, поэтому это решение может оказаться не очень полезным в текущих реализациях, поскольку FreeRTOS теперь поддерживает статическое распределение нативно. Однако оно очень хорошо подходит для большинства встраиваемых систем, поскольку они занимают мало памяти и являются глубоко встраиваемыми. При такой реализации вся необходимая память всегда выделяется в начале выполнения системы и перераспределяется только при перезагрузке системы.
heap_2.c
heap_2 использует алгоритм наибольшего соответсвия (best-fit) для выделения памяти, и пространство, которое больше не используется, освобождается для дальнейшего использования. Он не объединяет свободные места в один блок перед перераспределением. Эта схема может быть использована, когда во время выполнения приложения происходит многократное удаление и создание задач или других компонентов RTOS. Не рекомендуется использовать эту схему, если освобождаемые и перераспределяемые блоки памяти имеют произвольный размер, так как это может привести к фрагментации памяти. Кроме того, распределение не является детерминированным, но оно более эффективно, чем реализация malloc в языке Си.
heap_3.c
heap_3 - это простая, потокобезопасная обертка вокруг стандартных функций malloc() и free() языка Си. Эта схема требует, чтобы компоновщик настроил кучу, а библиотека компилятора предоставила функции malloc() и free(). Она не является детерминированной и может привести к увеличению размера кода ядра.
heap_4.c
heap_4 использует "первый подходящий" алгоритм (first-fit) для выделения памяти. В отличие от heap_2, он объединяет соседние свободные пространства в более крупный блок, а затем выделяет память; он включает алгоритм коалесценции, который поддерживает эту возможность. Эта схема может быть использована в системах, требующих многократного создания и удаления задач и других компонентов. Поскольку эта реализация объединяет области памяти в более крупные блоки памяти, она с меньшей вероятностью приведет к неправильной фрагментации памяти.
heap_5.c
Эта схема использует те же алгоритмы, что и heap_4, и дополнительно позволяет куче охватывать несколько несмежных свободных областей памяти.
Более подробные объяснения и примеры использования вышеперечисленных схем можно найти в руководстве FreeRTOS.
Задачи - это базовые компоненты FreeRTOS. Они позволяют разработчикам приложений определять конкретные части функциональности, которые должны быть выполнены в определенное время выполнения приложения. Внутри приложения может быть определено любое количество задач. Задачи можно понимать как небольшие подпрограммы, которые доступны для выполнения в течение всего времени работы основного приложения.
Планировщик (scheduler) RTOS отвечает за контроль над тем, какая задача должна быть выполнена в любой момент времени. В одноядерных системах только одна задача может быть активна в приложении в любой момент времени. Поэтому планировщик также отвечает за безопасное включение и выключение каждой задачи, а также за сохранение состояния, чтобы при повторном включении каждая задача возвращалась в свое предшествующее состояние. Это достигается планировщиком FreeRTOS за счёт ведения индивидуального стека для каждой задачи.
Задача может находиться в одном из следующих четырёх состояний:
В этом состоянии задача готова к выполнению, то есть она не находится в состоянии блокировки или приостановки. Однако она не выполняется, потому что на процессоре уже выполняется другая задача с более высоким или равным приоритетом.
В этом состоянии задача выполняется на процессоре. Если система имеет только одно ядро, то в каждый момент времени может выполняться только одна задача.
В этом состоянии задача не готова к выполнению, так как ожидает входных данных от внешних источников, других задач или временных событий (например, события таймера или задержки). Для каждой заблокированной задачи существует тайм-аут, по достижении которого задача переходит из заблокированного состояния в состояние готовности. После истечения тайм-аута задаче не нужно ждать наступления события, которое её блокировало.
Приостановленные задачи не могут автоматически выйти из этого состояния, так как для них не установлен тайм-аут. Они должны быть явно выведены из этого состояния приложением с помощью операции возобновления (resume).
Задачам можно назначать приоритеты по мере необходимости. FreeRTOS позволяет пользователю определить переменное количество уровней приоритетов. Уровни начинаются с 0, а максимальный уровень определяется в файле FreeRTOSConfig.h. Это максимальное значение должно быть разумным, чтобы минимизировать использование оперативной памяти.
Планирование задач осуществляется планировщиком. Планировщик гарантирует, что задачи в состоянии готовности с более высоким приоритетом будут выполняться перед задачами с более низким приоритетом, которые также находятся в состоянии готовности. FreeRTOS может быть настроена на выполнение задач с одинаковым приоритетом в режиме "нарезания времени" (time slicing), для чего в конфигурационном файле задается параметр configUSE_TIME_SLICING. Разделение между задачами с равным приоритетом осуществляется с помощью схемы арбитража round-robin.
Задачи создаются с помощью функции xTaskCreate() или xTaskCreateStatic() и могут быть удалены с помощью функции xTaskDelete().
Параметры могут быть переданы в задачу для дальнейшей обработки с помощью указателя параметров.
Примерная структура реализации задачи представлена ниже.
Шаг 1: Создание двух задач
xTaskCreate( prvQueueReceiveTask, "Rx", configMINIMAL_STACK_SIZE * 2U, NULL, mainQUEUE_RECEIVE_TASK_PRIORITY, NULL );
xTaskCreate( prvQueueSendTask, "Tx", configMINIMAL_STACK_SIZE * 2U, NULL, mainQUEUE_SEND_TASK_PRIORITY, NULL );
Шаг 2: Определение задачи 1 (prvQueueReceiveTask)
static void prvQueueReceiveTask( void *pvParameters )
{
unsigned long ulReceivedValue;
const unsigned long ulExpectedValue = 100UL;
const char * const pcMessage1 = "Blink1";
const char * const pcMessage2 = "Blink2";
const char * const pcFailMessage = "Unexpected value received\r\n";
int f = 1;
/* Remove compiler warning about unused parameter. */
( void ) pvParameters;
for( ;; )
{....
Очереди - основной механизм межзадачного взаимодействия. Задачи могут использовать их для обмена информацией друг с другом. Очереди реализованы как потокобезопасные FIFO (first in first out). Задачи добавляют информацию в конец очереди, а другие задачи, которым нужны данные из очереди, забирают их из начала и обрабатывают. При необходимости задачи также могут перемещать данные не в конец очереди, а в её начало.
FreeRTOS использует метод очереди путем копирования, где данные, отправленные в очередь, копируются в неё. Этот метод обеспечивает простую, но мощную реализацию. Данные могут передаваться через очередь в одном из следующих форматов:
FreeRTOS отвечает за выделение памяти для очереди и за хранение данных по мере необходимости.
В очередях может быть несколько задач, которые пишут в них или читают из них. Обычно в очередь записывают несколько задач, и реже из нее читают несколько задач.
Когда задача пытается читать из пустой очереди, она переходит в состояние "заблокирована", пока либо данные не станут доступны в очереди, либо не будет достигнут тайм-аут блокировки.
Когда задача пытается записать данные в заполненную очередь, она переходит в состояние "заблокирована" до тех пор, пока в очереди не освободится место или не будет достигнут тайм-аут блокировки.
Задачи, которые блокируются, не потребляют процессорное время, поэтому другие задачи могут выполняться.
Если несколько задач блокируются на одной и той же очереди, то задача с наивысшим приоритетом будет разблокирована первой.
В следующем примере показано, как можно реализовать и использовать очереди между двумя задачами.
Шаг 1. Создание очереди
/* Create the queue. */ xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( uint32_t ) );
Шаг 2: Использование очереди
/* Send a value to the queue, causing the task receiving this data from the queue to unblock and toggle the LED. 0 is used as the block time so that the sending operation will not block; it shouldn't need to block, as the queue should always be empty at this point in the code. */ xQueueSend( xQueue, ulValueToSend, 0U );
Помимо очередей, во FreeRTOS есть семафоры и мьютексы, которые можно использовать для межзадачного взаимодействия в зависимости от требований приложения. Более подробно о семафорах и мьютексах во FreeRTOS рассказывается в учебнике FreeRTOS.
Прямые уведомления о задачах (direct task notifications) - это события, отправляемые непосредственно задаче без промежуточного механизма, такого как очередь или семафор. Это ускоряет обмен данными и занимает гораздо меньше места в памяти. Задача блокируется, когда в массиве событий уведомления установлен бит уведомления. Заблокировать задачу может только одно уведомление; если бы произошло другое событие, оно не повлияло бы на состояние задачи.
Потоковые буферы предлагают механизм связи "один к одному" в следующих случаях:
Эти буферы оптимизированы для сценариев однократной записи и однократного чтения. Буферы потоков способны передавать байты, а буферы сообщений - дискретные сообщения переменного размера. Буферы сообщений строятся поверх буферов потоков.
Эти буферы очень полезны для следующих типов коммуникационных сценариев:
Данные передаются посредством копирования, то есть они копируются в буфер отправителем и выводятся из буфера операцией чтения.
Таймеры могут быть реализованы программно в RTOS, поэтому их также можно назвать программными таймерами. Они не используют аппаратные ресурсы и не потребляют процессорное время. Таймер позволяет запускать задачи или события, которые должны произойти в определенный момент в будущем. Будущее время выполнения контролируется настройками таймера. Задача, которая должна быть выполнена, называется функцией обратного вызова таймера. Функция обратного вызова (callback) таймера выполняется по истечении времени таймера или периода таймера.
Как и другие компоненты RTOS, таймер должен быть явно создан, прежде чем его можно будет использовать.
Функциональность программного таймера, в общем, легко реализовать, но трудно реализовать эффективно.
Реализация таймера в RTOS обладает следующими свойствами:
Задача обслуживания таймера в основном использует существующие возможности FreeRTOS, позволяя добавить функциональность таймера в приложение с минимальным влиянием на размер приложения.
Функции обратного вызова таймера выполняются в контексте задачи обслуживания таймера, поэтому важно, чтобы функции обратного вызова таймера никогда не пытались блокировать. Например, функция обратного вызова таймера не должна вызывать vTaskDelay() или vTaskDelayUntil(), а также не должна указывать ненулевое время блокировки при обращении к очереди или семафору.
Два типа таймеров могут быть определены и использованы в приложении:
Однократный таймер выполняется только один раз. По истечении срока действия таймера его обратный вызов вызывается и выполняется один раз.
Таймер автозагрузки выполняется неограниченное время, пока работает приложение. Каждый раз, когда таймер истекает, выполняется обратный вызов, и таймер сбрасывается; таймер снова работает до следующего истечения срока его действия, что приводит к выполнению обратного вызова. Этот процесс повторяется, что приводит к периодическому выполнению обратного вызова.
Лучше всего начать создание нового приложения, использующего FreeRTOS, с демонстрационного приложения для выбранного процессора. Рекомендуется модифицировать демо-версию в соответствии с текущими требованиями. Это обеспечит хорошую отправную точку для приложения и устранит многие проблемы портирования (porting), которые могут возникнуть при создании нового приложения с использованием FreeRTOS.
Затем разработчик должен указать следующую предварительную информацию, необходимую для создания чистого приложения RTOS:
Каждому приложению потребуется управлять различными частями функциональности в разные моменты времени. Эти функциональные компоненты называются задачами; перед созданием приложения необходимо понять и определить необходимое количество задач для системы.
Функциональность каждой задачи также должна быть определена, понята и подробно описана.
Зависимости между задачами должны быть перечислены, чтобы пользователь мог определить следующий шаг для каждой задачи.
Важно описать, как задачи будут общаться друг с другом и какой информацией нужно будет обмениваться между каждым набором зависимых задач.
Разработчику приложения необходимо определить различные входные данные (как внешние, так и внутренние), необходимые для системы, и то, как они связаны друг с другом.
Ограничения памяти системы необходимо понимать и определять, чтобы гарантировать, что система будет работать эффективно.
Наконец, перед внедрением приложения следует указать требования к производительности для каждой задачи, а также порядок приоритета среди задач.
После перечисления приведенных выше деталей пользователь может начать со следующих шагов по реализации приложения FreeRTOS.
Шаг 1: Настройка потока инструментов для контроллера
В качестве первого шага настройте поток инструментов (tool flow) для контроллера, на котором будет выполняться приложение RTOS. Используя процесс установки, запустите базовый тест Hello world, чтобы убедиться в следующем.
В качестве альтернативы пользователь может выбрать демонстрационное приложение FreeRTOS и запустить его в потоке инструментов, чтобы убедиться, что установка выполнена правильно, а затем использовать его в качестве отправной точки для разработки приложения.
Шаг 2: Включение исходных файлов FreeRTOS
Необходимые файлы
Ниже перечислены основные файлы, которые должны быть включены в любое приложение FreeRTOS:
FreeRTOS/Source/tasks.cFreeRTOS/Source/queue.cFreeRTOS/Source/list.cFreeRTOS/Source/portable/[compiler]/[architecture]/port.c, где [compiler] - используемый компилятор, [architecture] - тип используемой архитектурыFreeRTOS/Source/portable/MemMang/heap_x.c, где x - 1, 2, 3, 4 или 5Если каталог, содержащий файл port.c, также содержит файл на языке ассемблера, то файл на языке ассемблера также должен быть включен.
Необязательные файлы
FreeRTOS/Source/timers.c в список исходных файлов проекта.FreeRTOS/Source/event_group.c в список исходных файлов проекта.FreeRTOS/Source/stream_buffer.c в список исходных файлов проекта.Шаг 3: Включение необходимых заголовочных файлов RTOS
Следующие каталоги должны быть частью пути include сценария компиляции, чтобы компилятор мог найти заголовочные файлы RTOS:
FreeRTOS/Source/includeFreeRTOS/Source/portable/[compiler]/[architecture] FreeRTOSConfig.hВ зависимости от того, на какой процессор портируется RTOS, эти пути могут потребоваться и в include пути включения ассемблера.
Шаг 4: Обновление настроек файла конфигурации FreeRTOS
Каждый проект FreeRTOS требует наличия файла конфигурации FreeRTOSConfig.h. Это файл, который определяет настройки для ядра RTOS, подстраивая ядро под конкретное создаваемое приложение.
Этот файл зависит от пользователя или приложения и должен быть размещен в области кода приложения, а не вместе с исходным кодом ядра.
Подробнее о различных настройках, доступных в этом файле, можно ознакомиться в документации FreeRTOS.
Если в ваш проект включена куча heap_1, heap_2, heap_4 или heap_5, то значение параметра configTOTAL_HEAP_SIZE будет определять размер кучи FreeRTOS. Если для configTOTAL_HEAP_SIZE задано слишком большое значение, приложение не будет связываться, поэтому нужно устанавливать разумный размер кучи.
Параметр configMINIMAL_STACK_SIZE определяет размер стека, используемого бездействующей задачей. Если для configMINIMAL_STACK_SIZE установлено слишком малое значение, бездействующие задачи будут генерировать переполнение стека. Рекомендуется скопировать параметр configMINIMAL_STACK_SIZE из официальной демонстрации FreeRTOS, предоставленной для архитектуры микроконтроллера, используемой приложением. Однако некоторые демонстрационные проекты не были обновлены и могут не иметь всех необходимых параметров конфигурации; в этих случаях пользователь должен добавить их вручную по мере необходимости.
Шаг 5: Установка необходимых векторов прерывания
Каждый порт RTOS использует как минимум один таймер. Он используется для генерации периодического тикового прерывания. В зависимости от порта могут потребоваться дополнительные таймеры для управления переключением контекста и других связанных с этим задач. Прерывания, которые требуются RTOS, обслуживаются исходным файлом RTOS port.c.
В зависимости от порта и используемого компилятора, способ установки обработчиков прерываний также различается. Пользователи могут скопировать официальное демо-приложение для используемого порта из каталогов демо-версий RTOS.
После выполнения всех вышеперечисленных шагов пользователь сможет скомпилировать приложение для выбранного им контроллера. Затем пользователь может улучшить свое приложение в соответствии со своими требованиями и запустить его на выбранном им оборудовании.
Чтобы понять, как FreeRTOS работает с демонстрационным приложением, мы продемонстрируем, как запустить демонстрационное приложение с минимальной установкой программного обеспечения на вашем компьютере с Windows. Эту настройку можно использовать в качестве экспериментальной платформы, чтобы получить представление о FreeRTOS, прежде чем переходить к её использованию на выбранной вами встраиваемой платформе.
Далее в этом курсе мы рассмотрим, как запускать FreeRTOS на других платформах, включая платформы RISC?V, и как моделировать ваши приложения без использования физической аппаратной системы.
Настройка, необходимая для запуска демо-версии Windows, выглядит следующим образом:
Ниже приведены шаги, которые необходимо выполнить для запуска демо-приложения, после установки инструментов (Eclipse и Cygwin + GCC).
Шаг 1: Импорт проекта в Eclipse
Выполните следующие шаги, чтобы импортировать проект в Eclipse:



Шаг 2: Понимание демонстрационных файлов
Теперь давайте посмотрим на доступные демонстрационные файлы.
main.c - основной код для выполнения.main_blinky.c - это простое двухзадачное приложение, которое дает представление о том, как могут быть построены приложения FreeRTOS.main_full.c - более полный список приложений.main_blinky, установив define, как показано на скриншоте ниже, в файле main.c:

build в Eclipse (Eclipse будет использовать GCC от Cygwin для компиляции кода).Шаг 3: Запуск приложения
Теперь, когда ваше приложение готово к запуску в Windows через Eclipse, выполните следующие шаги:


\FreeRTOS\FreeRTOS\Demo\WIN32-MingW\Debug.RTOSDemo.exe
Поздравляем! Вы запустили свое первое приложение FreeRTOS!
Примечание переводчика
Представленное в курсе демонстрационное видео фактически повторяет шаги, описанные в предыдущем разделе. Ниже приведён транскрипт этого видео с кадрами его основных моментов.
Шаг первый - импортировать проект. Откройте из меню "File", "Import projects" и выберите имя проекта. Нажмите "Finish". Это приведет к импорту проекта в Eclipse.
Теперь вы можете собрать проект. Перейдите в раздел "Project" и нажмите "Clean"; таким образом, все существующие файлы будут очищены.
Затем выполните команду "Build All".
После выполнения команды "Build all" компилятор скомпилирует все необходимые файлы в проект, и вы получите исполняемый файл.
Видите, компилятор компилирует необходимый файл. И в конце компиляции вы можете увидеть, что исполняемый файл создан. Теперь компиляция завершена. Процесс сборки завершен.
А затем вы можете перейти к выполнению проекта. И вы можете видеть, что задачи выполняются одна за другой.
То же самое можно сделать и в командной строке Cygwin Перейдите в каталог проекта, где находится исполняемый файл, и запустите исполняемый файл, созданный в Eclipse.
FreeRTOSConfig.h?FreeRTOSConfig.h для нового проекта? Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.