Skip to end of banner
Go to start of banner

Mutex DRV_LOCKED

Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 23 Next »

Q

Why does DRV_MUTEX_TRYLOCK function return locked when being unlocked?

A

DRV_LOCKED is not only returned when the mutex is locked, but also occurs unwanted when the DRV_MUTEX_TRYLOCK function was interrupted between load exclusive and store exclusive (see below).

/*!
 * \brief   Try to lock the given mutex
 * \details Checks if the mutex is locked and acquires it by executing an exclusive LDREX, STREX cycle.
 * \memberof DRV_MUTEX_T
 * \param [in]  ptMutex  ptMutex to be locked
 * \return DRV_LOCKED The mutex was locked
 *         DRV_OK  The mutex is locked
 */
__STATIC_FORCEINLINE DRV_STATUS_E DRV_MUTEX_TRYLOCK(DRV_MUTEX_T* ptMutex)
{
  uint32_t ret;
  ret = __LDREXW((volatile uint32_t*) &ptMutex->eState);
  if(ret == (uint32_t) DRV_MUTEX_STATE_LOCKED)
  {
    return DRV_LOCKED;
  }
  else
  {
    ret = __STREXW(DRV_MUTEX_STATE_LOCKED, (volatile uint32_t*) &ptMutex->eState);
    __DMB();
    if(0 == ret)
    {
      return DRV_OK;
    }
    else
    {
      return DRV_LOCKED;
    }
  }
}

When using the mutex API, it is advisible to free mutexes after a certain time or a certain amount of trylocks in order to prevent deadlocks.

The following code snipped can help:

Q

Can I disable all interrupts before exclusively loading and then enable them after exclusively storing, to prevent that?

A

Yes, but it is not advisable. Time critical interrupts would then be delayed, which disturbs the program workflow. However, doing so does not stop timers and pending bits are still set. For this reason, Interrupts are not lost.

Q

Which procedure is appropriate for DRV_LOCK?

A

The appropriate approach depends on the Application. The goal is to understand the pros and cons, then determine the correct methods.

As can see in Cortex-M4 instruction the LDREX/ STREX requires 2 cycles to be executed and to disable/ enable interrupts 1 or 2 cycles. The mentioned disadvantage of disabling interrupts is that the critical interrupts are delayed for that period of time.

A different approach is the use of "DRV_MUTEX_LOCK" function by modifying the existing #define DRV_LOCK(__HANDLE__) (in netx_drv_conf.h file) to #define DRV_LOCK(__HANDLE__) DRV_MUTEX_LOCK(&(__HANDLE__)→tLock). Here, the system waits until an event occurs by using the following function:

/**
 \brief Wait For Event
 \details Wait For Event is a hint instruction that permits the processor to enter
 a low-power state until one of a number of events occurs.
 */
#define __WFE() __ASM volatile ("wfe")

Depending on the application, DRV_MUTEX can be converted into a simple lock. See the following example:

Note: If an interrupt interrupted this function shortly before ptMutex->eState = DRV_MUTEX_STATE_LOCKED; and set the eState to LOCKED, the application does not notice this.

#define DRV_LOCK(__HANDLE__) DRV_SIMPLE_LOCK(&(__HANDLE__)→tLock)
__STATIC_FORCEINLINE DRV_STATUS_E DRV_SIMPLE_LOCK(DRV_MUTEX_T* ptMutex)
{
	if(ptMutex->eState == DRV_MUTEX_STATE_LOCKED)
 	{
 		return DRV_LOCKED;
 	}
 	else if(ptMutex->eState == DRV_MUTEX_STATE_UNLOCKED)
 	{
 		ptMutex->eState = DRV_MUTEX_STATE_LOCKED;
	 	return DRV_OK;
 	}
 	else
 	{
 		return DRV_ERROR; /* please check the initialization of ptDriver->tLock = DRV_LOCK_INITIALIZER; */
 	}
}




DRV_LOCKED

  • No labels