Некоторая путаница в том, как FreeRTOS ставит задачи в очередь на платформе STM32 - PullRequest
0 голосов
/ 11 апреля 2019

В настоящее время я работаю над разработкой программного обеспечения для проекта на микроконтроллере 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();
    }
}

Ответы [ 2 ]

0 голосов
/ 12 апреля 2019

Боюсь, что ваши наблюдения ошибочны

  1. Если задача с более низким приоритетом не возвращает контроль, или процедура прерывания не пробуждает задачу с более высоким приоритетом - задача может получить контроль заново.,

  2. Здесь нет ничего подобного позиции в очереди.Это не Linux или Windows.

0 голосов
/ 11 апреля 2019

Init_all.c - должен запускаться первым и ТОЛЬКО один раз при запуске

Искать «Хук запуска задачи демона» на этой странице: https://www.freertos.org/a00016.html

2) Если в бесконечный цикл for (;;) ничего не помещено, эта задача будет выполняться только один раз (код вне цикла, скажем, для инициализации периферийных устройств один раз)

Если вы это сделаетезатем вы должны удалить задачу (вызов vTaskDelete (NULL)) в конце ее реализации.https://www.freertos.org/implementing-a-FreeRTOS-task.html

Что касается вашего основного вопроса - вы не показываете код задачи инициализации, поэтому его невозможно сказать.Однако, как правило, этот тип системы реализован так, чтобы быть управляемым событиями, поэтому большинство задач проводят большую часть своего времени в заблокированном состоянии (без использования каких-либо процессоров, поэтому могут выполняться задачи с более низким приоритетом).

...