Commit 5c39a1f6 authored by Johny Mattsson's avatar Johny Mattsson
Browse files

Reimplemented the NodeMCU task interface on top of RTOS.

Not yet hooked up to an RTOS task, however.
parent f3e2a3af
#ifndef _TASK_H_ #ifndef _TASK_H_
#define _TASK_H_ #define _TASK_H_
#include "ets_sys.h" #include <stdint.h>
#include "osapi.h" #include <stdbool.h>
#include "os_type.h" #include <c_types.h>
/* use LOW / MEDIUM / HIGH since it isn't clear from the docs which is higher */ /* use LOW / MEDIUM / HIGH since it isn't clear from the docs which is higher */
#define TASK_PRIORITY_LOW 0 typedef enum {
#define TASK_PRIORITY_MEDIUM 1 TASK_PRIORITY_LOW,
#define TASK_PRIORITY_HIGH 2 TASK_PRIORITY_MEDIUM,
#define TASK_PRIORITY_COUNT 3 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 * 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() * is just a fixed fingerprint and the count is allocated serially by the
* function. * 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_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_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_post_high(handle,param) task_post(TASK_PRIORITY_HIGH, handle, param)
#define task_handle_t os_signal_t typedef void (*task_callback_t)(task_param_t param, task_prio_t prio);
#define task_param_t os_param_t
typedef void (*task_callback_t)(task_param_t param, uint8 prio); bool task_init_handler(task_prio_t priority, uint8 qlen);
bool task_init_handler(uint8 priority, uint8 qlen);
task_handle_t task_get_id(task_callback_t t); task_handle_t task_get_id(task_callback_t t);
/* RTOS loop to pump task messages until infinity */
void task_pump_messages (void);
#endif #endif
...@@ -597,7 +597,7 @@ static int enduser_setup_http_urldecode(char *dst, const char *src, int src_len, ...@@ -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 * This config *cannot* be done in the network receive callback or serious
* issues like memory corruption occur. * 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; struct station_config *cnf = (struct station_config *)param;
(void)prio; (void)prio;
......
...@@ -32,7 +32,7 @@ static int gpio_cb_ref[GPIO_PIN_NUM]; ...@@ -32,7 +32,7 @@ static int gpio_cb_ref[GPIO_PIN_NUM];
// This task is scheduled by the ISR and is used // This task is scheduled by the ISR and is used
// to initiate the Lua-land gpio.trig() callback function // to initiate the Lua-land gpio.trig() callback function
// It also re-enables the pin interrupt, so that we get another callback queued // 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 pin = param >> 1;
unsigned level = param & 1; unsigned level = param & 1;
......
...@@ -451,7 +451,7 @@ static int node_compile( lua_State* L ) ...@@ -451,7 +451,7 @@ static int node_compile( lua_State* L )
// Task callback handler for node.task.post() // Task callback handler for node.task.post()
static task_handle_t do_node_task_handle; 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_State* L = lua_getstate();
lua_rawgeti(L, LUA_REGISTRYINDEX, (int)task_fn_ref); lua_rawgeti(L, LUA_REGISTRYINDEX, (int)task_fn_ref);
......
...@@ -349,7 +349,7 @@ static void lrotary_check_timer(DATA *d, uint32_t time_us, bool dotimer) ...@@ -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) param;
(void) prio; (void) prio;
......
...@@ -1309,7 +1309,7 @@ static const LUA_REG_TYPE wifi_map[] = { ...@@ -1309,7 +1309,7 @@ static const LUA_REG_TYPE wifi_map[] = {
{ LNILKEY, LNILVAL } { 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 #ifndef WIFI_STA_HOSTNAME
char temp[32]; char temp[32];
......
...@@ -183,7 +183,7 @@ static void wifi_event_monitor_handle_event_cb(System_Event_t *evt) ...@@ -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(); lua_State* L = lua_getstate();
evt_queue_t *temp = wifi_event_queue_head; //copy event_queue_head pointer to temporary pointer evt_queue_t *temp = wifi_event_queue_head; //copy event_queue_head pointer to temporary pointer
......
...@@ -15,6 +15,8 @@ ifndef PDIR ...@@ -15,6 +15,8 @@ ifndef PDIR
GEN_LIBS = libtask.a GEN_LIBS = libtask.a
endif endif
STD_CFLAGS=-std=gnu11 -Wimplicit
############################################################# #############################################################
# Configuration i.e. compile options etc. # Configuration i.e. compile options etc.
# Target specific stuff (defines etc.) goes in here! # Target specific stuff (defines etc.) goes in here!
......
...@@ -3,76 +3,135 @@ ...@@ -3,76 +3,135 @@
*/ */
#include "task/task.h" #include "task/task.h"
#include "mem.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_MONIKER 0x68680000
#define TASK_HANDLE_MASK 0xFFF80000 #define TASK_HANDLE_MASK 0xFFF80000
#define TASK_HANDLE_UNMASK (~TASK_HANDLE_MASK) #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_HANDLE_ALLOCATION_BRICK 4 // must be a power of 2
#define TASK_DEFAULT_QUEUE_LEN 8 #define TASK_DEFAULT_QUEUE_LEN 8
#define TASK_PRIORITY_MASK 3
#define CHECK(p,v,msg) if (!(p)) { NODE_DBG ( msg ); return (v); } #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 * Private arrays to hold the 3 event task queues and the dispatch callbacks
*/ */
LOCAL os_event_t *task_Q[TASK_PRIORITY_COUNT]; static xQueueHandle task_Q[TASK_PRIORITY_COUNT];
LOCAL task_callback_t *task_func;
LOCAL int task_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 * 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. * to be called explicitly as the get_id function will call this lazily.
*/ */
bool task_init_handler(uint8 priority, uint8 qlen) { bool task_init_handler(task_prio_t priority, uint8 qlen) {
#if 0 if (priority >= TASK_PRIORITY_COUNT)
if (priority <= TASK_PRIORITY_HIGH && task_Q[priority] == NULL) { return false;
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] == NULL)
if (task_Q[priority]) { {
return system_os_task( task_dispatch, priority, task_Q[priority], qlen ); task_Q[priority] = xQueueCreate (qlen, sizeof (task_event_t));
} return task_Q[priority] != NULL;
} }
#endif else
return false; return false;
} }
task_handle_t task_get_id(task_callback_t t) { task_handle_t task_get_id(task_callback_t t) {
#if 0
int p = TASK_PRIORITY_COUNT; int p = TASK_PRIORITY_COUNT;
/* Initialise and uninitialised Qs with the default Q len */ /* Initialise and uninitialised Qs with the default Q len */
while(p--) if (!task_Q[p]) { while(p--)
if (!task_Q[p]) {
CHECK(task_init_handler( p, TASK_DEFAULT_QUEUE_LEN ), 0, "Task initialisation failed"); CHECK(task_init_handler( p, TASK_DEFAULT_QUEUE_LEN ), 0, "Task initialisation failed");
} }
if ( (task_count & (TASK_HANDLE_ALLOCATION_BRICK - 1)) == 0 ) { 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 */ /* 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, task_func =(task_callback_t *)realloc(
task_func,
sizeof(task_callback_t)*(task_count+TASK_HANDLE_ALLOCATION_BRICK)); sizeof(task_callback_t)*(task_count+TASK_HANDLE_ALLOCATION_BRICK));
CHECK(task_func, 0 , "Malloc failure in task_get_id"); 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; task_func[task_count++] = t;
return TASK_HANDLE_MONIKER + ((task_count-1) << TASK_HANDLE_SHIFT); return TASK_HANDLE_MONIKER + (task_count-1);
#endif }
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);
}
} }
...@@ -52,14 +52,15 @@ void TEXT_SECTION_ATTR user_start_trampoline (void) ...@@ -52,14 +52,15 @@ void TEXT_SECTION_ATTR user_start_trampoline (void)
} }
// +================== New task interface ==================+ // +================== 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 }; char* lua_argv[] = { (char *)"lua", (char *)"-i", NULL };
NODE_DBG("Task task_lua started.\n"); NODE_DBG("Task task_lua started.\n");
lua_main( 2, lua_argv ); lua_main( 2, lua_argv );
} }
static void handle_input(task_param_t flag, uint8 priority) { static void handle_input(task_param_t flag, task_prio_t priority) {
// c_printf("HANDLE_INPUT: %u %u\n", flag, priority); REMOVE (void)priority;
lua_handle_input (flag); lua_handle_input (flag);
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment