Browse Source

Reimplemented the NodeMCU task interface on top of RTOS.

Not yet hooked up to an RTOS task, however.
Johny Mattsson 8 years ago
parent
commit
5c39a1f664

+ 22 - 16
app/include/task/task.h

@@ -1,34 +1,40 @@
 #ifndef _TASK_H_
 #define _TASK_H_
 
-#include "ets_sys.h"
-#include "osapi.h"
-#include "os_type.h"
+#include <stdint.h>
+#include <stdbool.h>
+#include <c_types.h>
 
 /* use LOW / MEDIUM / HIGH since it isn't clear from the docs which is higher */
 
-#define TASK_PRIORITY_LOW     0
-#define TASK_PRIORITY_MEDIUM  1
-#define TASK_PRIORITY_HIGH    2
-#define TASK_PRIORITY_COUNT   3
+typedef enum {
+  TASK_PRIORITY_LOW,
+  TASK_PRIORITY_MEDIUM,
+  TASK_PRIORITY_HIGH,
+  TASK_PRIORITY_COUNT
+} task_prio_t;
+
+typedef uint32_t task_handle_t;
+typedef intptr_t task_param_t;
 
 /*
-* Signals are a 32-bit number of the form header:14; count:16, priority:2.  The header
-* is just a fixed fingerprint and the count is allocated serially by the task get_id()
-* function.
+* Signals are a 32-bit number of the form header:14; count:18. The header
+* is just a fixed fingerprint and the count is allocated serially by the
+* task_get_id() function.
 */
-#define task_post(priority,handle,param) 1/*system_os_post(priority, ((handle) | priority), param)*/
+bool task_post(task_prio_t priority, task_handle_t handle, task_param_t param);
+
 #define task_post_low(handle,param)    task_post(TASK_PRIORITY_LOW,    handle, param)
 #define task_post_medium(handle,param) task_post(TASK_PRIORITY_MEDIUM, handle, param)
 #define task_post_high(handle,param)   task_post(TASK_PRIORITY_HIGH,   handle, param)
 
-#define task_handle_t os_signal_t
-#define task_param_t os_param_t
+typedef void (*task_callback_t)(task_param_t param, task_prio_t prio);
 
-typedef void (*task_callback_t)(task_param_t param, uint8 prio);
-
-bool task_init_handler(uint8 priority, uint8 qlen);
+bool task_init_handler(task_prio_t priority, uint8 qlen);
 task_handle_t task_get_id(task_callback_t t);
 
+/* RTOS loop to pump task messages until infinity */
+void task_pump_messages (void);
+
 #endif
 

+ 1 - 1
app/modules/enduser_setup.c

@@ -597,7 +597,7 @@ static int enduser_setup_http_urldecode(char *dst, const char *src, int src_len,
  * This config *cannot* be done in the network receive callback or serious
  * issues like memory corruption occur.
  */
-static void do_station_cfg (task_param_t param, uint8_t prio)
+static void do_station_cfg (task_param_t param, task_prio_t prio)
 {
   struct station_config *cnf = (struct station_config *)param;
   (void)prio;

+ 1 - 1
app/modules/gpio.c

@@ -32,7 +32,7 @@ static int gpio_cb_ref[GPIO_PIN_NUM];
 // This task is scheduled by the ISR and is used
 // to initiate the Lua-land gpio.trig() callback function
 // It also re-enables the pin interrupt, so that we get another callback queued
-static void gpio_intr_callback_task (task_param_t param, uint8 priority)
+static void gpio_intr_callback_task (task_param_t param, task_prio_t priority)
 {
   unsigned pin = param >> 1;
   unsigned level = param & 1;

+ 1 - 1
app/modules/node.c

@@ -451,7 +451,7 @@ static int node_compile( lua_State* L )
 
 // Task callback handler for node.task.post()
 static task_handle_t do_node_task_handle;
-static void do_node_task (task_param_t task_fn_ref, uint8_t prio)
+static void do_node_task (task_param_t task_fn_ref, task_prio_t prio)
 {
   lua_State* L = lua_getstate();
   lua_rawgeti(L, LUA_REGISTRYINDEX, (int)task_fn_ref);

+ 1 - 1
app/modules/rotary.c

@@ -349,7 +349,7 @@ static void lrotary_check_timer(DATA *d, uint32_t time_us, bool dotimer)
   }
 }
 
-static void lrotary_task(os_param_t param, uint8_t prio) 
+static void lrotary_task(task_param_t param, task_prio_t prio) 
 {
   (void) param;
   (void) prio;

+ 1 - 1
app/modules/wifi.c

@@ -1309,7 +1309,7 @@ static const LUA_REG_TYPE wifi_map[] =  {
   { LNILKEY, LNILVAL }
 };
 
-static void wifi_change_default_host_name(task_param_t param, uint8 priority)
+static void wifi_change_default_host_name(task_param_t param, task_prio_t priority)
 {
 #ifndef WIFI_STA_HOSTNAME
   char temp[32];

+ 1 - 1
app/modules/wifi_eventmon.c

@@ -183,7 +183,7 @@ static void wifi_event_monitor_handle_event_cb(System_Event_t *evt)
 }
 
 
-static void wifi_event_monitor_process_event_queue(task_param_t param, uint8 priority)
+static void wifi_event_monitor_process_event_queue(task_param_t param, task_prio_t priority)
 {
   lua_State* L = lua_getstate();
   evt_queue_t *temp = wifi_event_queue_head; //copy event_queue_head pointer to temporary pointer

+ 2 - 0
app/task/Makefile

@@ -15,6 +15,8 @@ ifndef PDIR
 GEN_LIBS = libtask.a
 endif
 
+STD_CFLAGS=-std=gnu11 -Wimplicit
+
 #############################################################
 # Configuration i.e. compile options etc.
 # Target specific stuff (defines etc.) goes in here!

+ 100 - 41
app/task/task.c

@@ -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);
+  }
 }

+ 4 - 3
app/user/user_main.c

@@ -52,14 +52,15 @@ void TEXT_SECTION_ATTR user_start_trampoline (void)
 }
 
 // +================== New task interface ==================+
-static void start_lua(task_param_t param, uint8 priority) {
+static void start_lua(task_param_t param, task_prio_t prio) {
+  (void)prio;
   char* lua_argv[] = { (char *)"lua", (char *)"-i", NULL };
   NODE_DBG("Task task_lua started.\n");
   lua_main( 2, lua_argv );
 }
 
-static void handle_input(task_param_t flag, uint8 priority) {
-//  c_printf("HANDLE_INPUT: %u %u\n", flag, priority);          REMOVE
+static void handle_input(task_param_t flag, task_prio_t priority) {
+  (void)priority;
   lua_handle_input (flag);
 }