Опубликован: 19.01.2025 | Доступ: свободный | Студентов: 0 / 0 | Длительность: 05:57:00
Лекция 12:

Лабораторная работа №11. Очереди FreeRTOS (на основе мьютексов и семафоров)

< Лекция 11 || Лекция 12 || Лекция 13 >

11.1 Цели и задачи

Целью работы является освоение механизма блокировок во FreeRTOS на основе мьютексов и семафоров.

Для достижения поставленной цели требуется решить следующие задачи:

  1. Изучить назначение мьютексов и семафоров.
  2. Ознакомиться с процессом использования мьютексов во FreeRTOS.
  3. Разработать задачи с блокировкой, выполняемые во FreeRTOS.

Презентация к блоку "Операционные системы реального времени RISC-V"

11.2 Основные теоретические сведения

Мьютекс (Mutex: MUTual EXception) является разновидностью семафора. Семафор - примитив синхронизации работы процессов и потоков, в основе которого лежит счётчик, над которым можно производить две операции: увеличение и уменьшение значения на единицу, при этом операция уменьшения для нулевого значения счетчика является блокирующейся. Служит для построения более сложных механизмов синхронизации и используется для синхронизации параллельно работающих задач, для защиты передачи данных через разделяемую память, для защиты критических секций, а также для управления доступом к аппаратному обеспечению. Параметром семафора является максимальное значение его счетчика. Мьютекс - семафор, максимальное значение которого равно единице.

Назначение мьютекса

Рис. 11.1. Назначение мьютекса

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

Для использования мьютексов и семафоров нужно создать макрос configSUPPORT_DYNAMIC_ALLOCATION, равный 1. Для использования мьютексов нужно также создать макрос configUSE_MUTEXES, равный 1. Мьютексы создаются функцией SemaphoreHandle_t xSemaphoreCreateMutex( void ), а семафоры - SemaphoreHandle_t xSemaphoreCreateBinary( void ).

Взятие семафора выполняется функцией xSemaphoreTake( SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait ), а освобождение - xSemaphoreGive( SemaphoreHandle_t xSemaphore ). В функции взятия используется параметр времени ожидания xTicksToWait. Он определяет количество системных тиков, в течение которых задача ждет получение семафора.

В более старых версиях FreeRTOS для определения мьютекса используется объект xSemaphoreHandle. Функционально он ничем не отличается от SemaphoreHandle_t.

Пример кода работы с мьютексами:

SemaphoreHandle_t xSemaphore = NULL;
void vATask( void * pvParameters )
 {
    xSemaphore = xSemaphoreCreateMutex();
    if( xSemaphore != NULL )
    {
        if( xSemaphoreGive( xSemaphore ) != pdTRUE ) // will fail!
        {
	…
        }
        if( xSemaphoreTake( xSemaphore, ( TickType_t ) 0 ) )
        {
	…
            if( xSemaphoreGive( xSemaphore ) != pdTRUE )
            {
	…
            }
        }
    }
 }

11.3 Задание к лабораторной работе

Для выполнения работы требуется:

  1. Подготовить проект с настроенной FreeRTOS для QEMU.
  2. Реализовать задачи с блокировкой, согласно требованиям.
  3. Запустить программу в эмуляторе и убедиться в работоспособности задач.

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

  • Количество светодиодов n = max(k, 2 + ((a+1) % 4));
  • Период зажигания светодиода T[i] = (a * t + b * t * (i));
  • Скважность 50%.
  • Количество одновременно горящих светодиодов: 1 + ((b)%(n/2))

где а = номер варианта, b = количество букв в фамилии, t - базовый период, принимаемый как 200 тиков процессора, k - количество доступных для работы светодиодов.

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

11.3.1 Описание последовательности выполнения работы

Для выполнения задания необходимо:

  1. Настроить среду для работы согласно инструкции из п. 11.2.1.
  2. Вычислить параметры вашего варианта задания.
  3. С помощью функций управления задачами FreeRTOS модифицировать поведение светодиодов.
  4. Реализовать блокировки доступа к общему ресурсу с помощью мьютекса
  5. Выполнить сборку и запуск модифицированного примера, зафиксировать результат работы в отчете.

11.3.2 Пример выполнения работы

typedef struct {
  int num;
  char* text;
  char* text_fail
} lab_task_data_w_fail;

char* names[] = {"Toggle 1", "Toggle 2", "Toggle 3"};
char* names_fail[] = {"Toggle 1 failed", "Toggle 2 failed", "Toggle 3 failed"};
lab_task_data_w_fail data_fail[3];

void mutex_task_function(void *pvParameters)
{
  lab_task_data_w_fail* config = (lab_task_data_w_fail*)pvParameters;
  while(1)
  {
      if(xSemaphoreTake(mutex,0)){
     	 vSendString(config->text);
     	 vTaskDelay(100*(250<<config->num));
     	 vSendString(config->text);
     	 xSemaphoreGive(mutex);
      } else {
     	 vSendString(config->text_fail);
      }
	vTaskDelay(100*(250<<config->num));
  }
}


int main_mutex(){
  mutex = xSemaphoreCreateMutex();

  for(int i=0;i<3;i++){
      data_fail[i].num = i;
      data_fail[i].text = names[i];
      data_fail[i].text_fail = names_fail[i];
 
      xTaskCreate((TaskFunction_t )mutex_task_function,
               	(const char*	)names[i],
               	(uint16_t   	)512,
               	(void*      	)&data_fail[i],
               	(UBaseType_t	)2,
               	(TaskHandle_t*  )NULL);

  }
  vTaskStartScheduler();
      return 0;
}

int main(){
	main_mutex();
while(1);
}

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

11.5 Вопросы для контроля:

  1. Какое основное назначение мьютексов и семафоров?
  2. В чем отличие семафоров и мьютексов во FreeRTOS?
  3. Какие существуют основные параметры семафоров и мьютексов?
  4. Что означает параметр времени ожидания при взятии мьютекса?
< Лекция 11 || Лекция 12 || Лекция 13 >