В настоящее время я работаю над разработкой программного обеспечения для проекта на микроконтроллере ARM Cortext M4, в котором необходимо выполнить три основных задачи:
1) Init_all.c - Must run first and ONLY once at startup
2) Task1.c - Runs infrequently; Once every 10 seconds
3) Task2.c - Must run most frequently
Я решил поэкспериментировать с использованием FreeRTOS, чтобы увидеть, есть ли какие-либо преимущества в использовании планирования FreeRTOS по сравнению с простым бесконечным циклом While(1)
На основании того, что я прочитал из документации (поправьте меня, если я ошибаюсь),
1) FreeRTOS запускает задачи на основе приоритета - если никакие прерывания или условия остановки не закодированы в задачу с наивысшим приоритетом, любая задача с более низким приоритетом никогда не будет поставлена в очередь и запущена
2) Если в бесконечный цикл for(;;)
ничего не помещено, эта задача будет выполняться только один раз (код вне цикла, скажем, для инициализации периферийных устройств один раз)
Поскольку FreeRTOS выбирает и ставит задачи в очередь по приоритету, первоначальное решение, которое я нашел при назначении и создании задач, было таким:
1) Init_all.c - Highest priority; for(;;) loop only contains code to trigger LED
2) Task1.c - Second highest priority **but** I include a 10 second interrupt vTaskDelay( xDelay10000ms ) right at the start of the for(;;) loop
3) Task2.c - Lowest priority
При проверке этого, если следует логика FreeRTOS, I должен ожидать, что он никогда не увидит ни Task1.c, ни Task2.c, поставленных в очередь , поскольку задача Init_all.c никогда не завершится, так как в ней есть код для запуска светодиода внутри цикл for(;;)
.
Что подводит меня к моему вопросу: два удивительных замечания были замечены, когда я реализовал вышеупомянутое:
Наблюдение 1:
1) Задача Init_all.c запускается
2) За ним следует Task1.c, который затем прерывается и немедленно останавливается на 10 секунд.
3) Во время которого Task2.c работает до истечения 10 секунд. Затем Task1.c вступает во владение и запускает код после vTaskDelay( xDelay6000ms )
прерывания.
Все это время Init_all.c все еще работает, но idk в какой позиции очереди это вообще. Светодиод действительно срабатывает каждую секунду, но опять же, возникает путаница, почему задача Init_all.c даже выполняется.
Код для Task1.c приведен ниже для лучшей иллюстрации:
// Task1.c
void Task1(void const * argument)
{
// Timer interrupt
const TickType_t xDelay10000ms = pdMS_TO_TICKS( 10000 );
for( ;; )
{
/** Immediately block this task for 10secs upon starting it **/
vTaskDelay( xDelay10000ms );
( code below to execute AFTER the Task1 resumes from the interrupt )
}
Наблюдение 2:
Задача 2 выполняется 1 секунда, поэтому теоретически она должна запускаться 10 раз в 10-секундном окне, заданном прерыванием.
Однако я бы увидел странный результат, когда Task2 иногда выполнялся 9 раз, а затем 10 раз.
Правильно ли я понимаю концепции FreeRTOS? Спасибо! Код ниже:
Init_all.c задача:
void StartDefaultTask(void const * argument)
{
init_sensor1();
init_sensor2();
init_sensor3();
init_sensor4();
for( ; ; )
{
GREEN_LED_ON();
osDelay(50);
GREEN_LED_OFF();
osDelay(1000);
}
}
Задание 1:
void Task1(void const * argument)
{
// Timer interrupt
const TickType_t xDelay6000ms = pdMS_TO_TICKS( 6000 );
// All Initialisation
for( ;; )
{
// Timer interrupt this task to ensure apptasks.c finishes first?
vTaskDelay( xDelay6000ms );
takesensor1data();
takesensor2data();
}
}
Задание 2:
void Task2(void const * argument)
{
// Timer interrupt
const TickType_t xDelay6000ms = pdMS_TO_TICKS( 6000 );
// All Initialisation
for( ;; )
{
takesensor3data();
takesensor4data();
}
}