Colin Walls has over thirty years experience in the electronics industry, largely dedicated to embedded software. A frequent presenter at conferences and seminars and author of numerous technical articles and two books on embedded software, Colin is an embedded software technologist with Mentor … More »
April 16th, 2018 by Colin Walls
I often joke that my job puts me in a difficult position, as I am a software guy and a very large proportion of Mentor employees are hardware design specialists; I am consorting with the “the enemy”. Although I am making a light-hearted comment, there is, sadly, something of an “us and them” attitude between software and hardware teams in many companies. It is in everybody’s interest to make this a thing of the past.
Sometimes, it seems as if this view is reasonable, when hardware seems to be designed specifically to make life hard for software developers …
The issue of hardware being challenging to control from software is well known. The whole idea of device drivers was conceived, as much as anything, to hide the nastiness of such interfaces from non-experts. My favorite example of hardware that seems to have been designed for intentional aggravation is a write-only port.
This type of interface has a register, to which data may be written, but from which the current value may not be read back. This may be problematic because the 8-, 16- or 32-bit port may consist of a number of single- or multi-bit registers with unrelated functionality. This means that different parts of the software may need to access the port and there are plenty of opportunities for unintentional interference. For example, to set the bottom 2 bits of the port without affecting the other bits, the following code would seem obvious:
WOPORT |= 0x03;
However, this construct will not work, as the |= operator generates code which will read the port (and get invalid data or trigger an exception) before writing an updated value. The solution is simple enough: keep a “shadow” copy of the port data and use that each time an update is required, like this:
woport_shadow |= 0x03; WOPORT = woport_shadow;
This is quite straightforward, but there are a few things to take care of:
All of these issues may be addressed by careful code design. Probably the best approach is to encapsulate the access to a port inside a function, thus providing a common API. Another approach might be to use C++ to encapsulate the details of write-only port access.