From Silicon Labs: Making Peripheral Drivers Thread-safe

Aug 17, 2019

If you are running in a multi-threaded environment in which you have more than one task making use of a peripheral driver such as USART, SPI, I2C, etc., you should consider making it thread-safe.

The Micrium OS kernel offers a variety of services designed to protect shared resources. In our case, let’s make use of the Mutual Exclusion Semaphore also known as mutex. Why a mutex? Because we want our resource (peripheral driver) to be accessed only by one task at a time. Regular semaphores present a vulnerability with priority-inversion. Mutexes, on the other hand, are implemented in a way that priority inversions are prevented by using priority inheritance.

For this exercise, you will be editing files from the Gecko SDK, which is not recommended therefore do this with caution.

In the peripheral driver file that you want to protect, include the following file:

#include  <kernel/include/os.h>

Now we have to declare a global variable for our mutex, for example, if you want to protect the SPI you could declare it as follows:


With the mutex now declared, you need to invoke the kernel call to create it. My recommendation is to make this in the initialization function of the peripheral driver that you are using. You create the mutex by calling:

OSMutexCreate(&SPI_Mutex, “SPI Mutex”, &err);

Notice how the function requires an error argument, just declare RTOS_ERR  err locally and pass it on.

Always make sure to check the error returned, if it’s not RTOS_ERR_NONE then something went wrong.

The mutex is now created and registered with the kernel. Now you will need to wrap around the driver calls that your application is using with:

void foo () {

  RTOS_ERR  err;

  OSMutexPend(&SPI_Mutex,            /* Pointer to the mutex */
               0,                    /* No timeout */
               OS_OPT_PEND_BLOCKING, /* Block if not available */
               DEF_NULL,             /*Timestamp not used */

  if (err.Code != RTOS_ERR_NONE) {
      /* handle error */

  /* peripheral driver function code */


  if (err.Code != RTOS_ERR_NONE) {
      /* handle error */

Please make sure to check the returned errors. A common one is RTOS_ERR_NOT_READY, this happens when the pend or post calls are made before the kernel is in its running state (after the call to OSStart()).

If the driver initialization function can potentially be called multiple times from more than one task, my recommendation is to also protect it.

With this setup, you can be sure that your peripheral is only being accessed by one task at a time.

Beware also that some drivers have abort functions, you have to be careful with this and not lock your system on a mutex pend. For more information on how to protect a resource using Micrium OS please visit




Looking to integrate Silicon Labs products with your design? Our Applications Engineers offer free design and technical help for your latest designs. Contact us today!



Symmetry Electronics Logo


Why partner with Symmetry Electronics? Symmetry's technical staff is specially trained by our suppliers to provide a comprehensive level of technical support. Our in-house Applications Engineers provide free design services to help customers early in the design cycle, providing solutions to save them time, money and frustration. Contact Symmetry for more information.


Sign up to get tech news, product updates and store promos from Symmetry Electronics.


Choose Topic

Blog Archive


Previously Viewed Products