Хранение управляющей структуры в вызывающем объекте
От: cppguard  
Дата: 08.08.23 22:20
Оценка:
Пытаюсь реализовать полность асинхронную обработку I2C без выделения памяти. Нюанс этой шины в том, что чтобы что-то прочитать, нужно сперва записать адрес регистра, из которого нужно выполнить чтение. И с точки зрения машины состояний, эти два шага — независимые. Если бы сиутация была как с UART, то достаточно было бы завести кольцевой буфер и все запросы на чтение и запись сваливать туда. А тут требуется разбивать запросы логически на блоки, иначе как понять, что после записи очередной порции данных, теперь нужно считывать?

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

Например, структура сообщения может иметь вид:
struct msg {
  int type; // 0 - READ, 1 - WRITE
  int size;
  char *data;
  msg *prev;
  msg *next;
  void (*callback)(); // вызывается драйвером из прерывания, когда данные прочитаны/записаны
};


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

Как идея — имеет право на жизнь?
Re: Хранение управляющей структуры в вызывающем объекте
От: andyp  
Дата: 20.09.23 09:32
Оценка: +2
Здравствуйте, cppguard, Вы писали:

C>Как идея — имеет право на жизнь?


Не очень имхо. Я бы в интерфейсе драйвера функцию request(int rw, data, size, callback) сделал. Остальное — детали реализации драйвера, нечего им наружу просачиваться. Любой клиент, криво владея твоей структурой, может порушить драйвер.
Re[2]: Хранение управляющей структуры в вызывающем объекте
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 20.09.23 17:53
Оценка:
Здравствуйте, andyp, Вы писали:

A>Я бы в интерфейсе драйвера функцию request(int rw, data, size, callback) сделал.


А я бы еще машину состояний делал на плюсовом объекте с методами, а не на сишной структуре с функциями.
Re[3]: Хранение управляющей структуры в вызывающем объекте
От: andyp  
Дата: 20.09.23 18:01
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>А я бы еще машину состояний делал на плюсовом объекте с методами, а не на сишной структуре с функциями.


да там непонятно, может на С все пишется. А так, я бы еще из request хотя бы номер запроса, присвоенный драйвером, возвращал, а когда драйвер callback дергает, совал бы его туда в качестве аргумента. Так пользовательский код сможет отследить выполнение конкретных своих запросов. Оно, конечно, и так можно жить, подсовывая разные коллбэки разным запросам, но с номерами мне больше нравится.
Re[2]: Хранение управляющей структуры в вызывающем объекте
От: cppguard  
Дата: 20.09.23 19:32
Оценка:
Здравствуйте, andyp, Вы писали:

A>Не очень имхо. Я бы в интерфейсе драйвера функцию request(int rw, data, size, callback) сделал. Остальное — детали реализации драйвера, нечего им наружу просачиваться. Любой клиент, криво владея твоей структурой, может порушить драйвер.


Суть проблемы в том, что шина очень медленная, а драйвер работает через прерывание, которое срабатывает, когда состояние шины меняется. И хочется клиентам дать неблокирующийся доступ к функциям драйвера. Самый простой вариат — односвязный список, где каждый элемент хранит буфер для приёма или отправки данных. Но руками оперировать памятью не хочется, потому что у нас даже кучи нормальной нет — микроконтроллер. Проблемы с владением могут быть, но такой пример проще будет написать искуственно, чем он всплывёт в реальной программе.
Re[3]: Хранение управляющей структуры в вызывающем объекте
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 20.09.23 19:44
Оценка:
Здравствуйте, cppguard, Вы писали:

C>односвязный список, где каждый элемент хранит буфер для приёма или отправки данных.


Сколько таких элементов может быть в одном списке?

C>Проблемы с владением могут быть, но такой пример проще будет написать искуственно


Да понятно, что при аккуратном подходе риск минимальный. Но, если уж такое делать, то добавить в отладочную сборку какие-нибудь проверочные поля, и менять/проверять и в клиенте, и в драйвере.
Re[4]: Хранение управляющей структуры в вызывающем объекте
От: cppguard  
Дата: 20.09.23 21:01
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Сколько таких элементов может быть в одном списке?


По одной записи на каждое устройство. Например, висит на шине I2C дисплей, компас, акселерометр и датчик влажности. Вот будет 4 узла — максимум.
Re[3]: Хранение управляющей структуры в вызывающем объекте
От: andyp  
Дата: 20.09.23 21:33
Оценка:
Здравствуйте, cppguard, Вы писали:

C>Суть проблемы в том, что шина очень медленная, а драйвер работает через прерывание, которое срабатывает, когда состояние шины меняется. И хочется клиентам дать неблокирующийся доступ к функциям драйвера. Самый простой вариат — односвязный список, где каждый элемент хранит буфер для приёма или отправки данных. Но руками оперировать памятью не хочется, потому что у нас даже кучи нормальной нет — микроконтроллер. Проблемы с владением могут быть, но такой пример проще будет написать искуственно, чем он всплывёт в реальной программе.


Блокировка там очень короткая будет — пока драйвер добавляет твою структуру в список запросов на обработку. Там всего-то несколько указателей заполнить имхо. Количество структур можно фиксированным сделать и держать пул свободных. Когда пул пустой, драйвер даёт отлуп на выполнение запроса. Памятью (той, на что указывает data в твоей структуре) могут и клиенты владеть, на контроллере проблем не будет, MMU-то нету. Ну я бы как-то так пил это всё.
Re[5]: Хранение управляющей структуры в вызывающем объекте
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 21.09.23 10:26
Оценка:
Здравствуйте, cppguard, Вы писали:

C>По одной записи на каждое устройство. Например, висит на шине I2C дисплей, компас, акселерометр и датчик влажности. Вот будет 4 узла — максимум.


Я о том, сколько машине состояний драйвера реально необходимо отдельных записей для обработки запросов клиентов. Состояние самой машины достаточно хранить в объекте, представляющем устройство/соединение — его создает клиент. Если в запросе на чтение/запись только один участок (буфер) данных, то адрес, размер и указатель логично положить туда же. Список из неопределенного количества описателей имеет смысл, когда клиент в одном запросе может указать несколько участков/буферов, разные виды операций и т.п., но у Вас такого, как я понял, не предусмотрено.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.