Over the last two blogs, we have examined Inter Processor Communication (part one and part two) between a Zynq and a MicroBlaze. We will wrap up this mini series on IPC with an exploration of mutual exclusion or mutexes it is more commonly known.
When we have several processors in our device, multiple processors may want to share a common resource, often at the same time (e.g. memory or UART). If access to these resources is uncontrolled, it can quickly and easily lead to corruption.
Mutual exclusion might seem one of the simplest problems to solve, surely a flag can be used which each side can test and if free set, claiming access to the resource.
However, a problem arises that in the time between of one processor testing and setting the flag, the opposing processor can also see the flag as free and start its lock process. This is commonly known as a race condition, other potential pitfalls around mutual exclusion include deadlock and starvation. Where processors cannot access the resource (starvation) or the system locks up as each processor is waiting on different locked processes to progress (deadlock).
There are many solutions to address these issues, including the use of multiple flags. Although, they begin to get very complex when considering anything other than the most simple case, in short they do not scale easily.
The way to address a race condition is to ensure the test and set operations are combined in to a single one operation, that is if we test the mutex flag and it is free then it is set.
This is exactly how the Xilinx mutex works, when we write to the mutex if it is free the processor is allocated the resources.
Designing the mutex in to our hardware design is very simple, each processor has its own AXI Interface. With the mutex being able to support from one to eight processors, we may use just a single interface when using a operating system and sharing resources between tasks running on the same processor.
In one mutex instantiation, we are able to implement up to 32 mutexes. For this example, though, we are only going to have a single one. When we implement the mutex, we can if we desire also enable hardware protection at the AXI level.
If we choose to enable this, the optional AXI HWID field is used to lock and unlock the mutex preventing CPUs from being able to fake a CPU ID and unlock it incorrectly.
Each mutex also has an optional 32 bit register that can be used for sharing configuration data between processors if necessary.
When it comes to using mutexes in our SW, we can use the Xmutex API (xmutex.h) provided by the board support packages (BSP) for both processors. Within this API, we will find the classes of functions :
Lifecycle management — Initialization and status reporting
User register — Set and unset the user register
Mutex operation — Functions to lock and unlock the mutex
Similar to the Mailbox example we looked at last week, mutex operations provide both blocking and non-blocking calls. The blocking call is provided by the function XMutex_Lock() while the none blocking function call is XMutex_Trylock().
To demonstrate the application of mutexes, we will update our SW application so the MircoBlaze application locks the mutex when the LED is set and unlocks the mutex when the LED is cleared.
The Zynq application will then test the mutex and report if it is set or not set along with the LED status. A simple but effective example showing how the mutex functions work.
The code for both processors is below.
When I ran the application using the code above, I observed the following in the terminal window. This indicates the mutex is being locked and unlocked as expected by the MicroBlaze as it access the LED resource.
This brings us to the end of the Inter Processor Communication mini series, in which we have looked at implementing Mailboxes and mutexes.
Hopefully we now understand the resources that are available to us when we want to use multiple processors in our heterogeneous SoC or FPGA devices. It turns out creating multiprocessor systems is not as daunting as it may at first appear.
Incidentally this is the 300th MicroZed Chronicles!