Easyelectronics.ru • Просмотр темы - Перезапуск задачи во FreeRTOS

Easyelectronics.ru

Электроника для всех
Текущее время: 16 авг 2018, 09:30

Часовой пояс: UTC + 5 часов



    • JLCPCB - Прототипы 10 PCBs всего за 2$ (100*100mm, 2-layer)
    • Как мы делаем платы, смотрите на YouTube
    • Крупнейшая китайская фабрика прототипов. 300000+ заказчиков и 10000+ заказов в день!
    • LCSC - Крупнейший китайский онлайн магазин комплектующих.

Начать новую тему Ответить на тему  [ Сообщений: 11 ] 
Автор Сообщение
 Заголовок сообщения: Перезапуск задачи во FreeRTOS
СообщениеДобавлено: 18 окт 2017, 16:57 
Старожил
Аватара пользователя

Зарегистрирован: 01 авг 2016, 10:47
Сообщения: 223
Откуда: Таганрог
Доброго времени суток,

Потребность в новых знаниях, как и голод - возникает неожиданно, но регулярно))

Допустим, имеется две задачи. Задача А ждет разрешения на работу от задачи Б при помощи семафора. После получения онного, происходит некая инициализация. Задача выполняет несколько последовательных запрос, после чего выставляет флаги. Далее эта задача работает исключительно по данным флагам.

Спустя какое-то время, задаче Б необходимо остановить и перезапустить задачу А. Т.е. чтобы весь цикл инициализации произошел заново, флаги были сброшены и установлены вновь.

Первое что приходит в голову, это сделать флаги глобальными, очищать их в задаче Б. Задача А видя что флаги чистые заблокируется на семафоре до следующего запуска. Вроде логично, но что мне не нравиться такая реализация ...

Немного дополнительной информации: задача А высокоприоритетная, запускается редко, работает малый промежуток времени. Задача Б - средний приоритет, работает по внешним сообщениям от сети.

Вопрос: существует ли красивый, но в то же самое время, правильный способ рестарт задачи без удаления её и повторного создания?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Перезапуск задачи во FreeRTOS
СообщениеДобавлено: 18 окт 2017, 17:37 
Старожил

Зарегистрирован: 16 ноя 2012, 07:47
Сообщения: 2664
Первое что приходит на ум - очередь. Задача А постоянно пробует что-то взять из очереди с нулевым временем ожидания (чтобы при штатной работе не тормозить ожидая что-либо из очереди). В очередь пишет задача Б. Если взяли - то очищаем флаги.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Перезапуск задачи во FreeRTOS
СообщениеДобавлено: 18 окт 2017, 19:29 
Старожил
Аватара пользователя

Зарегистрирован: 01 авг 2016, 10:47
Сообщения: 223
Откуда: Таганрог
как вариант и такой метод.

а использовать параметр который передается в задачу (void *pvParametrs) можно только по запуску или в процессе работы тоже?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Перезапуск задачи во FreeRTOS
СообщениеДобавлено: 18 окт 2017, 22:02 
Заглядывает иногда

Зарегистрирован: 15 ноя 2015, 12:11
Сообщения: 101
CheMax писал(а):
задача А высокоприоритетная, запускается редко

Чем она занимается когда не "запускается"? Если сидит в системном wait - организуйте это ожидание чтением из очереди с таймаутом равным периоду "редких запусков". Если чтение вышло по таймауту - отрабатываем idle и снова спать, если получили сообщение (а это произошло сразу-же после помещения данных в очередь с "другого конца", прошу заметить) - обрабатываем событие. Саму задачу организовываем как стейт-машинку - тогда "реинициализация" сведётся к простой смене статуса с, скажем, "idle" на "init" - и проходя от init до idle выполнятся те-же действия, что и при первом запуске задачи. События в очереди могут иметь сложную структуру. Подытоживая - внешние силы помещают событие в очередь, после чего спящая задача будет тут-же разбужена, получит событие и займётся его обработкой.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Перезапуск задачи во FreeRTOS
СообщениеДобавлено: 18 окт 2017, 22:16 
Старожил
Аватара пользователя

Зарегистрирован: 22 июл 2017, 11:48
Сообщения: 2103
Постановка задачи в ожидание vTaskSuspend() - http://www.freertos.org/a00130.html
и возобновление задачи vTaskResume() - http://www.freertos.org/a00131.html
При этом в конфиге FreeRTOS_Config.h должен быть включен этот функционал - INCLUDE_vTaskSuspend 1.
Удалять же задачи, если используется простая модель памяти heap1, вообще не имеет смысла, т.к. эта модель не поддерживает освобождение памяти.

Вчитываясь в вопрос, я не понял: Задача А все-таки должна быть приостановлена сама из себя после выполнения каких-то действий и далее должна ожидать разрешения от задачи Б, или же задача Б и запускает, и останавливает задачу А? Потому что это два разных способа.
В первом случае, задача А, после выполнения заложенных в неё действий должна сама себя приостановить командой vTaskSuspend, а запускаться она будет из задачи Б, которая будет подавать команду vTaskResume(xTaskA_Handle). Причем, флаги задачи А не обязательно делать глобальными. Достаточно того, что задача начинает свою работу со сброса флагов, определенных локально в задаче. И семафоры использовать не обязательно. Не стоит наворачивать лишних действий, RTOS и без того отжирает ресурсы.
Второй вариант похож на первый, но команда vTaskSuspend(xTaskA_Handle) подается из задачи Б.

CheMax писал(а):
а использовать параметр который передается в задачу (void *pvParametrs) можно только по запуску или в процессе работы тоже?

Параметры передаются в момент создания задачи командой xTaskCreate. В основном это используется когда создаются несколько копий задачи.
Параметры принимаются и сохраняются в локальные переменные задачи и могут быть использованы в дальнейшей работе задачи.

PS. Вот пример реализации первого варианта. Роль внешнего события для задачи Б выполняет аппаратный таймер, отслеживается флаг обновления и разрешается работа задачи А, запускаемой с повышенным приоритетом.
Код:
int main(void)
{
  static BaseType_t error __attribute((unused));
  //.......................................................
  HardwareNormalStart();
  //.......................................................

   //------- Задача B ------------------------
   error = xTaskCreate(prvTaskB,            // функция, реализующая задачу
            "TaskB",                     // имя задачи
            configMINIMAL_STACK_SIZE,      // запрашиваемый размер стека для задачи
            NULL,                     // нет параметров, передаваемых в задачу
            (tskIDLE_PRIORITY + 1),         // приоритет задачи
            &xTaskB_Handle);               // дескриптор задачи

   //------- Задача A ------------------------
   error = xTaskCreate(prvTaskA,            // функция, реализующая задачу
            "TaskA",                     // имя задачи
            configMINIMAL_STACK_SIZE,      // запрашиваемый размер стека для задачи
            NULL,                     // нет параметров, передаваемых в задачу
            (tskIDLE_PRIORITY),            // приоритет задачи
            &xTaskA_Handle);               // дескриптор задачи

  //*******************************************************
  /*------- Запуск планировщика задач -------------------*/
     vTaskStartScheduler();
} /* main() */

/*------------------------------------------------------------
* @brief:   Задача А запускается от задачи Б, выполняется и останавливается
* @param:   *pvParameters
* @retval:   нет
*/
static void prvTaskA(void *pvParameters)
{
   struct flags_t{
      uint8_t flag_1 :1;
      uint8_t flag_2 :1;
      uint8_t flag_3 :1;
      uint8_t flag_4 :1;
   }flags;

/*-- Функционал задачи ---------- ----------------------------*/
   for (int i; ;)
   {
      /* сброс флагов, инициализация задачи */
      i = 0;
      flags.flag_1 = 0;
      flags.flag_2 = 0;
      flags.flag_3 = 0;
      flags.flag_4 = 0;
      /*------------------------------------*/
      /* цикл работы задачи */
      do {
         BLUELED_ON;
         flags.flag_1 = 1;
         sDelay(200000);
         flags.flag_2 = 1;
         BLUELED_OFF;
         flags.flag_3 = 1;
         sDelay(200000);
      }while (++i < 3);

      /* остановка задачи А после выполнения рабочего цикла */
      vTaskSuspend(xTaskA_Handle);
   }
}//-----------------------------------------------------------

/*------------------------------------------------------------
* @brief:   Задача Б через промежутки времени запускает задачу А
* @param:   *pvParameters
* @retval:   нет
*/
static void prvTaskB(void *pvParameters)
{
/*-- Действия, выполняемые только при первом запуске задачи --*/
    vTaskSuspend(xTaskA_Handle);      // останавливается задача А

/*-- Функционал задачи ---------- ----------------------------*/
   for (;;)
   {
      GREENLED_ON;
      sDelay(800000);

      /* ожидается какое-то событие, например обновл.таймера */
      while(READ_BIT(TIM1->SR, TIM_SR_UIF) == 0)
      {   }
      TIM1->SR = ~TIM_SR_UIF;
      GREENLED_OFF;
      /* запуск задачи А с повышенным приоритетом */
      vTaskPrioritySet(xTaskA_Handle, tskIDLE_PRIORITY + 2);
      vTaskResume(xTaskA_Handle);
   }
}//-----------------------------------------------------------




Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Перезапуск задачи во FreeRTOS
СообщениеДобавлено: 19 окт 2017, 09:51 
Старожил

Зарегистрирован: 16 ноя 2012, 07:47
Сообщения: 2664
с resume и suspend есть одна фигня - они могут произойти в произвольный момент, когда задача А не доработала до логического конца. Надо как-то синхронизировать. В примере выше, это решается приоритетами, хотя мне не нравятся подобные решения, потом несколько сложно выстраивать логические цепочки кто и когда работает и кто кого может перебить.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Перезапуск задачи во FreeRTOS
СообщениеДобавлено: 19 окт 2017, 15:49 
Старожил
Аватара пользователя

Зарегистрирован: 01 ноя 2011, 23:51
Сообщения: 532
CheMax писал(а):
Доброго времени суток,

Потребность в новых знаниях, как и голод - возникает неожиданно, но регулярно))

Допустим, имеется две задачи. Задача А ждет разрешения на работу от задачи Б при помощи семафора. После получения онного, происходит некая инициализация. Задача выполняет несколько последовательных запрос, после чего выставляет флаги. Далее эта задача работает исключительно по данным флагам.

Спустя какое-то время, задаче Б необходимо остановить и перезапустить задачу А. Т.е. чтобы весь цикл инициализации произошел заново, флаги были сброшены и установлены вновь.

Первое что приходит в голову, это сделать флаги глобальными, очищать их в задаче Б. Задача А видя что флаги чистые заблокируется на семафоре до следующего запуска. Вроде логично, но что мне не нравиться такая реализация ...

Немного дополнительной информации: задача А высокоприоритетная, запускается редко, работает малый промежуток времени. Задача Б - средний приоритет, работает по внешним сообщениям от сети.

Вопрос: существует ли красивый, но в то же самое время, правильный способ рестарт задачи без удаления её и повторного создания?

Я бы для ожидания использовал Task Notifications
А как флаги можно использвать Event Groups (or 'flags')

Собственно как мне кажется они и созданы для этого


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Перезапуск задачи во FreeRTOS
СообщениеДобавлено: 19 окт 2017, 17:31 
Старожил
Аватара пользователя

Зарегистрирован: 01 авг 2016, 10:47
Сообщения: 223
Откуда: Таганрог
благодарности всем за ответы)

задача как обычно в процессе решения была изменена по решению верховного главнокомандующего начальства.

Задача А теперь перестала быть периодичной, управление перешло в задачу Б.
Для синхронизации управления использовать решил очередь сообщений.

нотификация это по сути то же сообщение или я что-то путаю? По сути так же возникает событие и задача о нем узнает... или тут вся соль в механизме передачи?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Перезапуск задачи во FreeRTOS
СообщениеДобавлено: 19 окт 2017, 17:36 
Старожил
Аватара пользователя

Зарегистрирован: 01 ноя 2011, 23:51
Сообщения: 532
CheMax писал(а):
благодарности всем за ответы)

задача как обычно в процессе решения была изменена по решению верховного главнокомандующего начальства.

Задача А теперь перестала быть периодичной, управление перешло в задачу Б.
Для синхронизации управления использовать решил очередь сообщений.

нотификация это по сути то же сообщение или я что-то путаю? По сути так же возникает событие и задача о нем узнает... или тут вся соль в механизме передачи?


Как было верно замечено "какая-то соль...." :) Как пишут разработчки FreeRTOS это меннее ресурсоемкая замена семафоров. Вообще довольно удобная штука по моему опыту. Но, да , она не поддерживает очереди. Т.е. можно потерять событие. Вообще рекомендую присмотреться.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Перезапуск задачи во FreeRTOS
СообщениеДобавлено: 19 окт 2017, 18:39 
Старожил
Аватара пользователя

Зарегистрирован: 01 авг 2016, 10:47
Сообщения: 223
Откуда: Таганрог
а сравнение по времени реакции с использование нотификации и семафора делал кто-нибудь?

у меня на 12.288МГц, использование семафора обеспечивает время переключения контекста порядка 70-75 мкс. Т.е. по словам разработчиков это время будет сокращено? было бы не плохо конечно ...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Перезапуск задачи во FreeRTOS
СообщениеДобавлено: 20 окт 2017, 12:26 
Старожил
Аватара пользователя

Зарегистрирован: 01 ноя 2011, 23:51
Сообщения: 532
CheMax писал(а):
а сравнение по времени реакции с использование нотификации и семафора делал кто-нибудь?

у меня на 12.288МГц, использование семафора обеспечивает время переключения контекста порядка 70-75 мкс. Т.е. по словам разработчиков это время будет сокращено? было бы не плохо конечно ...


вот что горят разработтчики
That flexibility allows task notifications to be used where previously it would have been necessary to create a separate queue, binary semaphore, counting semaphore or event group. Unblocking an RTOS task with a direct notification is 45% faster * and uses less RAM than unblocking a task with a binary semaphore.

http://www.freertos.org/RTOS-task-notifications.html


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 11 ] 

Часовой пояс: UTC + 5 часов


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB