Reimplemented the NodeMCU task interface on top of RTOS.
Not yet hooked up to an RTOS task, however.
This commit is contained in:
parent
f3e2a3afd9
commit
5c39a1f664
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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!
|
||||
|
|
141
app/task/task.c
141
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue