98
КОМПОНЕНТЫ И ТЕХНОЛОГИИ • № 6 '2011
компоненты
микроконтроллеры
Андрей КУРНИЦ
kurnits@stim.by
Необходимость
использования очередей
Самый простой способ организовать об-
мен информацией между задачами — ис-
пользовать общую глобальную переменную.
Доступ к такой переменной осуществляется
одновременно из нескольких задач. Такой
подход был продемонстрирован в [1, КиТ
№ 4] в учебной программе № 3.
Однако такой подход имеет существен-
ный недостаток: при совместном досту-
пе нескольких задач к общей переменной
возникает ситуация, когда выполнение одной
задачи прерывается планировщиком именно
в момент модификации общей переменной,
когда та содержит не окончательное (иска-
женное) значение. При этом результат рабо-
ты другой задачи, которая получит управле-
ние и обратится к этой переменной, также
окажется искаженным.
Продемонстрировать этот эффект позво-
ляет учебная программа № 1, в которой объ-
явлена глобальная переменная lVal и две за-
дачи: задача, которая модифицирует общую
переменную, — vModifyTask(), и задача, кото-
рая проверяет значение этой переменной, —
vCheckTask(). Модификация производится
так, чтобы итоговое значение глобальной
переменной после окончания вычислений
не изменялось. В случае если значение общей
переменной отличается от первоначального,
задача vCheckTask() выдает соответствующее
сообщение на экран.
Текст учебной программы № 1:
#include
#include
#include
#include “FreeRTOS.h”
#include “task.h”
#include “queue.h”
/* Глобальная переменная, доступ к которой будет
* осуществляться из нескольких задач */
long lVal = 100;
/*------------------------------------------------------------------------*/
/* Функция, реализующая задачи, которая модифицирует
* глобальную переменную */
void vModifyTask(void *pvParameters) {
/* Бесконечный цикл */
for (;;) {
/* Модифицировать переменную lVal так,
* чтобы ее значение не изменилось */
lVal
+=
10;
lVal
-=
10;
}
}
/*------------------------------------------------------------------------*/
/* Функция, реализующая задачу, которая проверяет значение
* переменной */
void vCheckTask(void *pvParameters) {
/* Бесконечный цикл */
for (;;) {
if (lVal != 100) {
puts(“Variable lVal is not 100!”);
}
vTaskDelay(100);
}
}
/*------------------------------------------------------------------------*/
/* Точка входа. С функции main() начнется выполнение
* программы. */
int main(void) {
/* Создать задачи с равным приоритетом */
xTaskCreate(vModifyTask, “Modify”, 1000, NULL, 1, NULL);
xTaskCreate(vCheckTask, “Check”, 1000, NULL, 1, NULL);
/* Запуск планировщика. Задачи начнут выполняться. */
vTaskStartScheduler();
for
(;;);
}
Результаты работы показывают (рис. 1),
что значение глобальной переменной часто
оказывается не равным ожидаемому (100).
Решить подобные проблемы позволяет ис-
пользование очередей для передачи инфор-
мации между задачами. Во FreeRTOS очереди
представляют собой фундаментальный ме-
ханизм взаимодействия задач друг с другом.
Они могут быть использованы для передачи
информации как между задачами, так и меж-
ду прерываниями и задачами. Основное
преимущество использования очередей —
это то, что их использование является безо-
Достарыңызбен бөлісу: |