Commit e7c29fe3 authored by Terry Ellison's avatar Terry Ellison Committed by Marcel Stör
Browse files

Lua 5.1 to 5.3 realignement phase 1

parent 3d917850
/**
This file encapsulates the SDK-based task handling for the NodeMCU Lua firmware.
*/
#include "task/task.h"
#include "mem.h"
#include <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);
}
......@@ -20,6 +20,7 @@
#include "ets_sys.h"
#include "driver/uart.h"
#include "driver/input.h"
#include "task/task.h"
#include "mem.h"
#include "espconn.h"
......@@ -29,9 +30,6 @@
#include "rtc/rtctime.h"
#endif
static task_handle_t input_sig;
static uint8 input_sig_flag = 0;
/* Contents of esp_init_data_default.bin */
extern const uint32_t init_data[], init_data_end[];
#define INIT_DATA_SIZE ((init_data_end - init_data)*sizeof(uint32_t))
......@@ -275,40 +273,11 @@ uint32 ICACHE_RAM_ATTR user_iram_memory_is_enabled(void) {
return FALSE; // NodeMCU runs like a dog if iRAM is enabled
}
// +================== New task interface ==================+
static void start_lua(task_param_t param, uint8 priority) {
char* lua_argv[] = { (char *)"lua", (char *)"-i", NULL };
NODE_DBG("Task task_lua started.\n");
lua_main( 2, lua_argv );
// Only enable UART interrupts once we've successfully started up,
// otherwise the task queue might fill up with input events and prevent
// the start_lua task from being posted.
ETS_UART_INTR_ENABLE();
}
static void handle_input(task_param_t flag, uint8 priority) {
(void)priority;
if (flag & 0x8000) {
input_sig_flag = flag & 0x4000 ? 1 : 0;
}
lua_handle_input (flag & 0x01);
}
bool user_process_input(bool force) {
return task_post_low(input_sig, force);
}
void nodemcu_init(void) {
NODE_ERR("\n");
// Initialize platform first for lua modules.
if( platform_init() != PLATFORM_OK )
{
// This should never happen
NODE_DBG("Can not init platform for modules.\n");
return;
}
if (!task_post_low(task_get_id(start_lua),'s'))
NODE_ERR("Failed to post the start_lua task!\n");
NODE_DBG("Task task_lua starting.\n");
// Call the Lua bootstrap startup directly. This uses the task interface
// internally to carry out the main lua libraries initialisation.
lua_main();
}
#ifdef LUA_USE_MODULES_WIFI
......@@ -328,18 +297,17 @@ void user_rf_pre_init(void)
* Parameters : none
* Returns : none
*******************************************************************************/
void user_init(void)
{
void user_init(void) {
#ifdef LUA_USE_MODULES_RTCTIME
rtctime_late_startup ();
#endif
if( platform_init() != PLATFORM_OK ) {
// This should never happen
NODE_DBG("Can not init platform for modules.\n");
return;
}
UartBautRate br = BIT_RATE_DEFAULT;
input_sig = task_get_id(handle_input);
uart_init (br, br, input_sig, &input_sig_flag);
uart_init (br, br);
#ifndef NODE_DEBUG
system_set_os_print(0);
#endif
......
......@@ -341,11 +341,7 @@ print(node.info("sw_version").git_release)
## node.input()
Submits a string to the Lua interpreter. Similar to `pcall(loadstring(str))`, but without the single-line limitation.
!!! attention
This function only has an effect when invoked from a callback. Using it directly on the console **does not work**.
Submits a string to the Lua interpreter. Similar to `pcall(loadstring(str))`, but without the single-line limitation. Note that the Line interpreter only actions complete Lua chunks. A Lue Lua chunk must comprise one or more complete `'\n'` terminaed lines that form a complete compilation unit.
#### Syntax
`node.input(str)`
......@@ -360,56 +356,29 @@ Submits a string to the Lua interpreter. Similar to `pcall(loadstring(str))`, bu
```lua
sk:on("receive", function(conn, payload) node.input(payload) end)
```
See the `telnet/telnet.lua` in `lua_examples` for a more comprehensive example.
#### See also
[`node.output()`](#nodeoutput)
## node.output()
Redirects the Lua interpreter output to a callback function. Optionally also prints it to the serial console.
!!! caution
Do **not** attempt to `print()` or otherwise induce the Lua interpreter to produce output from within the callback function. Doing so results in infinite recursion, and leads to a watchdog-triggered restart.
Redirects the Lua interpreter to a `stdout` pipe when a CB function is specified (See `pipe` module) and resets output to normal otherwise. Optionally also prints to the serial console.
#### Syntax
`node.output(function(str), serial_debug)`
`node.output(function(pipe), serial_debug)`
#### Parameters
- `output_fn(str)` a function accept every output as str, and can send the output to a socket (or maybe a file).
- `output_fn(pipe)` a function accept every output as str, and can send the output to a socket (or maybe a file). Note that this function must conform to the fules for a pipe reader callback.
- `serial_debug` 1 output also show in serial. 0: no serial output.
#### Returns
`nil`
#### Example
```lua
function tonet(str)
sk:send(str)
end
node.output(tonet, 1) -- serial also get the Lua output.
```
```lua
-- a simple telnet server
s=net.createServer(net.TCP)
s:listen(2323,function(c)
con_std = c
function s_output(str)
if(con_std~=nil)
then con_std:send(str)
end
end
node.output(s_output, 0) -- re-direct output to function s_ouput.
c:on("receive",function(c,l)
node.input(l) -- works like pcall(loadstring(l)) but support multiple separate line
end)
c:on("disconnection",function(c)
con_std = nil
node.output(nil) -- un-regist the redirect output function, output goes to serial
end)
end)
```
See the `telnet/telnet.lua` in `lua_examples` for a more comprehensive example of its use.
#### See also
[`node.input()`](#nodeinput)
......
......@@ -11,15 +11,15 @@ task to another.
Create a pipe.
#### Syntax
`pobj = pipe.create()`
`pobj = pipe.create([CB_function],[task_priority])`
#### Parameters
None
- `CB_function` optional reader callback which is called through the `ǹode.task.post()` when the pipe is written to. If the CB returns a boolean, then the reposting action is forced: it is reposted if true and not if false. If the return is nil or omitted then the deault is to repost if a pipe write has occured since the last call.
- `task_priority` See `ǹode.task.post()`
#### Returns
A pipe resource.
## pobj:read()
Read a record from a pipe object.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment