Reimplemented the NodeMCU task interface on top of RTOS.

Not yet hooked up to an RTOS task, however.
This commit is contained in:
Johny Mattsson 2016-05-24 18:07:27 +10:00
parent f3e2a3afd9
commit 5c39a1f664
10 changed files with 134 additions and 66 deletions

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

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

View File

@ -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;

View File

@ -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];

View File

@ -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

View File

@ -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!

View File

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

View File

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