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

Синхронное взаимодействие программных модулей

Подбросьте идей, как реализовать синхронность программных модулей. Организация программ на данный момент у меня следующая. Модульность. Никаких долгих циклов. Модули, задачи, процессы дробятся условиями, флагами, состояниями конечных автоматов. Итерация основного цикла выполняется с запасом за один системный тик. В основном системный тик у меня - 1 мс. Использую программные таймеры. То есть, у меня псевдопараллельность процессов.

Иногда бывают ситуации, когда несколько модулей после определенного события должны выполнить определенные действия. Речь идет не о быстром поочередном выполнении, а, скажем, в течении одной итерации основного цикла.

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

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


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

Не совсем понял суть проблемы. Как вариант

 

struct Action {
 bool todo = false;
 Action *next = 0;  
};

Action *event1;

void registerAction(Action **event, Action *a) {
 a->next = *event;
 *event = a;
}

void setOn(Action *event) {
 while(event) {
event->todo = true;
event = event->next;
 }
}

// модуль 1
Action mod1_event1;
registerAction(event1, mod1_event1);

void loop() {
 if (mod1_event.todo) {
mod1_event.todo = false;
  // ...
 }
}

// модуль 2
Action mod2_event1;
registerAction(event1, mod2_event1);

void loop() {
 if (mod2_event.todo) {
mod2_event.todo = false;
  // ...
 }
}

// где-то еще

ISR(isr) {
 setOn(event1);
}

 

Если ставить флаг в прерывании, то чтение и сброс надо переделать на атомарное

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


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

Попробую поточнее выразиться. Событие генерируется по условию и времени. Скажем, подавление дребезга контактных датчиков и входов. Одни входы - это контактные датчики, другие - контактные группы пускателей. У пускателей свои времянки включения-выключения. И чтобы не произошло сбоя, нужно синхронизировать действия модулей. Повторяю, речь не быстро-быстро выполнить действия. А о синхронизации действий в заданных рамках. Возьмем за такую рамку и условие, к примеру, итерацию основного цикла. Обработали все времянки подавления дребезга, по условиям модуль генерирует событие (что-то). Другими модулями видится это что-то, и выполняются определенные действия. Скажем, за итерацию основного цикла. Прошла итерация, это что-то больше не выставлено. Главное условие, сохранить инкапсуляцию программных модулей.

 

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

 

Подсмотрено у ЛИ.

//----------------------------- Переменные: ----------------------------------

volatile bool fTick;               //флаг обновления системного таймера
static bool tick;                  //флаг начала нового системного интервала

//------------------ Инициализация системного таймера ------------------------

void Main_Timer_Init(void)
{
// bla-bla
  fTick = 1;                       //принудительное обновление
}

//--------------------- Проверка системного таймера: -------------------------

__monitor bool Main_GetTick(void)
{
  if(!fTick) return(0);            //проверка нового системного интервала
  fTick = 0;                       //очистка флага
  return(1);                       //новый системный интервал
}

//------------------- Прерывание системного таймера: -------------------------

#pragma vector = TIMER1_COMPA_vect
__interrupt void Timer(void)
{
  fTick = 1;                       //новый системный интервал
}

//----------------------------------------------------------------------------

//----------------------------------------------------------------------------
//-------------------------- Основная программа: -----------------------------
//----------------------------------------------------------------------------

void main(void)
{  Main_Timer_Init();               //инициализация системного таймера
  __enable_interrupt();            //разрешение прерываний

  while(1)                         //основной цикл
  {
    tick = Main_GetTick();         //опрос системного таймера
    Meter_Exe(tick);               //обслуживание измерителя
  }
}

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

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


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

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

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

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


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

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

Что считаем входами?

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


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

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

нужно на нескольких выходах, в зависимости от входов, формировать состояние синхронно каждую мс?

Или нужно нечто другое?

«Правильно заданный вопрос – половина ответа»(с)

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


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

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

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

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

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


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

Что считаем входами?

Ну это Вам видней.

"Одни входы - это контактные датчики, другие - контактные группы пускателей."

Так как это Ваш контроллер, то что назначите.

Если интересны подробности того о чем я написал, то стоит почитать описания на тот же Симатик.

 

 

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


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

Речь идет не о быстром поочередном выполнении, а, скажем, в течении одной итерации основного цикла.

Т.е. Вам нужно медленно и параллельно?

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

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


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

По коду в сообщении #4:

Не затрагивая способы организации очерёдности вызовов, замечу,

что нет необходимости в переменной fTick, обработчике прерывания,

разрешении прерывания таймера.

 

Просто настраиваем и запускаем таймер и в основном цикле проверяем аппаратный флаг:

if ( TIFR1 & (1<<OCF1A) )
{
  TIFR1 = (1<<OCF1A); // не забыть сбросить флаг

  {/*полезные действия*/}
}

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


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

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

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

 

Так вы диаграммку временнУю нарисовали бы и всём стало бы понятнее…

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


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

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

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

 

Вы бы все таки сформулировали задачу :rolleyes:

 

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

 

Или задача звучит по другому?

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


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

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

Поднимаю тему. Опять столкнулся с этим. Да, вы точно описали мою проблему. Запутался уже как это реализовать.

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


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

Запутался уже как это реализовать.

Создаете переменную СОБЫТИЕ, в которой 8 бит, по числу модулей.

Если событие происходит, то приравниваете СОБЫТИЕ = 0xFF

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

Если система спроектирована правильно, то все модули обрабатывают событие раньше, чем произойдет новое событие.

 

 

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


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

Программы систем реального времени, по моему мнению, следует строить по принципу - на каждое событие есть свой обработчик. Завершилось преобразование АЦП, сработало прерывание, нужно сохранить данные и вызывать обработчик фоновой задачи, который преобразует сырые данные АЦП в формат с плавающей точкой. После завершения математики можно разрешать новое преобразование. Запускать новое преобразование АЦП, до того, как процессор завершит обработку, смысла нет. Чтобы программа так работала нужен диспетчер многозадачности. Вытесняющая многозадачность для одной единственной программы, которую пишешь сам - перебор. Кооперативной вполне достаточно. Есть два заблуждения. Заблуждение первое - кооперативная многозадачность создаёт множество неудобств. Заблуждение второе - вытесняющая многозадачность эти удобства решает. По степени важности обработчики делятся на три уровня - аппаратные прерывания (срочно, срочнее некуда), программные прерывания (не так срочно, как аппаратное прерывание, но срочнее, чем фоновая задача), фоновая задача (по остаточному принципу - сложная математика). Обработчик аппаратного прерывания инициирует либо программное прерывание, либо фоновую задачу. Системный таймер - надстройка над механизмом программного прерывания.

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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