Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
Nodemcu Firmware
Commits
e7c29fe3
Commit
e7c29fe3
authored
Jul 18, 2019
by
Terry Ellison
Committed by
Marcel Stör
Jun 09, 2020
Browse files
Lua 5.1 to 5.3 realignement phase 1
parent
3d917850
Changes
44
Expand all
Show whitespace changes
Inline
Side-by-side
app/lua/lflash.c
View file @
e7c29fe3
...
...
@@ -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
]);
}
...
...
app/lua/lnodemcu.c
0 → 100644
View file @
e7c29fe3
/*
** $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
;
}
app/lua/loadlib.c
View file @
e7c29fe3
...
...
@@ -397,7 +397,7 @@ static int loader_Lua (lua_State *L) {
#ifdef LUA_CROSS_COMPILER
if
(
luaL_loadfile
(
L
,
filename
)
!=
0
)
#else
if
(
luaL_loadf
sf
ile
(
L
,
filename
)
!=
0
)
if
(
luaL_loadfile
(
L
,
filename
)
!=
0
)
#endif
loaderror
(
L
,
filename
);
return
1
;
/* library loaded successfully */
...
...
app/lua/lobject.h
View file @
e7c29fe3
...
...
@@ -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 */
...
...
app/lua/lstate.c
View file @
e7c29fe3
...
...
@@ -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
)
{
...
...
app/lua/lstate.h
View file @
e7c29fe3
...
...
@@ -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
;
...
...
app/lua/lua.c
View file @
e7c29fe3
This diff is collapsed.
Click to expand it.
app/lua/lua.h
View file @
e7c29fe3
...
...
@@ -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
/******************************************************************************
...
...
app/modules/gpio.c
View file @
e7c29fe3
...
...
@@ -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>
...
...
app/modules/gpio_pulse.c
View file @
e7c29fe3
...
...
@@ -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
;
}
...
...
app/modules/net.c
View file @
e7c29fe3
...
...
@@ -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
;
}
...
...
app/modules/node.c
View file @
e7c29fe3
...
...
@@ -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_loadf
sf
ile
(
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
;
}
...
...
app/modules/pipe.c
View file @
e7c29fe3
...
...
@@ -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
);
app/modules/somfy.c
View file @
e7c29fe3
...
...
@@ -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"
...
...
app/modules/uart.c
View file @
e7c29fe3
...
...
@@ -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
);
...
...
app/platform/platform.c
View file @
e7c29fe3
...
...
@@ -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
);
}
app/platform/platform.h
View file @
e7c29fe3
...
...
@@ -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
app/platform/vfs.h
View file @
e7c29fe3
...
...
@@ -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
s
int32_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
,
s
int32_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
...
...
app/pm/swtimer.c
View file @
e7c29fe3
...
...
@@ -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"
...
...
app/task/Makefile
deleted
100644 → 0
View file @
3d917850
#############################################################
# 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
Prev
1
2
3
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment