diff --git a/epicardium/main.c b/epicardium/main.c index b6dad7636ad317a112f50f5b5fb4eb1cd64ea365..f4c004868d8366903010f4d1664e6b2b6f3ad5af 100644 --- a/epicardium/main.c +++ b/epicardium/main.c @@ -179,6 +179,18 @@ int main(void) panic("Failed to create %s task!", "Lifecycle"); } + /* Work Queue */ + if (xTaskCreate( + vWorkQueueTask, + (const char *)"Work Queue", + configMINIMAL_STACK_SIZE * 4, + NULL, + tskIDLE_PRIORITY + 1, + NULL) != pdPASS) { + panic("Failed to create %s task!", "Work Queue"); + } + workqueue_init(); + /* * Initialize serial driver data structures. */ diff --git a/epicardium/modules/light_sensor.c b/epicardium/modules/light_sensor.c index ea8d74c36c92e381dd8239a2bd9b02617fd92b6a..e7ab899d25232a9b2f1fed665991a9d04568594d 100644 --- a/epicardium/modules/light_sensor.c +++ b/epicardium/modules/light_sensor.c @@ -38,17 +38,14 @@ uint16_t epic_light_sensor_read() return last_value; } -static void readAdcCallback() +static void workpoll(void *data) { - if (hwlock_acquire_nonblock(HWLOCK_ADC) != 0) { - /* Can't do much about this here ... Retry next time */ - return; - } - - ADC_StartConvert(ADC_CH_7, 0, 0); - ADC_GetData(&last_value); + epic_light_sensor_read(); +} - hwlock_release(HWLOCK_ADC); +static void poll(TimerHandle_t xTimer) +{ + workqueue_schedule(workpoll, NULL); } int epic_light_sensor_run() @@ -65,7 +62,7 @@ int epic_light_sensor_run() READ_FREQ, pdTRUE, NULL, - readAdcCallback, + poll, &poll_timer_buffer ); // since &poll_timer_buffer is not NULL, xTimerCreateStatic should allways succeed, so diff --git a/epicardium/modules/meson.build b/epicardium/modules/meson.build index d77cfc2a2b7f491ad5b179d78ff4fc71fba7951c..31302e9f1e9f33a19557f202173879e0811f233c 100644 --- a/epicardium/modules/meson.build +++ b/epicardium/modules/meson.build @@ -28,5 +28,6 @@ module_sources = files( 'usb.c', 'vibra.c', 'watchdog.c', + 'work_queue.c', 'ws2812.c' ) diff --git a/epicardium/modules/modules.h b/epicardium/modules/modules.h index 14184bd9ca96b367ebcf57a7d8b7739a407df817..ccc8d0650497133bb193fc162fb112c6f364e82e 100644 --- a/epicardium/modules/modules.h +++ b/epicardium/modules/modules.h @@ -138,6 +138,13 @@ extern gpio_cfg_t gpio_configs[]; void sleep_deepsleep(void); +/* ---------- RNG ---------------------------------------------------------- */ void rng_init(void); +/* ---------- Work Queue --------------------------------------------------- */ +#define WORK_QUEUE_SIZE 20 +void workqueue_init(void); +int workqueue_schedule(void (*func)(void *data), void *data); +void vWorkQueueTask(void *pvParameters); + #endif /* MODULES_H */ diff --git a/epicardium/modules/work_queue.c b/epicardium/modules/work_queue.c new file mode 100644 index 0000000000000000000000000000000000000000..3af2c03cc0e12f3b9df555c25a8160cc4aa68829 --- /dev/null +++ b/epicardium/modules/work_queue.c @@ -0,0 +1,47 @@ +#include "epicardium.h" +#include "modules/log.h" +#include "modules.h" + +#include "FreeRTOS.h" +#include "queue.h" + +struct work { + void (*func)(void *data); + void *data; +}; + +static QueueHandle_t work_queue; +static uint8_t buffer[sizeof(struct work) * WORK_QUEUE_SIZE]; +static StaticQueue_t work_queue_data; + +void workqueue_init(void) +{ + work_queue = xQueueCreateStatic( + WORK_QUEUE_SIZE, sizeof(struct work), buffer, &work_queue_data + ); +} + +int workqueue_schedule(void (*func)(void *data), void *data) +{ + struct work work = { func, data }; + if (xQueueSend(work_queue, &work, 0) != pdTRUE) { + /* Likely full */ + LOG_WARN("workqueue", "could not schedule %p(%p)", func, data); + return -EAGAIN; + } + + return 0; +} + +void vWorkQueueTask(void *pvParameters) +{ + struct work work; + workqueue_init(); + while (1) { + if (xQueueReceive(work_queue, &work, portMAX_DELAY) == pdTRUE) { + if (work.func) { + work.func(work.data); + } + } + } +}