135
КОМПОНЕНТЫ И ТЕХНОЛОГИИ •
№ 8 '2011
www.kite.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;
}
Достарыңызбен бөлісу: