From bafda368fb817f8c857c3291ae472a88fe0540f8 Mon Sep 17 00:00:00 2001
From: schneider <schneider@blinkenlichts.net>
Date: Sun, 6 Dec 2020 23:41:54 +0100
Subject: [PATCH] feat(epicardium): Basic work queue

---
 epicardium/main.c               | 12 +++++++++
 epicardium/modules/meson.build  |  1 +
 epicardium/modules/modules.h    |  7 +++++
 epicardium/modules/work_queue.c | 47 +++++++++++++++++++++++++++++++++
 4 files changed, 67 insertions(+)
 create mode 100644 epicardium/modules/work_queue.c

diff --git a/epicardium/main.c b/epicardium/main.c
index b6dad7636..f4c004868 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/meson.build b/epicardium/modules/meson.build
index d77cfc2a2..31302e9f1 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 14184bd9c..ccc8d0650 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 000000000..3af2c03cc
--- /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);
+			}
+		}
+	}
+}
-- 
GitLab