Компоненты и технологии • №2 '2011 компоненты



Pdf көрінісі
бет83/129
Дата28.09.2023
өлшемі4.1 Mb.
#478975
1   ...   79   80   81   82   83   84   85   86   ...   129
Kurniz

Работа с мьютексами
Мьютекс представляет собой специальный 
вид семафора, поэтому доступ к мьютексу 
осуществляется так же, как и к семафору: с по-
мощью дескриптора (идентификатора) мью-
текса — переменной типа xSemaphoreHandle.
Для того чтобы API-функции для рабо-
ты с мьютексами были включены в про-
грамму, необходимо установить макро-
определение configUSE_MUTEXES в файле 
FreeRTOSConfig.h равным «1».
Мьютекс должен быть явно создан перед 
первым его использованием. API-функция 
xSemaphoreCreateMutex() служит для созда-
ния мьютекса:
xSemaphoreHandle xSemaphoreCreateMutex( void );


135
КОМПОНЕНТЫ И ТЕХНОЛОГИИ • № 8 '2011
www.kite.ru
компоненты
микроконтроллеры
Возвращаемое значение — дескриптор 
мьютекса, он должен быть сохранен в пере-
менной для дальнейшего обращения к мью-
тексу. Если мьютекс не создан по причине от-
сутствия достаточного объема памяти, воз-
вращаемым значением будет NULL.
Операции захвата и возврата (выдачи) 
мьютекса выполняются с помощью анало-
гичных API-функций для работы с семафора-
ми — xSemaphoreTake() и xSemaphoreGive()
которые были рассмотрены в [1, № 7].
Рассмотрим, как применение мьютекса по-
зволяет решить проблему совместного досту-
па к ресурсу, на примере учебной программы 
№ 1. В качестве разделяемого ресурса выступает 
консоль, две задачи выводят свое сообщение 
на дисплей. Обратите внимание на реализацию 
вывода строки на консоль: вместо стандартной 
функции используется посимвольный вывод.
Сначала рассмотрим учебную программу 
№ 1 без использования мьютекса:
#include
#include
#include
#include “FreeRTOS.h”
#include “task.h”
#include “semphr.h”
/* Дескриптор мьютекса — глобальная переменная*/
volatile xSemaphoreHandle xMutex;
/* Функция посимвольно выводит строку на консоль.
Консоль, как ресурс, никаким образом не защищена от совместного 
доступа из нескольких задач. */
static void prvNewPrintString(const portCHAR *pcString) {
portCHAR *p;
int i;
/* Указатель — на начало строки */
p = pcString;
/* Пока не дошли до нулевого символа — конца строки. */
while (*p) {
/* Вывод на консоль символа, на который ссылается указатель. */
putchar(*p);
/* Указатель — на следующий символ в строке. */
p++;
/* Вывести содержимое буфера экрана на экран. */
fflush(stdout);
/* Небольшая пауза */
for (i = 0; i < 10000; i++) ;
}
}
/* Функция, реализующая задачу.
Будет создано 2 экземпляра этой задачи.
Каждый получит строку символов в качестве аргумента 
при создании задачи. */
static void prvPrintTask(void *pvParameters) {
char *pcStringToPrint;
pcStringToPrint = (char *) pvParameters;
for (;;) {
/* Для вывода строки на консоль используется своя 
функция prvNewPrintString(). */
prvNewPrintString(pcStringToPrint);
/* Блокировать задачу на промежуток времени случайной 
длины: от 0 до 500 мс. */
vTaskDelay((rand() % 500));
/* Вообще функция rand() не является реентерабельной.
Однако в этой программе это неважно. */
}
}
/*-----------------------------------------------------------*/
/* Точка входа. С функции main() начнется выполнение 
программы. */
short main( void )
{
/* Создание мьютекса. */
xMutex = xSemaphoreCreateMutex();
/* Создание задач, если мьютекс был успешно создан. */
if (xMutex != NULL) {
/* Создать два экземпляра одной задачи. Каждому 
экземпляру задачи передать в качестве аргумента свою 
строку. Приоритет задач задать разным, чтобы имело 
место вытеснение задачи 1 задачей 2.
*/ xTaskCreate(prvPrintTask, “Print1”, 1000,
“Task 1 **************************************\r\n”, 1,
NULL);
xTaskCreate(prvPrintTask, “Print2”, 1000,
“Task 2 ----------------------------------\r\n”, 2,
NULL);
/* Запуск планировщика. */
vTaskStartScheduler();
}
return 1;
}


Достарыңызбен бөлісу:
1   ...   79   80   81   82   83   84   85   86   ...   129




©dereksiz.org 2024
әкімшілігінің қараңыз

    Басты бет