Top Banner
FreeRT OS
24
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: FreeRTOS

FreeRTOS

Page 2: FreeRTOS

Философия разработки

FreeRTOS разработана как:- Простая- Портируемая-Маленькая

Система FreeRTOS находится в стадии активной разработки, которая была начата Ричардом Барри (Richard Barry) в 2002 году.

Page 3: FreeRTOS

Некоторые возможности FreeRTOS• Выбор политики планирования• Всегда работает задача с наивысшим приоритетом

из доступных. Задачи с одинаковым приоритетом делят процессорное время.

• Coroutines(сопрограммы) - маленькие задачи, использующие очень мало RAM.

• БОльшая часть кода одинакова для всех средств разработки.

• Много портов и примеров.• Дополнительные возможности могут быть легко и

быстро добавлены.

Page 4: FreeRTOS

• Многозадачность и параллельностьОбычный процессор может выполнять только одну задачу одновременно

- но за счёт быстрого переключения между задачами делается вид, будто задачи выполняются одновременно.

• ПланированиеПланировщик - это часть ядра, отвечающий за то, какая задача должна

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

Page 5: FreeRTOS

ПланированиеКаждая задача имеет приоритет, назначенный пользователем, который равен от 0 (самый низкий приоритет) и до значения времени компиляции configMAX_PRIORITIES-1 (самый высокий приоритет)

Планировщик гарантирует, что процессорное время отдаётся задаче с максимальным приоритетом из доступных(ready) задач. Даже если задачи с низким приоритетом тоже находятся в состоянии готовности(ready) длительное время.

Page 6: FreeRTOS

Тактовая частота системы

Система 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

ЗадачиЗадачей является определяемая пользователем функция на языке C с заданным приоритетом. В tasks.c и task.h делается вся тяжелая работа по созданию, планированию и обслуживанию задач. Простая

Нет ограничений использования

Поддерживает полное вытеснение

Приоритет задаётся всей задаче

Каждая задача требует отдельного стека - это приводит к большому потреблению оперативной памяти

Повторная входимость должна быть тщательно продумана, если используется вытеснение

Page 8: FreeRTOS

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

Совместная работа упрощает проблему повторного входа.

Хорошо переносимо между разными архитектурами

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

Отсутствие индивидуального стека требует особого рассмотрения

Ограниченный API

Кооперативная многозадачность только между сопрограммами.

Page 9: FreeRTOS

Объявление задач• Задача должна иметь следующую структуру:

void vATaskFunction( void *pvParameters ){ for ( ; ; )

{ /* Код задачи пишется тут */ } }

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

Задачи создаются с помощью xTaskCreate() и удаляются с помощью vTaskDelete()

Page 10: FreeRTOS

Блок управления задачей 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

Списки

Page 12: FreeRTOS

СпискиСписок в системе 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

void * pvContainer это:

typedef struct xLIST {

volatile unsigned portBASE_TYPE uxNumberOfItems; volatile xListItem * pxIndex; /* Используется для прохода по списку. Указывает на последний элемент, возвращенный функцией

pvListGetOwnerOfNextEntry (). */ volatile xMiniListItem xListEnd; /* Элемент списка, в

котором находится максимально возможное значение, означающее, что он всегда находится в конце списка и, поэтому, используется как маркер. */

} xList;Размер списка в любое время хранится в переменной uxNumberOfItems, предназначенной для быстрого выполнения операций с размерами списков.

Page 14: FreeRTOS

Списки

• Поскольку списки сортируются в порядке убывания, элемент xListEnd используется как маркер начала списка. А поскольку список кольцевой, этот элемент xListEnd также является маркером конца списка.

• В большинстве «традиционных» операций доступа к списку, которыми мы пользуемся, вся работа выполняется в одном цикле for() или в функции, вызываемой следующим образом:

for (listPtr = listStart; listPtr != NULL; listPtr = listPtr->next) {

// Что-то здесь делается с указателями listPtr ... }

Каждый объект struct xListItem является, на самом деле, объектом xGenericListItem из соответствующего блока TCB.

Page 15: FreeRTOS

Очереди

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

Page 16: FreeRTOS

Базовая структура данных очереди выглядит следующим образом:

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

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

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

В системе FreeRTOS поддерживаются вставки и удаления в очереди с блокировкой и без блокировки.

Блокирования указываются с тайм-аутом. Задача может ожидать снятия блокировки бесконечно или в течение ограниченного периода времени.

В системе FreeRTOS используется список xTasksWaitingToSend для отслеживания задач, которые блокированы при выполнении операции вставки элемента в очередь. Каждый раз, когда элемент удаляется из очереди, проверяется список xTasksWaitingToSend. Если задача находится в состоянии ожидания в этом списке, то задача разблокируется.

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

Page 18: FreeRTOS

Семафоры

Механизм семафоров основан на механизме очередей. По большому счету API-функции для работы с семафорами представляют собой макросы — «обертки» других API-функций для работы с очередями.

Семафор должен быть явно создан перед первым его использованием.

Page 19: FreeRTOS

Двоичный семафорДвоичные семафоры предназначены для эффективной

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

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

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

Page 20: FreeRTOS

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

Существует два основных применения счетных семафоров:• 1. Подсчет событий. В этом случае обработчик прерывания будет

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

• 2. Управление доступом к ресурсам. В этом случае значение счетного семафора представляет собой количество доступных ресурсов. Для получения доступа к ресурсу задача должна сначала получить (захватить) семафор — это уменьшит значение семафора на единицу. Когда значение семафора станет равным нулю, это означает , что доступных ресурсов нет. Когда задача завершает работу с данным ресурсом, она отдает семафор — увеличивает его значение на единицу.

Page 21: FreeRTOS

Мьютекс

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

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

Page 22: FreeRTOS

Реализация семафоров и мьютексов

В системе FreeRTOS реализован N-элементный семафор в виде очереди, в которой может быть N элементов.

Семафор следит за тем, сколько записей в текущий момент помещено в очередь, что осуществляется с помощью поля uxMessagesWaiting, имеющегося в очереди.

Семафор реализует «чистую синхронизацию» так, как это названо в вызовах заголовочного файла semphr.h системы FreeRTOS. Поэтому размер элемента в очереди указан равным нулю байтов (uxItemSize == 0). Каждое обращение к семафору увеличивает или уменьшает на единицу значение поля uxMessagesWaiting; копирование элементов очереди или данных выполнять не требуется.

Page 23: FreeRTOS

Реализация семафоров и мьютексов

Точно также, как и семафоры, мьютексы реализованы в виде очередей, но в них с помощью определений #defines перегружены несколько полей xQUEUE:

/* Перепределение полей структуры xQUEUE. */ #define uxQueueType pcHead #define pxMutexHolder pcTail

Поскольку мьютекс не хранит никаких данных в очереди, ему не нужна внутренняя память, и, поэтому, не нужны поля pcHead и pcTail. Система FreeRTOS устанавливает поле uxQueueType (в действительности поле pcHead) равным 0, указывая, что эта очередь используется для мьютекса.

Page 24: FreeRTOS

Список используемой литературы

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