102
КОМПОНЕНТЫ И ТЕХНОЛОГИИ •
№ 4 '2011
компоненты
микроконтроллеры
2. Если программа
допускает использо-
вание
API-функции уничтожения за-
дачи
vTaskDelete(), то функция задачи
Бездействие должна завершать свое вы-
полнение в течение разумного периода
времени. Это
требование объясняется
тем, что функция задачи Бездействие от-
ветственна за освобождение ресурсов ядра
после уничтожения задачи. Таким образом,
временная задержка в теле функции задачи
Бездействие приведет к такой же задержке
в очистке ресурсов, связанных с уничто-
женной задачей, и ресурсы ядра не будут
освобождены вовремя.
Чтобы
задать свою функцию задачи
Бездействие, необходимо в файле настрой-
ки ядра
FreeRTOSConf ig.h задать макро-
определение
configUSE_IDLE_HOOK рав-
ным 1. В одном из файлов исходного кода
должна быть определена функция задачи
Бездействие, которая имеет следующий про-
тотип:
void vApplicationIdleHook( void );
Значение
configUSE_IDLE_HOOK, рав-
ное 0, используется, когда не нужно добав-
лять дополнительную функциональность.
Создадим учебную программу № 3, демон-
стрирующую использование функции зада-
чи Бездействие. В программе будет опреде-
лена глобальная переменная-счетчик, задача
Бездействие будет инкрементировать значе-
ние этой переменной. Также будет создана
задача вывода значения переменной-счетчика
на экран каждые 250 мс.
Текст учебной программы № 3:
#include
#include
#include
#include “FreeRTOS.h”
#include “task.h”
/* Глобальная переменная-счетчик, которая будет увеличиваться на 1
при каждом вызове функции задачи Бездействие */
volatile unsigned long ulIdleCycleCount = 0;
/*-----------------------------------------------------------*/
/* Функция, реализующая задачу вывода на экран значения
ulIdleCycleCount
каждые 250 мс */
void vTaskFunction( void *pvParameters )
{
/* Бесконечный цикл */
for( ;; )
{
/* Вывести на экран значение переменной ulIdleCycleCount */
printf( “ulIdleCycleCount = %lu\n\r”, ulIdleCycleCount );
/* Задержка на 250 мс */
vTaskDelay( 250 / portTICK_RATE_MS );
}
vTaskDelete( NULL );
}
/*-----------------------------------------------------------*/
/* Точка входа. С функции main() начнется выполнение программы. */
short main( void )
{
/* Создание задачи с приоритетом 1. Параметр не передается */
xTaskCreate( vTaskFunction, ( signed char * ) “Task”,
configMINIMAL_STACK_SIZE, NULL, 1, NULL );
/* Запуск планировщика */
vTaskStartScheduler();
return 1;
}
/* Функция, реализующая задачу Бездействие.
Ее имя ОБЯЗАТЕЛЬНО должно быть vApplicationIdleHook.
Аргументов не получает. Ничего не возвращает */
void vApplicationIdleHook( void )
{
/* Увеличить переменную-счетчик на 1 */
ulIdleCycleCount++;
}
Результат выполнения учебной программы
№ 3 приведен на рис. 14. Видно, что за 250 мс,
пока задача вывода значения на экран пребы-
вает в блокированном состоянии, функция
задачи Бездействие «успевает выполниться»
большое количество раз.
Учебная программа № 3 затрагивает
еще один очень важный аспект написания
программ, работающих под управлением
ОСРВ, — одновременное использование
одного аппаратного ресурса различными за-
дачами. В нашем случае в качестве такого
ресурса выступает глобальная переменная,
доступ к которой осуществляет как задача
Бездействие, так и задача отображения зна-
чения этой переменной. При совместном
доступе нескольких задач к общей перемен-
ной возможна ситуация, когда выполнение
одной задачи прерывается планировщиком
именно в тот момент, когда задача модифи-
цирует общую переменную, когда та еще со-
держит не окончательное (искаженное) зна-
чение. При этом результат работы другой
задачи, которая получит управление и об-
ратится к этой переменной, также окажется
искаженным.
Однако в учебной программе № 3 задача
Бездействие не может прервать операцию
с общей переменной в теле задачи ото-
бражения, так как задача Бездействие бу-
дет выполняться лишь тогда, когда задача
отображения завершит действия с общей
переменной (вывод ее на экран функцией
Достарыңызбен бөлісу: