Embedded systems code is mostly written in C and C++. Other languages are gaining popularity, but these two are still dominant. These languages have two interesting characteristics: they are very firmly standardized; neither was designed for embedded. The first point is OK – standardization cannot be a bad thing. The second point is odd; why are languages used for a purpose for which they were not designed? …
As C++ is essentially a superset of C, I will focus my attention the latter, older language. C was designed as a systems programming language and was intended to avoid too much assembly language usage, whilst still providing power and flexibility. C predates the arrival of microprocessors and embedded systems, but, because it was so readily available and almost fit the bill, it was widely adopted in the early days of embedded systems programming.
Although C was not designed for embedded, it came very close to fulfilling the needs of embedded developers and became widely adopted. Unsurprisingly, as standardization progressed, nothing was done to accommodate the needs of embedded developers, who were only a tiny subset of C developers. The few shortcomings in the language were quickly addressed by tool vendors by means of language extensions. Extending a very standardized language sounds foolish, but it was probably the only way forward to avoid resorting to assembly language.
Typically [and this varied from one tool vendor to another] the extensions to the language were limited to 4 new keywords: asm, interrupt, packed and unpacked:
asm – This is not strictly an extension keyword. In the standard, it is reserved, but not defined. In embedded toolkits this keyword is implemented to enable assembly language inserts, thus avoiding complete functions written in assembler.
interrupt – This keyword is used to qualify a function definition and instructs the compiler to code the function as an interrupt service routine, with the appropriate context save and restore.
packed – Embedded C compilers normally have an option to determine how data it laid out in memory. One possibility is unpacked data, which takes up more space, but is quicker to access. This key word overrides the option and declares an object that is packed as efficiently into memory as possible, at the expense of access time.
unpacked – This keyword is the complete reverse of packed. It is used to specify an exception when the default has been set to compress data into memory.
It should be noted that the use of both packed and unpacked in one program is very unlikely.