Programming language extensions
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.
Comments
Leave a Reply
You must be logged in to post a comment.
Hi Colin,
>It should be noted that the use of both packed and unpacked in one program is very unlikely.
It’s very likely whenever there’s a need for communication with an external device! 🙂
I remember I first learnt using packed in a project where uC had to talk with a WiFi module over SPI.
And now the damn endianess comes to my mind too 😉
Cheers!
—
Best regards,
Andrzej Telszewski
@Andrzej – Why would you use both keywords in that context? One of them is overriding the default set on the compiler and the other would have no effect. I guess it would serve to clarify the code, which, of course, is a very good idea.
@Colin – argh, got it 😉
I thought you meant not to use both packed and unpacked _structs_ in single program.
Which would obviously contradict what we embedded programmers are dealing with all the time.
My bad 😉
Have a good time!
—
Best regards,
Andrzej Telszewski