Перейти к содержанию
    

Архитектура программ во встраиваемой электронике

7 hours ago, tgruzd said:

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

Не знаю, возможно и не существует решения вашей задачи. 

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

Ну помимо этой задачи. Там еще 4 вопроса было. С двумя +\- разобрались, хотя конечно хотелось бы более глубокого обсуждения. Еще 3.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, Solonovatiy сказал:

Там еще 4 вопроса было

По остальным вопросам не могу ничего сказать.

Я человек простой надо  сохранить структуру во флешь  - считаю адреса-смещения в рантайме и сохраняю.  Надо данные отобразить - отображаю.  С плюсами дела не имел. Шаблонами не обмазывался.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 11/18/2022 at 4:19 AM, Solonovatiy said:

Короче мысль такая - всех асинхронных сущностей RTOS надо стараться избегать пока не припрет по полной, стараться до конца делать однопоточную БЛ, деля ее только тогда, когда кол-во оверхеда для синхронной работы сильно (именно сильно) превысит оверхед для асинхронности. Насколько по вашему это правильное мнение?

Мнение правильное. Встроенные механизмы вытесняющей многозадачности OS следует использовать только для системного уровня.
Для меня хорошим примером всегда была оглядка на старших товарищей, например построение игровых систем инженерами Silicon Graphics для игровой консоли N64.  Я не буду описывать её крайне интересную и последовательную архитектуру, отмечу лишь только что вместо примитивов синхронизации всегда используется Message Passing и вся многозадачность используется исключительно для системного или сопоставимого с системным уровня. Хотя это и возможно, но "бизнес" логика (она же игровая) или она же USER логика примитивы многозадачности OS целенаправленно не использует. Хотя внутри себя несомненно постоянно использует кооперативную многозадачность.

 

On 11/18/2022 at 4:19 AM, Solonovatiy said:

2. Я давно и долго не могу определиться, надо ли избегать по максимуму "активных" модулей (не уверен в термине, т.е. имеющих возможность самостоятельно начать некую цепочку действий, грубо говоря, модули имеющие методы\функции Process(void), Handler(void) и т.п. Т.к. это по факту асинхронность для бедных

Это называется не "асинхронность" для бедных, а кооперативная многозадачность. Подобную кооперативную многозадачность (кооперативную многопоточность) избегать не надо. Она отличается от примитивов многопоточности OS (которой, как раз, следует пользоваться только для системных задач). К коперативная многопоточность это очень, очень, очень часто используемый метод вычисления мелкими "квантами" с быстрым возвратом , избегать его никак не надо.

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

 

On 11/18/2022 at 4:19 AM, Solonovatiy said:

и возникают все те же самые проблемы вроде наличия некого "состояния", которое может неявно(для другого модуля) менятся.


Состояние именно что прямое понятие определенных парадигм программирования.  Например в функциональном программировании (ФП) как можно больше стремятся избегать понятия "состояние". Его, как раз, лишены так называемые "чистые функции" (pure functions). В том смысле что код у функциональщиков должен работать так - сколько бы его не запускал с одним и тем же параметром, он всегда вернет один и тот же результат (ну оно и понятно, т.к. состояние вообще нигде не сохраняется). Зато код должен быть парметризован или если можно на это посмотреть под таким углом - постоянно принимает состояние в качестве параметра извне (и нигде его не хранит). Ясное дело, это прямая противоположность ООП, где состояние повсеместно напрямую сохраняется в объектах. (Или модулях СИ). Отладка в ФП тем самым очень сильно упрощена, а системы в целом более предсказуемы и более легко проверяемы (одно из основных стремлений ФП к тому чтобы системы были вычислительно проверяемы, т.е. чтобы в принципе не было и не могло никак оказаться неких непроверяемых состояний системы).

И еще о состояниях в ООП или простом процедурном программировании. Одна из рекомендаций - не "размазывать" состояние по всему коду и модулям. Размазывать состояние системы вообще сильно чревато. Тем более, по выделенной malloc-памяти и переменным. К сожалению, концентрация состояния в одной единственной структурированной композитной переменной, пусть модули даже и никогда не имеют доступа к ней ко всей зачастую противоречит принципу инкапсуляции, т.е. сокрытия у себя своего собственного состояния. Поэтому я лично постоянно балансирую между инкапсуляцией и концентрацией всего в одном месте в одной комплексной структуре. И то и другое обладает своей собственной красотой. Задачи инкапсуляции решаются через указатели, тем более анонимные.
 

On 11/18/2022 at 4:19 AM, Solonovatiy said:

Пример:

  Reveal hidden contents
main:
  Head.Process();
  Legs.Process();

Head :
  if(stupid_thought) : Legs.Jump(); 
  else if(nice_thought) : Legs.WalkTo(nice_thought.destination); 

 

Код содержит ошибки, т.к. мы можем попытаться пойти, а уже ноги прыгнули. Пример рудиментарный, но помимо ног, могут быть руки, ноги, жопа или электродвигатель на пару десятков киловатт.
Что делать ногам в таком случае? Или может сделать очередь команд? Голове придется убеждаться, что с ногами все хорошо и т.д. и т.п. 

 

Эта проблема понятна, давно известна и ее единственно верное решение тоже давно известно.
Никакой модуль системы никогда не должен знать о других. Точка.
В рамочку - и на стену. 🙂 (шучу)

Т.е. все модули должны быть всегда строго изолированы (разделены) друг от друга.
Думайте при построении системы о микросхемах. Стройте систему также, как строится система из микросхем (или на более высоком уровне из плат, из модулей, блоков, стоек). Разве какая-либо микросхема внутри себя как-то учитывает другие? Нет конечно.
Еще, микросхема хоть и может содержать внутри себя массу состояний, но никто изменить извне их может. Микросхема - "закрыта в корпусе". Это и есть инкапсуляция. В т.ч. (очевидно) и её состояния.

Еще, инкапсуляцию можно интерпретировать как "пиши код модуля так, чтобы модулей можно было легко и безболезненно сделать N раз". И при этом ничто бы не изменилось и не сломалось. Понятно что при таком подходе никакого "я сам произвольно вызываю кого-то или меняю чужое состояние" быть не может. Ибо это свяжет модули, пристегнув к модулю допустим некий глобальный, куда он лезет и меняет его состояние вместо того чтобы изменить только своё состояние. Такого быть не должно.
 

На самом деле у полного разделения и изоляции существует масса достоинств, одно из которых - тестируемость модуля. Для этого никакой взаимной связки конечно быть не должно.
Вообще, стоит вплотную подойти к TDD (Test Driven Development). Следование этой парадигме само по себе сильно поменяет подход и таких вопросов как в этой сообщении не возникнет. К большому сожалению я бы хотел видеть книги по TDD электроники вообще, включая Embedded программирование, а то попавшаяся мне книга TDD по Embedded к сожалению оказалась о embedded software.

Это всё сильно упрощено. Существует масса вещей (действующих и в C и при желании хоть в ASM) которые полезно учитывать чтобы проектировать системы адекватно и не мучаться вопросами странности происходящего: Inversion of Control, Dependency Injection, SOLID. Обычно эти вещи ошибочно атрибутируют к ООП и обходят стороной, но это не более чем принципы разбиения софта и построения его архитектуры. И они не софтовые на самом деле. Софт-архитекторы сами того не зная переизобрели то, что давным-давно само-собой работает в электронике.

 

On 11/18/2022 at 4:19 AM, Solonovatiy said:

С другой стороны можно обмазаться абстрактными сущностями (вроде ThougtsRouter) и\или разделить голову на множество других, которые будут отвечать за свои "ноги" и работать только с ними. И я не знаю какой правильный и к какому стремиться. Оба ведут к сильному усложнению кода, первый к невероятно запутанным и многофункциональным "ногам" и "голове" занимающейся постоянной возней с состоянием ног (привет ОКР), второй ведет к тонне абстракций, что тоже увеличивает шанс сделать макаронного монстра, особенно когда они потекут...

Всё описано выше.  Ни голова о ногах знать не должна, ни ноги о голове.

Но вообще, дополнительно полезно знать о некоем глобальном принципе "ожидание".  Принцип готовности.   Всё это снова можно подсмотреть на микрухах.
Некто может захотеть дать команду. Но ждет пока что-либо придет в известное состояние. Исполнитель, соответственно, тупо игнорирует команду если не готов. Считается что это личные проблемы того кто дал команду/сигнал не проверив состояние (по крайней мере микрухи именно так себя и ведут) .
Также полезно знать о таком паттерне как очередь команд (Command List). Они бывают вполне себе хардварные. А там среди команд может быть ожидание (WAIT).
 

On 11/18/2022 at 4:19 AM, Solonovatiy said:

3. Я не знаю ничего кроме MVP, что пойдет для отображения данных. А MVP очень туго ложиться на С и туговато на С++, да и вообще, если делать его по феншую, надо ему систему ивентов заводить, а это привет лишняя асинхронность, да и тяжеловато. В то же время делать синхронный MVP это тоже чудище, которое добавляет зависимости. Есть какие-нибудь альтернативные пути? 

Отображение данных, серечь GUI нормально ложится и на кресты и на си.   Возможно, будет полезно изучить принцип сообщений (message). Не OS примитивы. Пойдет вместо системы event'ов. 
Кроме того, messages (с очередями сообщений) - архитектурное решение для асинхронщины вообще, советую присмотреться, авось избавит от головняков events. Самопальную очередь и свои сообщения в виде структур. И обработку сообщений из очереди. Но без конкретики, исходя из общих слов можно говорить ни о чем бесконечно.
 

On 11/18/2022 at 4:19 AM, Solonovatiy said:

4.  Бонусом к 3ему, идет если данные надо передавать во вне. Это же их надо СЕРИАЛИЗИРОВАТЬ. А сериализация на С\С++ это чертова боль, огромное кол-во бойлерплейта и вообще пахнет хидерами на 2000 строк. Ну или если у вас есть доступ к последнему стандарту С++ можно накинуть шаблонного чернокнижия, но вы проклянете свою душу и сами себя через несколько месяцев.

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

On 11/18/2022 at 4:19 AM, Solonovatiy said:

5. Я не знаю как сохранять данные на бинарный носитель (еепром какой), иначе, как хреначить какой очередной хидер на 2000 строк, в котором вы обязательно ошибетесь во время очередных правок\удаления адресов. 
Это вообще больная тема, я наверно с ней близок к тому, что для этого написать какую кодогенерацию всей этой фигни на JS. Может существует какая волшебная пилюля?

Всё очень сильно зависит от того какие данные и сколько их.  Но вот с адресами (никакими) работать вручную точно не надо.
Как вариант - это избегается подходом авто-инкремента адреса (он же квази-"стек").

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Один ли я вижу ошибку в названии темы?

Надо писа́ть "во встраиваемой".

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 11/18/2022 at 4:09 PM, tgruzd said:
typedef struct{
		module_a_config_t a;
		module_b_config_t b;
		module_c_config_t c;

}config_t;


config_t config;

и т.д

с этим уже проще будет работать

Это вы еще не добрались до новой версии настроек модуля a, размер которых станет больше и затрет все что ниже (модуль b и с). Надо резервировать пустое место между модулями, контролировать что они не пересекаются при добавлении настроек.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 hours ago, turnon said:

Это вы еще не добрались до новой версии настроек модуля a, размер которых станет больше и затрет все что ниже (модуль b и с). Надо резервировать пустое место между модулями, контролировать что они не пересекаются при добавлении настроек.

То есть сделать
typedef struct
{
    module_a_config_t a;
    module_b_config_t b;
    module_c_config_t c;
    module_c_config_t a_v2;
    module_c_config_t b_v2;
    module_c_config_t a_v3;
    module_c_config_t c_v2;
} config_t;
никак ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, x893 said:

То есть сделать
typedef struct
{
    module_a_config_t a;
    module_b_config_t b;
    module_c_config_t c;
    module_c_config_t a_v2;
    module_c_config_t b_v2;
    module_c_config_t a_v3;
    module_c_config_t c_v2;
} config_t;
никак ?

Неужели вам это нравится?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

13 minutes ago, turnon said:

Неужели вам это нравится?

Да при чём тут я ? Надо - значит можно и так. А можно и не так.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, turnon сказал:

Неужели вам это нравится?

Послушайте, мне и самому это не нравится. Но изначальный вопрос был в том, как уйти от прямой записи адреса типа #define CONFIG_A_ADDR 0x.....

9 часов назад, turnon сказал:

Это вы еще не добрались до новой версии настроек модуля

 Вы, видимо, уже добрались и хотите представить свою реализацию?  

Изменено пользователем tgruzd

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

12 hours ago, tgruzd said:

Послушайте, мне и самому это не нравится. Но изначальный вопрос был в том, как уйти от прямой записи адреса типа #define CONFIG_A_ADDR 0x.....

 Вы, видимо, уже добрались и хотите представить свою реализацию?

Мне нравится вариант как описал @jcxz здесь

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 часов назад, turnon сказал:

Мне нравится вариант как описал @jcxz здесь

Да, хороший вариант. Уже почти файловая система

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я склоняюсь к использованию FatFS. МК STM32F407, память W25Q64. Использую GCC. Прикручу FatFS к stdio, чтобы пользоваться стандартной библиотекой. Замечу, что все данные, которые я будут записывать, сопровождаются контрольной суммой. Ну а 4М на борту дадут возможность загружать через LAN прошивку для обновления.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

14 minutes ago, tonyk_av said:

Я склоняюсь к использованию FatFS. МК STM32F407, память W25Q64. Использую GCC. Прикручу FatFS к stdio, чтобы пользоваться стандартной библиотекой. Замечу, что все данные, которые я будут записывать, сопровождаются контрольной суммой. Ну а 4М на борту дадут возможность загружать через LAN прошивку для обновления.

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

16 минут назад, Forger сказал:

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

КМК - идеально, в том случае когда ресурсы мк позволяют иметь и ФC, и юсб стек, и ворочать JSON, и нет особых требований к поведению при случайном пропадании питания. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

21 minutes ago, tgruzd said:

и нет особых требований к поведению при случайном пропадании питания. 

ничего страшного при сбоях питания не происходит, изделие зависит от внешнего питания

и более того используются ДВА диска, в основной внутренний можно записать данные только с ПК или смартфона, сам девайс только читает,

а второй диск (внешняя флэшка или sd карта) - журнал событий, сбои ему не так критичны, т.к. эта файловая система поддерживает т.н журналирование.

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

 

 

21 minutes ago, tgruzd said:

и ворочать JSON

вот уж прям ресурсоемкая вещь )))

хотя из готовых в открытом доступе действительно есть довольно "тяжелые"

 

что касается  файловой системы и стека юсб, то они сами по себе "кушают" очень мало, конечно относительно объема основного кода

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...