pokk 0 Posted August 26, 2020 (edited) · Report post Подскажите как правильнее сделать взаимодействие двух модулей.Первый модуль (ShareParam) считывает значения с АПЦ, суммирует их и пересчитывает в реальные значения параметра в общем на выходе получаем глобальную структуру к которой имеет доступ любой модуль (экран, web … ).Второй модуль эта защита , он должен брать реальные значения(пересчитанные значения) из первого модуля, сравнивать с пороговыми значениями параметра и делать действия (выключать, блокировать...) Вижу два взаимодействие между ними: Первый вариант это из модуля ShareParam выходит сигнал готовности данных, а во втором модуле находиться задача которая ожидает этот сигнал и по нему включает проверку параметра. В принципе мне такое взаимодействие нравиться тем, что модуль ShareParam, развязан и может работать независимо есть ли второй модуль или нет. Но в данном варианте не нравиться: 1) То что используется лишняя задача в модуле защите, так как можно обойти без неё. 2) То что будет достаточно частое, отправлять сигнала готовности т.е частое переключение контента. Второй вариант это в модуле защиты написать функцию, и её вызывать в модуле ShareParam, это исключает все недостатки первого варианта, но логически модули становятся смешанными друг с другом и модуль ShareParam не сможет работать, без модуля защиты. У меня частично старые проекты написаны по второму варианту, и очень раздражает когда ты подключаешь всего один модуль (переносишь в новый проект), а он тянет за собой другой а тот, что-то ещё и ещё и так пока весь проект не перекопируешь. По этому хотелось бы сделать по первому варианту, можно ли как нибудь обойти его недостатки ? Edited August 26, 2020 by pokk Quote Ответить с цитированием Share this post Link to post Share on other sites
haker_fox 0 Posted August 26, 2020 · Report post 1 hour ago, pokk said: По этому хотелось бы сделать по первому варианту, можно ли как нибудь обойти его недостатки ? Не знаю, какая у вас вычислительная платформа. Но если это микроконтроллер, то можно задействовать программный вызов прерывания по готовности данных. И у вас: 1. Не будет лишней задачи. 2. Контекст по выходу из прерывания будет переключаться только по мере необходимости если значение параметров вышло из ОБР (область безопасной работы). Quote Ответить с цитированием Share this post Link to post Share on other sites
pokk 0 Posted August 26, 2020 · Report post 25 minutes ago, haker_fox said: Не знаю, какая у вас вычислительная платформа Stm32+FreeRTOS 24 minutes ago, haker_fox said: Контекст по выходу из прерывания будет переключаться только по мере необходимости если значение параметров вышло из ОБР (область безопасной работы). Можно подробнее про это. Quote Ответить с цитированием Share this post Link to post Share on other sites
haker_fox 0 Posted August 26, 2020 · Report post 17 minutes ago, pokk said: Stm32+FreeRTOS Stm32 Cortex-M какой?) 17 minutes ago, pokk said: Можно подробнее про это. Вы вызываете программно любое свободное прерывание. Вектор может принадлежать и какой-либо периферии. Но эта периферия не используется, либо не использует вектор. В контроллере прерываний (NVIC) вы настраиваете прерывание как и для обычной периферии, но активироать его будете программно, используя функцию NVIC_SetPengingIRQ либо свою. Неважно. Главное, она должна устанавливать соответстующий бит (номер совпадает с номером вектора) в единицу в регистре ISPR. После этого процессор прерывает текущий процесс и входит в ваш обработчик. Там вы проверяете свои параметры, и если они не выходят за границу, то просто выходите из прерывания и возращаетесь к перванному процессу (любому). Если параметры плохие, то вы сигнализируете задаче, которая это разрулит. Сигнализируете семафором или, что лучше, сервисом Task Notify (см. примеры на сайте и обратите внимание на макрос portYIELD_FROM_ISR, именно он "говорит" о необходимости перепланировки по выходу из прерывания). А вот в этом случа уже может потребоваться переключение контекста, но в том случае, если есть задача, готовая к исполнению с приоритетом выше прерванной. Quote Ответить с цитированием Share this post Link to post Share on other sites
juvf 0 Posted October 2, 2020 · Report post 26.08.2020 в 12:04, pokk сказал: Второй вариант это в модуле защиты написать функцию, и её вызывать в модуле ShareParam, это исключает все недостатки первого варианта, но логически модули становятся смешанными друг с другом и модуль ShareParam не сможет работать, без модуля защиты. а если закомментировать вызов этой функции, то модуль ShareParam не сможет работать без модуля защиты? Что-то с каркасом не так. Цитата 2) То что будет достаточно частое, отправлять сигнала готовности т.е частое переключение контента. на сколько я понял, у вас два последовательный действия: 1) вычитка с ацп 2) проверка данных (модуль защиты). зачем их параллелить в 2 задачи? Quote Ответить с цитированием Share this post Link to post Share on other sites
pokk 0 Posted October 16, 2020 (edited) · Report post 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 October 16, 2020 by pokk Quote Ответить с цитированием Share this post Link to post Share on other sites
juvf 0 Posted October 16, 2020 · Report post или вы задачу не правильно формулируете.... или .... Если не нужно выполнять два действия "параллельно", то зачем 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] в третей..... Можно и холоворд разбить на количество задач, равным кол-ву букв. Оверинженеринг. Quote Ответить с цитированием Share this post Link to post Share on other sites
pokk 0 Posted October 16, 2020 · Report post Что-то похожее пытался сделать, но тут же сразу возникла проблема Дело в том что у меня модуль АЦП выдает 2 ввида среднего значение по работа введется по нему. 1) Большое количество отсчетов (за 200ms) , для отображение параметра на экране 2) Парочку значений , для зашиты. Так вот что бы запустить функцию Protect она должна быть внутри функции GetDataFromAdc. Quote Ответить с цитированием Share this post Link to post Share on other sites
antis 0 Posted October 16, 2020 · Report post Можно передать указатель на Protect в фунцию GetDataFromAdc, потом сможете любой Protect подставить. Quote Ответить с цитированием Share this post Link to post Share on other sites
juvf 0 Posted October 17, 2020 · Report post 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 задачи... то всё равно нужно отделять мух от котлет модули др от др. Quote Ответить с цитированием Share this post Link to post Share on other sites