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