Embedded Software Colin Walls
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 » Reentrant write-only portsJuly 23rd, 2018 by Colin Walls
In my last posting, I illustrated the use of C++ to encapsulate the necessary coding nastiness of dealing with write-only ports. However, one aspect of the solution was not addressed: the proposed code was not reentrant … Reentrancy is a potential issue in any multi-threaded system. It needs to be considered if you are using an RTOS or have mainline code and interrupt service routines. In these cases, a sequence of instructions may be interrupted at any time and another thread be given control of the CPU. At some later point, the instruction sequence will be resumed. This is fine, unless it is essential that the sequence be completed in one go, without interruption. Such a sequence is often referred to as a “critical section” and measures need to be taken to avoid the interruption. In the write only port handling code that I have presented so far, the critical section is the two lines of code that update the shadow copy and the writing to the port, for example: shadow &= val; *address = shadow; The problem is that, if an interrupt occurred after the shadow was updated and the new thread utilizes the port, the correct value may never be written. In some cases that might not matter, but, in others, it is essential that every update is written to the port. The solution is conceptually quite straightforward: the port needs to be “locked” before this pair of statements and “unlocked” afterwards. The code would simply look like this: lock(); shadow &= val; *address = shadow; unlock() These member functions – lock() and unlock() – could be implemented in a variety of ways. The brute force approach would be to simply disable and re-enable interrupts. With an RTOS, using a semaphore or a mutex would be a better approach. In the spirit of object-oriented programming practice, it would be sensible to add these functions to the write_only_port class, but make them virtual. This means that, where reentrancy is not an issue, the class may be used as it stands. If a reentrant version is required, it may be derived from this base class and the lock() and unlock() instantiated appropriately. |