pokk 0 7 июля, 2020 Опубликовано 7 июля, 2020 · Жалоба Задача такая, есть несколько обработчиков вызываемые через FREERTOS из разных задач. В них должна происходить модификация параметра и запись всей структуру конфигурации в память. Из за того что обработчики вызываются из разных задач, что бы не было переключение контента при модификации параметра его надо заблокировать через mutext. Первое что приходит на ум в лоб xSemaphoreTake(xConfing,portMAX_DELAY); confing.var1=100; confingClcCrc(); SaveConfing(); xSemaphoreGive(xConfing); Но такой вариант не нравиться (загромождает логику). Потом подумал завернуть это все в функцию типа такого: SaveConfing(&confing.var1,100); В принципе, уже более понятно, но тут другая проблема вылезла, функций надо большое количество под каждый тип под массив, под одинарную переменную, а если надо записать больше 1 параметра в одном вызове ? Не гонять же всю структуру в память после каждого байт. В общем подскажите, как это делается что бы было удобно? Или набор функций каких используете ? Была мысль, что бы, передавать сохраняемые данные в одну задачу через очереди, а там производить, модификацию конфигурации + запись. Но отказался от такого нагромождения из за того что, очень малая вероятность, что два обработчика вызовутся одновременно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 7 июля, 2020 Опубликовано 7 июля, 2020 · Жалоба Зачем ограждать семафором изменение параметра? Унесите семафор и confingClcCrc() внутрь SaveConfing(); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
pokk 0 7 июля, 2020 Опубликовано 7 июля, 2020 · Жалоба 12 minutes ago, Сергей Борщ said: Зачем ограждать семафором изменение параметра? Что бы корректно произошла модификация параметра, ведь его может модифицировать другая задача. Хотя да, для одного и того же параметра наврятли, но структура модифицировать из другой задачи точно может. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexandrY 3 7 июля, 2020 Опубликовано 7 июля, 2020 · Жалоба 1 hour ago, pokk said: Но отказался от такого нагромождения из за того что, очень малая вероятность, что два обработчика вызовутся одновременно. Насчет малой вероятности - типичное когнитивное искажение. Например если у вас появяться два процесса с небольшой разницей в периоде повторения, то 100% будут случаи когда один будет вытеснять контекст другого. Даже если сами по себе процессы будут выполняться за микросекунды. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Grigorij 0 7 июля, 2020 Опубликовано 7 июля, 2020 · Жалоба 2 hours ago, pokk said: В принципе, уже более понятно, но тут другая проблема вылезла, функций надо большое количество под каждый тип под массив, под одинарную переменную, а если надо записать больше 1 параметра в одном вызове ? Если речь именно про ANSI C, то можно: Вариант 1. 2 hours ago, pokk said: В принципе, уже более понятно, но тут другая проблема вылезла, функций надо большое количество под каждый тип под массив, под одинарную переменную, а если надо записать больше 1 параметра в одном вызове ? Если речь именно про ANSI C, то можно: Вариант 1. случайно отправил раньше времени, продолжение... Вариант 2. Сделать что-то типа такого: enum { CONFIG_FIELD_1, CONFIG_FIELD_2, } void SaveConfig(int type, void * value) { // забираем семафор switch (type) { case CONFIG_FIELD_1: config.var1 = *((int *)value); break; case CONFIG_FIELD_2: config.var2 = *((double *)value); break; } // сохраняем все // отдаем семафор } // где-нибудь в коде int newValue = 5; SaveConfig(CONFIG_FIELD_2, (void *)&newValue); Вариант 3. Для каждого типа данных сделать свои функции Ну и наверняка можно еще что-нибудь придумать, так как выше - это первое что пришло в на ум из того, что сам использовал в коде в разное время. Все зависит от вам и вашей программы, т.к. совсем универсального решения нет. и редактирование нормально не работает. Вариант 1. Это посмотреть на va_start, va_list, va_end. Примеры можно найти здесь Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
pokk 0 7 июля, 2020 Опубликовано 7 июля, 2020 · Жалоба 17 minutes ago, AlexandrY said: Насчет малой вероятности - типичное когнитивное искажение. Например если у вас появяться два процесса с небольшой разницей в периоде повторения В том то и дело, что эти процессы не сильно то и повторяющиеся, их вызывает пользователь когда нажимает кнопки в меню и в web странице. По этому и решил сразу же в этих обработчиках сделать запись конфигурации в память(внешнуюю), а если все таки наложаться, то по семафором должно все разрулиться. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 7 июля, 2020 Опубликовано 7 июля, 2020 · Жалоба 2 часа назад, Сергей Борщ сказал: Зачем ограждать семафором изменение параметра? Унесите семафор и confingClcCrc() внутрь SaveConfing(); Видимо затем, что confing у автора - общая переменная, разделяемая разными процессами (задачами). А одновременный доступ к общим переменным из разных процессов чреват. 1 час назад, pokk сказал: В том то и дело, что эти процессы не сильно то и повторяющиеся, их вызывает пользователь когда нажимает кнопки в меню и в web странице. Кроме блокирующего доступа к общей переменной, другие возможные решения: 1. Строить новый экземпляр confing (или её части) в памяти, принадлежащей конкретной задаче, а потом передавать на обработку (объединение с confing) специальной задаче. Так можно избавиться от необходимости блокирующего доступа. 2. Обработку "меню" и "действий на web-странице" делать в одной задаче. Тогда проблема отпадёт сама собой. 3. Если вся проблема только из-за необходимости атомарного доступа SaveConfing() к переменной confing по чтению, то можно вообще обойтись одним флажком занятости. Который модифицирующая функция устанавливает перед модификацией confing и сбрасывает после. И после сброса флажка она пингует задачу с функцией записи. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
pokk 0 7 июля, 2020 Опубликовано 7 июля, 2020 · Жалоба 37 minutes ago, jcxz said: 3. Если вся проблема только из-за необходимости атомарного доступа SaveConfing() к переменной confing по чтению, то можно вообще обойтись одним флажком занятости. Который модифицирующая функция устанавливает перед модификацией confing и сбрасывает после. И после сброса флажка она пингует задачу с функцией записи. Флаг занятости, это же mutex? А зачем выделять функцию записи в отдельную задачу? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 7 июля, 2020 Опубликовано 7 июля, 2020 · Жалоба 3 минуты назад, pokk сказал: Флаг занятости, это же mutex? нет. Это char volatile flag; 3 минуты назад, pokk сказал: А зачем выделять функцию записи в отдельную задачу? Затем что задачи-клиенты - модифицируют confing, а задача-сервер - записывает содержимое confing куда-то. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexandrY 3 7 июля, 2020 Опубликовано 7 июля, 2020 · Жалоба 4 hours ago, pokk said: Не гонять же всю структуру в память после каждого байт. Почему бы и нет? Нормальная практика. Весь процес займет максимум десяток миллисекунд. Тик операционки дольше длится. Экономить тут время никакого смысла нет. Параметры еще и сериализовать можно в JSON, чтобы легко читалось и передавалось. Для записи во Flash надо стирать блоками, потом CRC блока конфигурации же тоже надо писать в отдельное место. Короче, каждый раз писать весь блок данных гораздо удобнее чем возиться с каждым байтом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
pokk 0 7 июля, 2020 Опубликовано 7 июля, 2020 · Жалоба 28 minutes ago, jcxz said: нет. Это char volatile flag; А можно по подробнее как это используеться? Если использовать в лоб то это как то так char volatile flag; void ModConfing(void){ //------------------------------------ while(1){ // ожидаем флаг if(flag==1){ break; }else{ taskYIELD(); } } //------------------------------------ //изменение конфигурации //------------------------------------ flag=0; } не вижу чем отличаеться от mutex, он даже проше. 29 minutes ago, jcxz said: Затем что задачи-клиенты - модифицируют confing, а задача-сервер - записывает содержимое confing куда-то. А в чем преимущество такого разделение ? Что задачи клиенты не будут подтупливать на момент записи ? 24 minutes ago, AlexandrY said: Короче, каждый раз писать весь блок данных гораздо удобнее чем возиться с каждым байтом. Это да запись идет всем блоком, я про такой момент ModAndSaveConfing(VAR1,100); ModAndSaveConfing(VAR2,100); ModAndSaveConfing(VAR3,100); на такой случий надо отдельные функции модификации городить confing.var1=100; confing.var2=200; confing.var3=300; SaveConfing(); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexandrY 3 7 июля, 2020 Опубликовано 7 июля, 2020 · Жалоба 23 minutes ago, pokk said: на такой случий надо отдельные функции модификации городить Почему бы и не нагородить? Используейте возможности редакторов по блочному редактированию. Я никогда не торможу если надо написать несколько десятков почти одинаковых функций. Они пушутся блочно и в одну строку, рефакторить их тоже очень просто. Но заметно упрощается отладка таких функций, по сравнению с шаблонами, макросами или некими итеративными методами. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 7 июля, 2020 Опубликовано 7 июля, 2020 · Жалоба 1 час назад, pokk сказал: А можно по подробнее как это используеться? Если использовать в лоб то это как то так Примерно так (если это Вы описали серверную задачу, записывающую данные из confing куда-то). Только ждать (серверной задаче) лучше на каком-нить объекте синхронизации, типа майл-бокса. И флаг она должна сбрасывать до записи(!), а не после. 1 час назад, pokk сказал: не вижу чем отличаеться от mutex, он даже проше. Странно что не видите... И кто говорил про "проще"? Какой подход применить - выбирает разработчик, основываясь на ТЗ. А плюс 3-го варианта: неблокирующая модификация параметров в confing. Что может быть очень важным, особенно если выполнение SaveConfing() занимает заметное время. 1 час назад, pokk сказал: А в чем преимущество такого разделение ? Что задачи клиенты не будут подтупливать на момент записи ? Именно так. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
pokk 0 7 июля, 2020 Опубликовано 7 июля, 2020 · Жалоба 4 hours ago, jcxz said: Примерно так (если это Вы описали серверную задачу, записывающую данные из confing куда-то). Вообще то нет, это я описал функцию модификацию параметра на клиенте. Если флаг был сброшен, то модифицируем параметр, иначе ждем когда флаг сброситься. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 7 июля, 2020 Опубликовано 7 июля, 2020 · Жалоба 5 минут назад, pokk сказал: Вообще то нет, это я описал функцию модификацию параметра на клиенте. Если флаг был сброшен, то модифицируем параметр, иначе ждем когда флаг сброситься. Зачем ждать??? Клиент не должен ничего ждать. Ну как ещё объяснить? Вроде всё до примитивного просто: Клиент (пишущий данные в confing): 1. Модифицирует confing. 2. Устанавливает flag = 1. 3. Пингует сервер (посылает ему сообщение в мэйл-бокс). Сервер (куда-то записывающий содержимое confing): while (1) { if (flag) { flag = 0; куда_записывает_содержимое_confing; } else { ждёт_майл-бокса; сброс_сигнального_состояния_мэйл-бокса; } } Всё! Очень просто! Клиент не ждёт. Клиентов может быть много. Клиенты работают без тормозов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться