Jump to content

    
pokk

Взаимодействие двух модулей, task или include ?

Recommended Posts

Подскажите как правильнее сделать взаимодействие двух модулей.
Первый модуль (ShareParam) считывает значения с АПЦ, суммирует их и пересчитывает в реальные значения параметра в общем на выходе получаем глобальную структуру к которой имеет доступ любой модуль (экран, web … ).
Второй модуль эта защита , он должен брать реальные значения(пересчитанные значения) из первого модуля, сравнивать с пороговыми значениями параметра и делать действия (выключать, блокировать...)
Вижу два взаимодействие между ними:
Первый вариант это из модуля ShareParam выходит сигнал готовности данных, а во втором модуле находиться задача которая ожидает этот сигнал и по нему включает проверку параметра. В принципе мне такое взаимодействие нравиться тем, что модуль ShareParam, развязан и может работать независимо есть ли второй модуль или нет.  
Но в данном варианте не нравиться:
1) То что используется лишняя задача в модуле защите, так как можно обойти без неё.  
2) То что будет достаточно частое, отправлять сигнала готовности т.е частое переключение контента.
 
Второй вариант это в модуле защиты написать функцию, и её вызывать в модуле ShareParam, это исключает  все недостатки первого варианта, но логически модули становятся смешанными друг с другом и модуль ShareParam не сможет работать, без модуля защиты.
У меня частично старые проекты написаны по второму варианту, и очень раздражает когда ты подключаешь всего один модуль (переносишь в новый проект), а он тянет за собой другой а тот, что-то ещё и ещё и так пока весь проект  не перекопируешь.
По этому хотелось бы сделать по первому варианту,  можно ли как нибудь обойти его  недостатки ?

 

Edited by pokk

Share this post


Link to post
Share on other sites
1 hour ago, pokk said:

По этому хотелось бы сделать по первому варианту,  можно ли как нибудь обойти его  недостатки ?

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

1. Не будет лишней задачи.

2. Контекст по выходу из прерывания будет переключаться только по мере необходимости если значение параметров вышло из ОБР (область безопасной работы).

Share this post


Link to post
Share on other sites
25 minutes ago, haker_fox said:

Не знаю, какая у вас вычислительная платформа

Stm32+FreeRTOS

24 minutes ago, haker_fox said:

Контекст по выходу из прерывания будет переключаться только по мере необходимости если значение параметров вышло из ОБР (область безопасной работы).

Можно  подробнее про это.

 

Share this post


Link to post
Share on other sites
17 minutes ago, pokk said:

Stm32+FreeRTOS

Stm32 Cortex-M какой?)

17 minutes ago, pokk said:

Можно  подробнее про это.

Вы вызываете программно любое свободное прерывание. Вектор может принадлежать и какой-либо периферии. Но эта периферия не используется, либо не использует вектор. В контроллере прерываний (NVIC) вы настраиваете прерывание как и для обычной периферии, но активироать его будете программно, используя функцию NVIC_SetPengingIRQ либо свою. Неважно. Главное, она должна устанавливать соответстующий бит (номер совпадает с номером вектора) в единицу в регистре ISPR. После этого процессор прерывает текущий процесс и входит в ваш обработчик. Там вы проверяете свои параметры, и если они не выходят за границу, то просто выходите из прерывания и возращаетесь к перванному процессу (любому). Если параметры плохие, то вы сигнализируете задаче, которая это разрулит. Сигнализируете семафором или, что лучше, сервисом Task Notify (см. примеры на сайте и обратите внимание на макрос portYIELD_FROM_ISR, именно он "говорит" о необходимости перепланировки по выходу из прерывания). А вот в этом случа уже может потребоваться переключение контекста, но в том случае, если есть задача, готовая к исполнению с приоритетом выше прерванной.

Share this post


Link to post
Share on other sites
26.08.2020 в 12:04, pokk сказал:

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

а если закомментировать вызов этой функции, то модуль ShareParam не сможет работать без модуля защиты? Что-то с каркасом не так.

Цитата

2) То что будет достаточно частое, отправлять сигнала готовности т.е частое переключение контента.

на сколько я понял, у вас два последовательный действия:

1) вычитка с ацп

2) проверка данных (модуль защиты).

зачем их параллелить в 2 задачи?

Share this post


Link to post
Share on other sites
On 10/2/2020 at 3:20 PM, juvf said:

а если закомментировать вызов этой функции, то модуль ShareParam не сможет работать без модуля защиты? Что-то с каркасом не так.

Да именно так, это я и назвал смешивание  логики работы.

On 10/2/2020 at 3:20 PM, juvf said:

на сколько я понял, у вас два последовательный действия:

1) вычитка с ацп

2) проверка данных (модуль защиты).

зачем их параллелить в 2 задачи?

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

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

typedef __packed struct{
    int32_t             adc;            //Текушее значение АЦП с учетом компенсации нуля !!
    uint32_t            RealAdc;        //Текушее значение АЦП без компенсации !!
    ParamMem_t          mem;
    ParamCallback_t     callback;
    ParamDec_t          dec;
    uint8_t             TypeParam;
    uint8_t             NumInAdc;       // физически номер канала АЦП
    Limit_t             lim;
    uint8_t             status;
}ParamValue_t;

И с выхода модуля ShareParam получаем:

1) Каждый параметр содержит свой АЦП

2) Расчитанно десятичное значение параметра в вольтах амперах ваттах, на основе коэфициента считанного из памяти  в структуру mem (по включению).

2) Расчитанный статус  параметра  на основе, его порогов.

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

И модуль защиты получился чисто из функций инициализации  Callback параметров  и самих  Callback  по требуемым параметрам + прерывание INT по выводам которые требуют обработку.

Edited by pokk

Share this post


Link to post
Share on other sites

или вы задачу не правильно формулируете.... или ....

Если не нужно выполнять два действия "параллельно", то зачем 2 задачи? У вас действия выполняются последовательно. Для того, что бы модули были независимы, не нужно разносить их в отдельные задачи, нужно их сделать независимыми. Например... первый модуль в ShareParam .h

void getDataFromAdc(void *data) {.....};

второй модуль Protection.h

void protection(void *data) {....};

Вот вам два абсолютно независимых модуля. Нет ни какого смешения логики. Оба модуля абсолютно абстрагированы др от др.

 

Теперь задача mainTask.c

#include "ShareParam.h"
#include "Protection.h"
  
void mainTask(void *context)
{

  uint8_t data[128];
  for(;;)
  {
  	getDataFromAdc(data);
  	pronection(data);
  	delayMs(10);
  }

}


 

оба модуля работают совершенно независимо и последовательно. Если нужно собрать без защиты, просто закомментировать функцию protection() и #include "Protection.h" в задаче.

Конечно, для практики с РТОС можно getDataFromAdc() вызывать в одной задаче, protection() вызывать в другой.... можно выделять память uint8_t data[128] в третей..... Можно и холоворд разбить на количество задач, равным кол-ву букв. Оверинженеринг.

Share this post


Link to post
Share on other sites

Что-то похожее пытался сделать, но тут же сразу возникла проблема
Дело в том что у меня модуль АЦП выдает 2 ввида среднего значение по  работа введется по нему.
1)    Большое количество отсчетов (за 200ms) , для отображение параметра на экране  
2)    Парочку значений ,  для зашиты.
 
Так вот что бы запустить функцию Protect  она должна быть внутри функции GetDataFromAdc.   

 

Share this post


Link to post
Share on other sites
23 часа назад, pokk сказал:

Что-то похожее пытался сделать, но тут же сразу возникла проблема
Дело в том что у меня модуль АЦП выдает 2 ввида среднего значение по  работа введется по нему.
1)    Большое количество отсчетов (за 200ms) , для отображение параметра на экране  
2)    Парочку значений ,  для зашиты.
 
Так вот что бы запустить функцию Protect  она должна быть внутри функции GetDataFromAdc.   

 

ShareParam .h

bool getDataFromAdc(void *data) {.....};

Protection.h

void protection(void *data) {....};

 mainTask.c

 

#include "ShareParam.h"
#include "Protection.h"
 
void mainTask(void *context)
{

  uint8_t data[128];
  for(;;)
  {
      if(getDataFromAdc(data));
          protection(data);
      delayMs(10);
  }

}


Это на вскидку.... можно void getDataFromAdc(void *data, bool *isNeedProtection = 0); Внутри getDataFromAdc, если isNeedProtection  != 0, то вернуть бул....  можно как antis

Даже если не нужна ртос и не нужно 2 задачи... то всё равно нужно отделять мух от котлет модули др от др.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.