#define configUSE_TIMERS
1
#define configTIMER_TASK_PRIORITY
1
#define configTIMER_QUEUE_LENGTH
( 10 )
#define configTIMER_TASK_STACK_DEPTH
configMINIMAL_STACK_SIZE
Результат работы учебной программы приведен на рис. 6.
В учебной программе демонстрируется прием, когда запуск (в дан-
ном случае сброс, как было сказано выше — не имеет значения) тай-
меров производится ДО запуска планировщика. В этом случае тайме-
ры начинают отсчет времени сразу после старта планировщика.
В графическом виде работа учебной программы представлена
на рис. 7.
Учебная программа демонстрирует также разницу между интер-
вальными и периодическими таймерами. Как видно на рис. 6 и 7, бу-
дучи единожды запущен, интервальный таймер вызовет свою функ-
цию один раз. Периодический же таймер напротив — вызывает свою
функцию
до тех пор, пока не будет удален или остановлен.
Справедливости ради следует отметить, что на практике можно
обойтись без использования идентификатора таймера для определе-
ния, какой таймер вызвал функцию таймера, как это сделано в учеб-
ной программе.
рис. 6. Выполнение
учебной программы
рис. 7. Отсчет временных промежутков в
учебной программе
100
КОМПОНЕНТЫ И ТЕХНОЛОГИИ •
№ 10 '2011
компоненты
микроконтроллеры
Для этой цели вполне достаточно использовать дескриптор тайме-
ра. В таком случае функция интервальных таймеров в модифициро-
ванной учебной программе примет вид:
/* Функция интервальных таймеров.
* Нескольким экземплярам интервальных таймеров соответствует одна-единственная функция.
* Эта функция автоматически вызывается при истечении времени любого из связанных с ней таймеров.
* Для того чтобы выяснить, время какого таймера истекло, используется идентификатор таймера. */
void vOneShotTimersFunction(xTimerHandle xTimer) {
/* Различные
действия в зависимости от того, какой таймер вызывал функцию */
/* Сработал интервальный таймер 1? */
if (xTimer == xOneShotTimers[0]) {
/* Индикация работы + текущее время */
printf(“\t\t\t\tOneShot timer ID = %d. Time = %d sec\n\r”, *pxTimerID, xTaskGetTickCount() /
configTICK_RATE_HZ);
xTimerChangePeriod(xAutoReloadTimer, 6000, 0);
/* Запустить интервальный таймер 2 */
xTimerStart(xOneShotTimers[1], 0);
/* Сработал интервальный таймер 2? */
} else if (xTimer == xOneShotTimers[1]) {
/* Индикация работы + текущее время */
printf(“\t\t\t\tOneShot timer ID = %d. Time = %d sec\n\r”, *pxTimerID, xTaskGetTickCount() /
configTICK_RATE_HZ);
/* Запустить интервальный таймер 3 */
xTimerStart(xOneShotTimers[2], 0);
/* Сработал интервальный таймер 3? */
} else if (xTimer == xOneShotTimers[2]) {
/* Индикация работы + текущее время */
printf(“\t\t\t\tOneShot timer ID = %d. Time = %d sec\n\r”, *pxTimerID, xTaskGetTickCount() /
configTICK_RATE_HZ);
puts(“\n\r\t\t\t\tAbout to delete AutoReload timer!”);
fflush();
/* Удалить периодический таймер.
* После этого активных таймеров в программе не останется. */
xTimerDelete(xAutoReloadTimer, 0);
}
}
Дескрипторы созданных интервальных таймеров хранятся в гло-
бальном массиве. Кроме того, дескриптор таймера, который привел
к вызову функции таймера, передается в эту функцию в виде ее ар-
гумента. Поэтому выполняя сравнение аргумента функции таймера
с дескриптором, который хранится в глобальной переменной, можно
сделать вывод о том, какой конкретно таймер инициировал вызов
этой функции таймера.
Результат выполнения модифицированной учебной программы
ничем не будет отличаться от приведенного на рис. 6, что подтверж-
дает, что для однозначной идентификации таймера вполне достаточ-
но иметь его дескриптор.
Выводы
Подводя итог можно сказать, что их применение оправдано в слу-
чаях, когда к точности отмеряемых временных интервалов не предъ-
является высоких требований, так как активность других задач в про-
грамме может существенно повлиять на точность работы програм-
мных таймеров. Кроме того, немаловажным ограничением является
дискретность работы таймеров величиной в один системный квант
времени.
В дальнейших публикациях речь пойдет о способах отладки про-
граммы, которая выполняется под управлением FreeRTOS. Внимание
будет сконцентрировано на:
способах
трассировки программы;
•
получении статистики
выполнения в реальном времени;
•
способах измерения потребляемого задачей объема стека и спосо-
•
бах защиты от его переполнения.
n
Литература
1. Курниц А. FreeRTOS — операционная система для микроконтроллеров //
Компоненты и технологии. 2011. № 2–9.
2.
www.freertos.org
3.
http://ru.wikipedia.org/wiki/FreeRTOS
4.
http://electronix.ru/forum/index.php?showforum=189
5.
http://sourceforge.net/projects/freertos/files/FreeRTOS/
6.
http://www.ee.ic.ac.uk/t.clarke/rtos/lectures/RTOSlec2x2bw.pdf