Перевод может содержать ошибки. Читайте первоисточник: Quick Co-routine Example
Назад: [Сопрограммы во FreeRTOS] | Вверх: [Сопрограммы во FreeRTOS] | Вперёд: [Сопрограммы во FreeRTOS] |
Этот быстрый пример (дурацкий перевод, а другого пока не знаю) демонстрирует использование сопрограмм.
Приведённый ниже код определяет очень простую сопрограмму, которая не делает ничего кроме периодического мигания светодиодом.
/*----------------------------------------------------------------------------*/
void vFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
{
/* Сопрограмма должна начинаться с вызова макроса crSTART(). */
crSTART( xHandle );
for( ;; )
{
/* Задержка на фиксированное время. */
crDELAY( xHandle, 10 );
/* Мигание светодиодом. */
vParTestToggleLED( 0 );
}
/* Сопрограмма должна заканчиваться вызовом макроса crEND(). */
crEND();
}
И всё!
Сопрограммы планируются повторяющимся вызовом vCoRoutineSchedule(). Наиболее подходящее место для этого - вызывать из задачи простоя, написав функцию-ловушку задачи простоя. Сначала убедитесь, что configUSE_IDLE_HOOK установлен в 1 в файле FreeRTOSConfig.h. Затем напишите ловушку задачи простоя следующим образом:
/*----------------------------------------------------------------------------*/
void vApplicationIdleHook( void )
{
vCoRoutineSchedule( void );
}
Другой способ, если задача простоя не выполняет никаких других функций, может быть более эффективным. Для этого нужно вызывать vCoRoutineSchedule() из цикла:
/*----------------------------------------------------------------------------*/
void vApplicationIdleHook( void )
{
for( ;; )
{
vCoRoutineSchedule( void );
}
}
Сопрограмма может быть создана внутри функции main().
/*----------------------------------------------------------------------------*/
#include "task.h"
#include "croutine.h"
#define PRIORITY_0 0
void main( void )
{
/* В этом случае индекс не используется, и функцию передаётся значение 0. */
xCoRoutineCreate( vFlashCoRoutine, PRIORITY_0, 0 );
/* Замечание: Здесь же могут быть созданы задачи ОС! */
/* Запуск планировщика ОС. */
vTaskStartScheduler();
}
Теперь предположим, что мы хотим создать восемь таких сопрограмм из одной и той же функции. Каждая сопрограмма будет мигать разными светодиодами с разной скоростью. Параметр index может быть использован для различения сопрограмм внутри самой функции сопрограммы.
На этот раз мы создаём 8 сопрограмм и передаём в каждую свой индивидуальный индекс.
/*----------------------------------------------------------------------------*/
#include "task.h"
#include "croutine.h"
#define PRIORITY_0 0
#define NUM_COROUTINES 8
void main( void )
{
int i;
for( i = 0; i < NUM_COROUTINES; i++ )
{
/* На этот раз значение i передаётся в качестве параметра index. */
xCoRoutineCreate( vFlashCoRoutine, PRIORITY_0, i );
}
/* Замечание: Здесь же могут быть созданы задачи ОС! */
/* Запуск планировщика ОС. */
vTaskStartScheduler();
}
Функция сопрограммы теперь также усложняется, т.к. использует различные светодиоды и различную частоту мигания.
/*----------------------------------------------------------------------------*/
const int iFlashRates[ NUM_COROUTINES ] = { 10, 20, 30, 40, 50, 60, 70, 80 };
const int iLEDToFlash[ NUM_COROUTINES ] = { 0, 1, 2, 3, 4, 5, 6, 7 }
void vFlashCoRoutine( CoRoutineHandle_t xHandle, UBaseType_t uxIndex )
{
/* Сопрограмма должна начинаться с вызова макроса crSTART(). */
crSTART( xHandle );
for( ;; )
{
/* Задержка на фиксированный период. uxIndex используется как индекс */
/* в таблице iFlashRates[]. Поскольку сопрограммы создавались с */
/* различными индексами, каждая будет задерживаться на своё время. */
crDELAY( xHandle, iFlashRate[ uxIndex ] );
/* Мигание светодиодом. Снова uxIndex используется как индекс */
/* в массиве, но на этот раз для того, чтобы определить светодиод, */
/* состояние которого нужно изменить. */
vParTestToggleLED( iLEDToFlash[ uxIndex ] );
}
/* Сопрограмма должна завершаться вызовом макроса crEND(). */
crEND();
}