Как стать автором
Обновить

Комментарии 36

Ну и классически прошу немного кармы для переноса в тематический журнал :)
Теперь можете
Перенес, спасибо всем участвовавшим :)
все такое делали, и делают каждый день. и что тут нового? К.О.
Мне такого обзора не хватало. Или готовый монстр типа FreeRTOS, или голая теория. Понаступал на грабли, выкристаллизовал свое виденье. Если кому-то пригодится еще — значит свою миссию этот пост выполнил.
ясно. эту штуку называют «карусель»
ой, простите, а 0K — это не вы?
Ждём продолжения :-)
Монстрообразно. Вы предполагаете излишнюю динамику там где ее не будет. Набор обработчиков у вас практически статичный, для каждого можно записать инвариант выполнения, и проверят список условий запуска. Истинность инварианта само по себе является событием, которое не нужно ни где хранить и передавать далее. А вообще почитайте про конечные автоматы :). Каким компилятором пользуетесь, в котором есть typedef, но нет enum'а? Зачем мешать в кучу unsigned char, unsigned int, int (в вашем компиляторе наверняка есть нечто вроде inttypes.h c человеческим uint8_t и др.)? Работа со массивом обработчиков то же не продумана. Выберете что-то одно: либо вставляйте в пустое место в массиве (в setHandler), либо не двигайте элементы (в killHandler). То что бросилось в глаза, внимательно не смотрел :)
Начну с конца

Элементы двигаю неспроста — мне надо, чтобы вновь вставляемые всегда шли после существующих. Некая система приоритетов обработчиков. Сначала событие обрабатывает самый последний зарегистрированный обработчик.

Компилятор avr-gcc, есть inttypes.h, но внятного объяснения, почему надо использовать uint8_t вместо unsigned char я не уловил, кроме идеи тотальной портабельности. Не спорю, что мог нарушить какие-то рекомендации, но хотелось бы узнать, какие именно.

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

А что есть список условий запуска, как не организованная очередь сообщений?
Если вы всегда сдвигаете обработчики к началу массива, то при вставке нового вам не нужно искать свободное место для вставки ;)

Все дело даже не в идее глобальной портабельности, а в том, и это особенно характерно для МК, что объемы памяти там микроскопичны, и использую uint8_t и др. вы сами себе облегчаете задачу контроля использования например стека. Мне практика показала что так удобнее, сугубо личный опыт.

Знаете, старую присказку про «кошек не любите?», так и про конечные автоматы. Конечно если попытатся запихать всю логику в один автомат то получиться монстр, который корректировать вручную сложно, никогда не нужно упираться в крайности.

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

А можно на пальцах, как будет выглядеть автомат для такой задачи:
Опрос датчика 1 каждые 750 мсек
Опрос датчика 2 каждые 200 мсек
Обновление экрана каждые 500 мсек (выводятся данные датчиков)
Реакция на клавиатуру (хотя бы старт-стоп).

Как я не прикидывал, от конечного автомата остается еще меньше, чем в моей системе от классической rtos ;)
Вы лукавите ;) Редкий код занимается _только_ опросом датчиков. У меня нет ни малейшего желания вас упрекнуть или критиковать. Я уже написал ниже, что для любого решения всегда найдется достаточно аргументов, мы же здесь делимся опытом, правда?
по поводу uint8_t — когда я увидел такую строчку

typedef unsigned char uint8_t;

в stdint.h, то понял, что фатальным нарушением использовать unsigned char не будет. Тем более, просмотрел листинг, структуры все ровно того размера как и планировалось. Где надо — 1 байт, где надо — два байта.

В любом случае, спасибо за науку, в следующем цикле рефакторинга обязательно исправлюсь.
Обычно такие мысл возникают после прочтения чужого кода, «да, автор идиот, надо всё переписать !!».

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

Я в таких случаях говорю себе — постой, ведь автор вряд ли идиот, и он тоже знает про конечные автоматы. В этом случае, если я в таком тоне ему об этом скажу, про меня подумают, что я не подумал про это, ммм… плохо.

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

Автор статьи молодец, по AVR вообще мало статей, а стиль — стиль у каждого свой, и это хорошо :-)
Ничего не имею против чужого кода, приходилось поддерживать тонны всякого, скорее подход автора мне показался несколько неуместным для тех задач, которые он описал. И ни в коем случае не призываю все выкинуть и переписать, как могло показаться, в конце концов, каждый сам принимает решение, и любое принятое решение будет иметь достаточно веских аргументов в свою пользу. Про источники, вероятно на русском языке все имеют определенную специфику. Программированием микроконтроллеров и нас часто занимаются люди пришедшие из электроники, что накладывает определенную специфику :(. Для тех, кто дружит с английским, могу порекомендовать пожалуй, www.avrfreaks.net, ну и сам немного пытаюсь исправить ситуацию houndsblog.blogspot.com
Думаю, пока на русском разойдётся инфа по AVR, ARM уже будет стоить копейки :-)
Всё-таки, приятнее писать код, когда оперативной памяти больше чем 500 байт :-)
Дело не в стоимости арм, а в том, что он много где совершенно избыточен
Согласен, но унификация великая вещь. ARM имеет запас, AVR — нет. Проще один раз написать и отладить софт под более мощный процессор, такой как ARM, и потом 20 лет им пользоваться, чем писать под AVR, а когда возникнет необходимость что-то добавить, всё переделывать второпях за оч. большие деньги.
«Через 20 лет ничего не будет, будет одно телевидение» ;) Ну буду с вами спорить, каждый сам себе бобр. Не надо крайностей, вот и все. Во многих проектах и AVR много.
Билл Гейтс:

«I have to say that in 1981, making those decisions, I felt like I was providing enough freedom for 10 years. That is, a move from 64k to 640k felt like something that would last a great deal of time. Well, it didn't — it took about only 6 years before people started to see that as a real problem.»

Так что, когда мы говорим о 20 годах, вполне возможно, что речь идёт всего о 12-ти. И проекты меняются и люди, так что запас всегда нужен, не раз в этом убеждался :-)
требование гарантированного времени отклика — главное в определении осрв
так что то, что тут описано, даже не «почти осрв». просто диспетчер событий, который быстро работает
вернее, реализация fsm
Вопрос классификации всегда спорный. Этот диспетчер гарантирует мне время отклика 1 мсек при всех возможных комбинациях входящих взаимодействий. Этого для решения моих практических задач хватает. Да, это достигнуто не только особенностью системы, но и оптимизацией функций-обработчиков, которые не занимают процессор дольше 10-100 мксек.

Вот и получилась «недоОСРВ».
Кстати про классификацию. Если речь идет про РВ, то лучше всегда формулировать то определение РВ, которое вы приняли для себя как руководствующее. Согласитесь два определения РВ: «превышение максимально допустимого времени реакции равнозначно отказу системы» и «детерминированность алгоритма по времени вне зависимости от входных данных» накладывают совершенно разные ограничения.
Отлично начало =) поскорее бы увидеть продолжение.
При выполнении установки события в очередь записывается структура. Если в этот момент будет интеррупт и там тоже будем записывать событие, то может быть конфликт с непредсказуемыми последствиями. Прерывания надо бы там запрещать.
Согласен, этот механизм уже переработан.
Но тут второй вопрос — когда разрешать прерывания? Если я разрешу прерывания в конце функции, то при возврат в обработчик прерывания будут разрешены, тоже с непредсказуемыми последствиями.

Пока реализовано так: вызываю занесение в очередь в самом конце обработчика прерываний (пока это возможно).

В принципе, вариантов два:
— предусмотреть параметр вызова — флажок, надо ли запрещать/разрешать прерывания;
— после вызова в обработчике принудительно запрещать прерывания;

Какие еще могут быть варианты?
В WinAVR есть такая интересная приблуда как atomic.h

Так вот в ней есть макросы клевые. atomic forseon и atomic restorestate

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

А вот второй хорош тем, что он запрещает прерывания однозначно, но на выходе разрешает их ТОЛЬКО если они были до этого разрешены.

Примерно то же самое только с другим синтаксисом есть в IAR. Вообще погугли по атомарным операциям. Собственно проблема у тебя именно с ними.
И приятно, что мэтр посетил пост :) AVR я изучал в основном по вашему сайту и даташитам.
Ну прям уж мэтр :))))

А сколько занимает скомпиленное ядро?
Само ядро диспетчера — чуть больше килослова. В принципе можно оптимизировать, но мне пока не критично.

А за atomic.h — спасибо, поробую применить )
Жирновато. Можно в 720 байт загнать. Могу дать пофтыкать один свой проектик.

Рекомендую избавиться от нумерации задачи и оперировать сразу же адресами. Это будет проще и эффективней.

З.Ы.
А я пожалуй себе потырю у тебя функцию kill Timer :) А то чет я до такой не догадался :)
Давай, конечно. Пофтыкать оно всегда полезно.

А по поводу нумерации — пока немного не понял. У меня ж не задачи, у меня — сообщения. Event-driven. То есть одно сообщение могут обрабатывать несколько обработчиков последовательно.
упс. Не килослова, а килобайта. 1124 байт, запутался в нумерации :)
НЛО прилетело и опубликовало эту надпись здесь
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории