-
Notifications
You must be signed in to change notification settings - Fork 7.7k
Description
Board
Any
Device Description
NA
Hardware Configuration
NS
Version
latest master
IDE Name
PlatformIO
Operating System
Win10
Flash frequency
80
PSRAM enabled
no
Upload speed
115200
Description
This is a proposed bugfix and feature improvement. In #6425 it was discovered that esp32-ha-spi.c never releases the Mutex created in spiStartBus(). Looking at the other libraries in arduino-esp32/cores/esp32/, I can see that the same issue occurs in:
esp32-hal-i2c.c
esp32-hal-i2c-slave.c
esp32-hal-spi.c
esp32-hal-uart.c
esp32-hap-cpu.c [There isn't a matching function to initApbChangeCallback() to release the Mutex]
Everything except the CPU file uses the Mutex when CONFIG_DISABLE_HAL_LOCKS==false. The code is littered with #if !CONFIG_DISABLE_HAL_LOCKS
, which makes it difficult to read and maintain. While I could edit each file and add the missing vSemaphoreDelete() calls, I propose creating a unified set of defines in esp32-hal.h, and possibly a couple supporting function calls. Then we can use the new defines in the core libraries to simplify HAL locks.
I'd be happy to create a PR if this would help.
Here's what I have so far. Keep in mind this is conceptual. Code has not been compiled or tested.
In esp32-hal.h:
#if !CONFIG_DISABLE_HAL_LOCKS
#define HAL_LOCKS_CREATEVAR(varname) xSemaphoreHandle varname = NULL
#define HAL_LOCKS_INIT(varname) HalLocksInit(&varname)
#define HAL_LOCKS_LOCK(varname, timeout, infiniteretries) HalLocksLock(&varname, timeout, infiniteretries)
#define HAL_LOCKS_UNLOCK(varname) HalLocksUnlock(&varname)
#define HAL_LOCKS_DEINIT(varname) HalLocksDeinit(&varname)
#else
#define HAL_LOCKS_CREATEVAR(varname)
#define HAL_LOCKS_INIT(varname) //Passing a missing variable name should work as it expands to nothing. TODO TEST!!
#define HAL_LOCKS_LOCK(varname, timeout, infiniteretries)
#define HAL_LOCKS_UNLOCK(varname)
#define HAL_LOCKS_DEINIT(varname)
#endif
Not sure where to put this:
bool HalLocksInit(xSemaphoreHandle *hnd) {
if(*hnd != NULL) {
return true; //Handle already exists
}
*hnd = xSemaphoreCreateMutex();
return (*hnd != NULL);
}
bool HalLocksLock(xSemaphoreHandle *hnd, TickType_t timeout_ticks, bool InfiniteRetries) { //So far all code uses portMAX_DELAY for the timeout, so we could remove the timeout parameter.
if(*hnd == NULL) {
return false;
}
BaseType_t result = xSemaphoreTake(*hnd, timeout_ticks);
while(InfiniteRetries && (result != pdTRUE)) {
result = xSemaphoreTake(*hnd, timeout_ticks);
}
return result == pdTRUE;
}
//Could return the result of xSemaphoreGive(), but I didn't find any code that uses it.
void HalLocksUnlock(xSemaphoreHandle *hnd) {
if(*hnd == NULL) {
return;
}
xSemaphoreGive(*hnd);
}
void HalLocksDeinit(xSemaphoreHandle *hnd) {
if(*hnd == NULL) {
return;
}
vSemaphoreDelete(*hnd);
*hnd = NULL; //Clear handle so it can't be released again
}
USAGE:
HAL_LOCKS_CREATEVAR(_hal_uart_lock); //Note we don't have to include "#if !CONFIG_DISABLE_HAL_LOCKS" here.
HAL_LOCKS_INIT(_hal_uart_lock);
HAL_LOCKS_LOCK(_hal_uart_lock, portMAX_DELAY, true);
HAL_LOCKS_UNLOCK(_hal_uart_lock);
HAL_LOCKS_DEINIT(_hal_uart_lock);
Compare this to esp32-hal-uart.c:
#if !CONFIG_DISABLE_HAL_LOCKS
xSemaphoreHandle lock;
#endif
#if CONFIG_DISABLE_HAL_LOCKS
#define UART_MUTEX_LOCK()
#define UART_MUTEX_UNLOCK()
...
#else
#define UART_MUTEX_LOCK() do {} while (xSemaphoreTake(uart->lock, portMAX_DELAY) != pdPASS)
#define UART_MUTEX_UNLOCK() xSemaphoreGive(uart->lock)
...
#endif
...
uart_t* uartBegin(...)
{
...
#if !CONFIG_DISABLE_HAL_LOCKS
if(uart->lock == NULL) {
uart->lock = xSemaphoreCreateMutex();
if(uart->lock == NULL) {
return NULL;
}
}
#endif
UART_MUTEX_LOCK();
...
UART_MUTEX_UNLOCK();
...
}
...
void uartEnd(uart_t* uart)
{
if(uart == NULL) {
return;
}
UART_MUTEX_LOCK();
uart_driver_delete(uart->num);
UART_MUTEX_UNLOCK();
// [[ SHOULD RELEASE MUTEX HERE ]]
}
Sketch
NA
Debug Message
NA
Other Steps to Reproduce
No response
I have checked existing issues, online documentation and the Troubleshooting Guide
- I confirm I have checked existing issues, online documentation and Troubleshooting guide.
Edit: renamed HalLocksCreateMutex() to HalLocksInit().
Metadata
Metadata
Assignees
Labels
Type
Projects
Status