void ATaskFunction( void *pvParameters );
void ATaskFunction( void *pvParameters )
{
/* Переменные могут быть определены точно так же, как и в обычной функции. Каждый экземпляр созданной по этой функции задачи будет иметь собственную копию переменной iVariableExample. Это не верно, если переменная была продекларирована как статическая (static) – в этом случае будет сущесвовать только одна копия переменной, и она будет использоваться совместно всеми созданными экземплярами задачи. */
int iVariableExample = 0;
/* Задача должна быть нормально реализована как бесконечный цикл. */
for( ;; )
{
/* Код, который реализует функционал задачи, должен быть помещен здесь. */
}
/* Код должен быть организован так, чтобы в случае выхода (break) из указанного
выше
бесконечного цикла задачи, задача должна быть удалена ПРЕЖДЕ чем управление достигнет
конца этой функции. Параметр NULL, переданный
vTaskDelete(),
показывает, что должна
быть удалена вызванная (эта, которая
работает) задача. */ vTaskDelete( NULL );
}
portBASE_TYPE xTaskCreate( pdTASK_CODE pvTaskCode,
const signed portCHAR * const pcName,
unsigned portSHORT usStackDepth,
void *pvParameters,
unsigned portBASE_TYPE uxPriority,
xTaskHandle *pxCreatedTask );
pvTaskCode | Задачи - это простые C-функции, которые никогда не делают возврата из своего тела (постоянно выполняют свой бесконечный цикл). Параметр pvTaskCode - простой указатель на функцию (т. е. просто имя функции), которая реализует задачу. |
pcName |
Описательное имя для задачи. Оно никак не используется внутри FreeRTOS, и нужно только для целей отладки. Идентификация задачи по легкочитаемому имени намного проще, чем по хендлу задачи (handle).
В приложении указана константа времени компиляции configMAX_TASK_NAME_LEN, которая задает максимальную длину для этого имени - включая нулевой байт окончания строки. Если в качестве pcName предоставлена более длинная строка, то она молча урезается до величины, заданной configMAX_TASK_NAME_LEN.
|
usStackDepth |
Каждая задача имеет собственное уникальное хранилище состояния, выделенное ядром при создании задачи. Значение параметра usStackDepth говорит ядру, какой величины стек необходимо создать.
Значение usStackDepth указывает количество слов, которое можно сохранить в стеке, а не количество байт. Например, если стек имеет ширину 32 бита, и переданное значение usStackDepth равно 100, то под стек будет выделено 400 байт (100 * 4 байт). Глубина стека, умноженная на его ширину, не должна превышать максимальное значение, которое может содержать переменная типа size_t.
Размер стека, используемого для задачи ожидания (idle task, об этой задаче подробнее говорится далее), задается константой configMINIMAL_STACK_SIZE. Значение, назначенное этой константе в демо-приложении FreeRTOS (для определенной архитектуры микроконтроллера) может быть использовано как минимально рекомендованное для любой задачи. Если Ваша программа использует пространство в стеке, то нужно указать для константы configMINIMAL_STACK_SIZE увеличенное значение.
Нет простого способа узнать, какого размера стек нужен для задачи. Этот размер можно вычислить, но в большинстве случаев можно просто назначить подходящее значение, подобранное опытным путем, либо взятое приблизительно. Подобрать правильный размер стека важно, чтобы обеспечить адекватное использование RAM без ненужных затрат. Часть 6 содержит информацию о том, как запросить размер стека, используемого задачей.
|
pvParameters | Функции задач принимают параметр, имеющий тип указателя на void (т. е. void*). Значение, указанное в pvParameters, будет передано в задачу. Несколько примеров в этом документе демонстрируют, как этот параметр может быть использован в реальных задачах. |
uxPriority |
Задает приоритет, с которым будет выполняться задача. Приоритеты могут быть назначены в любое значение от 0 минимальный приоритет до (configMAX_PRIORITIES – 1) максимальный приоритет.
Константа configMAX_PRIORITIES определяется пользователем. Нет ограничения на верхний предел для количества приоритетов, которые можно задать (кроме ограничения на лимит используемого типа данных ограничения по количеству RAM, доступному в микроконтроллере), но желательно использовать как можно меньшее количество приоритетов, которое действительно необходимо - с целью уменьшения расхода RAM.
Передача в параметре значения uxPriority выше (configMAX_PRIORITIES – 1) приведет к молчаливому назначению приоритета задачи в максимально допустимое значение configMAX_PRIORITIES.
|
pxCreatedTask |
Параметр pxCreatedTask может использоваться для передачи наружу хендла созданной задачи. Этот хендл можно использовать как ссылку на задачу в вызовах API FreeRTOS, например для изменения приоритета задачи или для удаления задачи.
Если Ваше приложение не использует хендл задачи, то pxCreatedTask может быть установлен в NULL.
|
Возвращаемое значение |
Имеется два возможных возвращаемых значения:
1. pdTRUE показывает, что задача успешно создана.
2. errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY показывает, что задача не создана, так как в куче (heap) недостаточно свободной памяти для FreeRTOS, чтобы она могла выделить место для структур данных задачи и стека. Часть 5 предоставляет больше информации по управлению памятью.
|
int main( void )
{
/* Создание одной из двух задач. Имейте в виду, что реальное приложение должно
проверить возвращаемое значение из вызова xTaskCreate(), чтобы удостовериться,
что задача была успешно создана. */
xTaskCreate( vTask1, /* Указатель на функцию, которая реализует задачу. */
"Task 1",/* Текстовое имя задачи. Этот параметр нужен только для
упрощения отладки. */
1000, /* Глубина стека - самые маленькие микроконтроллеры будут
использовать значение намного меньше, чем здесь
указано. */
NULL, /* Мы не используем параметр задачи. */
1, /* Задача будет запущена с приоритетом 1. */
NULL ); /* Мы не будем использовать хендл задачи. */
/* Создание другой задачи полностью совпадает с созданием первой,
приориет задачи тот же. */
xTaskCreate( vTask2, "Task 2", 1000, NULL, 1, NULL );
/* Запуск шедулера, после чего задачи запустятся на выполнение. */
vTaskStartScheduler();
/* Если все хорошо, то управление в main() никогда не дойдет до этой точки,
и теперь шедулер будет управлять задачами. Если main() довела
управление
до
этого места, то это может означать, что не хватает памяти кучи
(heap)
для создания специальной задачи ожидания (idle task, об этой задаче
далее).
Часть 5 предоставляет больше информации по управлению памятью. */
for( ;; );
}