From 52fc4af393e68e511f9ee715efadb055ca9e2bef Mon Sep 17 00:00:00 2001 From: Rahix <rahix@rahix.de> Date: Tue, 20 Aug 2019 13:55:09 +0200 Subject: [PATCH] feat(epicardium): Add hardware/peripheral-lock module Signed-off-by: Rahix <rahix@rahix.de> --- epicardium/modules/hardware.c | 5 +++ epicardium/modules/hw-lock.c | 62 ++++++++++++++++++++++++++++++++++ epicardium/modules/meson.build | 1 + epicardium/modules/modules.h | 11 ++++++ epicardium/modules/pmic.c | 6 ++++ 5 files changed, 85 insertions(+) create mode 100644 epicardium/modules/hw-lock.c diff --git a/epicardium/modules/hardware.c b/epicardium/modules/hardware.c index 3905ceb81..75a995e97 100644 --- a/epicardium/modules/hardware.c +++ b/epicardium/modules/hardware.c @@ -150,6 +150,11 @@ int hardware_early_init(void) */ stream_init(); + /* + * Hardware/Peripheral Locks + */ + hwlock_init(); + return 0; } diff --git a/epicardium/modules/hw-lock.c b/epicardium/modules/hw-lock.c new file mode 100644 index 000000000..f02a5882b --- /dev/null +++ b/epicardium/modules/hw-lock.c @@ -0,0 +1,62 @@ +#include "modules/log.h" +#include "modules/modules.h" + +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +#include <errno.h> + +static StaticSemaphore_t hwlock_mutex_data[_HWLOCK_MAX]; +static SemaphoreHandle_t hwlock_mutex[_HWLOCK_MAX]; +/* Which task is holding the lock */ +static TaskHandle_t hwlock_tasks[_HWLOCK_MAX]; + +void hwlock_init(void) +{ + for (int i = 0; i < _HWLOCK_MAX; i++) { + hwlock_mutex[i] = + xSemaphoreCreateMutexStatic(&hwlock_mutex_data[i]); + } +} + +int hwlock_acquire(enum hwlock_periph p, TickType_t wait) +{ + if (p >= _HWLOCK_MAX) { + return -EINVAL; + } + + if (xSemaphoreTake(hwlock_mutex[p], wait) != pdTRUE) { + LOG_WARN("hwlock", "Lock %u is busy.", p); + return -EBUSY; + } + + hwlock_tasks[p] = xTaskGetCurrentTaskHandle(); + + return 0; +} + +int hwlock_release(enum hwlock_periph p) +{ + int ret = 0; + + if (p >= _HWLOCK_MAX) { + return -EINVAL; + } + + if (hwlock_tasks[p] != xTaskGetCurrentTaskHandle()) { + LOG_ERR("hwlock", + "Lock %u is released by task \"%s\" while it was acquired by \"%s\"", + p, + pcTaskGetName(NULL), + pcTaskGetName(hwlock_tasks[p])); + ret = -EACCES; + } + + if (xSemaphoreGive(hwlock_mutex[p]) != pdTRUE) { + LOG_ERR("hwlock", "Lock %u not released correctly.", p); + ret = -EINVAL; + } + + return ret; +} diff --git a/epicardium/modules/meson.build b/epicardium/modules/meson.build index 31e7f5c07..4966be6c9 100644 --- a/epicardium/modules/meson.build +++ b/epicardium/modules/meson.build @@ -5,6 +5,7 @@ module_sources = files( 'fileops.c', 'gpio.c', 'hardware.c', + 'hw-lock.c', 'leds.c', 'lifecycle.c', 'light_sensor.c', diff --git a/epicardium/modules/modules.h b/epicardium/modules/modules.h index 535dcf5c1..abf1c7709 100644 --- a/epicardium/modules/modules.h +++ b/epicardium/modules/modules.h @@ -37,6 +37,17 @@ void vBleTask(void *pvParameters); bool ble_shall_start(void); void ble_uart_write(uint8_t *pValue, uint8_t len); +/* ---------- Hardware (Peripheral) Locks ---------------------------------- */ +void hwlock_init(void); + +enum hwlock_periph { + HWLOCK_I2C = 0, + _HWLOCK_MAX, +}; + +int hwlock_acquire(enum hwlock_periph p, TickType_t wait); +int hwlock_release(enum hwlock_periph p); + /* ---------- Display ------------------------------------------------------ */ /* Forces an unlock of the display. Only to be used in Epicardium */ void disp_forcelock(); diff --git a/epicardium/modules/pmic.c b/epicardium/modules/pmic.c index 492545bb3..c02691dc2 100644 --- a/epicardium/modules/pmic.c +++ b/epicardium/modules/pmic.c @@ -45,7 +45,13 @@ void vPmicTask(void *pvParameters) MAX77650_setSFT_RST(0x2); } + while (hwlock_acquire(HWLOCK_I2C, pdMS_TO_TICKS(500)) < 0) { + LOG_WARN("pmic", "Failed to acquire I2C. Retrying ..."); + vTaskDelay(pdMS_TO_TICKS(500)); + } + uint8_t int_flag = MAX77650_getINT_GLBL(); + hwlock_release(HWLOCK_I2C); if (int_flag & MAX77650_INT_nEN_F) { /* Button was pressed */ -- GitLab