freertos
TRANSCRIPT
![Page 1: FreeRTOS](https://reader036.vdocuments.us/reader036/viewer/2022062704/555e1c26d8b42a6a4c8b4622/html5/thumbnails/1.jpg)
FreeRTOS
![Page 2: FreeRTOS](https://reader036.vdocuments.us/reader036/viewer/2022062704/555e1c26d8b42a6a4c8b4622/html5/thumbnails/2.jpg)
Философия разработки
FreeRTOS разработана как:- Простая- Портируемая-Маленькая
Система FreeRTOS находится в стадии активной разработки, которая была начата Ричардом Барри (Richard Barry) в 2002 году.
![Page 3: FreeRTOS](https://reader036.vdocuments.us/reader036/viewer/2022062704/555e1c26d8b42a6a4c8b4622/html5/thumbnails/3.jpg)
Некоторые возможности FreeRTOS• Выбор политики планирования• Всегда работает задача с наивысшим приоритетом
из доступных. Задачи с одинаковым приоритетом делят процессорное время.
• Coroutines(сопрограммы) - маленькие задачи, использующие очень мало RAM.
• БОльшая часть кода одинакова для всех средств разработки.
• Много портов и примеров.• Дополнительные возможности могут быть легко и
быстро добавлены.
![Page 4: FreeRTOS](https://reader036.vdocuments.us/reader036/viewer/2022062704/555e1c26d8b42a6a4c8b4622/html5/thumbnails/4.jpg)
• Многозадачность и параллельностьОбычный процессор может выполнять только одну задачу одновременно
- но за счёт быстрого переключения между задачами делается вид, будто задачи выполняются одновременно.
• ПланированиеПланировщик - это часть ядра, отвечающий за то, какая задача должна
выполняться в какой момент времени. Ядро может приостановить и потом продолжить задачу несколько раз за время работы задачи.
![Page 5: FreeRTOS](https://reader036.vdocuments.us/reader036/viewer/2022062704/555e1c26d8b42a6a4c8b4622/html5/thumbnails/5.jpg)
ПланированиеКаждая задача имеет приоритет, назначенный пользователем, который равен от 0 (самый низкий приоритет) и до значения времени компиляции configMAX_PRIORITIES-1 (самый высокий приоритет)
Планировщик гарантирует, что процессорное время отдаётся задаче с максимальным приоритетом из доступных(ready) задач. Даже если задачи с низким приоритетом тоже находятся в состоянии готовности(ready) длительное время.
![Page 6: FreeRTOS](https://reader036.vdocuments.us/reader036/viewer/2022062704/555e1c26d8b42a6a4c8b4622/html5/thumbnails/6.jpg)
Тактовая частота системы
Система FreeRTOS настраивается таким образом, чтобы периодически выдавать прерывания. Пользователь может регулировать частоту прерываний, которая обычно находится в диапазоне миллисекунд.
/* Поиск очереди с наивысшим приоритетом, в которой есть готовые к запуску задачи. */
while( listLIST_IS_EMPTY( &( pxReadyTasksLists [uxTopReadyPriority ] ) ) ) {
configASSERT( uxTopReadyPriority );--uxTopReadyPriority; } /*
}
/* listGET_OWNER_OF_NEXT_ENTRY проходит по списку, поскольку задачи с одинаковым приоритетом получают одинаковое право пользоваться процессорным временем. */
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopReadyPriority ] ) );
![Page 7: FreeRTOS](https://reader036.vdocuments.us/reader036/viewer/2022062704/555e1c26d8b42a6a4c8b4622/html5/thumbnails/7.jpg)
ЗадачиЗадачей является определяемая пользователем функция на языке C с заданным приоритетом. В tasks.c и task.h делается вся тяжелая работа по созданию, планированию и обслуживанию задач. Простая
Нет ограничений использования
Поддерживает полное вытеснение
Приоритет задаётся всей задаче
Каждая задача требует отдельного стека - это приводит к большому потреблению оперативной памяти
Повторная входимость должна быть тщательно продумана, если используется вытеснение
![Page 8: FreeRTOS](https://reader036.vdocuments.us/reader036/viewer/2022062704/555e1c26d8b42a6a4c8b4622/html5/thumbnails/8.jpg)
СопрограммыСопрограммы концептуально схожи с задачами, но имеют некоторые различия. Требуется меньше оперативной памяти за счёт общего стека
Совместная работа упрощает проблему повторного входа.
Хорошо переносимо между разными архитектурами
Полностью приоритезована по отношению к другим сопрограммам, но всегда может быть вытеснена задачей, имеющей больший приоритет, чем задача, запускающая сопрограммы
Отсутствие индивидуального стека требует особого рассмотрения
Ограниченный API
Кооперативная многозадачность только между сопрограммами.
![Page 9: FreeRTOS](https://reader036.vdocuments.us/reader036/viewer/2022062704/555e1c26d8b42a6a4c8b4622/html5/thumbnails/9.jpg)
Объявление задач• Задача должна иметь следующую структуру:
void vATaskFunction( void *pvParameters ){ for ( ; ; )
{ /* Код задачи пишется тут */ } }
Функции-задачи никогда не прерываются, поэтому обычно реализуются при помощи непрерывного цикла. Опять-же можно посмотреть примеры.
Задачи создаются с помощью xTaskCreate() и удаляются с помощью vTaskDelete()
![Page 10: FreeRTOS](https://reader036.vdocuments.us/reader036/viewer/2022062704/555e1c26d8b42a6a4c8b4622/html5/thumbnails/10.jpg)
Блок управления задачей TCB (tasks.c) typedef struct tskTaskControlBlock {
volatile portSTACK_TYPE *pxTopOfStack; /* Указывает на месторасположение последнего элемента, размещенного в стеке задач. */ xListItem xGenericListItem; /* Элемент списка, используемый для помещения блока TCB в
очереди готовых и заблокированных задач. */ xListItem xEventListItem; /* Элемент списка, используемый для помещения блока TCB в
списки событий.*/ unsigned portBASE_TYPE uxPriority; /* Приоритет задачи; 0 является низшим приоритетом.*/ portSTACK_TYPE *pxStack; /* Указывает на начало стека. */ signed char pcTaskName[ configMAX_TASK_NAME_LEN ]; /* Описательное имя, которое
присваивается стеку, когда он создается. Используется только для отладки. */ #if ( portSTACK_GROWTH > 0 )
portSTACK_TYPE *pxEndOfStack; /* Используется для проверки стека на переполнение в тех архитектурах, где стек растет с младших адресов памяти. */ #endif #if ( configUSE_MUTEXES == 1 )
unsigned portBASE_TYPE uxBasePriority; /* Приоритет, назначенный задаче последним – используется механизм наследования
приоритетов. */ #endif
} tskTCB;
![Page 11: FreeRTOS](https://reader036.vdocuments.us/reader036/viewer/2022062704/555e1c26d8b42a6a4c8b4622/html5/thumbnails/11.jpg)
Списки
![Page 12: FreeRTOS](https://reader036.vdocuments.us/reader036/viewer/2022062704/555e1c26d8b42a6a4c8b4622/html5/thumbnails/12.jpg)
СпискиСписок в системе FreeRTOS является стандартным закольцованным двусвязным
списком с парой интересных дополнений.
struct xLIST_ITEM { portTickType xItemValue; /* Значение, помещаемое в список. В
большинстве случае используется для сортировки списка в порядке уменьшения значений */ volatile struct xLIST_ITEM * pxNext; /* Указатель на следующий
элемент xListItem в списке. */ volatile struct xLIST_ITEM * pxPrevious; /* Указатель на предыдущий элемент xListItem в списке. */ void * pvOwner; /* Указатель на объект (обычно блок TCB), в котором находится элемент списка. Таким образом, организуется двусвязный список между объектами, хранящимися в списке, и элементами самого списка. */ void * pvContainer; /* Указатель на список (если таковой имеется), в который этот элемент списка помещается. */
};
![Page 13: FreeRTOS](https://reader036.vdocuments.us/reader036/viewer/2022062704/555e1c26d8b42a6a4c8b4622/html5/thumbnails/13.jpg)
void * pvContainer это:
typedef struct xLIST {
volatile unsigned portBASE_TYPE uxNumberOfItems; volatile xListItem * pxIndex; /* Используется для прохода по списку. Указывает на последний элемент, возвращенный функцией
pvListGetOwnerOfNextEntry (). */ volatile xMiniListItem xListEnd; /* Элемент списка, в
котором находится максимально возможное значение, означающее, что он всегда находится в конце списка и, поэтому, используется как маркер. */
} xList;Размер списка в любое время хранится в переменной uxNumberOfItems, предназначенной для быстрого выполнения операций с размерами списков.
![Page 14: FreeRTOS](https://reader036.vdocuments.us/reader036/viewer/2022062704/555e1c26d8b42a6a4c8b4622/html5/thumbnails/14.jpg)
Списки
• Поскольку списки сортируются в порядке убывания, элемент xListEnd используется как маркер начала списка. А поскольку список кольцевой, этот элемент xListEnd также является маркером конца списка.
• В большинстве «традиционных» операций доступа к списку, которыми мы пользуемся, вся работа выполняется в одном цикле for() или в функции, вызываемой следующим образом:
for (listPtr = listStart; listPtr != NULL; listPtr = listPtr->next) {
// Что-то здесь делается с указателями listPtr ... }
Каждый объект struct xListItem является, на самом деле, объектом xGenericListItem из соответствующего блока TCB.
![Page 15: FreeRTOS](https://reader036.vdocuments.us/reader036/viewer/2022062704/555e1c26d8b42a6a4c8b4622/html5/thumbnails/15.jpg)
Очереди
Система FreeRTOS позволяет задачам с помощью очередей общаться и синхронизироваться друг с другом. Процедуры сервиса прерываний (ISR) также используют очереди для взаимодействий и синхронизации.
![Page 16: FreeRTOS](https://reader036.vdocuments.us/reader036/viewer/2022062704/555e1c26d8b42a6a4c8b4622/html5/thumbnails/16.jpg)
Базовая структура данных очереди выглядит следующим образом:
typedef struct QueueDefinition {
signed char *pcHead; /* Указывает на начало области хранения очереди. */ signed char *pcTail; /* Указывает на байт в конце области хранения очереди. Еще один байт требуется поскольку хранятся отдельные элементы очереди; он используется как маркер. */ signed char *pcWriteTo; /* Указывает на следующее свободное место в в области
хранения очереди. */ signed char *pcReadFrom; /* Указывает на последнюю позицию, откуда происходило чтение очереди. */ xList xTasksWaitingToSend; /* Список задач, которые блокированы, ожидая пока не
произойдет обращение к этой очереди; Запомнены в порядке приоритета. */ xList xTasksWaitingToReceive; /* Список задач, которые блокированы, ожидая пока
не произойдет чтение из этой очереди; Запомнены в порядке приоритета. */ volatile unsigned portBASE_TYPE uxMessagesWaiting; /* Количество элементов,
имеющихся в очереди в текущий момент. */ unsigned portBASE_TYPE uxLength; /* Длина очереди, определяемая как количество
элементов, находящихся в очереди, а не как количество байтов памяти, занимаемой очередью. */ unsigned portBASE_TYPE uxItemSize; /* Размер каждого элемента, который хранится
в очереди. */ } xQUEUE;
![Page 17: FreeRTOS](https://reader036.vdocuments.us/reader036/viewer/2022062704/555e1c26d8b42a6a4c8b4622/html5/thumbnails/17.jpg)
ОчередиКогда создается очередь, пользователь указывает длину очереди и размер
каждого элемента, который будет отслеживаться с помощью очереди.
В системе FreeRTOS поддерживаются вставки и удаления в очереди с блокировкой и без блокировки.
Блокирования указываются с тайм-аутом. Задача может ожидать снятия блокировки бесконечно или в течение ограниченного периода времени.
В системе FreeRTOS используется список xTasksWaitingToSend для отслеживания задач, которые блокированы при выполнении операции вставки элемента в очередь. Каждый раз, когда элемент удаляется из очереди, проверяется список xTasksWaitingToSend. Если задача находится в состоянии ожидания в этом списке, то задача разблокируется.
Аналогично, с помощью списка xTasksWaitingToReceive отслеживаются задачи, которые блокируются при выполнении операции удаления из очереди. Каждый раз, когда новый элемент вставляется в очередь, проверяется список xTasksWaitingToReceive. Если задача находится в состоянии ожидания в этом списке, то задача разблокируется.
![Page 18: FreeRTOS](https://reader036.vdocuments.us/reader036/viewer/2022062704/555e1c26d8b42a6a4c8b4622/html5/thumbnails/18.jpg)
Семафоры
Механизм семафоров основан на механизме очередей. По большому счету API-функции для работы с семафорами представляют собой макросы — «обертки» других API-функций для работы с очередями.
Семафор должен быть явно создан перед первым его использованием.
![Page 19: FreeRTOS](https://reader036.vdocuments.us/reader036/viewer/2022062704/555e1c26d8b42a6a4c8b4622/html5/thumbnails/19.jpg)
Двоичный семафорДвоичные семафоры предназначены для эффективной
синхронизации выполнения задачи с возникновением прерывания. Они позволяют переводить задачу из со стояния блокировки в состояние готовности к выполнению каждый раз, когда происходит прерывание.
Организация обработки прерываний с помощью двоичных семафоров — отличное решение, если частота возникновения одного и того же прерывания не превышает некоторый порог.
Если это же самое прерывание возникнет до того, как задача-обработчик завершит его обработку, то задача-обработчик не перейдет в блокированное состояние по завершении обработки предыдущего прерывания, а сразу же займется обслуживанием следующего. Предыдущее прерывание окажется потерянным.
![Page 20: FreeRTOS](https://reader036.vdocuments.us/reader036/viewer/2022062704/555e1c26d8b42a6a4c8b4622/html5/thumbnails/20.jpg)
Счетный семафор
Существует два основных применения счетных семафоров:• 1. Подсчет событий. В этом случае обработчик прерывания будет
отдавать семафор, то есть увеличивать его значение на единицу, когда происходит событие. Задача-обработчик будет захватывать семафор (уменьшать его значение на единицу) каждый раз при обработке события. Текущее значение семафора будет представлять собой разность между количеством событий, которые произошли, и количеством событий, которые обработаны.
• 2. Управление доступом к ресурсам. В этом случае значение счетного семафора представляет собой количество доступных ресурсов. Для получения доступа к ресурсу задача должна сначала получить (захватить) семафор — это уменьшит значение семафора на единицу. Когда значение семафора станет равным нулю, это означает , что доступных ресурсов нет. Когда задача завершает работу с данным ресурсом, она отдает семафор — увеличивает его значение на единицу.
![Page 21: FreeRTOS](https://reader036.vdocuments.us/reader036/viewer/2022062704/555e1c26d8b42a6a4c8b4622/html5/thumbnails/21.jpg)
Мьютекс
2. Мьютекс используется для защиты общего ресурса. Задача включает мьютекс, использует общий ресурс, а затем отключает мьютекс. Никакая задача не может включить мьютекс, пока он включен другой задачей.
2. Мьютекс во FreeRTOS представляет собой специальный тип двоичного семафора, который используется для реализации совместного доступа к ресурсу двух или большего числа задач.
![Page 22: FreeRTOS](https://reader036.vdocuments.us/reader036/viewer/2022062704/555e1c26d8b42a6a4c8b4622/html5/thumbnails/22.jpg)
Реализация семафоров и мьютексов
В системе FreeRTOS реализован N-элементный семафор в виде очереди, в которой может быть N элементов.
Семафор следит за тем, сколько записей в текущий момент помещено в очередь, что осуществляется с помощью поля uxMessagesWaiting, имеющегося в очереди.
Семафор реализует «чистую синхронизацию» так, как это названо в вызовах заголовочного файла semphr.h системы FreeRTOS. Поэтому размер элемента в очереди указан равным нулю байтов (uxItemSize == 0). Каждое обращение к семафору увеличивает или уменьшает на единицу значение поля uxMessagesWaiting; копирование элементов очереди или данных выполнять не требуется.
![Page 23: FreeRTOS](https://reader036.vdocuments.us/reader036/viewer/2022062704/555e1c26d8b42a6a4c8b4622/html5/thumbnails/23.jpg)
Реализация семафоров и мьютексов
Точно также, как и семафоры, мьютексы реализованы в виде очередей, но в них с помощью определений #defines перегружены несколько полей xQUEUE:
/* Перепределение полей структуры xQUEUE. */ #define uxQueueType pcHead #define pxMutexHolder pcTail
Поскольку мьютекс не хранит никаких данных в очереди, ему не нужна внутренняя память, и, поэтому, не нужны поля pcHead и pcTail. Система FreeRTOS устанавливает поле uxQueueType (в действительности поле pcHead) равным 0, указывая, что эта очередь используется для мьютекса.
![Page 24: FreeRTOS](https://reader036.vdocuments.us/reader036/viewer/2022062704/555e1c26d8b42a6a4c8b4622/html5/thumbnails/24.jpg)
Список используемой литературы
1. http://wiki.fh-up.ru/?title=FreeRTOS2. http://rus-linux.net/MyLDP/BOOKS/Architecture-Open-Sourc
e-Applications/Vol-2/freertos-01.html3. http://robot-develop.org/archives/2777