pokk 0 August 26, 2020 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 More sharing options...
haker_fox 63 August 26, 2020 Posted August 26, 2020 · Report post 1 hour ago, pokk said: По этому хотелось бы сделать по первому варианту, можно ли как нибудь обойти его недостатки ? Не знаю, какая у вас вычислительная платформа. Но если это микроконтроллер, то можно задействовать программный вызов прерывания по готовности данных. И у вас: 1. Не будет лишней задачи. 2. Контекст по выходу из прерывания будет переключаться только по мере необходимости если значение параметров вышло из ОБР (область безопасной работы). Quote Share this post Link to post Share on other sites More sharing options...
pokk 0 August 26, 2020 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 More sharing options...
haker_fox 63 August 26, 2020 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 More sharing options...
juvf 22 October 2, 2020 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 More sharing options...
pokk 0 October 16, 2020 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 More sharing options...
juvf 22 October 16, 2020 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 More sharing options...
pokk 0 October 16, 2020 Posted October 16, 2020 · Report post Что-то похожее пытался сделать, но тут же сразу возникла проблема Дело в том что у меня модуль АЦП выдает 2 ввида среднего значение по работа введется по нему. 1) Большое количество отсчетов (за 200ms) , для отображение параметра на экране 2) Парочку значений , для зашиты. Так вот что бы запустить функцию Protect она должна быть внутри функции GetDataFromAdc. Quote Share this post Link to post Share on other sites More sharing options...
antis 1 October 16, 2020 Posted October 16, 2020 · Report post Можно передать указатель на Protect в фунцию GetDataFromAdc, потом сможете любой Protect подставить. Quote Share this post Link to post Share on other sites More sharing options...
juvf 22 October 17, 2020 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 More sharing options...