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



Pdf көрінісі
бет25/129
Дата28.09.2023
өлшемі4.1 Mb.
#478975
1   ...   21   22   23   24   25   26   27   28   ...   129
Kurniz

реализация задержек
с помощью API-функции vTaskDelay()
Вернемся к рассмотрению учебной программы № 1. Задачи в этой 
программе выполняли полезное действие (в нашем случае — вывод 
текстовой строки на экран), после чего ожидали определенный про-
межуток времени, то есть выполняли задержку на какое-то время. 
Реализация задержки в виде пустого цикла не эффективна. Один 
из основных недостатков мы продемонстрировали, когда задачам 
был назначен разный приоритет. А именно, когда высокоприоритет-
ная задача все время остается в состоянии готовности к выполнению 
(не переходит ни в блокированное, ни в приостановленное состоя-
ние), она поглощает все процессорное время, и низкоприоритетные 
задачи никогда не выполняются.
Для корректной реализации задержек средствами FreeRTOS следует 
применять API-функцию vTaskDelay(), которая переводит задачу, 
вызывающую эту функцию, в блокированное состояние на заданное 
количество квантов времени. Ее прототип:
void vTaskDelay( portTickType xTicksToDelay );
Единственным аргументом является xTicksToDelay, который непо-
средственно задает количество квантов времени задержки.
рис. 9. Разделение времени между задачами,
когда Задача 2 имеет более высокий приоритет, чем Задача 1


100
КОМПОНЕНТЫ И ТЕХНОЛОГИИ • № 4 '2011
компоненты
микроконтроллеры
Например, пусть задача вызвала функ-
цию xTicksToDelay(100) в момент времени, 
когда счетчик квантов был равен 5000. Задача 
сразу же блокируется, планировщик отдаст 
управление другой задаче, а вызывающая за-
дача вернется в состояние готовности к вы-
полнению, только когда счетчик квантов до-
стигнет значения 5100. В течение времени, 
пока счетчик квантов будет увеличиваться 
от 5000 до 5100, планировщик будет выпол-
нять другие задачи, в том числе задачи с бо-
лее низким приоритетом.
Следует отметить, что программисту нет
необходимости отслеживать переполнение 
счетчика квантов времени. API-функции, 
связанные с отсчетом времени (в том числе 
и vTaskDelay()), берут эту обязанность на себя.
Рассмотрим учебную программу № 2, ко-
торая выполняет те же функции, что и про-
грамма № 1, но для создания задержек в ней 
используется API-функция vTaskDelay()
Кроме того, задаче при ее создании передает-
ся не абстрактное значение периода, а значе-
ние периода в миллисекундах:
#include
#include
#include
#include “FreeRTOS.h”
#include “task.h”
/* Структура, содержащая передаваемую в задачу информацию */
typedef struct TaskParam_t {
char string[32]; /* строка */
long period; /* период, миллисекунды*/
} TaskParam;
/* Объявление двух структур TaskParam */
TaskParam xTP1, xTP2;
/*-----------------------------------------------------------*/
/* Функция, реализующая задачу */
void vTask( void *pvParameters )
{
volatile TaskParam *pxTaskParam;
/* Преобразование типа void* к типу TaskParam* */
pxTaskParam = (TaskParam *) pvParameters;
for( ;; )
{
/* Вывести на экран строку, переданную в качестве параметра 
при создании задачи */
puts( (const char*)pxTaskParam->string );
/* Задержка на время, заданное в миллисекундах */
/* pxTaskParam->period задан в миллисекундах /*
/* Разделив его на кол-во мс в кванте, получим кол-во квантов */
vTaskDelay(pxTaskParam->period / portTICK_RATE_MS); 
}
vTaskDelete( NULL );
}
/*-----------------------------------------------------------*/
/* Точка входа. С функции main() начнется выполнение программы. */
short main( void )
{
/* Заполнение полей структуры, передаваемой Задаче 1 */
strcpy(xTP1.string, “Task 1 is running”);
xTP1.period = 1000L; 
/* 1000 мс */
/* Заполнение полей структуры, передаваемой Задаче 2 */
strcpy(xTP2.string, “Task 2 is running”);
xTP2.period = 3000L; 
/* 3000 мс */
/* Создание Задачи 1 с приоритетом 1. Передача ей в качестве 
параметра указателя на структуру xTP1 */
xTaskCreate( vTask, ( signed char * ) “Task1”, configMINIMAL_
STACK_SIZE, (void*)&xTP1, 1, NULL );
/* Создание Задачи 2 с приоритетом 2. Передача ей указателя 
на структуру xTP2 */
xTaskCreate( vTask, ( signed char * ) “Task2”, configMINIMAL_
STACK_SIZE, (void*)&xTP2, 2, NULL );
/* Запуск планировщика */
vTaskStartScheduler();
return 1;
}
По результатам работы учебной програм-
мы № 2 (рис. 10) видно, что процессорное 
время теперь получает как высокоприори-
тетная задача 2, так и низкоприоритетная за-
дача 1.
Выполнение задач в учебной программе 
№ 2 приведено на рис. 11. Выполнение кода 
планировщика в целях упрощения рисунка 
не приводится. Б
óльшую часть времени про-
цессор бездействует, а следовательно, теперь 
задачи очень экономно расходуют процес-
сорное время.
В момент времени (1) происходит запуск 
планировщика. На этот момент Задача 1 
и Задача 2 находятся в состоянии готовности 
к выполнению, однако приоритет Задачи 2 
выше, поэтому именно ей планировщик 
передает управление. Задача 2 выполняет 
полезную работу (выводит строку “Task 2 


Достарыңызбен бөлісу:
1   ...   21   22   23   24   25   26   27   28   ...   129




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

    Басты бет