Обычно вы используете подход сдвига битов, потому что многие микросхемы не позволяют копировать, например, 4-байтовое целое число в нечетный адрес байта (или, точнее, в набор из 4 байтов, начиная снечетный адрес байта).Это называется выравниванием.Если переносимость является проблемой, или если ваш DSP не разрешает несогласованный доступ, то необходимо смещение.Если ваш DSP подвергается значительному снижению производительности при неправильном выравнивании доступа, вы можете беспокоиться об этом.
Однако я бы не стал писать код со сдвигами для различных типов, сделанных от руки, как показано.Я ожидал бы использовать функции (возможно, встроенные) или макросы для обработки как сериализации, так и десериализации данных.Например:
unsigned char dataTx[1024];
unsigned char *dst = dataTx;
dst += st_int2(short1, dst);
dst += st_int4(int1, dst);
dst += st_char(str, len, dst);
...
В функциональной форме эти функции могут быть:
size_t st_int2(uint16_t value, unsigned char *dst)
{
*dst++ = (value >> 8) & 0xFF;
*dst = value & 0xFF;
return 2;
}
size_t st_int4(uint32_t value, unsigned char *dst)
{
*dst++ = (value >> 24) & 0xFF;
*dst++ = (value >> 16) & 0xFF;
*dst++ = (value >> 8) & 0xFF;
*dst = value & 0xFF;
return 4;
}
size_t st_char(unsigned char *str, size_t len, unsigned char *dst)
{
memmove(dst, str, len);
return len;
}
Конечно, такие функции делают код скучным;с другой стороны, они также снижают вероятность ошибок.Вы можете решить, должны ли имена быть st_uint2()
вместо st_int2()
- и, действительно, вы можете решить, должны ли длины быть в байтах (как здесь) или в битах (как в типах параметров).Пока вы последовательны и скучны, вы можете делать как хотите.Вы также можете объединить эти функции в более крупные, которые упаковывают целые структуры данных.
Операции маскирования (& 0xFF
) могут не потребоваться в современных компиляторах.Когда-то давным-давно я, кажется, помнил, что они были необходимы, чтобы избежать случайных проблем с некоторыми компиляторами на некоторых платформах (поэтому у меня есть код 1980-х годов, который включает такие операции маскирования).Упомянутые платформы, вероятно, успокоились, поэтому, с моей стороны, это может быть чистой паранойей, что они (все еще) там.
Обратите внимание, что эти функции передают данные в порядке с прямым порядком байтов.Функции можно использовать «как есть» как на машинах с прямым порядком байтов, так и на машинах с прямым порядком байтов, и данные будут правильно интерпретироваться для обоих типов, поэтому вы можете использовать различные аппаратные средства для передачи данных по проводам, используя этот код, и будетнет недопонимания.Если у вас есть значения с плавающей точкой для передачи, вам нужно немного больше беспокоиться о представлениях по проводам.Тем не менее, вам, вероятно, следует стремиться к тому, чтобы данные передавались в независимом от платформы формате, чтобы взаимодействие между типами микросхем было как можно более простым.(Именно поэтому я использовал размеры типов с числами в них; в частности, 'int' и 'long' могут означать разные вещи на разных платформах, но 4-байтовое целое число со знаком остается 4-байтовым целым числом со знаком, даже если выне повезло - или повезло - достаточно иметь машину с 8-байтовыми целыми числами.)