Add New Tasking I/F and rework GPIO, UART, etc to support it
As with the last commit this rolls up the follwowing, but include the various
review comments on the PR.
- **Documentation changes**. I've added the taks FAQ as a stub new Extension
developer FAQ, and split the old FAQ into a Lua Developer FAQ and a Hardware
FAQ.
- **Tasking I/F**. New `app/task/Makefile`, `app/task/task.c`,
`app/include/task/task.h` and `app/Makefile` as per previous commit. Cascade
changes to `app/driver/uart.c`, `app/include/driver/uart.h`,
`app/user/user_main.c` and `app/modules/node.c`
- **GPIO Rework** to `app/modules/gpio.c` and `pin_map.[hc]`, `platform.[hc]`
in `app/platform`
- **Other Optimisations** Move the `platform_*_exists()` from
`app/platform/common.c` to static inline declarations in `platform.h` as
this generates faster, smaller code. Move lgc.a routines out of iram0.
2016-02-17 18:13:17 +01:00
|
|
|
/**
|
|
|
|
This file encapsulates the SDK-based task handling for the NodeMCU Lua firmware.
|
|
|
|
*/
|
|
|
|
#include "task/task.h"
|
|
|
|
#include "mem.h"
|
2019-07-21 23:58:21 +02:00
|
|
|
#include <stdio.h>
|
Add New Tasking I/F and rework GPIO, UART, etc to support it
As with the last commit this rolls up the follwowing, but include the various
review comments on the PR.
- **Documentation changes**. I've added the taks FAQ as a stub new Extension
developer FAQ, and split the old FAQ into a Lua Developer FAQ and a Hardware
FAQ.
- **Tasking I/F**. New `app/task/Makefile`, `app/task/task.c`,
`app/include/task/task.h` and `app/Makefile` as per previous commit. Cascade
changes to `app/driver/uart.c`, `app/include/driver/uart.h`,
`app/user/user_main.c` and `app/modules/node.c`
- **GPIO Rework** to `app/modules/gpio.c` and `pin_map.[hc]`, `platform.[hc]`
in `app/platform`
- **Other Optimisations** Move the `platform_*_exists()` from
`app/platform/common.c` to static inline declarations in `platform.h` as
this generates faster, smaller code. Move lgc.a routines out of iram0.
2016-02-17 18:13:17 +01:00
|
|
|
|
|
|
|
#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);
|
|
|
|
}
|