Merge pull request #1105 from TerryE/dev-node-task

Extend the node library to include a Lua implementation of task posting
This commit is contained in:
Terry Ellison 2016-03-06 17:17:55 +00:00
commit 76f2654f82
3 changed files with 96 additions and 9 deletions

View File

@ -17,10 +17,10 @@
* is just a fixed fingerprint and the count is allocated serially by the task get_id()
* function.
*/
#define task_post_low(handle,param) system_os_post(0, (handle | TASK_PRIORITY_LOW), param)
#define task_post_medium(handle,param) system_os_post(1, (handle | TASK_PRIORITY_MEDIUM), param)
#define task_post_high(handle,param) system_os_post(2, (handle | TASK_PRIORITY_HIGH), param)
#define task_post(priority,handle,param) system_os_post(priority, ((handle) | priority), 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

View File

@ -26,6 +26,7 @@
#include "flash_fs.h"
#include "user_version.h"
#include "rom.h"
#include "task/task.h"
#define CPU80MHZ 80
#define CPU160MHZ 160
@ -448,6 +449,42 @@ static int node_compile( lua_State* L )
return 0;
}
// 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)
{
lua_State* L = lua_getstate();
lua_rawgeti(L, LUA_REGISTRYINDEX, (int)task_fn_ref);
luaL_unref(L, LUA_REGISTRYINDEX, (int)task_fn_ref);
lua_pushinteger(L, prio);
lua_call(L, 1, 0);
}
// Lua: node.task.post([priority],task_cb) -- schedule a task for execution next
static int node_task_post( lua_State* L )
{
int n = 1, Ltype = lua_type(L, 1);
unsigned priority = TASK_PRIORITY_MEDIUM;
if (Ltype == LUA_TNUMBER) {
priority = (unsigned) luaL_checkint(L, 1);
luaL_argcheck(L, priority <= TASK_PRIORITY_HIGH, 1, "invalid priority");
Ltype = lua_type(L, ++n);
}
luaL_argcheck(L, Ltype == LUA_TFUNCTION || Ltype == LUA_TLIGHTFUNCTION, n, "invalid function");
lua_pushvalue(L, n);
int task_fn_ref = luaL_ref(L, LUA_REGISTRYINDEX);
if (!do_node_task_handle) // bind the task handle to do_node_task on 1st call
do_node_task_handle = task_get_id(do_node_task);
if(!task_post(priority, do_node_task_handle, (task_param_t)task_fn_ref)) {
luaL_unref(L, LUA_REGISTRYINDEX, task_fn_ref);
luaL_error(L, "Task queue overflow. Task not posted");
}
return 0;
}
// Lua: setcpufreq(mhz)
// mhz is either CPU80MHZ od CPU160MHZ
static int node_setcpufreq(lua_State* L)
@ -554,29 +591,37 @@ static int node_stripdebug (lua_State *L) {
#endif
// Lua: node.egc.setmode( mode, [param])
// where the mode is one of the node.egc constants NOT_ACTIVE , ON_ALLOC_FAILURE,
// where the mode is one of the node.egc constants NOT_ACTIVE , ON_ALLOC_FAILURE,
// ON_MEM_LIMIT, ALWAYS. In the case of ON_MEM_LIMIT an integer parameter is reqired
// See legc.h and lecg.c.
static int node_egc_setmode(lua_State* L) {
unsigned mode = luaL_checkinteger(L, 1);
unsigned limit = luaL_optinteger (L, 2, 0);
luaL_argcheck(L, mode <= (EGC_ON_ALLOC_FAILURE | EGC_ON_MEM_LIMIT | EGC_ALWAYS), 1, "invalid mode");
luaL_argcheck(L, !(mode & EGC_ON_MEM_LIMIT) || limit>0, 1, "limit must be non-zero");
legc_set_mode( L, mode, limit );
return 0;
}
// Module function map
static const LUA_REG_TYPE node_egc_map[] = {
{ LSTRKEY( "setmode" ), LFUNCVAL( node_egc_setmode ) },
{ LSTRKEY( "setmode" ), LFUNCVAL( node_egc_setmode ) },
{ LSTRKEY( "NOT_ACTIVE" ), LNUMVAL( EGC_NOT_ACTIVE ) },
{ LSTRKEY( "ON_ALLOC_FAILURE" ), LNUMVAL( EGC_ON_ALLOC_FAILURE ) },
{ LSTRKEY( "ON_MEM_LIMIT" ), LNUMVAL( EGC_ON_MEM_LIMIT ) },
{ LSTRKEY( "ALWAYS" ), LNUMVAL( EGC_ALWAYS ) },
{ LNILKEY, LNILVAL }
};
static const LUA_REG_TYPE node_task_map[] = {
{ LSTRKEY( "post" ), LFUNCVAL( node_task_post ) },
{ LSTRKEY( "LOW_PRIORITY" ), LNUMVAL( TASK_PRIORITY_LOW ) },
{ LSTRKEY( "MEDIUM_PRIORITY" ), LNUMVAL( TASK_PRIORITY_MEDIUM ) },
{ LSTRKEY( "HIGH_PRIORITY" ), LNUMVAL( TASK_PRIORITY_HIGH ) },
{ LNILKEY, LNILVAL }
};
static const LUA_REG_TYPE node_map[] =
{
{ LSTRKEY( "restart" ), LFUNCVAL( node_restart ) },
@ -603,7 +648,8 @@ static const LUA_REG_TYPE node_map[] =
#ifdef LUA_OPTIMIZE_DEBUG
{ LSTRKEY( "stripdebug" ), LFUNCVAL( node_stripdebug ) },
#endif
{ LSTRKEY( "egc" ), LROVAL( node_egc_map ) },
{ LSTRKEY( "egc" ), LROVAL( node_egc_map ) },
{ LSTRKEY( "task" ), LROVAL( node_task_map ) },
// Combined to dsleep(us, option)
// { LSTRKEY( "dsleepsetoption" ), LFUNCVAL( node_deepsleep_setoption) },

View File

@ -403,3 +403,44 @@ provides more detailed information on the EGC.
`node.egc.setmode(node.egc.ALWAYS, 4096) -- This is the default setting at startup.`
`node.egc.setmode(node.egc.ON_ALLOC_FAILURE) -- This is the fastest activeEGC mode.`
# node.task module
## node.task.post()
Enable a Lua callback or task to post another task request. Note that as per the
example multiple tasks can be posted in any task, but the highest priority is
always delivered first.
If the task queue is full then a queue full error is raised.
####Syntax
`node.task.post([task_priority], function)`
#### Parameters
- `task_priority` (optional)
- `node.task.LOW_PRIORITY` = 0
- `node.task.MEDIUM_PRIORITY` = 1
- `node.task.HIGH_PRIORITY` = 2
- `function` a callback function to be executed when the task is run.
If the priority is omitted then this defaults to `node.task.MEDIUM_PRIORITY`
#### Returns
`nil`
#### Example
```lua
for i = node.task.LOW_PRIORITY, node.task.HIGH_PRIORITY do
node.task.post(i,function(p2)
print("priority is "..p2)
end)
end
```
prints
```
priority is 2
priority is 1
priority is 0
```