This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Problem with size of structers

Hi anybody

I declare the folowing stuctures:

typedef struct {
    ubyte	bLength;
    ubyte	bDescriptorType;
    ubyte	bInterfaceNumber;
    ubyte	bAlternateSetting;
    ubyte	bNumEndpoints;
    ubyte	bInterfaceClass;
    ubyte	bInterfaceSubClass;
    ubyte	bInterfaceProtocol;
    ubyte	iInterface;
} USB_interface_desc_t;

typedef struct {
    ubyte	bLength;
    ubyte	bDescriptorType;
    uword	wTotalLength;
    ubyte	bNumInterfaces;
    ubyte	bConfigurationValue;
    ubyte	iConfiguration;
    ubyte	bmAttributes;
    ubyte	MaxPower;
} USB_config_desc_t;


typedef struct {
    ubyte	bLength;
    ubyte	bDescriptorType;
    struct {
	ubyte address:4;
	ubyte reserved:3;
	ubyte direction:1;
    } bEndpointAddress;
    ubyte	bmAttributes;
    uword	wMaxPacketSize;
    ubyte	bInterval;
} USB_endpoint_desc_t;

typedef struct {
    USB_config_desc_t	usb_dev_config_desc;
    USB_interface_desc_t	usb_interface_0_alt_0_desc;
    USB_endpoint_desc_t	usb_dev_endpoint_alt_0_desc[2];
} USB_long_config_desc_t;

When I use the sizeof I obtain folowing values:

sizeof(USB_long_config_desc_t) = 0x24
sizeof(USB_endpoint_desc_t) = 0x08
sizeof(USB_interface_desc_t) = 0x09
sizeof(USB_config_desc_t) = 0x0A


What happens and what is wrong?

Thanks

Aram

  • Does C166 insert "padding" bytes? - check the manual.

  • If I understood it correctly, there are pad bytes in structures.
    But still there is a problem. I am trying to establish communication with
    PC (Windows 98) via USB port, and with this pad bytes I need to know
    how to do that if the first sizeof(USB_interface_desc_t) returns 0x09,
    but actually 10 bytes were sent and second sizeof(USB_endpoint_desc_t)
    in C166 returns 0x08, while on PC side this structure has size of 7 bytes,
    and standard Windows DDK function for USB can't properly receive
    Endpoints information.

    I need help ASAP!!!!!

  • I am not familiar with Keil's C166 product, but usually if a compiler adds padding within a structure, it also provides a mechanism for controlling the padding. The control is usually in the form of a #pragma. Check the manual for #pragma support. Search the manual for "padding" or "packing".

  • Thanks guys

    The directive
    #pragma pack(1) /* byte alignment */
    #pragma BYTEALIGN

    works fine even on C166 version 4.05, witch I have.

  • " I am trying to establish communication with PC (Windows 98)"

    Welcome to the world of cross-platform interworking!

    If you're going to try to use 'C' structures to map language types onto the communications frame/packet format, you are going to have to study the manuals for both platforms very carefully - playing particular attention to data sizes, endianness, packing, alignments, and all the other implementation-specific details.

    Don't forget that Win98 runs on 32-bit Intel x86 architecture, and there is no guarantee that the data representation will match Keil's implementation on the 16-bit(?) C16x/ST10 - in fact, it's more likely that they won't match! :-(

  • Rather than try to force your system(s) to work with mis-aligned data - which could well be grossly inefficient - it might be better to have your driver(s) parse the communication packets into sutiable target-friendly structures?

  • When I work with controllers that "prefer" word alignments, I always make the length of structures even (insert a dummy char at the end if required) <b<and make sure all ints start after an even number of bytes. Even if this were to be transferred to a controller that did not care about alignment, no harm would be done.

     7* ubyte
        ubyte	bInterfaceProtocol;
        ubyte	iInterface;
        ubyte       bdummy
    } USB_interface_desc_t;
    
    6*  ubyte
        ubyte	MaxPower;
        ubyte       bdummy
    } USB_config_desc_t;
    

    etc


    Erik

  • "...controllers that "prefer" word alignments..."

    Don't forget that the PC is a 32-bit architecture these days, so there are alignment issues with both 16- and 32-bit "objects!"


  • While we're on the topic, I notice there are some bitfield declarations in the structure. Bitfield endianess (that is, whether they are allocated from the LSB first or MSB first) is implementation-specific, and is independent of multi-byte word endianness. Given the fragment

    struct
       {
       ubyte myBits:4;
       ubyte myOtherBits:4;
       } nibble;
    
       nibble.myBits = 0xF;
       nibble.myOtherBits = 0;
    

    nibble might wind up looking like either 0xF0 or 0x0F. So check the manuals or write a little test.

    ANSI also says that bitfields are always part of an 'int', so there's a potential portability issue for bitfields in other sizes like bytes. Most embedded compilers will let you specify other sizes for bitfields, but it's non-standard behavior.

    Oddly enough, even though ANSI-standard bitfields are "ints", whether or not they are signed is also left up to the implementation. int myBit:1 may take on the values 0 and 1, or 0 and -1, depending on your compiler. Plain "int" doesn't necessarily mean "signed int" in the context of bitfields (unlike its normal meaning), and if you have a concern for portability or even just clarity, you might want to always specify "signed int" or "unsigned int" to be sure.