bit fields with pragma packed still generates pad nibbles in 16 bit case.

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

bit fields with pragma packed still generates pad nibbles in 16 bit case.

Jump to solution
2,778 Views
Leong
Contributor III

Folks,

 

I'm using CW7.1 for codefire 5225x to generate some byte streams. in the definition document, it asks for 2 consecutive 12 bit numbers that takes 3 bytes. so i used the code below (simplified) but it seems the sizeof is 4 bytes instead of 3. if I assign foo and bar with 0x1111, they show up in the stream as 0x1110, which means a padding nibble is added to each var..

 

any recommendations other than split the 2 vars into 2 int8 + 2 nibbles?

 

#pragma options align=packed

typedef struct

{

  int16_t     foo:12 ;       

  int16_t     bar:12 ;

}

expect_3_byte_t;

 

thanks in advance.

 

Leong

 

Labels (1)
0 Kudos
Reply
1 Solution
2,008 Views
bigmac
Specialist III

Hello Leong,

I think that the main issue here is that there are no 12-bit or 24 bit types in C.  Therefore either 16-bit or 32-bit types need to be used to fit the data, and will obviously include padding bits.  Since the C standard does not define how a compiler should pack the bits within a bitfield, the current packing arrangement by the CW compiler, within a 16 bit multiple, would seem to make a lot of sense because it would produce the most efficient access to each bitfield element, with no compromise on the total size of the bit field.  Any other arrangement, such as your packing requirement, would involve additional implicit arithmetic to access each element, with a reduction of efficiency.

My understanding is that the MISRA standard does also not condone the use of bitfields.  This would mean that you will need to provide either a function or a macro that uses explicit arithmetic to pack the data in the required manner.  In your case, the 24 bits could be either left-aligned or right-aligned within the 32 bit type.  The following functions do not use either a bitfield or a union.

dword packR24( word high12, word low12)  // Right aligned result
{
  return ((dword)high12 << 12) | (low12 & 0x0FFF);
}

dword packL24( word high12, word low12)  // Left aligned result
{
  return packR24( high12, low12) << 8;
}

  result = packL24( foo, bar);

  result = packR24( foo, bar);

#define get_fooR(x) (word)((x) >> 12)

#define get_barR(x) (word)((x) & 0x0FFF)

#define get_fooL(x) (word)((x) >> 20)

#define get_barL(x) (word)((x) >> 8) & 0x0FFF

  foo = get_fooR( result);

  bar = get_barR( result);

  

Regards,

Mac

View solution in original post

0 Kudos
Reply
5 Replies
2,008 Views
Monica
Senior Contributor III

Hello Leong!

How is the project going, were you able to try that suggestion?

Please keep us posted, we'd like to know! :smileywink:

Best regards,

Monica

0 Kudos
Reply
2,008 Views
bigmac
Specialist III


Hello Leong,

The padding bits inserted into a bit field will be compiler dependent.  See if the following alternative method, using a union, will work for you.

typedef union {

  byte array[3];

  struct {

    word high16;

    byte low8;

  } seq16_8;

  struct {

    byte high8;

    word low16;

  } seq8_16;

} PACK24;

 

word foo = 0x0ABC;

word bar = 0x0DEF;

PACK24 three_byte;

  three_byte.seq16_8.high16 = foo << 4;

  three_byte.seq16_8.low8 = 0;

  three_byte.seq8_16.low16 |= bar & 0x0FFF;

Regards,

Mac

2,008 Views
Leong
Contributor III

Mac,

Thanks for the reply. Yes this would work but there are 2 reasons that I can not use this in the code: 1 no direct reference to foo or bar in the code, it would always require arithmetic before referencing to the variables. 2. MISRA C does not like the usage of union.... (misra is an automotive programming standard)...

so i've been negotiating with the other party to change the protocol.... in case there is no direct solution to this issue...

any one from the freescale compiler team can verify if this is a limitation or there is a way to get around in the code generation?

Thanks

Leong

0 Kudos
Reply
2,009 Views
bigmac
Specialist III

Hello Leong,

I think that the main issue here is that there are no 12-bit or 24 bit types in C.  Therefore either 16-bit or 32-bit types need to be used to fit the data, and will obviously include padding bits.  Since the C standard does not define how a compiler should pack the bits within a bitfield, the current packing arrangement by the CW compiler, within a 16 bit multiple, would seem to make a lot of sense because it would produce the most efficient access to each bitfield element, with no compromise on the total size of the bit field.  Any other arrangement, such as your packing requirement, would involve additional implicit arithmetic to access each element, with a reduction of efficiency.

My understanding is that the MISRA standard does also not condone the use of bitfields.  This would mean that you will need to provide either a function or a macro that uses explicit arithmetic to pack the data in the required manner.  In your case, the 24 bits could be either left-aligned or right-aligned within the 32 bit type.  The following functions do not use either a bitfield or a union.

dword packR24( word high12, word low12)  // Right aligned result
{
  return ((dword)high12 << 12) | (low12 & 0x0FFF);
}

dword packL24( word high12, word low12)  // Left aligned result
{
  return packR24( high12, low12) << 8;
}

  result = packL24( foo, bar);

  result = packR24( foo, bar);

#define get_fooR(x) (word)((x) >> 12)

#define get_barR(x) (word)((x) & 0x0FFF)

#define get_fooL(x) (word)((x) >> 20)

#define get_barL(x) (word)((x) >> 8) & 0x0FFF

  foo = get_fooR( result);

  bar = get_barR( result);

  

Regards,

Mac

0 Kudos
Reply
2,008 Views
Leong
Contributor III

Mac,

Thanks for diving into this... I will buy that explanation on the C intrinsic types only has 8 16 32 64 bits now that i think about the compiler complexity if they were to support nibbles... I've seen some other compiler does have 12 bit or 24 bit internal alignment (may be TI?) but mw may not... I wouldn't call this a bug but need to confirm with some documentation (could not find the exact compiler behavior in such case under the #pragma  packed doc)....

Yes Misra is ok with bit-field just not with the union type. I would need to write a couple of accessors to do a 'simple get/set' to the vars as you suggested. At the same time, i have explained to the customer and see if they can move around other bit field definitions to fill the nibbles instead of using 3 consecutive 12bits..

Thanks again

leong

0 Kudos
Reply