|
|
  |
Структуры данных |
|
|
|
Jan 18 2018, 10:25
|
Профессионал
    
Группа: Свой
Сообщений: 1 508
Регистрация: 26-06-06
Из: Киев
Пользователь №: 18 364

|
Примерно так: Код typedef union //rx_tx_packet_union { unsigned char buffer[SIZE_RX_TX_BUFFER]; /// принимаемые короткие short_rx_input sh_rx; // короткая посылка приема tag_packet_check_struct tag_check; tag_packet_prog_struct tag_prog; // tag_packet_password_struct tag_password; /// принимаемые длинные long_rx_input lg_rx; // длинная посылка приема /// передаваемые короткие short_tx_output sh_tx; // короткая посылка передачи master_packet_struct master_send; //
/// передаваемые длинные // long_tx_output lg_tx; // длинная посылка передачи }rx_tx_packet_union; Ну и пример парочки структур: Код typedef struct // short_rx_input { unsigned char data[2][3]; // unsigned char parity[2][3]; // }short_rx_input;
typedef struct //tag_packet_check_struct { unsigned long rnd :8; // unsigned long low_bat :1; // unsigned long button :1; // unsigned long cnt :22; // unsigned int signature; // }tag_packet_check_struct;
|
|
|
|
|
Jan 18 2018, 17:28
|
Участник

Группа: Участник
Сообщений: 40
Регистрация: 20-05-12
Из: Санкт-Петербург
Пользователь №: 71 932

|
Не очень понял вопрос. Нужно как то хранить посылки разной длины? Список списков подойдет?
|
|
|
|
|
Jan 18 2018, 17:51
|

Просто Che
    
Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881

|
Цитата(inventor @ Jan 18 2018, 12:02)  я хочу реализовать какой то хранитель или тип для данных разного размера пример: по COM порту приходит пачка данных размером от 10 до 1000 байт. я хочу положить их в свою структуру данных данные разного размера Если вы хотите статический буфер, то придется выделять память под максимальный размер данных. Далее применять union, как расписал ArtemKADЕсли же вы хотите каждый раз иметь буфер различной длины по размеру пришедшего пакета, то применяйте динамическое выделение памяти из heap, при помоши malloc/free. В первом слове буфера храните длину данных, указатель на буфер передавайте в другой поток для чтения. Семафоры не забудьте.
|
|
|
|
|
Jan 19 2018, 07:42
|
Знающий
   
Группа: Свой
Сообщений: 524
Регистрация: 25-12-08
Из: Москва
Пользователь №: 42 748

|
Цитата(Baser @ Jan 18 2018, 20:51)  Если вы хотите статический буфер, то придется выделять память под максимальный размер данных. Далее применять union, как расписал ArtemKAD
Если же вы хотите каждый раз иметь буфер различной длины по размеру пришедшего пакета, то применяйте динамическое выделение памяти из heap, при помоши malloc/free. В первом слове буфера храните длину данных, указатель на буфер передавайте в другой поток для чтения. Семафоры не забудьте. похоже придется сделать кольцевой буфер на максимальное число с malloc/free мне не нравится-так как засегментируется все за час при интенсивном использовании
|
|
|
|
|
Jan 19 2018, 10:14
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(inventor @ Jan 19 2018, 10:42)  кольцевой буфер на максимальное число Зачем кольцевой? Почему не линейный? Приняли посылку разной длины - разобрали, начиная с начала (сохраняя поля в структуру), поставили указатель на начало, начали опять принимать. Если нужно принимать во время разбора - можно принимать в другой буфер, все равно в обоих случаях размер памяти не меняется. Протокол обмена стандартный или самопал?
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Jan 19 2018, 10:57
|
Профессионал
    
Группа: Свой
Сообщений: 1 508
Регистрация: 26-06-06
Из: Киев
Пользователь №: 18 364

|
Цитата Зачем кольцевой? Почему не линейный? Приняли посылку разной длины - разобрали, Пока разбираешь, пару-тройку байт из потока теряешь. Что-бы не терять за время разбора кольцевой буфер и нужен. Цитата можно принимать в другой буфер, все равно в обоих случаях размер памяти не меняется. Меняется. Кольцевой буфер обычно гораздо меньше основного.
|
|
|
|
|
Jan 20 2018, 17:57
|

I WANT TO BELIEVE
     
Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751

|
Ну имеется ввиду, что существуют разные архитектуры процессоров. С разными требованиями по выравниванию данных. И даже с разным расположением байт в многобайтовых интах. Таким образом описанная абсолютно одинаково на языке Си структура будет представлена в памяти совершенно по-разному! Если обе системы и для приёма и для передачи будут применять простое копирование этого региона памяти в линию передачи данных то при неудачном стечении обстоятельств вы прините совсем не то что вам отправляли. Например STM8 big endian - вообще редкость, скажем так. На AVR требований по выравниванию нет и все поля структуры лягут в память по порядку без дыр. На STM32 же между uint8 и uint32 в структуре будет padding т.е. дыра. Всё это не важно пока и приёмник и передатчик работают на одном процессоре(точнее с одинаковым порядком байт и требованиями по выравниванию). Кажется в этой статье можно найти что-то полезное на эту тему. https://thatskriptkid.wordpress.com/2015/01...80%D1%83%D0%BA/И вот что-то нашел https://habrahabr.ru/company/xakep/blog/258959/
--------------------
The truth is out there...
|
|
|
|
|
Jan 20 2018, 21:12
|
Профессионал
    
Группа: Свой
Сообщений: 1 508
Регистрация: 26-06-06
Из: Киев
Пользователь №: 18 364

|
Цитата(sigmaN @ Jan 20 2018, 19:57)  Ну имеется ввиду, что существуют разные архитектуры процессоров. С разными требованиями по выравниванию данных. И даже с разным расположением байт в многобайтовых интах. Таким образом описанная абсолютно одинаково на языке Си структура будет представлена в памяти совершенно по-разному! Если обе системы и для приёма и для передачи будут применять простое копирование этого региона памяти в линию передачи данных то при неудачном стечении обстоятельств вы прините совсем не то что вам отправляли.
Например STM8 big endian - вообще редкость, скажем так. На AVR требований по выравниванию нет и все поля структуры лягут в память по порядку без дыр. На STM32 же между uint8 и uint32 в структуре будет padding т.е. дыра. #pragma pack(1) или __packed для описания структуры вполне спасет от возможных дырок и будет гораздо проще чем заниматься сериализацией. Цитата(sigmaN @ Jan 20 2018, 19:57)  По-моему в этом "что-то" как раз написано почему сериализацию лучше не делать. По-моему весьма однозначно: Цитата WARNING
Если дорожишь эффективностью при передаче данных, то отдавай предпочтение бинарным протоколам (если, конечно, у тебя есть выбор).
|
|
|
|
|
Jan 21 2018, 11:58
|

I WANT TO BELIEVE
     
Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751

|
#pragma pack(1) вроде как моветон, на сколько я знаю. Я приведенные ссылки полностью не читал, но в моем понимании бинарность протокола не исключает нормальной сериализации структур и приведения протокола к стандартному порядку байт... Передавать всё в JSON я не предлагал на маленьком контроллере ) Цитата In computer science, in the context of data storage, serialization is the process of translating data structures or object state into a format that can be stored (for example, in a file or memory buffer) or transmitted (for example, across a network connection link) and reconstructed later (possibly in a different computer environment).[1] When the resulting series of bits is reread according to the serialization format, it can be used to create a semantically identical clone of the original object. В предложенном выше в топике подходе, для сериализации тупо используется memcpy из структуры в буфер->линия передачи данных->буфер->memcpy в union. Со всеми вытекающими последствиями о которых я говорил ранее. По идее вы должны вместо memcpy() реализовать некий метод serialize() который структуру преобразует в поток байтов в соответствии с принятым стандартом(serialization format). На приёмнике обратное преобразование. И никто не запрещает сделать этот протокол бинарным. Передача чего-то вроде JSON или строк - всего лишь частный случай serialization format.
--------------------
The truth is out there...
|
|
|
|
|
Jan 22 2018, 00:01
|
Профессионал
    
Группа: Свой
Сообщений: 1 508
Регистрация: 26-06-06
Из: Киев
Пользователь №: 18 364

|
Цитата(sigmaN @ Jan 21 2018, 13:58)  #pragma pack(1) вроде как моветон, на сколько я знаю. Плохо знаешь. Моветон использовать его для рабочих переменных из-за оверхеда в коде при работе на 32 разрядных платформах. А там где надо что-бы было как написано, а не как оптимизатор посчитал нужным, там ему самое место. Цитата(sigmaN @ Jan 21 2018, 13:58)  Я приведенные ссылки полностью не читал, но в моем понимании бинарность протокола не исключает нормальной сериализации структур и приведения протокола к стандартному порядку байт... Передавать всё в JSON я не предлагал на маленьком контроллере ) Ну если не JSON, то ваять придется нечто свое. А значит вставлять дополнительные поля в передаваемые данные с метаинформацией и разбирать метаинформацию на приемном конце и все это писать своими руками. И что это поменяет кроме оверхеда в передаваемых данных, оверхеда в коде и оверхеда во времени обработки? Теперь надо особо обрабатывать не только на отдельных платформах, а обрабатывать метаинформацию в рантайме на всех платформах. Цитата(sigmaN @ Jan 21 2018, 13:58)  По идее вы должны вместо memcpy() реализовать некий метод serialize() который структуру преобразует в поток байтов в соответствии с принятым стандартом(serialization format). На приёмнике обратное преобразование. И никто не запрещает сделать этот протокол бинарным. Передача чего-то вроде JSON или строк - всего лишь частный случай serialization format. По-моему, у топикстартера как раз работа и состоит в том, что приходит некий поток данных который надо разобрать. Т.е. вашим языком - у него вопрос по реализации самой "deserialize()"
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|