In this video, we will talk about structure bit fields. In general C programming, we rarely need to use data types smaller than a byte. A microcontroller's data memory does not even allow for address that is smaller than a byte, because all memory is byte addressable. Conversely, there are many pieces of data that we do treat as boolean. The C99 standard introduced a new type called bool, to help track these types more effectively. In contrast, microcontroller peripheral memory regular tracks smaller than byte sized data, but packs it into a larger data type with other smaller bit fields to store information. These track things like peripheral status, control, and it's done to save space and cost. Luckily, C programming provides a feature similar, called bit fields that helps us manage smaller data types and sizes within a structure. Bit fields are a C programming feature that we can use with both unions and structs. By using a bit field within these types, we can pack more data into a built in type without wasting excess data space. Bit fields can be defined just like a normal member in a structure or union, except you will add a colon after the bit field variable name and then a bit field width. Here's an example of where we declared a structure with bit fields x, y and z, with respective bit sizes of three, two and one bits. We can declare an instance of these structures and assign values to these bit fields. Here, we have assigned the values four, three and one, to the structure members using the dot operator. Bit fields must be assigned a value that can fit within its bit width. Otherwise, the operation is undefined. For example, a bit field of width one should never see an assignment larger than one. The bit field width must also be larger than zero, but smaller than the bit width of the underlying type you've declared it for. For example, if you declared a structure member X with a uint8 type but a bit field size of nine, you would get a compiler error. Additionally, you will get a compiler error if you define a bit field to be of size zero. If two successive bit fields are defined as the same type and they do not overflow the initial type, they are being declared with, they will be put in the same grouping. Meaning a bit field of three and two bit widths within a uint8 type, will only need that one byte to store those data bits or a total of five bits. If there was a third bit field of width one, then we would still only need that one byte to store this within a structure using bit fields. If we define this as a union, with those same three bit fields, only the least significant bit would overlap the two other bit fields. You can mix bit fields with other regular variable types. When you do this, the remainder bits in the initial type allocation will go unused. Additionally, the full member not defined with a bit field will be allocated at the next properly aligned location for that type. For example, say you defined two bit fields as uint8 and you use seven of the possible 8 bits. Then you follow that up with a uint16 member definition with no bit fields. This will require the compiler to allocate three to four bytes depending on if the structure is packed or aligned. The packing of bits is analogous to the packing of a structure. Instead, of allowing the compiler to align certain data types at specific memory locations, each variable is placed one right after another. This has two corollaries. First, this makes reading and writing to a packed data structure more difficult. There are more instruction needed to perform the unaligned access and thus decreases our program efficiency. Secondly, this will increase our storage efficiency, meaning, more data can be grouped together and result in the need for less memory. This concept is no different than in bit fields. We would pack smaller sets of data within bytes in words. There would be more overhead of reading and writing to bit fields, but we would decrease the overall memory footprint needed for data if we pack these into smaller structures. It is possible your application may see a significant decrease in cost by either choosing a platform with less processing power or limited memory. Bit field can also be directly added to enforce a particular alignment on the next member. This can be done by adding a bit field of length zero with no name. This means the next member will be aligned to the next available memory region. You would use this, as a way to help ensure a specific bit orientation or mapping. Bit fields are used in the core microcontroller software interface standard or CMSIS provided by ARM. Let's look at the program status registers that we discussed before. The program status register or PSR is made up of three separate registers. These include the APSR, the IPSR, and the EPSR. These registers have multiple bit fields that are smaller than the fundamental types. We can declare a structure overlay for these different registers with bit fields to simplify the interaction. Here we have the APSR type structure provided by the core_CM for header file, for the cortex and for ARM core processor. You will notice that this is first defined as a union. This allows the programmer to read the register, either as a 32-bit word using the W keyword or by individual bit fields using the B keyword. The bit fields have numerous single bit widths that map to the negative zero, carry, overflow, and saturation flags. Here, the designer added two bit fields for the unused or reserved sections of the register. They also added greater than flags near the bottom of the definition. To write to the register, the entire register can be written to by just using the dot operator and the W member. If you wish to write to the bit fields, you would need to use two dot operators. The first selects the bit field structure, and the second, the individual field we intend to write to. The APSR is not something you would typically be writing to. You may read from this, but you would first have to read the APSR from the core CPU register and then assign that value to an instance of the structure. Because this register does not live in the normal address map. You cannot create a structure overlay for that address. Instead, you need to use specialized inline assembly commands to read the APSR register. This uses a new compiler directive called _ASM. This allows us to write assembly code within our C program. We will cover inline assembly in more detail in a later module. Bit fields are useful for creating variable data sizes more dynamically than the typical built in types from C program. Additionally, it gives us an easy mechanism to interface with these fields without having to do our own bit manipulation. This is especially useful when working with a processor core, status register, or peripheral registers. Understanding how to manage and manipulate peripheral registers will be key to writing effective microcontroller programs.