|
@@ -3,76 +3,135 @@
|
|
|
*/
|
|
|
#include "task/task.h"
|
|
|
#include "mem.h"
|
|
|
-#include "c_stdio.h"
|
|
|
+#include "user_config.h"
|
|
|
+
|
|
|
+#include "freertos/queue.h"
|
|
|
+#include "freertos/semphr.h"
|
|
|
|
|
|
#define TASK_HANDLE_MONIKER 0x68680000
|
|
|
#define TASK_HANDLE_MASK 0xFFF80000
|
|
|
#define TASK_HANDLE_UNMASK (~TASK_HANDLE_MASK)
|
|
|
-#define TASK_HANDLE_SHIFT 2
|
|
|
#define TASK_HANDLE_ALLOCATION_BRICK 4 // must be a power of 2
|
|
|
#define TASK_DEFAULT_QUEUE_LEN 8
|
|
|
-#define TASK_PRIORITY_MASK 3
|
|
|
|
|
|
#define CHECK(p,v,msg) if (!(p)) { NODE_DBG ( msg ); return (v); }
|
|
|
|
|
|
+typedef struct
|
|
|
+{
|
|
|
+ task_handle_t sig;
|
|
|
+ task_param_t par;
|
|
|
+} task_event_t;
|
|
|
+
|
|
|
/*
|
|
|
* Private arrays to hold the 3 event task queues and the dispatch callbacks
|
|
|
*/
|
|
|
-LOCAL os_event_t *task_Q[TASK_PRIORITY_COUNT];
|
|
|
-LOCAL task_callback_t *task_func;
|
|
|
-LOCAL int task_count;
|
|
|
+static xQueueHandle task_Q[TASK_PRIORITY_COUNT];
|
|
|
+
|
|
|
+/* Rather than using a QueueSet (which requires queues to be empty when created)
|
|
|
+ * we use a binary semaphore to unblock the pump whenever something is posted */
|
|
|
+static xSemaphoreHandle pending;
|
|
|
+
|
|
|
+static task_callback_t *task_func;
|
|
|
+static int task_count;
|
|
|
|
|
|
-LOCAL void task_dispatch (os_event_t *e) {
|
|
|
- #if 0
|
|
|
- task_handle_t handle = e->sig;
|
|
|
- if ( (handle & TASK_HANDLE_MASK) == TASK_HANDLE_MONIKER) {
|
|
|
- uint16 entry = (handle & TASK_HANDLE_UNMASK) >> TASK_HANDLE_SHIFT;
|
|
|
- uint8 priority = handle & TASK_PRIORITY_MASK;
|
|
|
- if ( priority <= TASK_PRIORITY_HIGH && task_func && entry < task_count ){
|
|
|
- /* call the registered task handler with the specified parameter and priority */
|
|
|
- task_func[entry](e->par, priority);
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
- /* Invalid signals are ignored */
|
|
|
- NODE_DBG ( "Invalid signal issued: %08x", handle);
|
|
|
- #endif
|
|
|
-}
|
|
|
|
|
|
/*
|
|
|
* Initialise the task handle callback for a given priority. This doesn't need
|
|
|
* to be called explicitly as the get_id function will call this lazily.
|
|
|
*/
|
|
|
-bool task_init_handler(uint8 priority, uint8 qlen) {
|
|
|
- #if 0
|
|
|
- if (priority <= TASK_PRIORITY_HIGH && task_Q[priority] == NULL) {
|
|
|
- task_Q[priority] = (os_event_t *) os_malloc( sizeof(os_event_t)*qlen );
|
|
|
- os_memset (task_Q[priority], 0, sizeof(os_event_t)*qlen);
|
|
|
- if (task_Q[priority]) {
|
|
|
- return system_os_task( task_dispatch, priority, task_Q[priority], qlen );
|
|
|
- }
|
|
|
+bool task_init_handler(task_prio_t priority, uint8 qlen) {
|
|
|
+ if (priority >= TASK_PRIORITY_COUNT)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ if (task_Q[priority] == NULL)
|
|
|
+ {
|
|
|
+ task_Q[priority] = xQueueCreate (qlen, sizeof (task_event_t));
|
|
|
+ return task_Q[priority] != NULL;
|
|
|
}
|
|
|
- #endif
|
|
|
- return false;
|
|
|
+ else
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
task_handle_t task_get_id(task_callback_t t) {
|
|
|
- #if 0
|
|
|
int p = TASK_PRIORITY_COUNT;
|
|
|
/* Initialise and uninitialised Qs with the default Q len */
|
|
|
- while(p--) if (!task_Q[p]) {
|
|
|
- CHECK(task_init_handler( p, TASK_DEFAULT_QUEUE_LEN ), 0, "Task initialisation failed");
|
|
|
- }
|
|
|
+ while(p--)
|
|
|
+ if (!task_Q[p]) {
|
|
|
+ CHECK(task_init_handler( p, TASK_DEFAULT_QUEUE_LEN ), 0, "Task initialisation failed");
|
|
|
+ }
|
|
|
|
|
|
if ( (task_count & (TASK_HANDLE_ALLOCATION_BRICK - 1)) == 0 ) {
|
|
|
/* With a brick size of 4 this branch is taken at 0, 4, 8 ... and the new size is +4 */
|
|
|
- task_func =(task_callback_t *) os_realloc(task_func,
|
|
|
- sizeof(task_callback_t)*(task_count+TASK_HANDLE_ALLOCATION_BRICK));
|
|
|
+ task_func =(task_callback_t *)realloc(
|
|
|
+ task_func,
|
|
|
+ sizeof(task_callback_t)*(task_count+TASK_HANDLE_ALLOCATION_BRICK));
|
|
|
+
|
|
|
CHECK(task_func, 0 , "Malloc failure in task_get_id");
|
|
|
- os_memset (task_func+task_count, 0, sizeof(task_callback_t)*TASK_HANDLE_ALLOCATION_BRICK);
|
|
|
+ memset (task_func+task_count, 0, sizeof(task_callback_t)*TASK_HANDLE_ALLOCATION_BRICK);
|
|
|
}
|
|
|
|
|
|
task_func[task_count++] = t;
|
|
|
- return TASK_HANDLE_MONIKER + ((task_count-1) << TASK_HANDLE_SHIFT);
|
|
|
- #endif
|
|
|
+ return TASK_HANDLE_MONIKER + (task_count-1);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+bool task_post (task_prio_t priority, task_handle_t handle, task_param_t param)
|
|
|
+{
|
|
|
+ if (priority >= TASK_PRIORITY_COUNT ||
|
|
|
+ !task_Q[priority] ||
|
|
|
+ (handle & TASK_HANDLE_MASK != TASK_HANDLE_MONIKER))
|
|
|
+ return false;
|
|
|
+
|
|
|
+ task_event_t ev = { handle, param };
|
|
|
+ bool res = pdPASS == xQueueSendToBackFromISR (task_Q[priority], &ev, NULL);
|
|
|
+
|
|
|
+ if (pending) /* only need to raise semaphore if it's been initialised */
|
|
|
+ xSemaphoreGiveFromISR (pending, NULL);
|
|
|
+
|
|
|
+ return res;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static bool next_event (task_event_t *ev, task_prio_t *prio)
|
|
|
+{
|
|
|
+ for (task_prio_t p = TASK_PRIORITY_COUNT; p != TASK_PRIORITY_LOW; --p)
|
|
|
+ {
|
|
|
+ if (xQueueReceive (task_Q[p-1], ev, 0) == pdTRUE)
|
|
|
+ {
|
|
|
+ *prio = p-1;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false; // no events queued
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static void dispatch (task_event_t *e, uint8_t prio) {
|
|
|
+ task_handle_t handle = e->sig;
|
|
|
+ if ( (handle & TASK_HANDLE_MASK) == TASK_HANDLE_MONIKER) {
|
|
|
+ uint16_t entry = (handle & TASK_HANDLE_UNMASK);
|
|
|
+ if ( task_func && entry < task_count ){
|
|
|
+ /* call the registered task handler with the specified parameter and priority */
|
|
|
+ task_func[entry](e->par, prio);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /* Invalid signals are ignored */
|
|
|
+ NODE_DBG ( "Invalid signal issued: %08x", handle);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void task_pump_messages (void)
|
|
|
+{
|
|
|
+ vSemaphoreCreateBinary (pending);
|
|
|
+ for (;;)
|
|
|
+ {
|
|
|
+ task_event_t ev;
|
|
|
+ task_prio_t prio;
|
|
|
+ if (next_event (&ev, &prio))
|
|
|
+ dispatch (&ev, prio);
|
|
|
+ else
|
|
|
+ xSemaphoreTake (pending, portMAX_DELAY);
|
|
|
+ }
|
|
|
}
|