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
......@@ -70,7 +70,7 @@ struct OUTPUT {
outBlock buffer;
int ndx;
uint32_t crc;
int (*fullBlkCB) (void);
void (*fullBlkCB) (void);
int flashLen;
int flagsLen;
int flagsNdx;
......@@ -79,7 +79,6 @@ struct OUTPUT {
} *out;
#ifdef NODE_DEBUG
extern void dbg_printf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
void dumpStrt(stringtable *tb, const char *type) {
int i,j;
GCObject *o;
......@@ -173,15 +172,15 @@ LUAI_FUNC void luaN_init (lua_State *L) {
}
if ((fh->flash_sig & (~FLASH_SIG_ABSOLUTE)) != FLASH_SIG ) {
NODE_ERR("Flash sig not correct: %p vs %p\n",
NODE_ERR("Flash sig not correct: 0x%08x vs 0x%08x\n",
fh->flash_sig & (~FLASH_SIG_ABSOLUTE), FLASH_SIG);
return;
}
if (fh->pROhash == ALL_SET ||
((fh->mainProto - cast(FlashAddr, fh)) >= fh->flash_size)) {
NODE_ERR("Flash size check failed: %p vs 0xFFFFFFFF; %p >= %p\n",
fh->mainProto - cast(FlashAddr, fh), fh->flash_size);
NODE_ERR("Flash size check failed: 0x%08x vs 0xFFFFFFFF; 0x%08x >= 0x%08x\n",
fh->pROhash, fh->mainProto - cast(FlashAddr, fh), fh->flash_size);
return;
}
......@@ -194,7 +193,7 @@ LUAI_FUNC void luaN_init (lua_State *L) {
//extern void software_reset(void);
static int loadLFS (lua_State *L);
static int loadLFSgc (lua_State *L);
static int procFirstPass (void);
static void procFirstPass (void);
/*
* Library function called by node.flashreload(filename).
......@@ -270,7 +269,6 @@ LUALIB_API int luaN_reload_reboot (lua_State *L) {
* - An array of the module names in the LFS
*/
LUAI_FUNC int luaN_index (lua_State *L) {
int i;
int n = lua_gettop(L);
/* Return nil + the LFS base address if the LFS size > 0 and it isn't loaded */
......@@ -406,11 +404,10 @@ static uint8_t recall_byte (unsigned offset) {
* - Once the flags array is in-buffer this is also captured.
* This logic is slightly complicated by the last buffer is typically short.
*/
int procFirstPass (void) {
void procFirstPass (void) {
int len = (out->ndx % WRITE_BLOCKSIZE) ?
out->ndx % WRITE_BLOCKSIZE : WRITE_BLOCKSIZE;
if (out->ndx <= WRITE_BLOCKSIZE) {
uint32_t fl;
/* Process the flash header and cache the FlashHeader fields we need */
FlashHeader *fh = cast(FlashHeader *, out->block[0]);
out->flashLen = fh->flash_size; /* in bytes */
......@@ -442,12 +439,10 @@ int procFirstPass (void) {
memcpy(out->flags + out->flagsNdx, out->block[0]->byte + start, len - start);
out->flagsNdx += (len -start) / WORDSIZE; /* flashLen and len are word aligned */
}
return 1;
}
int procSecondPass (void) {
void procSecondPass (void) {
/*
* The length rules are different for the second pass since this only processes
* upto the flashLen and not the full image. This also works in word units.
......@@ -456,7 +451,7 @@ int procSecondPass (void) {
int i, len = (out->ndx > out->flashLen) ?
(out->flashLen % WRITE_BLOCKSIZE) / WORDSIZE :
WRITE_BLOCKSIZE / WORDSIZE;
uint32_t *buf = (uint32_t *) out->buffer.byte, flags;
uint32_t *buf = (uint32_t *) out->buffer.byte, flags = 0;
/*
* Relocate all the addresses tagged in out->flags. This can't be done in
* place because the out->blocks are still in use as dictionary content so
......@@ -492,7 +487,7 @@ int procSecondPass (void) {
*/
static int loadLFS (lua_State *L) {
const char *fn = cast(const char *, lua_touserdata(L, 1));
int i, n, res;
int i, res;
uint32_t crc;
/* Allocate and zero in and out structures */
......@@ -541,12 +536,11 @@ static int loadLFS (lua_State *L) {
flashErase(0,(out->flashLen - 1)/FLASH_PAGE_SIZE);
flashSetPosition(0);
if (uzlib_inflate(get_byte, put_byte, recall_byte,
in->len, &crc, &in->inflate_state) != UZLIB_OK)
if (res < 0) {
if ((res = uzlib_inflate(get_byte, put_byte, recall_byte,
in->len, &crc, &in->inflate_state)) != UZLIB_OK) {
const char *err[] = {"Data_error during decompression",
"Chksum_error during decompression",
"Dictionary error during decompression"
"Dictionary error during decompression",
"Memory_error during decompression"};
flash_error(err[UZLIB_DATA_ERROR - res]);
}
......
/*
** $Id: ltm.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $
** Tag methods
** See Copyright Notice in lua.h
*/
#define lnodemcu_c
#define LUA_CORE
#include "lua.h"
#include <string.h>
#include "lobject.h"
#include "lstate.h"
#include "lauxlib.h"
#include "lgc.h"
#include "lstring.h"
#include "ltable.h"
#include "ltm.h"
#include "lrotable.h"
#include "platform.h"
extern int debug_errorfb (lua_State *L);
#if 0
extern int pipe_create(lua_State *L);
extern int pipe_read(lua_State *L);
extern int pipe_unread(lua_State *L);
extern int pipe_write(lua_State *L);
#endif
/*
** Error Reporting Task. We can't pass a string parameter to the error reporter
** directly through the task interface the call is wrapped in a C closure with
** the error string as an Upval and this is posted to call the Lua reporter.
*/
static int report_traceback (lua_State *L) {
// **Temp** lua_rawgeti(L, LUA_REGISTRYINDEX, G(L)->error_reporter);
lua_getglobal(L, "print");
lua_pushvalue(L, lua_upvalueindex(1));
lua_call(L, 1, 0); /* Using an error handler would cause an infinite loop! */
return 0;
}
/*
** Catch all error handler for CB calls. This uses debug.traceback() to
** generate a full Lua traceback.
*/
int luaN_traceback (lua_State *L) {
if (lua_isstring(L, 1)) {
lua_pushlightfunction(L, &debug_errorfb);
lua_pushvalue(L, 1); /* pass error message */
lua_pushinteger(L, 2); /* skip this function and traceback */
lua_call(L, 2, 1); /* call debug.traceback and return it as a string */
lua_pushcclosure(L, report_traceback, 1); /* report with str as upval */
luaN_posttask(L, LUA_TASK_HIGH);
}
return 0;
}
/*
** Use in CBs and other C functions to call a Lua function. This includes
** an error handler which will catch any error and then post this to the
** registered reporter function as a separate follow-on task.
*/
int luaN_call (lua_State *L, int narg, int res, int doGC) { // [-narg, +0, v]
int status;
int base = lua_gettop(L) - narg;
lua_pushcfunction(L, luaN_traceback);
lua_insert(L, base); /* put under args */
status = lua_pcall(L, narg, (res < 0 ? LUA_MULTRET : res), base);
lua_remove(L, base); /* remove traceback function */
/* force a complete garbage collection if requested */
if (doGC)
lua_gc(L, LUA_GCCOLLECT, 0);
return status;
}
static platform_task_handle_t task_handle = 0;
/*
** Task callback handler. Uses luaN_call to do a protected call with full traceback
*/
static void do_task (platform_task_param_t task_fn_ref, uint8_t prio) {
lua_State* L = lua_getstate();
if (prio < 0|| prio > 2)
luaL_error(L, "invalid posk task");
/* Pop the CB func from the Reg */
//dbg_printf("calling Reg[%u]\n", task_fn_ref);
lua_rawgeti(L, LUA_REGISTRYINDEX, (int) task_fn_ref);
luaL_checkanyfunction(L, -1);
luaL_unref(L, LUA_REGISTRYINDEX, (int) task_fn_ref);
lua_pushinteger(L, prio);
luaN_call (L, 1, 0, 1);
}
/*
** Schedule a Lua function for task execution
*/
#include "lstate.h" /*DEBUG*/
LUA_API int luaN_posttask( lua_State* L, int prio ) { // [-1, +0, -]
if (!task_handle)
task_handle = platform_task_get_id(do_task);
if (!lua_isanyfunction(L, -1) || prio < LUA_TASK_LOW|| prio > LUA_TASK_HIGH)
luaL_error(L, "invalid posk task");
//void *cl = clvalue(L->top-1);
int task_fn_ref = luaL_ref(L, LUA_REGISTRYINDEX);
//dbg_printf("posting Reg[%u]=%p\n",task_fn_ref,cl);
if(!platform_post(prio, task_handle, (platform_task_param_t)task_fn_ref)) {
luaL_unref(L, LUA_REGISTRYINDEX, task_fn_ref);
luaL_error(L, "Task queue overflow. Task not posted");
}
return task_fn_ref;
}
......@@ -397,7 +397,7 @@ static int loader_Lua (lua_State *L) {
#ifdef LUA_CROSS_COMPILER
if (luaL_loadfile(L, filename) != 0)
#else
if (luaL_loadfsfile(L, filename) != 0)
if (luaL_loadfile(L, filename) != 0)
#endif
loaderror(L, filename);
return 1; /* library loaded successfully */
......
......@@ -113,7 +113,7 @@ typedef struct lua_TValue {
#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA)
#define ttisrotable(o) (ttype(o) == LUA_TROTABLE)
#define ttislightfunction(o) (ttype(o) == LUA_TLIGHTFUNCTION)
#define ttisanyfunction(o) (ttisfunction(o) || ttislightfunction(o))
/* Macros to access values */
......
......@@ -202,6 +202,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
g->ROstrt.hash = NULL;
g->ROpvmain = NULL;
g->LFSsize = 0;
g->error_reporter = 0;
#endif
for (i=0; i<NUM_TAGS; i++) g->mt[i] = NULL;
if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
......
......@@ -98,6 +98,7 @@ typedef struct global_State {
stringtable ROstrt; /* Flash-based hash table for RO strings */
Proto *ROpvmain; /* Flash-based Proto main */
int LFSsize; /* Size of Lua Flash Store */
int error_reporter; /* Registry Index of error reporter task */
#endif
} global_State;
......
This diff is collapsed.
......@@ -273,9 +273,11 @@ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION)
#define lua_islightfunction(L,n) (lua_type(L, (n)) == LUA_TLIGHTFUNCTION)
#define lua_isanyfunction(L,n) (lua_isfunction(L,n) || lua_islightfunction(L,n))
#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE)
#define lua_isrotable(L,n) (lua_type(L, (n)) == LUA_TROTABLE)
#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA)
#define lua_isanytable(L,n) (lua_istable(L,n) || lua_isrotable(L,n))
#define lua_islightuserdata(L,n) (lua_type(L, (n) == LUA_TLIGHTUSERDATA)
#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL)
#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN)
#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD)
......@@ -375,20 +377,19 @@ struct lua_Debug {
/* }====================================================================== */
typedef struct __lua_load{
lua_State *L;
int firstline;
char *line;
int line_position;
size_t len;
int done;
const char *prmt;
}lua_Load;
int lua_main( int argc, char **argv );
#ifndef LUA_CROSS_COMPILER
void lua_handle_input (bool force);
#define LUA_QUEUE_APP 0
#define LUA_QUEUE_UART 1
#define LUA_TASK_LOW 0
#define LUA_TASK_MEDIUM 1
#define LUA_TASK_HIGH 2
void lua_main (void);
void lua_input_string (const char *line, int len);
int luaN_posttask (lua_State* L, int prio);
int luaN_call (lua_State *L, int narg, int res, int dogc);
/**DEBUG**/extern void dbg_printf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
#endif
/******************************************************************************
......
......@@ -5,6 +5,7 @@
#include "lauxlib.h"
#include "lmem.h"
#include "platform.h"
#include "task/task.h"
#include "user_interface.h"
#include <stdint.h>
#include <string.h>
......
......@@ -45,7 +45,7 @@ typedef struct {
static int active_pulser_ref;
static pulse_t *active_pulser;
static task_handle_t tasknumber;
static platform_task_handle_t tasknumber;
static int gpio_pulse_push_state(lua_State *L, pulse_t *pulser) {
uint32_t now;
......@@ -321,7 +321,7 @@ static void ICACHE_RAM_ATTR gpio_pulse_timeout(os_param_t p) {
active_pulser->steps++;
}
platform_hw_timer_close(TIMER_OWNER);
task_post_low(tasknumber, (task_param_t)0);
platform_post_low(tasknumber, 0);
return;
}
active_pulser->steps++;
......@@ -341,7 +341,7 @@ static void ICACHE_RAM_ATTR gpio_pulse_timeout(os_param_t p) {
int16_t stop = active_pulser->stop_pos;
if (stop == -2 || stop == active_pulser->entry_pos) {
platform_hw_timer_close(TIMER_OWNER);
task_post_low(tasknumber, (task_param_t)0);
platform_post_low(tasknumber, 0);
return;
}
......@@ -488,7 +488,7 @@ LROT_END( gpio_pulse, gpio_pulse, LROT_MASK_INDEX )
int gpio_pulse_init(lua_State *L)
{
luaL_rometatable(L, "gpio.pulse", LROT_TABLEREF(pulse));
tasknumber = task_get_id(gpio_pulse_task);
tasknumber = platform_task_get_id(gpio_pulse_task);
return 0;
}
......
......@@ -736,6 +736,14 @@ int net_getaddr( lua_State *L ) {
lua_pushstring(L, addr_str);
return 2;
}
#if 0
static void dbg_print_ud(const char *title, lnet_userdata *ud) {
int i;
dbg_printf("%s: Userdata %p:", title, ud);
for (i=0; i<(sizeof(*ud)/sizeof(uint32_t)); i++)
dbg_printf( " 0x%08x", ((uint32_t *)ud)[i]);
dbg_printf("\n");
#endif
// Lua: client/server/socket:close()
int net_close( lua_State *L ) {
......@@ -764,11 +772,14 @@ int net_close( lua_State *L ) {
}
if (ud->type == TYPE_TCP_SERVER ||
(ud->pcb == NULL && ud->client.wait_dns == 0)) {
lua_gc(L, LUA_GCSTOP, 0);
// lua_gc(L, LUA_GCSTOP, 0);
luaL_unref(L, LUA_REGISTRYINDEX, ud->self_ref);
ud->self_ref = LUA_NOREF;
lua_gc(L, LUA_GCRESTART, 0);
// lua_gc(L, LUA_GCRESTART, 0);
}
#if 0
dbg_print_ud("close exit", ud);
#endif
return 0;
}
......@@ -813,10 +824,13 @@ int net_delete( lua_State *L ) {
ud->server.cb_accept_ref = LUA_NOREF;
break;
}
lua_gc(L, LUA_GCSTOP, 0);
// lua_gc(L, LUA_GCSTOP, 0);
luaL_unref(L, LUA_REGISTRYINDEX, ud->self_ref);
ud->self_ref = LUA_NOREF;
lua_gc(L, LUA_GCRESTART, 0);
// lua_gc(L, LUA_GCRESTART, 0);
#if 0
dbg_print_ud("delete end", ud);
#endif
return 0;
}
......
......@@ -227,69 +227,59 @@ static int node_heap( lua_State* L )
return 1;
}
extern int lua_put_line(const char *s, size_t l);
extern bool user_process_input(bool force);
// Lua: input("string")
static int node_input( lua_State* L ) {
size_t l = 0;
const char *s = luaL_checklstring(L, 1, &l);
if (lua_put_line(s, l)) {
NODE_DBG("Result (if any):\n");
user_process_input(true);
}
luaL_checkstring(L, 1);
lua_getfield(L, LUA_REGISTRYINDEX, "stdin");
lua_rawgeti(L, -1, 1); /* get the pipe_write func from stdin[1] */
lua_insert(L, -2); /* and move above the pipe ref */
lua_pushvalue(L, 1);
lua_call(L, 2, 0); /* stdin:write(line) */
return 0;
}
static int output_redir_ref = LUA_NOREF;
static int serial_debug = 1;
void output_redirect(const char *str) {
lua_State *L = lua_getstate();
// if(strlen(str)>=TX_BUFF_SIZE){
// NODE_ERR("output too long.\n");
// return;
// }
if (output_redir_ref == LUA_NOREF) {
int n = lua_gettop(L);
lua_pushliteral(L, "stdout");
lua_rawget(L, LUA_REGISTRYINDEX); /* fetch reg.stdout */
if (lua_istable(L, -1)) { /* reg.stdout is pipe */
if (serial_debug) {
uart0_sendStr(str);
return;
}
lua_rawgeti(L, -1, 1); /* get the pipe_write func from stdout[1] */
lua_insert(L, -2); /* and move above the pipe ref */
lua_pushstring(L, str);
lua_call(L, 2, 0); /* Reg.stdout:write(str) */
if (serial_debug != 0) {
} else { /* reg.stdout == nil */
uart0_sendStr(str);
}
lua_rawgeti(L, LUA_REGISTRYINDEX, output_redir_ref);
lua_pushstring(L, str);
lua_call(L, 1, 0); // this call back function should never user output.
lua_settop(L, n); /* Make sure all code paths leave stack unchanged */
}
extern int pipe_create(lua_State *L);
// Lua: output(function(c), debug)
static int node_output( lua_State* L )
{
// luaL_checkanyfunction(L, 1);
if (lua_type(L, 1) == LUA_TFUNCTION || lua_type(L, 1) == LUA_TLIGHTFUNCTION) {
lua_pushvalue(L, 1); // copy argument (func) to the top of stack
if (output_redir_ref != LUA_NOREF)
luaL_unref(L, LUA_REGISTRYINDEX, output_redir_ref);
output_redir_ref = luaL_ref(L, LUA_REGISTRYINDEX);
} else { // unref the key press function
if (output_redir_ref != LUA_NOREF)
luaL_unref(L, LUA_REGISTRYINDEX, output_redir_ref);
output_redir_ref = LUA_NOREF;
serial_debug = 1;
return 0;
}
if ( lua_isnumber(L, 2) )
{
serial_debug = lua_tointeger(L, 2);
if (serial_debug != 0)
serial_debug = (lua_isnumber(L, 2) && lua_tointeger(L, 2) == 0) ? 0 : 1;
lua_settop(L, 1);
if (lua_isanyfunction(L, 1)) {
lua_pushlightfunction(L, &pipe_create);
lua_insert(L, 1);
lua_pushinteger(L, LUA_TASK_MEDIUM);
lua_call(L, 2, 1); /* T[1] = pipe.create(dojob, low_priority) */
} else { // remove the stdout pipe
lua_pop(L,1);
lua_pushnil(L); /* T[1] = nil */
serial_debug = 1;
} else {
serial_debug = 1; // default to 1
}
lua_pushliteral(L, "stdout");
lua_insert(L, 1);
lua_rawset(L, LUA_REGISTRYINDEX); /* Reg.stdout = nil or pipe */
return 0;
}
......@@ -330,7 +320,7 @@ static int node_compile( lua_State* L )
output[strlen(output) - 1] = '\0';
NODE_DBG(output);
NODE_DBG("\n");
if (luaL_loadfsfile(L, fname) != 0) {
if (luaL_loadfile(L, fname) != 0) {
luaM_free( L, output );
return luaL_error(L, lua_tostring(L, -1));
}
......@@ -371,39 +361,19 @@ 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);
int n=1;
unsigned priority = TASK_PRIORITY_MEDIUM;
if (Ltype == LUA_TNUMBER) {
if (lua_type(L, 1) == 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");
n++;
}
luaL_checkanyfunction(L, n);
lua_settop(L, n);
(void) luaN_posttask(L, priority);
return 0;
}
......
......@@ -3,15 +3,45 @@
** table to store the LUAL_BUFFERSIZE byte array chunks instead of the stack.
** Writing is always to the last UD in the table and overflow pushes a new UD to
** the end of the table. Reading is always from the first UD in the table and
** underrun removes the first UD to shift a new one into slot 1.
** underrun removes the first UD to shift a new one into slot 2. (Slot 1 of the
** table is reserved for the pipe reader function with 0 denoting no reader.)
**
** Reads and writes may span multiple UD buffers and if the read spans multiple UDs
** then the parts are collected as strings on the Lua stack and then concatenated
** with a `lua_concat()`.
** with a lua_concat().
**
** Note that pipes also support the undocumented length and tostring operators
** for debugging puposes, so if p is a pipe then #p[1] gives the effective
** length of pipe slot 1 and printing p[1] gives its contents
** Note that pipe tables also support the undocumented length and tostring
** operators for debugging puposes, so if p is a pipe then #p[i] gives the
** effective length of pipe slot i and printing p[i] gives its contents.
**
** The pipe library also supports the automatic scheduling of a reader task. This
** is declared by including a Lua CB function and an optional prioirty for it to
** execute at in the pipe.create() call. The reader task may or may not empty the
** FIFO (and there is also nothing to stop the task also writing to the FIFO. The
** reader automatically reschedules itself if the pipe contains unread content.
**
** The reader tasks may be interleaved with other tasks that write to the pipe and
** others that don't. Any task writing to the pipe will also trigger the posting
** of a read task if one is not already pending. In this way at most only one
** pending reader task is pending, and this prevents overrun of the task queueing
** system.
**
** Implementation Notes:
**
** - The Pipe slot 1 is used to store the Lua CB function reference of the reader
** task. Note that is actually an auxiliary wrapper around the supplied Lua CB
** function, and this wrapper also uses upvals to store internal pipe state.
** The remaining slots are the Userdata buffer chunks.
**
** - This internal state needs to be shared with the pipe_write function, but a
** limitation of Lua 5.1 is that C functions cannot share upvals; to avoid this
** constraint, this function is also denormalised to act as the pipe_write
** function: if Arg1 is the pipe then its a pipe:write() otherwise its a
** CB wrapper.
**
** Also note that the pipe module is used by the Lua VM and therefore the create
** read, and unread methods are exposed as directly callable C functions. (Write
** is available throogh pipe[1].)
**
** Read the docs/modules/pipe.md documentation for a functional description.
*/
......@@ -19,6 +49,8 @@
#include "module.h"
#include "lauxlib.h"
#include <string.h>
#include "platform.h"
#include "lstate.h"
#define INVALID_LEN ((unsigned)-1)
......@@ -31,10 +63,36 @@ typedef struct buffer {
LROT_TABLE(pipe_meta)
/* Validation and utility functions */
#define AT_TAIL 0x00
#define AT_HEAD 0x01
#define WRITING 0x02
#define AT_HEAD 1
#define AT_TAIL 0
static buffer_t *checkPipeUD (lua_State *L, int ndx);
static buffer_t *newPipeUD(lua_State *L, int ndx, int n);
static int pipe_write_aux(lua_State *L);
/* Validation and utility functions */
// [-0, +0, v]
static buffer_t *checkPipeTable (lua_State *L, int tbl, int flags) {
int m = lua_gettop(L), n = lua_objlen(L, tbl);
if (lua_istable(L, tbl) && lua_getmetatable(L, tbl)) {
lua_pushrotable(L, LROT_TABLEREF(pipe_meta));/* push comparison metatable */
if (lua_rawequal(L, -1, -2)) { /* check these match */
buffer_t *ud;
if (n == 1) {
ud = (flags & WRITING) ? newPipeUD(L, tbl, 2) : NULL;
} else {
int i = flags & AT_HEAD ? 2 : n; /* point to head or tail of T */
lua_rawgeti(L, tbl, i); /* and fetch UD */
ud = checkPipeUD(L, -1);
}
lua_settop(L, m);
return ud; /* and return ptr to buffer_t rec */
}
}
luaL_typerror(L, tbl, "pipe table");
return NULL; /* NORETURN avoid compiler error */
}
static buffer_t *checkPipeUD (lua_State *L, int ndx) { // [-0, +0, v]
buffer_t *ud = lua_touserdata(L, ndx);
......@@ -59,27 +117,6 @@ static buffer_t *newPipeUD(lua_State *L, int ndx, int n) { // [-0,+0,-]
return ud; /* ud points to new T[#T] */
}
static buffer_t *checkPipeTable (lua_State *L, int tbl, int head) {//[-0, +0, v]
int m = lua_gettop(L), n = lua_objlen(L, tbl);
if (lua_type(L, tbl) == LUA_TTABLE && lua_getmetatable(L, tbl)) {
lua_pushrotable(L, LROT_TABLEREF(pipe_meta));/* push comparison metatable */
if (lua_rawequal(L, -1, -2)) { /* check these match */
buffer_t *ud;
if (n == 0) {
ud = head ? NULL : newPipeUD(L, tbl, 1);
} else {
int i = head ? 1 : n; /* point to head or tail of T */
lua_rawgeti(L, tbl, i); /* and fetch UD */
ud = checkPipeUD(L, -1);
}
lua_settop(L, m);
return ud; /* and return ptr to buffer_t rec */
}
}
luaL_typerror(L, tbl, "pipe table");
return NULL; /* NORETURN avoid compiler error */
}
#define CHAR_DELIM -1
#define CHAR_DELIM_KEEP -2
static char getsize_delim (lua_State *L, int ndx, int *len) { // [-0, +0, v]
......@@ -104,20 +141,113 @@ static char getsize_delim (lua_State *L, int ndx, int *len) { // [-0, +0, v]
return delim;
}
/* Lua callable methods */
/*
** Read CB Initiator AND pipe_write. If arg1 == the pipe, then this is a pipe
** write(); otherwise it is the Lua CB wapper for the task post. This botch allows
** these two functions to share Upvals within the Lua 5.1 VM:
*/
#define UVpipe lua_upvalueindex(1) // The pipe table object
#define UVfunc lua_upvalueindex(2) // The CB's Lua function
#define UVprio lua_upvalueindex(3) // The task priority
#define UVstate lua_upvalueindex(4) // Pipe state;
#define CB_NOT_USED 0
#define CB_ACTIVE 1
#define CB_WRITE_UPDATED 2
#define CB_QUIESCENT 4
/*
** Note that nothing precludes the Lua CB function from itself writing to the
** pipe and in this case this routine will call itself recursively.
**
** The Lua CB itself takes the pipe object as a parameter and returns an optional
** boolean to force or to suppress automatic retasking if needed. If omitted,
** then the default is to repost if the pipe is not empty, otherwise the task
** chain is left to lapse.
*/
static int pipe_write_and_read_poster (lua_State *L) {
int state = lua_tointeger(L, UVstate);
if (lua_rawequal(L, 1, UVpipe)) {
/* arg1 == the pipe, so this was invoked as a pipe_write() */
if (pipe_write_aux(L) && state && !(state & CB_WRITE_UPDATED)) {
/*
* if this resulted in a write and not already in a CB and not already
* toggled the write update then post the task
*/
state |= CB_WRITE_UPDATED;
lua_pushinteger(L, state);
lua_replace(L, UVstate); /* Set CB state write updated flag */
if (state == CB_QUIESCENT | CB_WRITE_UPDATED) {
lua_rawgeti(L, 1, 1); /* Get CB ref from pipe[1] */
luaN_posttask(L, (int) lua_tointeger(L, UVprio)); /* and repost task */
}
}
//Lua s = pipeUD:tostring()
static int pipe__tostring (lua_State *L) {
if (lua_type(L, 1) == LUA_TTABLE) {
lua_pushfstring(L, "Pipe: %p", lua_topointer(L, 1));
} else if (state != CB_NOT_USED) {
/* invoked by the luaN_taskpost() so call the Lua CB */
int repost; /* can take the values CB_WRITE_UPDATED or 0 */
lua_pushinteger(L, CB_ACTIVE); /* CB state set to active only */
lua_replace(L, UVstate);
lua_pushvalue(L, UVfunc); /* Lua CB function */
lua_pushvalue(L, UVpipe); /* pipe table */
lua_call(L, 1, 1);
/*
* On return from the Lua CB, the task is never reposted if the pipe is empty.
* If it is not empty then the Lua CB return status determines when reposting
* occurs:
* - true = repost
* - false = don't repost
* - nil = only repost if there has been a write update.
*/
if (lua_isboolean(L,-1)) {
repost = (lua_toboolean(L, -1) == true &&
lua_objlen(L, UVpipe) > 1) ? CB_WRITE_UPDATED : 0;
} else {
buffer_t *ud = checkPipeUD(L, 1);
lua_pushlstring(L, ud->buf + ud->start, ud->end - ud->start);
repost = state & CB_WRITE_UPDATED;
}
return 1;
state = CB_QUIESCENT | repost;
lua_pushinteger(L, state); /* Update the CB state */
lua_replace(L, UVstate);
if (repost) {
lua_rawgeti(L, UVpipe, 1); /* Get CB ref from pipe[1] */
luaN_posttask(L, (int) lua_tointeger(L, UVprio)); /* and repost task */
}
}
return 0;
}
/* Lua callable methods. Since the metatable is linked to both the pipe table */
/* and the userdata entries the __len & __tostring functions must handle both */
// Lua: buf = pipe.create()
int pipe_create(lua_State *L) {
int prio = -1;
lua_settop(L, 2); /* fix stack sze as 2 */
if (!lua_isnil(L, 1)) {
luaL_checkanyfunction(L, 1); /* non-nil arg1 must be a function */
if (lua_isnil(L, 2)) {
prio = PLATFORM_TASK_PRIORITY_MEDIUM;
} else {
prio = (int) lua_tointeger(L, 2);
luaL_argcheck(L, prio >= PLATFORM_TASK_PRIORITY_LOW &&
prio <= PLATFORM_TASK_PRIORITY_HIGH, 2, "invalid priority");
}
}
lua_createtable (L, 1, 0); /* create pipe table */
lua_pushrotable(L, LROT_TABLEREF(pipe_meta));
lua_setmetatable(L, -2); /* set pipe table's metabtable to pipe_meta */
lua_pushvalue(L, -1); /* UV1: pipe object */
lua_pushvalue(L, 1); /* UV2: CB function */
lua_pushinteger(L, prio); /* UV3: task priority */
lua_pushinteger(L, prio == -1 ? CB_NOT_USED : CB_QUIESCENT);
lua_pushcclosure(L, pipe_write_and_read_poster, 4); /* post aux func as C task */
lua_rawseti(L, -2, 1); /* and wrtie to T[1] */
return 1; /* return the table */
}
// len = #pipeobj[1]
// len = #pipeobj[i]
static int pipe__len (lua_State *L) {
if (lua_type(L, 1) == LUA_TTABLE) {
lua_pushinteger(L, lua_objlen(L, 1));
......@@ -128,16 +258,19 @@ static int pipe__len (lua_State *L) {
return 1;
}
// Lua: buf = pipe.create()
static int pipe_create(lua_State *L) {
lua_createtable (L, 1, 0);
lua_pushrotable(L, LROT_TABLEREF(pipe_meta));
lua_setmetatable(L, 1); /* set table's metabtable to pipe_meta */
return 1; /* return the table */
//Lua s = pipeUD:tostring()
static int pipe__tostring (lua_State *L) {
if (lua_istable(L, 1)) {
lua_pushfstring(L, "Pipe: %p", lua_topointer(L, 1));
} else {
buffer_t *ud = checkPipeUD(L, 1);
lua_pushlstring(L, ud->buf + ud->start, ud->end - ud->start);
}
return 1;
}
// Lua: rec = p:read(end_or_delim) // also [-2, +1,- ]
static int pipe_read(lua_State *L) {
int pipe_read(lua_State *L) {
buffer_t *ud = checkPipeTable(L, 1, AT_HEAD);
int i, k=0, n;
lua_settop(L,2);
......@@ -158,6 +291,7 @@ static int pipe_read(lua_State *L) {
want = used = i + 1 - ud->start; /* case where we've hit a delim */
if (n == CHAR_DELIM)
want--;
n = 0; /* force loop exit because delim found */
}
} else {
want = used = (n < avail) ? n : avail;
......@@ -169,12 +303,12 @@ static int pipe_read(lua_State *L) {
if (ud->start == ud->end) {
/* shift the pipe array down overwriting T[1] */
int nUD = lua_objlen(L, 1);
for (i = 1; i < nUD; i++) { /* for i = 1, nUD-1 */
for (i = 2; i < nUD; i++) { /* for i = 2, nUD-1 */
lua_rawgeti(L, 1, i+1); lua_rawseti(L, 1, i); /* T[i] = T[i+1] */
}
lua_pushnil(L); lua_rawseti(L, 1, nUD--); /* T[n] = nil */
if (nUD) {
lua_rawgeti(L, 1, 1);
if (nUD>1) {
lua_rawgeti(L, 1, 2);
ud = checkPipeUD(L, -1);
lua_pop(L, 1);
} else {
......@@ -190,29 +324,33 @@ static int pipe_read(lua_State *L) {
}
// Lua: buf:unread(some_string)
static int pipe_unread(lua_State *L) {
int pipe_unread(lua_State *L) {
size_t l = INVALID_LEN;
const char *s = lua_tolstring(L, 2, &l);
if (l==0)
return 0;
luaL_argcheck(L, l != INVALID_LEN, 2, "must be a string");
buffer_t *ud = checkPipeTable(L, 1, AT_HEAD);
buffer_t *ud = checkPipeTable(L, 1, AT_HEAD | WRITING);
do {
int used = ud->end - ud->start, lrem = LUAL_BUFFERSIZE-used;
int used = ud->end - ud->start;
int lrem = LUAL_BUFFERSIZE-used;
if (used == LUAL_BUFFERSIZE) {
/* If the current UD is full insert a new UD at T[2] */
int i, nUD = lua_objlen(L, 1);
for (i = nUD; i > 0; i--) { /* for i = nUD-1,1,-1 */
lua_rawgeti(L, 1, i); lua_rawseti(L, 1, i+1); /* T[i+1] = T[i] */
}
ud = newPipeUD(L, 1, 1);
used = 0; lrem = LUAL_BUFFERSIZE;
} else if (ud->end < LUAL_BUFFERSIZE) {
} else if (ud->start < l) {
/* If the unread can't fit it before the start then shift content to end */
memmove(ud->buf + lrem,
ud->buf + ud->start, used); /* must be memmove not cpy */
}
ud->start = lrem; ud->end = LUAL_BUFFERSIZE;
}
if (l <= (unsigned )lrem)
break;
......@@ -232,21 +370,24 @@ static int pipe_unread(lua_State *L) {
}
// Lua: buf:write(some_string)
static int pipe_write(lua_State *L) {
static int pipe_write_aux(lua_State *L) {
size_t l = INVALID_LEN;
const char *s = lua_tolstring(L, 2, &l);
//dbg_printf("pipe write(%u): %s", l, s);
if (l==0)
return 0;
return false;
luaL_argcheck(L, l != INVALID_LEN, 2, "must be a string");
buffer_t *ud = checkPipeTable(L, 1, AT_TAIL);
buffer_t *ud = checkPipeTable(L, 1, AT_TAIL | WRITING);
do {
int used = ud->end - ud->start;
if (used == LUAL_BUFFERSIZE) {
/* If the current UD is full insert a new UD at T[end] */
ud = newPipeUD(L, 1, lua_objlen(L, 1)+1);
used = 0;
} else if (ud->start) {
} else if (LUAL_BUFFERSIZE - ud->end < l) {
/* If the write can't fit it at the end then shift content to the start */
memmove(ud->buf, ud->buf + ud->start, used); /* must be memmove not cpy */
ud->start = 0; ud->end = used;
}
......@@ -267,7 +408,7 @@ static int pipe_write(lua_State *L) {
/* Copy any residual tail to the UD buffer. Note that this is l>0 and */
memcpy(ud->buf + ud->end, s, l);
ud->end += l;
return 0;
return true;
}
// Lua: fread = pobj:reader(1400) -- or other number
......@@ -289,21 +430,36 @@ static int pipe_reader(lua_State *L) {
return 1;
}
LROT_BEGIN(pipe_meta)
LROT_TABENTRY( __index, pipe_meta)
LROT_BEGIN(pipe_funcs)
LROT_FUNCENTRY( __len, pipe__len )
LROT_FUNCENTRY( __tostring, pipe__tostring )
LROT_FUNCENTRY( read, pipe_read )
LROT_FUNCENTRY( reader, pipe_reader )
LROT_FUNCENTRY( unread, pipe_unread )
LROT_FUNCENTRY( write, pipe_write )
LROT_END( pipe_meta, NULL, LROT_MASK_INDEX )
/* Using a index func is needed because the write method is at pipe[1] */
static int pipe__index(lua_State *L) {
lua_settop(L,2);
const char *k=lua_tostring(L,2);
if(!strcmp(k,"write")){
lua_rawgeti(L, 1, 1);
} else {
lua_pushrotable(L, LROT_TABLEREF(pipe_funcs));
lua_replace(L, 1);
lua_rawget(L, 1);
}
return 1;
}
LROT_BEGIN(pipe_meta)
LROT_FUNCENTRY( __index, pipe__index)
LROT_FUNCENTRY( __len, pipe__len )
LROT_FUNCENTRY( __tostring, pipe__tostring )
LROT_END( pipe_meta, NULL, LROT_MASK_INDEX )
LROT_BEGIN(pipe)
LROT_FUNCENTRY( create, pipe_create )
LROT_END( lb, NULL, 0 )
NODEMCU_MODULE(PIPE, "pipe", pipe, NULL);
......@@ -20,6 +20,7 @@
#include "lauxlib.h"
#include "lmem.h"
#include "platform.h"
#include "task/task.h"
#include "hw_timer.h"
#include "user_interface.h"
......
......@@ -7,83 +7,57 @@
#include <stdint.h>
#include <string.h>
#include "rom.h"
#include "driver/input.h"
static int uart_receive_rf = LUA_NOREF;
bool run_input = true;
bool uart_on_data_cb(const char *buf, size_t len){
if(!buf || len==0)
return false;
if(uart_receive_rf == LUA_NOREF)
return false;
void uart_on_data_cb(const char *buf, size_t len){
lua_State *L = lua_getstate();
if(!L)
return false;
lua_rawgeti(L, LUA_REGISTRYINDEX, uart_receive_rf);
lua_pushlstring(L, buf, len);
lua_call(L, 1, 0);
return !run_input;
luaN_call(L, 1, 0, 0);
}
uint16_t need_len = 0;
int16_t end_char = -1;
// Lua: uart.on("method", [number/char], function, [run_input])
static int l_uart_on( lua_State* L )
{
size_t sl, el;
int32_t run = 1;
uint8_t stack = 1;
const char *method = luaL_checklstring( L, stack, &sl );
stack++;
if (method == NULL)
return luaL_error( L, "wrong arg type" );
if( lua_type( L, stack ) == LUA_TNUMBER )
size_t el;
int stack = 2, data_len = -1;
char end_char = 0;
const char *method = lua_tostring( L, 1);
bool run_input = true;
luaL_argcheck(L, method && !strcmp(method, "data"), 1, "method not supported");
if (lua_type( L, stack ) == LUA_TNUMBER)
{
need_len = ( uint16_t )luaL_checkinteger( L, stack );
data_len = luaL_checkinteger( L, stack );
luaL_argcheck(L, data_len >= 0 && data_len <= LUA_MAXINPUT, stack, "wrong arg range");
stack++;
end_char = -1;
if( need_len > 255 ){
need_len = 255;
return luaL_error( L, "wrong arg range" );
}
}
else if(lua_isstring(L, stack))
else if (lua_isstring(L, stack))
{
const char *end = luaL_checklstring( L, stack, &el );
data_len = 0;
end_char = (int16_t) end[0];
stack++;
if(el!=1){
if(el!=1) {
return luaL_error( L, "wrong arg range" );
}
end_char = (int16_t)end[0];
need_len = 0;
}
// luaL_checkanyfunction(L, stack);
if (lua_type(L, stack) == LUA_TFUNCTION || lua_type(L, stack) == LUA_TLIGHTFUNCTION){
if ( lua_isnumber(L, stack+1) ){
run = lua_tointeger(L, stack+1);
}
lua_pushvalue(L, stack); // copy argument (func) to the top of stack
} else {
lua_pushnil(L);
if (lua_anyfunction(L, stack)) {
if (lua_isnumber(L, stack+1) && lua_tointeger(L, stack+1) == 0) {
run_input = false;
}
if(sl == 4 && strcmp(method, "data") == 0){
run_input = true;
if(uart_receive_rf != LUA_NOREF){
lua_pushvalue(L, stack);
luaL_unref(L, LUA_REGISTRYINDEX, uart_receive_rf);
uart_receive_rf = LUA_NOREF;
}
if(!lua_isnil(L, -1)){
uart_receive_rf = luaL_ref(L, LUA_REGISTRYINDEX);
if(run==0)
run_input = false;
} else {
lua_pop(L, 1);
}
}else{
lua_pop(L, 1);
return luaL_error( L, "method not supported" );
luaL_unref(L, LUA_REGISTRYINDEX, uart_receive_rf);
uart_receive_rf = LUA_NOREF;
}
input_setup_receive(uart_on_data_cb, data_len, end_char, run_input);
return 0;
}
......@@ -91,7 +65,7 @@ bool uart0_echo = true;
// Lua: actualbaud = setup( id, baud, databits, parity, stopbits, echo )
static int l_uart_setup( lua_State* L )
{
uint32_t id, databits, parity, stopbits, echo = 1;
uint32_t id, databits, parity, stopbits;
uint32_t baud, res;
id = luaL_checkinteger( L, 1 );
......@@ -101,12 +75,8 @@ static int l_uart_setup( lua_State* L )
databits = luaL_checkinteger( L, 3 );
parity = luaL_checkinteger( L, 4 );
stopbits = luaL_checkinteger( L, 5 );
if(lua_isnumber(L,6)){
echo = lua_tointeger(L,6);
if(echo!=0)
uart0_echo = true;
else
uart0_echo = false;
if (lua_isnumber(L,6)) {
input_setecho(lua_tointeger(L,6) ? true : false);
}
res = platform_uart_setup( id, baud, databits, parity, stopbits );
......
......@@ -17,7 +17,8 @@
#define INTERRUPT_TYPE_IS_LEVEL(x) ((x) >= GPIO_PIN_INTR_LOLEVEL)
#ifdef GPIO_INTERRUPT_ENABLE
static task_handle_t gpio_task_handle;
static platform_task_handle_t gpio_task_handle;
static int task_init_handler(void);
#ifdef GPIO_INTERRUPT_HOOK_ENABLE
struct gpio_hook_entry {
......@@ -55,11 +56,13 @@ static const int uart_bitrates[] = {
BIT_RATE_3686400
};
int platform_init()
int platform_init ()
{
// Setup the various forward and reverse mappings for the pins
get_pin_map();
(void) task_init_handler();
cmn_platform_init();
// All done
return PLATFORM_OK;
......@@ -83,7 +86,7 @@ uint8_t platform_key_led( uint8_t level){
/*
* Set GPIO mode to output. Optionally in RAM helper because interrupts are dsabled
*/
static void NO_INTR_CODE set_gpio_no_interrupt(uint8 pin, uint8_t push_pull) {
static void NO_INTR_CODE set_gpio_no_interrupt(uint8_t pin, uint8_t push_pull) {
unsigned pnum = pin_num[pin];
ETS_GPIO_INTR_DISABLE();
#ifdef GPIO_INTERRUPT_ENABLE
......@@ -113,7 +116,7 @@ static void NO_INTR_CODE set_gpio_no_interrupt(uint8 pin, uint8_t push_pull) {
* Set GPIO mode to interrupt. Optionally RAM helper because interrupts are dsabled
*/
#ifdef GPIO_INTERRUPT_ENABLE
static void NO_INTR_CODE set_gpio_interrupt(uint8 pin) {
static void NO_INTR_CODE set_gpio_interrupt(uint8_t pin) {
ETS_GPIO_INTR_DISABLE();
PIN_FUNC_SELECT(pin_mux[pin], pin_func[pin]);
GPIO_DIS_OUTPUT(pin_num[pin]);
......@@ -209,9 +212,9 @@ int platform_gpio_read( unsigned pin )
#ifdef GPIO_INTERRUPT_ENABLE
static void ICACHE_RAM_ATTR platform_gpio_intr_dispatcher (void *dummy){
uint32 j=0;
uint32 gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
uint32 now = system_get_time();
uint32_t j=0;
uint32_t gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
uint32_t now = system_get_time();
UNUSED(dummy);
#ifdef GPIO_INTERRUPT_HOOK_ENABLE
......@@ -244,8 +247,8 @@ static void ICACHE_RAM_ATTR platform_gpio_intr_dispatcher (void *dummy){
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, BIT(j));
if (diff == 0 || diff & 0x8000) {
uint32 level = 0x1 & GPIO_INPUT_GET(GPIO_ID_PIN(j));
if (!task_post_high (gpio_task_handle, (now << 8) + (i<<1) + level)) {
uint32_t level = 0x1 & GPIO_INPUT_GET(GPIO_ID_PIN(j));
if (!platform_post_high (gpio_task_handle, (now << 8) + (i<<1) + level)) {
// If we fail to post, then try on the next interrupt
pin_counter[i].seen |= 0x8000;
}
......@@ -260,7 +263,7 @@ static void ICACHE_RAM_ATTR platform_gpio_intr_dispatcher (void *dummy){
}
}
void platform_gpio_init( task_handle_t gpio_task )
void platform_gpio_init( platform_task_handle_t gpio_task )
{
gpio_task_handle = gpio_task;
......@@ -871,7 +874,7 @@ uint32_t platform_s_flash_write( const void *from, uint32_t toaddr, uint32_t siz
memcpy(apbuf, from, size);
}
system_soft_wdt_feed ();
r = flash_write(toaddr, apbuf?(uint32 *)apbuf:(uint32 *)from, size);
r = flash_write(toaddr, apbuf?(uint32_t *)apbuf:(uint32_t *)from, size);
if(apbuf)
free(apbuf);
if(SPI_FLASH_RESULT_OK == r)
......@@ -899,7 +902,7 @@ uint32_t platform_s_flash_read( void *to, uint32_t fromaddr, uint32_t size )
if( ((uint32_t)to) & blkmask )
{
uint32_t size2=size-INTERNAL_FLASH_READ_UNIT_SIZE;
uint32* to2=(uint32*)((((uint32_t)to)&(~blkmask))+INTERNAL_FLASH_READ_UNIT_SIZE);
uint32_t* to2=(uint32_t*)((((uint32_t)to)&(~blkmask))+INTERNAL_FLASH_READ_UNIT_SIZE);
r = flash_read(fromaddr, to2, size2);
if(SPI_FLASH_RESULT_OK == r)
{
......@@ -910,7 +913,7 @@ uint32_t platform_s_flash_read( void *to, uint32_t fromaddr, uint32_t size )
}
}
else
r = flash_read(fromaddr, (uint32 *)to, size);
r = flash_read(fromaddr, (uint32_t *)to, size);
if(SPI_FLASH_RESULT_OK == r)
return size;
......@@ -1079,3 +1082,84 @@ void* platform_print_deprecation_note( const char *msg, const char *time_frame)
{
printf( "Warning, deprecated API! %s. It will be removed %s. See documentation for details.\n", msg, time_frame );
}
#define TH_MONIKER 0x68680000
#define TH_MASK 0xFFF80000
#define TH_UNMASK (~TH_MASK)
#define TH_SHIFT 2
#define TH_ALLOCATION_BRICK 4 // must be a power of 2
#define TASK_DEFAULT_QUEUE_LEN 8
#define TASK_PRIORITY_MASK 3
#define TASK_PRIORITY_COUNT 3
/*
* Private struct to hold the 3 event task queues and the dispatch callbacks
*/
static struct taskQblock {
os_event_t *task_Q[TASK_PRIORITY_COUNT];
platform_task_callback_t *task_func;
int task_count;
} TQB = {0};
static void platform_task_dispatch (os_event_t *e) {
platform_task_handle_t handle = e->sig;
if ( (handle & TH_MASK) == TH_MONIKER) {
uint16_t entry = (handle & TH_UNMASK) >> TH_SHIFT;
uint8_t priority = handle & TASK_PRIORITY_MASK;
if ( priority <= PLATFORM_TASK_PRIORITY_HIGH &&
TQB.task_func &&
entry < TQB.task_count ){
/* call the registered task handler with the specified parameter and priority */
TQB.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.
*/
static int task_init_handler (void) {
int p, qlen = TASK_DEFAULT_QUEUE_LEN;
for (p = 0; p < TASK_PRIORITY_COUNT; p++){
TQB.task_Q[p] = (os_event_t *) c_malloc( sizeof(os_event_t)*qlen );
if (TQB.task_Q[p]) {
os_memset(TQB.task_Q[p], 0, sizeof(os_event_t)*qlen);
system_os_task(platform_task_dispatch, p, TQB.task_Q[p], TASK_DEFAULT_QUEUE_LEN);
} else {
NODE_DBG ( "Malloc failure in platform_task_init_handler" );
return PLATFORM_ERR;
}
}
}
/*
* Allocate a task handle in the relevant TCB.task_Q. Note that these Qs are resized
* as needed growing in 4 unit bricks. No GC is adopted so handles are permanently
* allocated during boot life. This isn't an issue in practice as only a few handles
* are created per priority during application init and the more volitile Lua tasks
* are allocated in the Lua registery using the luaX interface which is layered on
* this mechanism.
*/
platform_task_handle_t platform_task_get_id (platform_task_callback_t t) {
if ( (TQB.task_count & (TH_ALLOCATION_BRICK - 1)) == 0 ) {
TQB.task_func = (platform_task_callback_t *) os_realloc(
TQB.task_func,
sizeof(platform_task_callback_t) * (TQB.task_count+TH_ALLOCATION_BRICK));
if (!TQB.task_func) {
NODE_DBG ( "Malloc failure in platform_task_get_id");
return 0;
}
os_memset (TQB.task_func+TQB.task_count, 0,
sizeof(platform_task_callback_t)*TH_ALLOCATION_BRICK);
}
TQB.task_func[TQB.task_count++] = t;
return TH_MONIKER + ((TQB.task_count-1) << TH_SHIFT);
}
bool platform_post (uint8 prio, platform_task_handle_t handle, platform_task_param_t par) {
return system_os_post(prio, handle | prio, par);
}
......@@ -8,8 +8,6 @@
#include "driver/pwm.h"
#include "driver/uart.h"
#include "task/task.h"
// Error / status codes
enum
{
......@@ -18,6 +16,9 @@ enum
PLATFORM_UNDERFLOW = -1
};
typedef uint32_t platform_task_handle_t;
typedef uint32_t platform_task_param_t;
// Platform initialization
int platform_init(void);
void platform_int_init(void);
......@@ -52,7 +53,7 @@ int platform_gpio_register_intr_hook(uint32_t gpio_bits, platform_hook_function
#define platform_gpio_unregister_intr_hook(hook) \
platform_gpio_register_intr_hook(0, hook);
void platform_gpio_intr_init( unsigned pin, GPIO_INT_TYPE type );
void platform_gpio_init( task_handle_t gpio_task );
void platform_gpio_init( platform_task_handle_t gpio_task );
// *****************************************************************************
// Timer subsection
......@@ -353,4 +354,22 @@ typedef union {
uint32_t platform_rcr_read (uint8_t rec_id, void **rec);
uint32_t platform_rcr_write (uint8_t rec_id, const void *rec, uint8_t size);
#define PLATFORM_TASK_PRIORITY_LOW 0
#define PLATFORM_TASK_PRIORITY_MEDIUM 1
#define PLATFORM_TASK_PRIORITY_HIGH 2
/*
* 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.
*/
#define platform_post_low(handle,param) platform_post(PLATFORM_TASK_PRIORITY_LOW, handle, param)
#define platform_post_medium(handle,param) platform_post(PLATFORM_TASK_PRIORITY_MEDIUM, handle, param)
#define platform_post_high(handle,param) platform_post(PLATFORM_TASK_PRIORITY_HIGH, handle, param)
typedef void (*platform_task_callback_t)(platform_task_param_t param, uint8 prio);
platform_task_handle_t platform_task_get_id(platform_task_callback_t t);
bool platform_post(uint8 prio, platform_task_handle_t h, platform_task_param_t par);
#endif
......@@ -15,7 +15,7 @@
// vfs_close - close file descriptor and free memory
// fd: file descriptor
// Returns: VFS_RES_OK or negative value in case of error
static int32_t vfs_close( int fd ) {
static inline int32_t vfs_close( int fd ) {
vfs_file *f = (vfs_file *)fd;
return f ? f->fns->close( f ) : VFS_RES_ERR;
}
......@@ -25,7 +25,7 @@ static int32_t vfs_close( int fd ) {
// ptr: destination data buffer
// len: requested length
// Returns: Number of bytes read, or VFS_RES_ERR in case of error
static int32_t vfs_read( int fd, void *ptr, size_t len ) {
static inline int32_t vfs_read( int fd, void *ptr, size_t len ) {
vfs_file *f = (vfs_file *)fd;
return f ? f->fns->read( f, ptr, len ) : VFS_RES_ERR;
}
......@@ -35,7 +35,7 @@ static int32_t vfs_read( int fd, void *ptr, size_t len ) {
// ptr: source data buffer
// len: requested length
// Returns: Number of bytes written, or VFS_RES_ERR in case of error
static int32_t vfs_write( int fd, const void *ptr, size_t len ) {
static inline sint32_t vfs_write( int fd, const void *ptr, size_t len ) {
vfs_file *f = (vfs_file *)fd;
return f ? f->fns->write( f, ptr, len ) : VFS_RES_ERR;
}
......@@ -51,7 +51,7 @@ int vfs_ungetc( int c, int fd );
// VFS_SEEK_CUR - set pointer to current position + off
// VFS_SEEK_END - set pointer to end of file + off
// Returns: New position, or VFS_RES_ERR in case of error
static int32_t vfs_lseek( int fd, int32_t off, int whence ) {
static inline int32_t vfs_lseek( int fd, sint32_t off, int whence ) {
vfs_file *f = (vfs_file *)fd;
return f ? f->fns->lseek( f, off, whence ) : VFS_RES_ERR;
}
......@@ -59,7 +59,7 @@ static int32_t vfs_lseek( int fd, int32_t off, int whence ) {
// vfs_eof - test for end-of-file
// fd: file descriptor
// Returns: 0 if not at end, != 0 if end of file
static int32_t vfs_eof( int fd ) {
static inline int32_t vfs_eof( int fd ) {
vfs_file *f = (vfs_file *)fd;
return f ? f->fns->eof( f ) : VFS_RES_ERR;
}
......@@ -67,7 +67,7 @@ static int32_t vfs_eof( int fd ) {
// vfs_tell - get read/write position
// fd: file descriptor
// Returns: Current position
static int32_t vfs_tell( int fd ) {
static inline int32_t vfs_tell( int fd ) {
vfs_file *f = (vfs_file *)fd;
return f ? f->fns->tell( f ) : VFS_RES_ERR;
}
......@@ -75,7 +75,7 @@ static int32_t vfs_tell( int fd ) {
// vfs_flush - flush write cache to file
// fd: file descriptor
// Returns: VFS_RES_OK, or VFS_RES_ERR in case of error
static int32_t vfs_flush( int fd ) {
static inline int32_t vfs_flush( int fd ) {
vfs_file *f = (vfs_file *)fd;
return f ? f->fns->flush( f ) : VFS_RES_ERR;
}
......@@ -83,7 +83,7 @@ static int32_t vfs_flush( int fd ) {
// vfs_size - get current file size
// fd: file descriptor
// Returns: File size
static uint32_t vfs_size( int fd ) {
static inline uint32_t vfs_size( int fd ) {
vfs_file *f = (vfs_file *)fd;
return f ? f->fns->size( f ) : 0;
}
......@@ -100,13 +100,13 @@ int32_t vfs_ferrno( int fd );
// vfs_closedir - close directory descriptor and free memory
// dd: dir descriptor
// Returns: VFS_RES_OK, or VFS_RES_ERR in case of error
static int32_t vfs_closedir( vfs_dir *dd ) { return dd->fns->close( dd ); }
static inline int32_t vfs_closedir( vfs_dir *dd ) { return dd->fns->close( dd ); }
// vfs_readdir - read next directory item
// dd: dir descriptor
// buf: pre-allocated stat structure to be filled in
// Returns: VFS_RES_OK if next item found, otherwise VFS_RES_ERR
static int32_t vfs_readdir( vfs_dir *dd, struct vfs_stat *buf ) { return dd->fns->readdir( dd, buf ); }
static inline int32_t vfs_readdir( vfs_dir *dd, struct vfs_stat *buf ) { return dd->fns->readdir( dd, buf ); }
// ---------------------------------------------------------------------------
// volume functions
......@@ -115,7 +115,7 @@ static int32_t vfs_readdir( vfs_dir *dd, struct vfs_stat *buf ) { return dd->fns
// vfs_umount - unmount logical drive and free memory
// vol: volume object
// Returns: VFS_RES_OK, or VFS_RES_ERR in case of error
static int32_t vfs_umount( vfs_vol *vol ) { return vol->fns->umount( vol ); }
static inline int32_t vfs_umount( vfs_vol *vol ) { return vol->fns->umount( vol ); }
// ---------------------------------------------------------------------------
// file system functions
......
......@@ -41,6 +41,7 @@
#include "module.h"
#include "lauxlib.h"
#include "platform.h"
#include "task/task.h"
#include "user_interface.h"
#include "user_modules.h"
......
#############################################################
# Required variables for each makefile
# Discard this section from all parent makefiles
# Expected variables (with automatic defaults):
# CSRCS (all "C" files in the dir)
# SUBDIRS (all subdirs with a Makefile)
# GEN_LIBS - list of libs to be generated ()
# GEN_IMAGES - list of images to be generated ()
# COMPONENTS_xxx - a list of libs/objs in the form
# subdir/lib to be extracted and rolled up into
# a generated lib/image xxx.a ()
#
ifndef PDIR
GEN_LIBS = libtask.a
endif
#############################################################
# Configuration i.e. compile options etc.
# Target specific stuff (defines etc.) goes in here!
# Generally values applying to a tree are captured in the
# makefile at its root level - these are then overridden
# for a subtree within the makefile rooted therein
#
#DEFINES +=
#############################################################
# Recursion Magic - Don't touch this!!
#
# Each subtree potentially has an include directory
# corresponding to the common APIs applicable to modules
# rooted at that subtree. Accordingly, the INCLUDE PATH
# of a module can only contain the include directories up
# its parent path, and not its siblings
#
# Required for each makefile to inherit from the parent
#
PDIR := ../$(PDIR)
sinclude $(PDIR)Makefile
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