Перейти к содержанию
    

Плавный переход C -> C++ под МК

9 часов назад, _pv сказал:

для месье понимающих толк, С вроде как умеет вот так:

int get_data_size(){ return 0xF + (rand() & 0xF);}

int main(){
  struct { uint8_t hdr[8]; uint8_t byte[get_data_size()]; uint32_t crc; } *pkt = (void*)data;
  pkt->crc = 42;
...

Это будет подтягивать динамическое выделение памяти, такое меня уже не устроит.

Ух тут сколько всего написали (это хорошо, дискуссия жива🙂) - однако я внесу немножко понятностей. Не важно, что за протокол, важно то, что он пакетный: длина пакета выкорчевывается внеполосной сигнализацией на уровне проводов или (для примитивных байтовых интерфейсов) промежуточный канальный фреймер разбирает поток байтов на кадры/пакеты. Короче говоря, я всегда знаю, сколько данных мне прилетело в пакете. Пакет, как обычно, уже содержит заголовок со всякими типами содержимого для идентификации этого пакета и т.д. Шмалять в сеть пакеты фиксированной длины здесь очень избыточно - это точно красный флаг.

Так вот. У меня девайс состоит из множества плат, каскадно соединенных друг с другом порой сильно разными интерфейсами. Пакет данных со входа до самой дальней платы может пройти пару-тройку интерфейсных мостов со своими протокольно-зависимыми особенностями. Каждая "промежуточная" плата имеет механизм проброса "не своих" пакетов данных туда дальше в "паровозик". Чтобы облегчить ПО каждой платы, она детально даже не разбирает "не свои" пакеты, а как есть его пересылает дальше. Где-то закладывать CRC не имело бы смысла, а где-то, из-за этого "прозрачного режима", CRC пакету нужен. Например: девайс состоит из двух плат (1) и (2), между ними прокинут UART. С платы (1) наружу девайса торчит Ethernet, воткнутый в комп. С компа шлю данные плате (2) - и, казалось бы, езернет уже гарантирует целостность своего фрейма, т.е. можно не вносить контрольную сумму для данных, но данные ведь предназначены плате (2), а чтобы туда попасть, данные должны преобразоваться в UART платой (1) и транслироваться на плату (2). Этот UART - байтовый, поэтому поверх него работает SLIP. Но для контроля целостности данных на приеме платой (2) пакет нужно долполнить контрольной суммой. Что и делает сразу отправляющая сторона перед засовыванием в езернет.

Насчет положения CRC в структуре: да, можно в хедер ее пихнуть. Однако это маааленький такой костыль с тасованием расположения, который конкретно в данном случае вполне поможет (за счет наличия в Си и (с позволения компиляторов) C++ FAM в структурах). Да, удобно, если КС в конце - сверил - и результат будет 0. Оданко по затратам на вычисление это будет почти один-в-один с пробегом по хедеру и по данным и последующим сравнением полученной КС с той, что в хедере лежит (в случае размещения КС в хедере). Исторически у меня так завелось, что хедеры могут быть разных размеров, и поэтому КС размещалась строго в конце, несмотря на то, что размер кадра плавающий. Меня полностью устраивает этот вариант и поныне. И я хотел, чтобы несколько "костыльно" выглядящее определение структуры с гибким массивом в конце наконец обрело лаконичный вид в C++. Мне не нужна динамическая память - мне нужно как-то сказать компайлеру, чтобы на статически выделенном куске создавал структуру, в которой после гибкого массива расположен еще какой-то элемент. Условно, чтобы это выглядело примерно так (как я это вижу):

struct FlexFrame {
  Header hdr;
  u8     data[];                        // <- гибкий массив, а значит дальше можно ставить только элементы с атрибутом "гибкого положения"
  u32    crc __attribute__((flexible)); // положение этого члена "гибкое", в зависимости от объема поля data при создании структуры
};

...

static u8 RxPacketMemory[1024]; // статически выделенная память для создания "гибких" структур

// вызвали с len == 10
void sendPacket(u32 len) {
  // тут нужен был бы синтаксис объявления структуры, например
  FlexFrame frame __attribute__((RxPacketMemory, len)); // компилятор думает, что frame имеет data[10], размещая frame в памяти RxPacketMemory
  
  frame.crc = ...; // компилятор для доступа к полю crc использует соответствующее смещение, полученное на основе аргумента функции
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, Arlleex said:

Это будет подтягивать динамическое выделение памяти, такое меня уже не устроит.

какое ещё выделение памяти??? это просто объявление указателя, на структуру. и он даже эти несчастные 4 байта под указатель на стэке выделять не будет, а просто посчитает адрес crc.

тоже самое что

uint8_t *pkt = data;

*(uint32_t*) &pkt[crc_offset] = 42;

только crc_offset компилятор посчитает в рантайме, исходя из подсунутого в объявление типа структуры размера массива.

правда кроме gcc остальные скорее всего на vla внутри структуры ругаться будут.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 hours ago, Arlleex said:

И я хотел, чтобы несколько "костыльно" выглядящее определение структуры с гибким массивом в конце

А как идёт приём пакета, неужели побайтно, с прерыванием по приходу очередного байта?

Если всё-таки с использованием DMA, то вопрос не понятен, потому что как не крути, но нужно знать максимальный размер пакета, и тогда вопрос с гибким массивом в конце отпадает сам собой.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 17.04.2024 в 07:55, tonyk_av сказал:

потому что как не крути, но нужно знать максимальный размер пакета

ну допустим, в основном, 90% пакетов - это 10...20 байт. Но есть пакеты до 128 байт. Т.е. максимальный размер 128. Как это поможет?

 

В стандратном C++ нет прямой поддержки добавления переменных после fam в структуре. гибкий массив должен быть последним членом структуры. Но компиляторы могут поддерживать расширения, позволяющие размещать дополнительные члены после fam. Например, расширение GCC "Zero-Length Array" (ZLA) позволяет добавлять дополнительные члены после гибкого массива. 

struct FlexFrame {
  Header hdr;
  int length;
  u8     data[];                        // <- гибкий массив, а значит дальше можно ставить только элементы с атрибутом "гибкого положения"
  u32    crc; // положение этого члена "гибкое", в зависимости от объема поля data при создании структуры
};

использование таких расширений делает код нестандартным и не переносимым между различными компиляторами и платформами. Лучше избегать использования таких расширений и следовать стандарту C++.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 16.04.2024 в 23:55, Arlleex сказал:

несколько "костыльно" выглядящее определение структуры с гибким массивом в конце наконец обрело лаконичный вид в C++

структура в с++ это уже костыльно. Зачем в с++ в этом случае структура? 

В 15.04.2024 в 12:27, Arlleex сказал:

мне проще (как всегда, собственно) написать свой небольшой класс.

коль вы выехали из деревни, так и бросьте деревенские привычки переехали в с++, так и пишите на с++, пишите классы. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 часов назад, _pv сказал:

какое ещё выделение памяти??? это просто объявление указателя, на структуру. и он даже эти несчастные 4 байта под указатель на стэке выделять не будет, а просто посчитает адрес crc.

Прошу прощения, не обратил внимания, что указатель. Вы правы.

Однако да, мой компайлер обозвал меня представителем европейского модного движения за VLA внутри структуры:vava:

А так - это почти то, что я хотел🙂
 

3 часа назад, tonyk_av сказал:

А как идёт приём пакета, неужели побайтно, с прерыванием по приходу очередного байта?

Если всё-таки с использованием DMA...

А разница? В одном проекте - по прерываниям делал, в текущем - DMA принимает. Как это влияет на разбор байтового потока?

Цитата

... потому что как не крути, но нужно знать максимальный размер пакета, и тогда вопрос с гибким массивом в конце отпадает сам собой.

Зачем его знать? DMA настраивается в кольцевой режим. Задача, обслуживающая канал приема, читает эти байты и отдает его фреймеру SLIP-а, а тот уже на выходе выдает пакеты данных.
 

32 минуты назад, juvf сказал:

структура в с++ это уже костыльно. Зачем в с++ в этом случае структура?

Потому что структуру в ее самом девственном виде проще читать и давать ее другим разработчикам, дабы понимали ее формат при поддержке протоколов общения.

Когда передается 100500 разных классов, начиненных еще каким-то функционалом - становится вообще-то затруднительно сходу въехать в порядок разложения этой порнографии на байтики в реальном проводе.

Структура весьма самодокументируема - сразу понятно, что за чем идет. В классе, в котором помимо данных набито еще 100 строк всяких методов и перегрузок, разобраться тяжелее сходу.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 hours ago, Arlleex said:

Зачем его знать? DMA настраивается в кольцевой режим.

Можно и так.

 

3 hours ago, juvf said:

Но есть пакеты до 128 байт. Т.е. максимальный размер 128. Как это поможет?

Выделяете место под пакет максимальной длины. 128 байт- это не много. Приняли пакет- получили одно прерывание по RTO или IDLE. Дпльше уже разбираетесь с тем, что получили.

u8     data[ 128 ];

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 17.04.2024 в 12:58, tonyk_av сказал:

128 байт- это не много.

а с какой цифры начинается много? лично для меня и 128 бит много. Нужно массив в 10 байт - выделяем 128. 👍 

А потом почему-то памяти для какого нибудь регистратора не хватает или канал передачи в 1 Gb не прокачивает.  

В 16.04.2024 в 23:55, Arlleex сказал:
static u8 RxPacketMemory[1024]; // статически выделенная память для создания "гибких" структур

1024/128 = 8. +хидер, +кс, как итог максимально 7 пакетов в такой буфер влезет. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 hours ago, juvf said:

а с какой цифры начинается много?

Смотрите процент, которые составляют эти 128 байт от всего ОЗУ.


Конечно, можно с самого начала убиваться за каждый бит-байт. Вот когда не будет хватать памяти, тогда и будете думать, что делать: взять кристалл с бОльшим ОЗУ или заняться оптимизацией.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

19 minutes ago, tonyk_av said:

Конечно, можно с самого начала убиваться за каждый бит-байт.

ну вот и тут коснулись традиционной темы "религии", местные служители "Культа Экономии Драгоценного Бита" скоро прибудут )))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, Forger said:

местные служители "Культа Экономии Драгоценного Бита" скоро прибудут )))

Не хотел, чтобы из-за меня срач начался. Вроде, почти процитировал известное изречение уважаемого человека.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 4/17/2024 at 4:54 PM, tonyk_av said:

уважаемого человека.

Прочитал цитаты из приведенной вами ссылки.

Как по мне, так бред полнейший.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 minutes ago, dimka76 said:

Как по мне, так бред полнейший.

Или мир сошёл с ума, или кто-то чего-то недопонимает, потому что

Quote

На январь 2013 года Кнут занимал 37-е место в списке самых цитируемых авторов в области информатики согласно проекту CiteSeer[9].

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

19 часов назад, dimka76 сказал:

Прочитал цитаты из приведенной вами ссылки.

Как по мне, так бред полнейший.

Именно. Профессоры обычно только и печатали книжки, не имея ни малейшего представления о реальном коде.

Туда же книжки Макконела и Мартина - т.е. в жопито😉

Посмотрел цитаты великого цитируемого (с моими скромными комментами):

Цитата

Цитаты[править]

  • Лучший способ в чём-то разобраться до конца — это попробовать научить этому компьютер. - Вообще-то, ребенка.
  • Опасайтесь багов в приведенном коде; я доказал его корректность, но не запускал. - Крыша поехала? О чем ты, дядь?
  • Математические формулы не могут «принадлежать» кому-либо! Математика принадлежит Богу. - Беды с башкой, очевидно.
  • Я не могу заказать блюдо в ресторане потому, что постоянно смотрю на шрифты в меню. - Проф.деформация.
  • Самая важная вещь в языке программирования — его имя. Язык не будет иметь успеха без хорошего имени. Я недавно придумал очень хорошее имя, теперь осталось изобрести подходящий язык. - Без комментариев.
  •  

Давайте сменим традиционный подход к построению программ: будем считать, что наша цель — не дать указания компьютеру о ходе его работы, а объяснить человеку, что именно мы хотим добиться от компьютера. - Давайте.

18 часов назад, tonyk_av сказал:

Или мир сошёл с ума, или кто-то чего-то недопонимает, потому что

За любым столом после 3-й рюмки уже обычно начинаются пространные рассуждения о смысле жизни и трехэтажная философия.

Здесь из этого же разряда - просто потому, что "классики" больше никакой нет. За неимением цитируют вот таких вот деятелей.

P.S. И кстати, а причем тут щас вообще оптимизация? Я вроде о ней даже не говорил. Нет, ну я конечно стараюсь сразу более менее вменяемо подходить к написанию кода - т.е. там, где можно сразу сделать хорошо - делаю. Другой подход мне уже не приживется, ибо это, как и любовь к говнокодингу - либо навсегда, либо никогда. Сегодня вот на моем смартфоне при открытии камеры вываливалось сообщение "Невозможно подключиться к камере". Б%ять! И никакая перезагрузка не помогает. Калькулятор весит 100 мегов - скоро, видимо, и считать правильно перестанет. И так со всем программным, что меня окружает в нынешнем мире. Вот такая философия с преждевременной оптимизацией и породила покрасчиков кнопок, которым похрен на юзеров, которым для моргания лымпочкой нужна ардуина на распбери пай, не меньше.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...