c - Initializing, constructing and converting struct to byte array causes misalignment -


i trying design data structure (i have made shorter save space here think idea) used byte level communication:

/* packet.h */     #define cm_header_size          3 #define cm_data_size            16 #define cm_footer_size          3 #define cm_packet_size       (cm_header_size + cm_data_size + cm_footer_size) // + other definitions  typedef struct cm_header{     uint8_t       packetstart;   //start indicator 0x5b [   uint8_t       deviceid;       //id of device sending   uint8_t       packettype; } cm_header;  typedef struct cm_footer {   uint16_t      datacrc;        //crc of 'data' part of cm_packet   uint8_t       packetend;      //should 0x5d or ] } cm_footer;  //here trying conver few u8[4] tp u32 (4*u32 = 16 byte, hence data size) typedef struct cm_data {   union {       struct{         uint8_t           value_0_0:2;         uint8_t           value_0_1:2;         uint8_t           value_0_2:2;         uint8_t           value_0_3:2;                 };     uint32_t              value_0;   };   //same thing value_1, 2 , 3 } cm_data;  typedef struct cm_packet {   cm_header header;   cm_data data;   cm_footer footer; } cm_packet;  typedef struct cm_inittypedef{   uint8_t               deviceid;   cm_packet             packet;         } cm_inittypedef;  typedef struct cm_appendresult{   uint8_t result;   uint8_t reason; } cm_appendresult;  extern cm_inittypedef cmhandler; 

the goal here make reliable structure transmitting data on usb interface. @ end cm_packet should converted uint8_t array , given data transmit register of mcu (stm32).

in main.c file try init structure other stuff related packet:

/* main.c */ uint8_t packet[cm_packet_size]; int main(void) {     //use extern defined in packet.h init struct     cmhandler.deviceid = 0x01; //assign device id     cm_init(&cmhandler); //construct handler     //rest of stuff         while(1) {         cm_getpacket(&cmhandler, (uint8_t*)packet);         cdc_transmit_fs(&packet, cm_packet_size);     } } 

and here implementation of packet.h screws bad. added packet[cm_packet_size] watch being generated randomly. pure luck can see in array of values interested in! 1% of time!

/* packet.c */ cm_inittypedef cmhandler;  void cm_init(cm_inittypedef *cm_initer) {   cmhandler.deviceid = cm_initer->deviceid;    static cm_packet cmpacket;   cmpacket.header.deviceid = cm_initer->deviceid;   cmpacket.header.packetstart = cm_start;   cmpacket.footer.packetend = cm_end;   cm_initer->packet = cmpacket; }  cm_appendresult cm_appenddata(cm_inittypedef *handler, uint8_t identifier,                                uint8_t *data){          cm_appendresult result;      switch(identifier){       case cm_value_0:         handler->packet.data.value_0_0 = data[0];         handler->packet.data.value_0_1 = data[1];         handler->packet.data.value_0_2 = data[2];         handler->packet.data.value_0_3 = data[3];         break;         //also cases cm_value_0, 1 , 2        //to build cm_data sturct of cm_packet      default:       result.result = cm_append_failure;       result.reason = cm_append_case_error;       return result;       break;      }          result.result = cm_append_success;     result.reason = 0x00;     return result; }  void cm_getpacket(cm_inittypedef *handler, uint8_t *packet){     //copy whole struct in given buffer , later send usb host     memcpy(packet, &handler->packet, sizeof(cm_packet_size)); } 

so, problem code gives me 99% of time random stuff. never has cm_start start indicator of packet value want to. of time has cm_end byte correctly! got confused , cant find out reason. being working on embedded platform hard debugg kind of lost here...

if transfer data (different) architecture, not pass structure blob. way hell: endianess, alignment, padding bytes, etc. can (and will) cause trouble.

better serialize struct in conforming way, possily using interpreted control stream not have write every field out manually. (but still use standard functions generate stream).

some areas of potential or trouble:

  • cm_footer: second field might start @ 32 or 64 bit boundary, preceeding field followed padding. also, end of struct padded @ least 1 bytes on 32 bit architecture allow proper alignment if used in array (the compiler not care if need this). might 8 byte aligned.
  • cm_header: here (not guaranteed) 1 uint8_t 4*2 bits ordering not standardized. field followed 3 unused bytes required uint32_t interprettion of union.
  • how guarantee same endianess (for >uint8_t: high byte first or low byte first?) host , target?
  • in general, structs/unions need not have same layout host , target. if same compiler used, abis may differ, etc. if same cpu, there might other system constraints. also, cpus, different abis (application binary interface) exist.

Comments

Popular posts from this blog

facebook - android ACTION_SEND to share with specific application only -

python - Creating a new virtualenv gives a permissions error -

javascript - cocos2d-js draw circle not instantly -