Кодинг МК. Применение планировщика/очереди задач

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
AndryG
Открыл глаза
Сообщения: 76
Зарегистрирован: Сб ноя 10, 2007 14:28:04
Откуда: UA
Контактная информация:

Кодинг МК. Применение планировщика/очереди задач

Сообщение AndryG »

Доброго.
Очередь задач - один из вариантов структуры программы на МК. Среди множества велосипедов остановимся на таком:
Спойлер

Код: Выделить всё

// Добавить задачу в очередь
void qtTask(qtTaskPtr ptr, qtDelay tick);

// Вызывается при каждом "tick", проводит отсчет задержки
void qtDecrementDelay(void);

// Пытается выполнить одну задачу из очереди
void qtDispatch(void);
Мы можем запланировать задачу либо "на сейчас" либо через N тиков. Для периодичного вызова задача планирует свой вызов сама.

Код: Выделить всё


volatile uint8_t f;

ISR(TIMER0_OVF_vect){
  TCNT0 = TCNT_TICK; // 125Hz
  f |= 1;
}

void tBlink(){
  PORTB ^= 0x01;
  qtTask(tBlink, 64);
}

int main(void)
{
    init();
    tBlink();
    while (1)
    {
      if(f & 0x01){
        f &= ~1;
        qtDecrementDelay();
      }
      qtDispatch();        
    }
}
Всё понятно, всё работает и вопросов нет... пока не начнешь навешивать задачи. Вместе с ними появляется путаница с "внешними данными" и "разделяемыми ресурсами".

Добавляю клавиатуру с тремя кнопками +/-/Set. Нажимая Set, заходим в настройки, +/- меняем значение параметра и повторным нажатием Set сохраняем значение.
Задача qtButton молотит с нужной периодичностью, всё отлавливает и на гора выдает в глобальной переменной битовую маску "кнопка нажата".

Код: Выделить всё

unit8_t btState; // Битовая маска. Единичка поднимается задачей qtButton при нажатии кнопки либо срабатывании автоповтора
И вот ту первый косяк: юзер нажимает +, затем только Set. Активируется задача изменения параметра, которая сразу увидит нажатый плюс и обработает его. Как исправить это правильно?

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

В конкретном примере с кнопками можно очищать btState вместе с активацией задачи или внутри задачи контролировать первый запуск и очищать буфер - аналог выполнения действия на дуге конечного автомата. Но выглядит это какось корявенько. Сдается мне, что я упустил одну из главных фишек очереди заданий и просто неправильно её готовлю.

Вторая часть про разделяемый ресурс чуть позже. После осознания ошибок первой.
Реклама
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Кодинг МК. Применение планировщика/очереди задач

Сообщение Аlex »

AndryG писал(а):юзер нажимает +, затем только Set. Активируется задача изменения параметра,
Вы не описали - в какой момент он нажимает эти "+" и "Set" (и зачем еиу вообще их нажимать ?), и что из себя представляет задача "Изменение параметра" ?
Реклама
Martian
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32
Контактная информация:

Re: Кодинг МК. Применение планировщика/очереди задач

Сообщение Martian »

Задача может обработать изменение настроек пользователем во временную переменную, и лишь по нажатию Set записывать в действующую
AndryG
Открыл глаза
Сообщения: 76
Зарегистрирован: Сб ноя 10, 2007 14:28:04
Откуда: UA
Контактная информация:

Re: Кодинг МК. Применение планировщика/очереди задач

Сообщение AndryG »

Аlex, в начальный момент времени задача qtDefault мониторит переход по кнопке Set в режим изменения параметра (где уже будут мониторится все три кнопки). Юзер до нажатия set нажимает плюс, а потом set. Задача изменения параметра сразу при начале работы увидит уже нажатый плюс. А это есть ошибка.

Вообще меня интересует не конкретный пример, а общая проблема событий в таком планировщике.

Если программа сделана на куче автоматов, которые по очереди вызываются в главном цикле, то там все ясно - пришедшие события обрабатываются в следующей итерации, по концу итерации все события очищаются. А в случае очереди задач эта идея не работает...
Последний раз редактировалось AndryG Пн дек 20, 2021 20:32:36, всего редактировалось 1 раз.
Реклама
Эиком - электронные компоненты и радиодетали
jcxz
Мудрый кот
Сообщения: 1731
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: Кодинг МК. Применение планировщика/очереди задач

Сообщение jcxz »

[uquote="AndryG",url="/forum/viewtopic.php?p=4145079#p4145079"]Юзер до нажатия set нажимает плюс, а потом set. Задача изменения параметра сразу при начале работы увидит уже нажатый плюс. А это есть ошибка.[/uquote]Непонятно - в чём именно проблема?
Задаём текущее состояние:

Код: Выделить всё

enum ConfigChange {ConfigChange_NONE, ConfigChange_EDIT};
ConfigChange state = ConfigChange_NONE;
Пока state==ConfigChange_NONE - ждём только "Set" (вход в режим редактирования), остальные нажатия или игнорим или пикаем (недопустимая кнопа). В режиме редактирования (ConfigChange_EDIT) же принимаем всё: "+","-","Set". Проще некуда....
Реклама
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Кодинг МК. Применение планировщика/очереди задач

Сообщение Аlex »

[uquote="AndryG",url="/forum/viewtopic.php?p=4145079#p4145079"]Юзер до нажатия set нажимает плюс, а потом set. Задача изменения параметра сразу при начале работы увидит уже нажатый плюс. А это есть ошибка.[/uquote]Вы сами построили такую систему задач. Единственный выход в Вашем случае - очищать весь ненужный мусор перед созданием задачи.
А по-правильному - делать (или взять готовое) нормальный диспетчер, обслуживающий задачи с вечным циклом. Тогда всю подготовку можно будет делать вначале функции-задачи, до основного цикла.

PS: Ваша система ничем не отличается от КА. Те же периодичные вызовы, обычные функции с завершением, всё тоже самое ...
Реклама
AndryG
Открыл глаза
Сообщения: 76
Зарегистрирован: Сб ноя 10, 2007 14:28:04
Откуда: UA
Контактная информация:

Re: Кодинг МК. Применение планировщика/очереди задач

Сообщение AndryG »

Можете привести пример "нормальный диспетчер" для средних камней? Что я встречал - вопрос событий не особо рассматривался.

http://we.easyelectronics.ru/AVR/mashin ... oshek.html

https://chipenable.ru/index.php/embedde ... llera.html

https://www.yumpu.com/en/document/view/ ... s-jennaron по мотивам этой статьи мой велосипед :)
Morroc
Друг Кота
Сообщения: 19495
Зарегистрирован: Чт фев 20, 2014 18:57:55

Re: Кодинг МК. Применение планировщика/очереди задач

Сообщение Morroc »

Чем ваш то ненормальный ? IMHO вы хотите от него чего то не того. Обработка тех кнопок - это ваша задача/реализация, а не диспетчера.
"Вся военная пропаганда, все крики, ложь и ненависть исходят от людей, которые на эту войну не пойдут !" / Джордж Оруэлл /
"Война - это,когда за интересы других,гибнут совершенно безвинные люди." / Уинстон Черчилль /
AndryG
Открыл глаза
Сообщения: 76
Зарегистрирован: Сб ноя 10, 2007 14:28:04
Откуда: UA
Контактная информация:

Re: Кодинг МК. Применение планировщика/очереди задач

Сообщение AndryG »

Если копаешь глубже моргания светодиодов, то радужное восхищение архитектурой начинает испарятся. Вот я и спрашиваю совета, как таким пользуются? Может я просто не умею его готовить и для таким курьезов, типа описанного мною с "фантомного" нажатия кнопок, есть готовые рецепты.

Склоняюсь к мысли Аlex, что рассматривать эту очередь стоит как конечный вариант и никуда от кучи флагов и странных хитросплетений не уйти.

Второй мой вопрос был про организацию разделения ресурсов. Для примера берем AV-показометр в блоке питания. По умолчанию он показывает A и V, но если идет перегрев радиаторов, то он должен показать на индикаторе сообщение о перегреве. Если крутнуть ручку ограничения тока, то на индикаторе некоторое время показываются значения максимальной уставки.
Мы имеем один ресурс - "видеопамять индикатора" и три задачи, которые в разные моменты хотят им владеть.
Как в таких случаях организовать программу? Расталкивать по коду кучу взаимных условий и регулировать их совместную работу - это жуть.
Поделитесь, пжлст, опытом :)
Пока, надумал вариант рассматривать два отдельных индикатора. У каждого из них есть атрибут "номер владельца" он же приоритет. Новая задача может забрать управление индикатором на себя, если она более приоритетна.
Тогда получается так:
задача AV-метра крутится постоянно. Приоритет для индикатора равен единице.
задача уставки макс тока - 2
задача перегрева радиаторов - 3

В начале "владельца" у индикатора нет - в поле прописан ноль.
Задача AV-метр пишет туда единицу и вписывает свои значения для отображения.
Когда покрутили ручку тока, задача макс уставки перебивает владение индикатором тока, отображает значение тока. Через три секунды стабильных показаний (ручку больше не крутят) сбрасывает владение индикатором в ноль и его тут же подхватывает задача AV-метр.
Задача перегрева плюет на всех и на некоторое время выводит сообщение о перегреве - её никто не смеет затереть.
Какось так выглядит в планах мой велосипед. Хочется услышать мнение/совет опытных товарищей
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Кодинг МК. Применение планировщика/очереди задач

Сообщение Reflector »

[uquote="AndryG",url="/forum/viewtopic.php?p=4145506#p4145506"]Для примера берем AV-показометр в блоке питания. По умолчанию он показывает A и V, но если идет перегрев радиаторов, то он должен показать на индикаторе сообщение о перегреве. Если крутнуть ручку ограничения тока, то на индикаторе некоторое время показываются значения максимальной уставки.
Мы имеем один ресурс - "видеопамять индикатора" и три задачи, которые в разные моменты хотят им владеть.[/uquote]
Не нужно все усложнять - это одна задача которая выводит разные данные в зависимости от того крутили ли недавно ручку или есть ли перегрев.
jcxz
Мудрый кот
Сообщения: 1731
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: Кодинг МК. Применение планировщика/очереди задач

Сообщение jcxz »

[uquote="AndryG",url="/forum/viewtopic.php?p=4145506#p4145506"]Может я просто не умею его готовить и для таким курьезов, типа описанного мною с "фантомного" нажатия кнопок, есть готовые рецепты.[/uquote]Чем не устраивает описанный мной алгоритм?

[uquote="AndryG",url="/forum/viewtopic.php?p=4145506#p4145506"]Для примера берем AV-показометр в блоке питания. По умолчанию он показывает A и V, но если идет перегрев радиаторов, то он должен показать на индикаторе сообщение о перегреве. Если крутнуть ручку ограничения тока, то на индикаторе некоторое время показываются значения максимальной уставки.
Мы имеем один ресурс - "видеопамять индикатора" и три задачи, которые в разные моменты хотят им владеть.
Как в таких случаях организовать программу?[/uquote]Как уже сказал Alex: Задача индикации - единственная, а источник события "покрутили ручку" выставляет флаг этой задаче "активен режим отображения спец.значения" и устанавливает таймер таймаута, по истечении которого флаг будет сброшен и задача вернётся в обычный режим "отображения A и V".
AndryG
Открыл глаза
Сообщения: 76
Зарегистрирован: Сб ноя 10, 2007 14:28:04
Откуда: UA
Контактная информация:

Re: Кодинг МК. Применение планировщика/очереди задач

Сообщение AndryG »

jcxz, ваш алгоритм игнорирует саму соль - фантомный плюс, который прилетает в вновь запущенную задачу.
Пока state==ConfigChange_NONE - ждём только "Set" (вход в режим редактирования), остальные нажатия или игнорим или пикаем (недопустимая кнопа). В режиме редактирования (ConfigChange_EDIT) же принимаем всё: "+","-","Set". Проще некуда....
Если в первой задаче нажать плюс, то ничего внешне не изменится, но в программе флаг будет висеть. Через сутки юзер нажимает Set, запускается вторая задача, которая сразу видит нажатый плюс и обрабатывает его. Это косяк. Для его разрешения есть масса вариантов решения разного уровня костыльности. Цель этого топика - выявить наиболее подходящий для ситуаций такого рода. В архитектуре https://kit-e.ru/circuit/primenenie-swi ... v-chast-2/ , например, вопрос "зависших" событий решается централизовано "все сообщения должны быть обработаны на следующем шаге после генерации".

В моем случае, как я понял из ответов, нужно обработку делать на месте:
- предварительная очистка буфера при добавлении задачи qtEdit() в очередь
- дополнительная задача qtStartEdit, в которую выделить код предыдущего пункта
- флаг "первый запуск" в самой задаче qtEdit, по которому буфер клавиатуры будет игнорится.

Попробуем в коде, как оно будет.
jcxz
Мудрый кот
Сообщения: 1731
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: Кодинг МК. Применение планировщика/очереди задач

Сообщение jcxz »

[uquote="AndryG",url="/forum/viewtopic.php?p=4145607#p4145607"]jcxz, ваш алгоритм игнорирует саму соль - фантомный плюс, который прилетает в вновь запущенную задачу.[/uquote]Не знаю что такое "фантомный плюс".

[uquote="AndryG",url="/forum/viewtopic.php?p=4145607#p4145607"]Если в первой задаче нажать плюс, то ничего внешне не изменится, но в программе флаг будет висеть. Через сутки юзер нажимает Set, запускается вторая задача, которая сразу видит нажатый плюс и обрабатывает его.[/uquote]Что за "флаг"? Зачем он там? И зачем какая-то "2-я задача"? В моём описании ничего этого нет.
Почему у вас "нажатый плюс" может где-то "висеть" целые сутки??? :shock: Может надо сперва в этом разобраться - почему у вас так происходит?
Ничего не понятно......

PS: Выдумываете проблемы на ровном месте, в примитивнейшей задаче.
Аватара пользователя
Ivanoff-iv
Друг Кота
Сообщения: 7077
Зарегистрирован: Пт ноя 11, 2016 05:48:09
Откуда: Сердце Пармы

Re: Кодинг МК. Применение планировщика/очереди задач

Сообщение Ivanoff-iv »

странно...
есть ресурс - видеопамять и есть задача вывода на дисплей, которая, в зависимости от переменных (температура, открытый пункт меню и т.д.) выводит на экран те или иные показания.

таже кнопка обрабатывается своей задачей, по результатам, в зависимости от длительности, сочетания нажатых кнопок и.т.д взводится свой флаг

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

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


и не очень важно как это реализовано, через диспетчер или свитч—кейсом...
Для тех, кто не учил магию мир полон физики :)
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Ответить

Вернуться в «Разные вопросы по МК»