= Using Bit-Fields in a MicroBlaze C Project = We use a very useful C programming tool in the [wiki:802.11 802.11 Reference Design] known as [http://en.wikipedia.org/wiki/Bit_field a Bit-Field]. Bits are not individually addressable in C. When unaligned access is enabled in a processor, the minimum addressable unit of data is a byte. Bit-fields provide a useful way of interpreting the bits that make up larger type definitions. They can help abstract away the low level bit shifts and bit masks needed for bit manipulation. This document is a tutorial on how to use bit-fields in MicroBlaze C projects. A typical situation where you might see a bit-field is a definition like the following: {{{ #!div style="font-size: 90%" {{{#!C /* * This is an example of a simple 1-byte bitfield with three members: A, B, and C * * Bit mask: * MSB _ _ _ _ _ _ _ _ LSB * C|-----B-----|A * * A, C are 1-bit flags. * B is a 6-bit integer. * */ typedef union{ u8 raw_value; struct __attribute__ ((__packed__)){ unsigned A :1; //b[0] unsigned B :6; //b[6:1] unsigned C :1; //b[7] }; } bitfield_example_type; }}} }}} The above type definition defines a bit-field named {{{bitfield_example_type}}}. There are four important features to notice in the above syntax: * A [http://en.wikipedia.org/wiki/Union_type union] is used between to designate that {{{raw_value}}} and the proceeding struct occupy the same space. * The {{{__attribute__ ((__packed__))}}} struct attribute informs the compiler that that each member of the structure should be placed such that the memory required is minimized. This minimizes the chances that the bit-field will be automatically padded to an unexpected length when it is placed into a larger structure with other elements. * By convention, {{{raw_value}}} is the same size as the proceeding struct (a single byte). If the code does not need to interpret the individual bits in the bit-field, it can instead access the fully byte itself by using {{{raw_value}}}. * In the struct definition, the {{{ :X }}} notation is used to tell the compiler that the element is {{{X}}} bits wide. {{{bitfield_example_type}}} defines three bit-fields: A, B, and C. B is a 6-bit integer that is surrounding by single-bit values A and C. Let's first define a function that will print this bit-field for us. This function will print the entire byte in hexadecimal and will then print the fields A, B, and C as decimal values. We'll use this function in the coming examples: {{{ #!div style="font-size: 90%" {{{#!C void print_bitfield_example_type(bitfield_example_type my_bitfield){ xil_printf("bitfield_example_type Contents:\n"); xil_printf(".raw_value = 0x%02x\n", my_bitfield.raw_value); xil_printf(".A = %d\n", my_bitfield.A); xil_printf(".B = %d\n", my_bitfield.B); xil_printf(".C = %d\n", my_bitfield.C); } }}} }}} == Case 1: Manually Initializing a Bit-field == One way to create and initialize a bit-field is to manually declare a local variable and assign values to the bit-field's elements. {{{ #!div style="font-size: 90%" {{{#!C bitfield_example_type my_bitfield; my_bitfield.raw_value = 0; //clear out the entire bitfield my_bitfield.A = 1; my_bitfield.B = 60; my_bitfield.C = 0; print_bitfield_example_type(my_bitfield); }}} }}} The above code creates a {{{bitfield_example_type}}} named {{{my_bitfield}}} and sets the A, B, and C elements to 1, 60, and 0 respectively. It then calls the previously-defined print function to verify the contents of the bit-field. The output of that print function is the following: {{{ #!div style="font-size: 90%" }}} == Case 2: Using a Constructor Function to Initialize a Bit-field == ---- = Example: Interpretation of Byte Array = = Example: Register Access =