Задачи в операционной системе FreeRTOS


Все задачи, выполняемые FreeRTOS, строятся по достаточно простому шаблону: как функция на языке С, которой в качестве аргументов можно передать указатель (адрес)

void vUserTask(void *pvParam)
{
  //- объявление/определение, инициализация переменных
  //- однократно выполняемый код
  ...

  for(;;)
  {
    //- код выполняемой задачи
    ...
  }
  vTaskDelete(NULL);
}

Большинство задач проектируется так, что они не могут никогда закончиться и функционируют всё время работы микроконтроллера. Задачи могут быть заблокированы или остановлены, но нет особых причин удалять задачу, чтобы через некоторое время пытаться снова её создать и запустить. Связано это прежде всего с памятью: с распределением памяти при создании задачи, освобождением памяти и "уборкой мусора" при завершении задачи. Освобождаемая память должна очищаться, дефрагментироваться и учитываться операционной системой для последующего выделения без потерь. Это достаточно сложный алгоритм, к тому же требущий определённой вычислительной мощности от ядра микроконтроллера.

Для переключения между задачами можно (как один из вариантов):

  - разбить всё время работы микроконтроллера на некоторые равные промежутки времени - кванты

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

  - по истечении выделенного кванта времени передать выполнение следующей в очереди задаче

Для реализации такого механизма разумно:

  - выделить один из таймеров микроконтроллера для отсчета квантов времени (системный таймер)

  - разбить все задачи по важности на группы и раздать им приоритеты

  - разбить задачи по статусу для оптимального управления: помещаемые в очередь, не помещаемые в очередь (заблокированные) в течении какого-то определённого времени, остановленные и не учитываемые системой до особого разрешения.

  - каждый раз при срабатывании системного таймера (системный тик, или просто - тик) вызывать обработчик прерывания: планировщик задач (shediler)

  - в планировщике реализовать механизм очерёдности выполнения задач исходя из их приоритетов

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

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

Планировщик должен:

  - знать какие вообще задачи существуют в операционной системе

  - знать приоритет каждой задачи и её статус и формировать очередь на выполнение

  - запускать задачи в порядке очереди.

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