/** This file encapsulates the SDK-based task handling for the NodeMCU Lua firmware. */ #include "task/task.h" #include "mem.h" #include "c_stdio.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); } /* * 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; LOCAL void task_dispatch (os_event_t *e) { 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); } /* * 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 (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 ); } } return false; } task_handle_t task_get_id(task_callback_t t) { 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"); } 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)); 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); } task_func[task_count++] = t; return TASK_HANDLE_MONIKER + ((task_count-1) << TASK_HANDLE_SHIFT); }