4.6 C
New York
Sunday, December 4, 2022

Programming embedded systems: Structures in C and CMSIS – Embedded


Structures (or “structs” in C) allow you to group several related variables and treat them as one unit. They are a mechanism for extending the type system of the C language by introducing user-defined types. In embedded systems, structs can provide an elegant, intuitive, and efficient way of accessing hardware registers. The latter property of structs is the foundation of the Cortex Microcontroller Software Interface Standard (CMSIS) [3]. You can learn about all of this in video lesson #12 of the “Modern Embedded Systems Programming” course:
Lesson 12 – Structures in C and Cortex Microcontroller Software Interface Standard (CMSIS)

The way to declare structs (as well as unions and enums) in C is quite peculiar because the identifier following the keyword ‘struct’ is a tag (e.g., struct Foo {…};). Interestingly, the tag (e.g., Foo) occupies a different namespace than variables, functions, and types. Such a tag cannot be used standalone but must always be preceded by the keyword ‘struct’ to form an elaborated type specifier. These rules of hiding tag names are probably a mistake in the C language design, and I recommend following the guidelines of Dan Saks to turn tags into typedefs [1]. For simple (non-self-referential) structs, the declaration does not need to use a tag at all:
For self-referential structs (such as linked lists or trees), the tag is necessary, but the tag name is intentionally kept the same as the typedef’d name.
Both recommended struct declarations comply with the MISRA-C:2012 guidelines, specifically Directive 2.4 [2].
The C compiler will always honor the order of struct members precisely as you declared them in your struct. Also, the first struct member is always aligned with the beginning of the struct in memory. (This will be useful for emulating inheritance in C, which you’ll see in future installments.)
But, as illustrated in the video, the compiler can insert extra padding bytes after each member, including the last member. The compiler adds padding to achieve optimal alignment of the struct members for more efficient access. Therefore, the number of padding bytes inserted depends on the CPU and its particular alignment rules, which means that the struct layout is generally not portable.
Embedded compilers typically provide non-standard C language extensions to allow you to avoid padding in a struct. For example, the IAR compiler in the video provides the extended keyword ‘__packed’ that you can apply to a struct. However, the “packed” structs might require more CPU instructions to access the misaligned members, as illustrated in the video after switching to the Cortex-M0 CPU.
A good rule of thumb to minimize the waste of memory by the padding is declaring the struct members starting from the biggest to the smallest.
A struct in C defines a specific memory layout, which can be mapped to blocks of related hardware registers. That allows you to conveniently access the registers in the hardware block as struct members, leaving all the address computations (offsets from the beginning of the struct) to the compiler. Moreover, that way of accessing the hardware can take advantage of the special addressing modes of modern CPUs (register-based with an immediate offset), which might be more efficient than hard-coding individual hardware addresses.
This idea is the basis of the Cortex Microcontroller Software Interface Standard (CMSIS) [3], which defines hardware interfaces as C structs mapped to the various hardware blocks.
“All problems in computer science can be solved by another level of indirection” [4]. But too many levels of indirection quickly become counterproductive. With this in mind, CMSIS strikes the right balance of providing just the right level of abstraction so that the struct member names can correspond directly to the registers as they appear in the datasheets.
[1] Dan Saks, “Tag vs. Type Names,” Embedded Systems Programming, October 2002
[2] MISRA-C Standards: https://www.misra.org.uk
[3] ARM software, Cortex Microcontroller Software Interface Standard (CMSIS)
[4] aphorism attributed to David Wheeler or Butler Lampson
Related Contents:
For more Embedded, subscribe to Embedded’s weekly email newsletter.

You must or to post a comment.
This site uses Akismet to reduce spam. Learn how your comment data is processed.


Related Articles


Please enter your comment!
Please enter your name here

Latest Articles