Interrupt Handling

Previously, I mentioned that there were issues with setting the CONTROL and BASEPRI registers. Trying to set BASEPRI or change CONTROL caused a usage fault with an undefined instruction error. Trying to use an SVC instruction to enter Handler mode and set CONTROL or BASEPRI also failed to work.

Looking at the assembled code with the Capstone disassembler revealed that the instructions I had generated were not recognised. I quickly wrote a small test program to compile with gcc and discovered that I'd encoded the mask field of the MSR instruction with a different value to the one that gcc generated. Using the same value fixed the problem.

More interrupt issues

I was hoping that this would resolve issues with the priority-setting approach, and it was possible to change the base priority to effectively enable and disable the SysTick exception. However, occasionally there would be a crash caused by the contents of the static base register appearing in the program counter. Why this should happen is only sort of clear if you know how I implemented task switching for the Thumb-2/Cortex-M ports of Inferno. The summary is that the static base register (R12) is used to temporarily hold the return address of the SysTick exception until it can be stacked for the eventual return to pre-empted code. Since there is a very narrow window of time where this register can be overwritten, this approach can be potentially undermined if another process resets R12.

Now that we're using BASEPRI to manage the SysTick interrupt, we can use PRIMASK to disable interrupts and protect the vulnerable region of code against interruptions. I initially experimented with using the unused register, R10, as a mutex to guard against reentry into the problematic code, but this approach is perhaps more robust, at least for now. Having said that, the use of R10 opened up the approach of setting registers in a routine while modifying the stack to reset them when the routine returns. This could be helpful in similar situations where we can't disable interrupts completely.

And toolchain issues

While experimenting with solutions, I discovered that the compiler was not generating the AND.S instruction correctly. This was a problem I'd introduced a while ago, so it was good to go back and fix it.


David Boddie
13 November 2023