There is a paradox with programming languages. Everyone would agree that standardizing languages is a good thing, leading to portability of software and programming skills. But what if the resulting standard lacks features required by certain types of applications? One possible approach is to define a language specification that is so large that it encompasses every possible eventuality. In the late 1960s, IBM created the “ultimate” programming language, which had capabilities that accommodated numerous types of applications - it was called PL/1. Although it was widely used [on IBM mainframes] for some years, it had a fundamental problem: because the language was so large, each programmer would tend to learn and use just a sub-set of the available facilities, so they would not necessarily be able to understand one another’s code. This rather defeats the point of a standard. Another approach is to keep the specification quite lean, but complete enough for most applications and accept that language extensions may be necessary for specific specialized needs.
The most common languages for embedded applications are C and C++, neither of which were designed for embedded. Both of them lack a few key capabilities and this lack is addressed in three ways:
- language extensions - extra keywords
- inline compiler directives - #pragma
- linker capabilities
It is worth minimizing the number of new keywords to avoid compromising code portability too much. The important ones are: packed and unpacked [which override prevailing memory usage optimization strategy], interrupt and asm. These are quite specific to embedded developers, who need fine control over memory usage and want to minimize the use of assembly language. Maybe I will discuss these in more detail another time - I have covered them in a recent Webinar [slide #42].
Compiler directives are flexible, but result in very non-portable code, as they are quite specific to particular compilers.
Using the linker to address language shortcomings is a creative solution. Linkers are critical tools for embedded developers and their flexibility is valued by developers. Technology like Fine Grain Allocation, developed by the Mentor Graphics compiler team, is a good example of an approach to making C/C++ work well for embedded development. Again, I have covered this in a recent Webinar [slide #39].