ESP32: uart 1/2 supports (#1982)
* uart 1/2 * call -> pcall in uart_on_* functions * fix docs * fixed console driver when using custom console uart * fixed line_inverse and error callback * fixed a crash when uart.start() called more than one time
This commit is contained in:
parent
819284530e
commit
329bd73b63
|
@ -3,46 +3,71 @@
|
|||
#include "module.h"
|
||||
#include "lauxlib.h"
|
||||
#include "platform.h"
|
||||
#include "driver/console.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
extern uart_status_t uart_status[NUM_UART];
|
||||
|
||||
static lua_State *gL = NULL;
|
||||
static int uart_receive_rf = LUA_NOREF;
|
||||
bool run_input = true;
|
||||
bool uart_on_data_cb(const char *buf, size_t len){
|
||||
bool uart_on_data_cb(unsigned id, const char *buf, size_t len){
|
||||
if(!buf || len==0)
|
||||
return false;
|
||||
if(uart_receive_rf == LUA_NOREF)
|
||||
if(uart_status[id].receive_rf == LUA_NOREF)
|
||||
return false;
|
||||
if(!gL)
|
||||
return false;
|
||||
lua_rawgeti(gL, LUA_REGISTRYINDEX, uart_receive_rf);
|
||||
|
||||
lua_rawgeti(gL, LUA_REGISTRYINDEX, uart_status[id].receive_rf);
|
||||
lua_pushlstring(gL, buf, len);
|
||||
lua_call(gL, 1, 0);
|
||||
lua_pcall(gL, 1, 0, 0);
|
||||
return !run_input;
|
||||
}
|
||||
|
||||
uint16_t need_len = 0;
|
||||
int16_t end_char = -1;
|
||||
// Lua: uart.on("method", [number/char], function, [run_input])
|
||||
bool uart_on_error_cb(unsigned id, const char *buf, size_t len){
|
||||
if(!buf || len==0)
|
||||
return false;
|
||||
if(uart_status[id].error_rf == LUA_NOREF)
|
||||
return false;
|
||||
if(!gL)
|
||||
return false;
|
||||
|
||||
lua_rawgeti(gL, LUA_REGISTRYINDEX, uart_status[id].error_rf);
|
||||
lua_pushlstring(gL, buf, len);
|
||||
lua_pcall(gL, 1, 0, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Lua: uart.on([id], "method", [number/char], function, [run_input])
|
||||
static int uart_on( lua_State* L )
|
||||
{
|
||||
unsigned id = CONSOLE_UART;
|
||||
size_t sl, el;
|
||||
int32_t run = 1;
|
||||
uint8_t stack = 1;
|
||||
const char *method = luaL_checklstring( L, stack, &sl );
|
||||
const char *method;
|
||||
uart_status_t *us;
|
||||
|
||||
if( lua_isnumber( L, stack ) ) {
|
||||
id = ( unsigned )luaL_checkinteger( L, stack );
|
||||
MOD_CHECK_ID( uart, id );
|
||||
stack++;
|
||||
}
|
||||
us = & uart_status[id];
|
||||
method = luaL_checklstring( L, stack, &sl );
|
||||
stack++;
|
||||
if (method == NULL)
|
||||
return luaL_error( L, "wrong arg type" );
|
||||
|
||||
if( lua_type( L, stack ) == LUA_TNUMBER )
|
||||
{
|
||||
need_len = ( uint16_t )luaL_checkinteger( L, stack );
|
||||
us->need_len = ( uint16_t )luaL_checkinteger( L, stack );
|
||||
stack++;
|
||||
end_char = -1;
|
||||
if( need_len > 255 ){
|
||||
need_len = 255;
|
||||
us->end_char = -1;
|
||||
if( us->need_len > 255 ){
|
||||
us->need_len = 255;
|
||||
return luaL_error( L, "wrong arg range" );
|
||||
}
|
||||
}
|
||||
|
@ -53,8 +78,8 @@ static int uart_on( lua_State* L )
|
|||
if(el!=1){
|
||||
return luaL_error( L, "wrong arg range" );
|
||||
}
|
||||
end_char = (int16_t)end[0];
|
||||
need_len = 0;
|
||||
us->end_char = (int16_t)end[0];
|
||||
us->need_len = 0;
|
||||
}
|
||||
|
||||
// luaL_checkanyfunction(L, stack);
|
||||
|
@ -67,20 +92,32 @@ static int uart_on( lua_State* L )
|
|||
lua_pushnil(L);
|
||||
}
|
||||
if(sl == 4 && strcmp(method, "data") == 0){
|
||||
run_input = true;
|
||||
if(uart_receive_rf != LUA_NOREF){
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, uart_receive_rf);
|
||||
uart_receive_rf = LUA_NOREF;
|
||||
if(id == CONSOLE_UART)
|
||||
run_input = true;
|
||||
if(us->receive_rf != LUA_NOREF){
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, us->receive_rf);
|
||||
us->receive_rf = LUA_NOREF;
|
||||
}
|
||||
if(!lua_isnil(L, -1)){
|
||||
uart_receive_rf = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
us->receive_rf = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
gL = L;
|
||||
if(run==0)
|
||||
if(id == CONSOLE_UART && run==0)
|
||||
run_input = false;
|
||||
} else {
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}else{
|
||||
} else if(sl == 5 && strcmp(method, "error") == 0){
|
||||
if(us->error_rf != LUA_NOREF){
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, us->error_rf);
|
||||
us->error_rf = LUA_NOREF;
|
||||
}
|
||||
if(!lua_isnil(L, -1)){
|
||||
us->error_rf = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
gL = L;
|
||||
} else {
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
} else {
|
||||
lua_pop(L, 1);
|
||||
return luaL_error( L, "method not supported" );
|
||||
}
|
||||
|
@ -93,6 +130,7 @@ static int uart_setup( lua_State* L )
|
|||
{
|
||||
unsigned id, databits, parity, stopbits, echo = 1;
|
||||
uint32_t baud, res;
|
||||
uart_pins_t pins;
|
||||
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( uart, id );
|
||||
|
@ -100,15 +138,36 @@ static int 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)){
|
||||
if(id == CONSOLE_UART && lua_isnumber(L,6)){
|
||||
echo = lua_tointeger(L,6);
|
||||
if(echo!=0)
|
||||
uart0_echo = true;
|
||||
else
|
||||
uart0_echo = false;
|
||||
} else if(id != CONSOLE_UART && lua_istable( L, 6 )) {
|
||||
lua_getfield (L, 6, "tx");
|
||||
pins.tx_pin = luaL_checkint(L, -1);
|
||||
lua_getfield (L, 6, "rx");
|
||||
pins.rx_pin = luaL_checkint(L, -1);
|
||||
lua_getfield (L, 6, "cts");
|
||||
pins.cts_pin = luaL_optint(L, -1, -1);
|
||||
lua_getfield (L, 6, "rts");
|
||||
pins.rts_pin = luaL_optint(L, -1, -1);
|
||||
|
||||
lua_getfield (L, 6, "tx_inverse");
|
||||
pins.tx_inverse = lua_toboolean(L, -1);
|
||||
lua_getfield (L, 6, "rx_inverse");
|
||||
pins.rx_inverse = lua_toboolean(L, -1);
|
||||
lua_getfield (L, 6, "cts_inverse");
|
||||
pins.cts_inverse = lua_toboolean(L, -1);
|
||||
lua_getfield (L, 6, "rts_inverse");
|
||||
pins.rts_inverse = lua_toboolean(L, -1);
|
||||
|
||||
lua_getfield (L, 6, "flow_control");
|
||||
pins.flow_control = luaL_optint(L, -1, PLATFORM_UART_FLOW_NONE);
|
||||
}
|
||||
|
||||
res = platform_uart_setup( id, baud, databits, parity, stopbits );
|
||||
res = platform_uart_setup( id, baud, databits, parity, stopbits, &pins );
|
||||
lua_pushinteger( L, res );
|
||||
return 1;
|
||||
}
|
||||
|
@ -116,9 +175,9 @@ static int uart_setup( lua_State* L )
|
|||
// Lua: write( id, string1, [string2], ..., [stringn] )
|
||||
static int uart_write( lua_State* L )
|
||||
{
|
||||
int id;
|
||||
unsigned id;
|
||||
const char* buf;
|
||||
size_t len, i;
|
||||
size_t len;
|
||||
int total = lua_gettop( L ), s;
|
||||
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
|
@ -131,24 +190,46 @@ static int uart_write( lua_State* L )
|
|||
if( len > 255 )
|
||||
return luaL_error( L, "invalid number" );
|
||||
platform_uart_send( id, (uint8_t)len );
|
||||
platform_uart_flush( id );
|
||||
}
|
||||
else
|
||||
{
|
||||
luaL_checktype( L, s, LUA_TSTRING );
|
||||
buf = lua_tolstring( L, s, &len );
|
||||
for( i = 0; i < len; i ++ )
|
||||
platform_uart_send( id, buf[ i ] );
|
||||
platform_uart_flush( id );
|
||||
platform_uart_send_multi( id, buf, len );
|
||||
}
|
||||
}
|
||||
platform_uart_flush( id );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Lua: stop( id )
|
||||
static int uart_stop( lua_State* L )
|
||||
{
|
||||
unsigned id;
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( uart, id );
|
||||
platform_uart_stop( id );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Lua: start( id )
|
||||
static int uart_start( lua_State* L )
|
||||
{
|
||||
unsigned id;
|
||||
int err;
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( uart, id );
|
||||
err = platform_uart_start( id );
|
||||
lua_pushboolean( L, err == 0 );
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Module function map
|
||||
static const LUA_REG_TYPE uart_map[] = {
|
||||
{ LSTRKEY( "setup" ), LFUNCVAL( uart_setup ) },
|
||||
{ LSTRKEY( "write" ), LFUNCVAL( uart_write ) },
|
||||
{ LSTRKEY( "start" ), LFUNCVAL( uart_start ) },
|
||||
{ LSTRKEY( "stop" ), LFUNCVAL( uart_stop ) },
|
||||
{ LSTRKEY( "on" ), LFUNCVAL( uart_on ) },
|
||||
{ LSTRKEY( "STOPBITS_1" ), LNUMVAL( PLATFORM_UART_STOPBITS_1 ) },
|
||||
{ LSTRKEY( "STOPBITS_1_5" ), LNUMVAL( PLATFORM_UART_STOPBITS_1_5 ) },
|
||||
|
@ -156,7 +237,22 @@ static const LUA_REG_TYPE uart_map[] = {
|
|||
{ LSTRKEY( "PARITY_NONE" ), LNUMVAL( PLATFORM_UART_PARITY_NONE ) },
|
||||
{ LSTRKEY( "PARITY_EVEN" ), LNUMVAL( PLATFORM_UART_PARITY_EVEN ) },
|
||||
{ LSTRKEY( "PARITY_ODD" ), LNUMVAL( PLATFORM_UART_PARITY_ODD ) },
|
||||
{ LSTRKEY( "FLOWCTRL_NONE" ), LNUMVAL( PLATFORM_UART_FLOW_NONE ) },
|
||||
{ LSTRKEY( "FLOWCTRL_CTS" ), LNUMVAL( PLATFORM_UART_FLOW_CTS ) },
|
||||
{ LSTRKEY( "FLOWCTRL_RTS" ), LNUMVAL( PLATFORM_UART_FLOW_RTS ) },
|
||||
{ LNILKEY, LNILVAL }
|
||||
};
|
||||
|
||||
NODEMCU_MODULE(UART, "uart", uart_map, NULL);
|
||||
int luaopen_uart( lua_State *L ) {
|
||||
uart_status_t *us;
|
||||
for(int id = 0; id < NUM_UART; id++) {
|
||||
us = & uart_status[id];
|
||||
us->receive_rf = LUA_NOREF;
|
||||
us->error_rf = LUA_NOREF;
|
||||
us->need_len = 0;
|
||||
us->end_char = -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
NODEMCU_MODULE(UART, "uart", uart_map, luaopen_uart);
|
||||
|
|
|
@ -159,7 +159,7 @@ void console_init (const ConsoleSetup_t *cfg, task_handle_t tsk)
|
|||
|
||||
console_setup (cfg);
|
||||
|
||||
esp_intr_alloc (ETS_UART0_INTR_SOURCE,
|
||||
esp_intr_alloc (ETS_UART0_INTR_SOURCE + CONSOLE_UART,
|
||||
ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_INTRDISABLED,
|
||||
uart0_rx_intr_handler, NULL, &intr_handle);
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define CONSOLE_UART 0
|
||||
#define CONSOLE_UART CONFIG_CONSOLE_UART_NUM
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
|
|
@ -287,7 +287,7 @@ static int handle_script (lua_State *L, char **argv, int n) {
|
|||
#endif
|
||||
|
||||
/* check that argument has no extra characters at the end */
|
||||
#define notail(x) {if ((x)[2] != '\0') return -1;}
|
||||
#define notail(x) {if ((x)[2] != '\0') return -1;}
|
||||
|
||||
|
||||
static int collectargs (char **argv, int *pi, int *pv, int *pe) {
|
||||
|
@ -534,16 +534,16 @@ static void dojob(lua_Load *load){
|
|||
fflush (stdout);
|
||||
}
|
||||
|
||||
extern bool uart_on_data_cb(const char *buf, size_t len);
|
||||
extern bool uart_on_data_cb(unsigned id, const char *buf, size_t len);
|
||||
extern bool uart0_echo;
|
||||
extern bool run_input;
|
||||
extern uint16_t need_len;
|
||||
extern int16_t end_char;
|
||||
extern uart_status_t uart_status[];
|
||||
static char last_nl_char = '\0';
|
||||
static bool readline(lua_Load *load){
|
||||
// NODE_DBG("readline() is called.\n");
|
||||
bool need_dojob = false;
|
||||
char ch;
|
||||
uart_status_t *us = & uart_status[CONSOLE_UART];
|
||||
while (console_getc(&ch))
|
||||
{
|
||||
if(run_input)
|
||||
|
@ -590,7 +590,7 @@ static bool readline(lua_Load *load){
|
|||
|
||||
load->line[load->line_position] = 0;
|
||||
if(uart0_echo) putchar('\n');
|
||||
uart_on_data_cb(load->line, load->line_position);
|
||||
uart_on_data_cb(CONSOLE_UART, load->line, load->line_position);
|
||||
if (load->line_position == 0)
|
||||
{
|
||||
/* Get a empty line, then go to get a new line */
|
||||
|
@ -623,11 +623,11 @@ static bool readline(lua_Load *load){
|
|||
|
||||
if(!run_input)
|
||||
{
|
||||
if( ((need_len!=0) && (load->line_position >= need_len)) || \
|
||||
if( ((us->need_len!=0) && (load->line_position >= us->need_len)) || \
|
||||
(load->line_position >= load->len) || \
|
||||
((end_char>=0) && ((unsigned char)ch==(unsigned char)end_char)) )
|
||||
((us->end_char>=0) && ((unsigned char)ch==(unsigned char)us->end_char)) )
|
||||
{
|
||||
uart_on_data_cb(load->line, load->line_position);
|
||||
uart_on_data_cb(CONSOLE_UART, load->line, load->line_position);
|
||||
load->line_position = 0;
|
||||
}
|
||||
}
|
||||
|
@ -635,9 +635,9 @@ static bool readline(lua_Load *load){
|
|||
ch = 0;
|
||||
}
|
||||
|
||||
if( (load->line_position > 0) && (!run_input) && (need_len==0) && (end_char<0) )
|
||||
if( (load->line_position > 0) && (!run_input) && (us->need_len==0) && (us->end_char<0) )
|
||||
{
|
||||
uart_on_data_cb(load->line, load->line_position);
|
||||
uart_on_data_cb(CONSOLE_UART, load->line, load->line_position);
|
||||
load->line_position = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
#ifndef _PLATFORM_H_
|
||||
#define _PLATFORM_H_
|
||||
|
||||
#include "driver/uart.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "cpu_esp32.h"
|
||||
|
||||
#include "esp_task.h"
|
||||
|
||||
|
||||
#define PLATFORM_ALIGNMENT __attribute__((aligned(4)))
|
||||
#define PLATFORM_ALIGNMENT_PACKED __attribute__((aligned(4),packed))
|
||||
|
||||
|
@ -44,6 +48,8 @@ int platform_gpio_output_exists( unsigned gpio );
|
|||
// *****************************************************************************
|
||||
// UART subsection
|
||||
|
||||
#define UART_BUFFER_SIZE 512
|
||||
|
||||
// Parity
|
||||
enum
|
||||
{
|
||||
|
@ -63,6 +69,36 @@ enum
|
|||
PLATFORM_UART_STOPBITS_1_5 = 3
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int tx_pin;
|
||||
int rx_pin;
|
||||
int rts_pin;
|
||||
int cts_pin;
|
||||
bool tx_inverse;
|
||||
bool rx_inverse;
|
||||
bool rts_inverse;
|
||||
bool cts_inverse;
|
||||
int flow_control;
|
||||
} uart_pins_t;
|
||||
|
||||
typedef struct {
|
||||
QueueHandle_t queue;
|
||||
xTaskHandle taskHandle;
|
||||
int receive_rf;
|
||||
int error_rf;
|
||||
char *line_buffer;
|
||||
size_t line_position;
|
||||
uint16_t need_len;
|
||||
int16_t end_char;
|
||||
} uart_status_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned id;
|
||||
int type;
|
||||
size_t size;
|
||||
char* data;
|
||||
} uart_event_post_t;
|
||||
|
||||
// Flow control types (this is a bit mask, one can specify PLATFORM_UART_FLOW_RTS | PLATFORM_UART_FLOW_CTS )
|
||||
#define PLATFORM_UART_FLOW_NONE 0
|
||||
#define PLATFORM_UART_FLOW_RTS 1
|
||||
|
@ -70,10 +106,12 @@ enum
|
|||
|
||||
// The platform UART functions
|
||||
static inline int platform_uart_exists( unsigned id ) { return id < NUM_UART; }
|
||||
uint32_t platform_uart_setup( unsigned id, uint32_t baud, int databits, int parity, int stopbits );
|
||||
uint32_t platform_uart_setup( unsigned id, uint32_t baud, int databits, int parity, int stopbits, uart_pins_t* pins );
|
||||
void platform_uart_send_multi( unsigned id, const char *data, size_t len );
|
||||
void platform_uart_send( unsigned id, uint8_t data );
|
||||
void platform_uart_flush( unsigned id );
|
||||
int platform_uart_set_flow_control( unsigned id, int type );
|
||||
int platform_uart_start( unsigned id );
|
||||
void platform_uart_stop( unsigned id );
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
|
|
|
@ -2,7 +2,13 @@
|
|||
#include "driver/console.h"
|
||||
#include "driver/sigmadelta.h"
|
||||
#include "driver/adc.h"
|
||||
#include "driver/uart.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
|
||||
int platform_init (void)
|
||||
{
|
||||
|
@ -20,7 +26,136 @@ int platform_gpio_output_exists( unsigned gpio ) { return GPIO_IS_VALID_OUTPUT_G
|
|||
// ****************************************************************************
|
||||
// UART
|
||||
|
||||
uint32_t platform_uart_setup( unsigned id, uint32_t baud, int databits, int parity, int stopbits )
|
||||
#define PLATFORM_UART_EVENT_DATA (UART_EVENT_MAX + 1)
|
||||
#define PLATFORM_UART_EVENT_OOM (UART_EVENT_MAX + 2)
|
||||
#define PLATFORM_UART_EVENT_RX (UART_EVENT_MAX + 3)
|
||||
#define PLATFORM_UART_EVENT_BREAK (UART_EVENT_MAX + 4)
|
||||
|
||||
static const char *UART_TAG = "uart";
|
||||
|
||||
uart_status_t uart_status[NUM_UART];
|
||||
|
||||
extern bool uart_on_data_cb(unsigned id, const char *buf, size_t len);
|
||||
extern bool uart_on_error_cb(unsigned id, const char *buf, size_t len);
|
||||
task_handle_t uart_event_task_id = 0;
|
||||
|
||||
void uart_event_task( task_param_t param, task_prio_t prio ) {
|
||||
size_t p;
|
||||
uint16_t need_len;
|
||||
int16_t end_char;
|
||||
char ch;
|
||||
unsigned id;
|
||||
uart_status_t *us;
|
||||
uart_event_post_t *post = (uart_event_post_t *)param;
|
||||
id = post->id;
|
||||
us = & uart_status[id];
|
||||
if(post->type == PLATFORM_UART_EVENT_DATA) {
|
||||
need_len = us->need_len;
|
||||
end_char = us->end_char;
|
||||
|
||||
for(p = 0; p < post->size; p++) {
|
||||
ch = *(post->data + p);
|
||||
us->line_buffer[us->line_position] = ch;
|
||||
us->line_position++;
|
||||
|
||||
if((end_char == -1 && us->line_position == (need_len == 0? LUA_MAXINPUT : need_len))
|
||||
|| (end_char >= 0 && (unsigned char)ch == (unsigned char)end_char)) {
|
||||
// us->line_buffer[us->line_position] = 0;
|
||||
uart_on_data_cb(id, us->line_buffer, us->line_position);
|
||||
us->line_position = 0;
|
||||
}
|
||||
if(us->line_position + 1 >= LUA_MAXINPUT) {
|
||||
us->line_position = 0;
|
||||
}
|
||||
}
|
||||
if(end_char == -1 && need_len == 0 && us->line_position > 0) {
|
||||
// us->line_buffer[us->line_position] = 0;
|
||||
uart_on_data_cb(id, us->line_buffer, us->line_position);
|
||||
us->line_position = 0;
|
||||
}
|
||||
|
||||
free(post->data);
|
||||
free(post);
|
||||
} else {
|
||||
char *err;
|
||||
switch(post->type) {
|
||||
case PLATFORM_UART_EVENT_OOM:
|
||||
err = "out_of_memory";
|
||||
break;
|
||||
case PLATFORM_UART_EVENT_BREAK:
|
||||
err = "break";
|
||||
break;
|
||||
case PLATFORM_UART_EVENT_RX:
|
||||
default:
|
||||
err = "rx_error";
|
||||
}
|
||||
uart_on_error_cb(id, err, strlen(err));
|
||||
}
|
||||
}
|
||||
|
||||
static void task_uart( void *pvParameters ){
|
||||
unsigned id = (unsigned)pvParameters;
|
||||
|
||||
uart_event_post_t* post = NULL;
|
||||
uart_event_t event;
|
||||
|
||||
for(;;) {
|
||||
if(xQueueReceive(uart_status[id].queue, (void * )&event, (portTickType)portMAX_DELAY)) {
|
||||
switch(event.type) {
|
||||
case UART_DATA:
|
||||
post = (uart_event_post_t*)malloc(sizeof(uart_event_post_t));
|
||||
if(post == NULL) {
|
||||
ESP_LOGE(UART_TAG, "Can not alloc memory in task_uart()");
|
||||
// reboot here?
|
||||
continue;
|
||||
}
|
||||
post->data = malloc(event.size);
|
||||
if(post->data == NULL) {
|
||||
ESP_LOGE(UART_TAG, "Can not alloc memory in task_uart()");
|
||||
post->id = id;
|
||||
post->type = PLATFORM_UART_EVENT_OOM;
|
||||
} else {
|
||||
post->id = id;
|
||||
post->type = PLATFORM_UART_EVENT_DATA;
|
||||
post->size = uart_read_bytes(id, (uint8_t *)post->data, event.size, 0);
|
||||
}
|
||||
break;
|
||||
case UART_BREAK:
|
||||
post = (uart_event_post_t*)malloc(sizeof(uart_event_post_t));
|
||||
if(post == NULL) {
|
||||
ESP_LOGE(UART_TAG, "Can not alloc memory in task_uart()");
|
||||
// reboot here?
|
||||
continue;
|
||||
}
|
||||
post->id = id;
|
||||
post->type = PLATFORM_UART_EVENT_BREAK;
|
||||
case UART_FIFO_OVF:
|
||||
case UART_BUFFER_FULL:
|
||||
case UART_PARITY_ERR:
|
||||
case UART_FRAME_ERR:
|
||||
post = (uart_event_post_t*)malloc(sizeof(uart_event_post_t));
|
||||
if(post == NULL) {
|
||||
ESP_LOGE(UART_TAG, "Can not alloc memory in task_uart()");
|
||||
// reboot here?
|
||||
continue;
|
||||
}
|
||||
post->id = id;
|
||||
post->type = PLATFORM_UART_EVENT_RX;
|
||||
break;
|
||||
case UART_PATTERN_DET:
|
||||
default:
|
||||
;
|
||||
}
|
||||
if(post != NULL) {
|
||||
task_post_medium( uart_event_task_id, (task_param_t)post );
|
||||
post = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pins must not be null for non-console uart
|
||||
uint32_t platform_uart_setup( unsigned id, uint32_t baud, int databits, int parity, int stopbits, uart_pins_t* pins )
|
||||
{
|
||||
if (id == CONSOLE_UART)
|
||||
{
|
||||
|
@ -57,16 +192,74 @@ uint32_t platform_uart_setup( unsigned id, uint32_t baud, int databits, int pari
|
|||
}
|
||||
else
|
||||
{
|
||||
printf("UART1/UART2 not yet supported\n");
|
||||
return 0;
|
||||
int flow_control = UART_HW_FLOWCTRL_DISABLE;
|
||||
if(pins->flow_control & PLATFORM_UART_FLOW_CTS) flow_control |= UART_HW_FLOWCTRL_CTS;
|
||||
if(pins->flow_control & PLATFORM_UART_FLOW_RTS) flow_control |= UART_HW_FLOWCTRL_RTS;
|
||||
|
||||
uart_config_t cfg = {
|
||||
.baud_rate = baud,
|
||||
.flow_ctrl = flow_control,
|
||||
.rx_flow_ctrl_thresh = UART_FIFO_LEN - 16,
|
||||
};
|
||||
|
||||
switch (databits)
|
||||
{
|
||||
case 5: cfg.data_bits = UART_DATA_5_BITS; break;
|
||||
case 6: cfg.data_bits = UART_DATA_6_BITS; break;
|
||||
case 7: cfg.data_bits = UART_DATA_7_BITS; break;
|
||||
case 8: // fall-through
|
||||
default: cfg.data_bits = UART_DATA_8_BITS; break;
|
||||
}
|
||||
switch (parity)
|
||||
{
|
||||
case PLATFORM_UART_PARITY_EVEN: cfg.parity = UART_PARITY_EVEN; break;
|
||||
case PLATFORM_UART_PARITY_ODD: cfg.parity = UART_PARITY_ODD; break;
|
||||
default: // fall-through
|
||||
case PLATFORM_UART_PARITY_NONE: cfg.parity = UART_PARITY_DISABLE; break;
|
||||
}
|
||||
switch (stopbits)
|
||||
{
|
||||
default: // fall-through
|
||||
case PLATFORM_UART_STOPBITS_1:
|
||||
cfg.stop_bits = UART_STOP_BITS_1; break;
|
||||
case PLATFORM_UART_STOPBITS_1_5:
|
||||
cfg.stop_bits = UART_STOP_BITS_1_5; break;
|
||||
case PLATFORM_UART_STOPBITS_2:
|
||||
cfg.stop_bits = UART_STOP_BITS_2; break;
|
||||
}
|
||||
uart_param_config(id, &cfg);
|
||||
uart_set_pin(id, pins->tx_pin, pins->rx_pin, pins->rts_pin, pins->cts_pin);
|
||||
uart_set_line_inverse(id, (pins->tx_inverse? UART_INVERSE_TXD : UART_INVERSE_DISABLE)
|
||||
| (pins->rx_inverse? UART_INVERSE_RXD : UART_INVERSE_DISABLE)
|
||||
| (pins->rts_inverse? UART_INVERSE_RTS : UART_INVERSE_DISABLE)
|
||||
| (pins->cts_inverse? UART_INVERSE_CTS : UART_INVERSE_DISABLE)
|
||||
);
|
||||
|
||||
if(uart_event_task_id == 0) uart_event_task_id = task_get_id( uart_event_task );
|
||||
|
||||
return baud;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void platform_uart_send_multi( unsigned id, const char *data, size_t len )
|
||||
{
|
||||
size_t i;
|
||||
if (id == CONSOLE_UART) {
|
||||
for( i = 0; i < len; i ++ ) {
|
||||
putchar (data[ i ]);
|
||||
}
|
||||
} else {
|
||||
uart_write_bytes(id, data, len);
|
||||
}
|
||||
}
|
||||
|
||||
void platform_uart_send( unsigned id, uint8_t data )
|
||||
{
|
||||
if (id == CONSOLE_UART)
|
||||
putchar (data);
|
||||
else
|
||||
uart_write_bytes(id, (const char *)&data, 1);
|
||||
}
|
||||
|
||||
void platform_uart_flush( unsigned id )
|
||||
|
@ -75,6 +268,52 @@ void platform_uart_flush( unsigned id )
|
|||
fflush (stdout);
|
||||
}
|
||||
|
||||
|
||||
int platform_uart_start( unsigned id )
|
||||
{
|
||||
if (id == CONSOLE_UART)
|
||||
return 0;
|
||||
else {
|
||||
uart_status_t *us = & uart_status[id];
|
||||
|
||||
esp_err_t ret = uart_driver_install(id, UART_BUFFER_SIZE, UART_BUFFER_SIZE, 3, & us->queue, 0);
|
||||
if(ret != ESP_OK) {
|
||||
return -1;
|
||||
}
|
||||
us->line_buffer = malloc(LUA_MAXINPUT);
|
||||
us->line_position = 0;
|
||||
if(us->line_buffer == NULL) {
|
||||
uart_driver_delete(id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char pcName[6];
|
||||
snprintf( pcName, 6, "uart%d", id );
|
||||
pcName[5] = '\0';
|
||||
if(xTaskCreate(task_uart, pcName, 2048, (void*)id, ESP_TASK_MAIN_PRIO + 1, & us->taskHandle) != pdPASS) {
|
||||
uart_driver_delete(id);
|
||||
free(us->line_buffer);
|
||||
us->line_buffer = NULL;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void platform_uart_stop( unsigned id )
|
||||
{
|
||||
if (id == CONSOLE_UART)
|
||||
;
|
||||
else {
|
||||
uart_status_t *us = & uart_status[id];
|
||||
uart_driver_delete(id);
|
||||
if(us->line_buffer) free(us->line_buffer);
|
||||
us->line_buffer = NULL;
|
||||
if(us->taskHandle) vTaskDelete(us->taskHandle);
|
||||
us->taskHandle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// Sigma-Delta platform interface
|
||||
|
||||
|
|
|
@ -5,40 +5,29 @@
|
|||
|
||||
The [UART](https://en.wikipedia.org/wiki/Universal_asynchronous_receiver/transmitter) (Universal asynchronous receiver/transmitter) module allows configuration of and communication over the UART serial port.
|
||||
|
||||
The default setup for the uart is controlled by build-time settings. The default rate is 115,200 bps. In addition, auto-baudrate detection is enabled for the first two minutes
|
||||
The default setup for the console uart is controlled by build-time settings. The default uart for console is `UART0`. The default rate is 115,200 bps. In addition, auto-baudrate detection is enabled for the first two minutes
|
||||
after platform boot. This will cause a switch to the correct baud rate once a few characters are received. Auto-baudrate detection is disabled when `uart.setup` is called.
|
||||
## uart.alt()
|
||||
Change UART pin assignment.
|
||||
|
||||
#### Syntax
|
||||
`uart.alt(on)`
|
||||
|
||||
#### Parameters
|
||||
`on`
|
||||
|
||||
- 0 for standard pins
|
||||
- 1 to use alternate pins GPIO13 and GPIO15
|
||||
|
||||
#### Returns
|
||||
`nil`
|
||||
For other uarts, you should call `uart.setup` and `uart.start` to get them working.
|
||||
|
||||
## uart.on()
|
||||
|
||||
Sets the callback function to handle UART events.
|
||||
|
||||
Currently only the "data" event is supported.
|
||||
|
||||
#### Syntax
|
||||
`uart.on(method, [number/end_char], [function], [run_input])`
|
||||
`uart.on([id], method, [number/end_char], [function], [run_input])`
|
||||
|
||||
#### Parameters
|
||||
- `method` "data", data has been received on the UART
|
||||
- `number/end_char`
|
||||
- `id` uart id, default value is uart num of the console.
|
||||
- `method` "data", data has been received on the UART. "error", error occurred on the UART.
|
||||
- `number/end_char`. Only for event `data`.
|
||||
- if pass in a number n<255, the callback will called when n chars are received.
|
||||
- if n=0, will receive every char in buffer.
|
||||
- if pass in a one char string "c", the callback will called when "c" is encounterd, or max n=255 received.
|
||||
- `function` callback function, event "data" has a callback like this: `function(data) end`
|
||||
- `run_input` 0 or 1. If 0, input from UART will not go into Lua interpreter, can accept binary data. If 1, input from UART will go into Lua interpreter, and run.
|
||||
- `function` callback function.
|
||||
- event "data" has a callback like this: `function(data) end`
|
||||
- event "error" has a callback like this: `function(err) end`. `err` could be one of "out_of_memory", "break", "rx_error".
|
||||
- `run_input` 0 or 1. Only for "data" event on console uart. If 0, input from UART will not go into Lua interpreter, can accept binary data. If 1, input from UART will go into Lua interpreter, and run.
|
||||
|
||||
To unregister the callback, provide only the "data" parameter.
|
||||
|
||||
|
@ -63,6 +52,18 @@ uart.on("data", "\r",
|
|||
uart.on("data") -- unregister callback function
|
||||
end
|
||||
end, 0)
|
||||
|
||||
-- uart 2
|
||||
uart.on(2, "data", "\r",
|
||||
function(data)
|
||||
print("receive from uart:", data)
|
||||
end)
|
||||
|
||||
-- error handler
|
||||
uart.on(2, "error",
|
||||
function(data)
|
||||
print("error from uart:", data)
|
||||
end)
|
||||
```
|
||||
|
||||
## uart.setup()
|
||||
|
@ -70,15 +71,26 @@ end, 0)
|
|||
(Re-)configures the communication parameters of the UART.
|
||||
|
||||
#### Syntax
|
||||
`uart.setup(id, baud, databits, parity, stopbits, echo)`
|
||||
`uart.setup(id, baud, databits, parity, stopbits, echo_or_pins)`
|
||||
|
||||
#### Parameters
|
||||
- `id` always zero, only one uart supported
|
||||
- `id` uart id
|
||||
- `baud` one of 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 74880, 115200, 230400, 256000, 460800, 921600, 1843200, 3686400
|
||||
- `databits` one of 5, 6, 7, 8
|
||||
- `parity` `uart.PARITY_NONE`, `uart.PARITY_ODD`, or `uart.PARITY_EVEN`
|
||||
- `stopbits` `uart.STOPBITS_1`, `uart.STOPBITS_1_5`, or `uart.STOPBITS_2`
|
||||
- `echo` if 0, disable echo, otherwise enable echo
|
||||
- `echo_or_pins`
|
||||
- for console uart, this should be a int. if 0, disable echo, otherwise enable echo
|
||||
- for others, this is a table:
|
||||
- `tx` int. TX pin. Required
|
||||
- `rx` int. RX pin. Required
|
||||
- `cts` in. CTS pin. Optional
|
||||
- `rts` in. RTS pin. Optional
|
||||
- `tx_inverse` boolean. Inverse TX pin. Default: `false`
|
||||
- `rx_inverse` boolean. Inverse RX pin. Default: `false`
|
||||
- `cts_inverse` boolean. Inverse CTS pin. Default: `false`
|
||||
- `rts_inverse` boolean. Inverse RTS pin. Default: `false`
|
||||
- `flow_control` int. Combination of `uart.FLOWCTRL_NONE`, `uart.FLOWCTRL_CTS`, `uart.FLOWCTRL_RTS`. Default: `uart.FLOWCTRL_NONE`
|
||||
|
||||
#### Returns
|
||||
configured baud rate (number)
|
||||
|
@ -89,6 +101,36 @@ configured baud rate (number)
|
|||
uart.setup(0, 9600, 8, uart.PARITY_NONE, uart.STOPBITS_1, 1)
|
||||
```
|
||||
|
||||
```lua
|
||||
uart.setup(2, 115200, 8, uart.PARITY_NONE, uart.STOPBITS_1, {tx = 16, rx = 17})
|
||||
```
|
||||
|
||||
## uart.start()
|
||||
Start the UART. You do not need to call `start()` on the console uart.
|
||||
|
||||
#### Syntax
|
||||
`uart.start(id)`
|
||||
|
||||
#### Parameters
|
||||
- `id` uart id, except console uart
|
||||
|
||||
#### Returns
|
||||
Boolean. `true` if uart is started.
|
||||
|
||||
|
||||
## uart.stop()
|
||||
Stop the UART. You should not call `stop()` on the console uart.
|
||||
|
||||
#### Syntax
|
||||
`uart.stop(id)`
|
||||
|
||||
#### Parameters
|
||||
- `id` uart id, except console uart
|
||||
|
||||
#### Returns
|
||||
`nil`
|
||||
|
||||
|
||||
## uart.write()
|
||||
|
||||
Write string or byte to the UART.
|
||||
|
@ -97,7 +139,7 @@ Write string or byte to the UART.
|
|||
`uart.write(id, data1 [, data2, ...])`
|
||||
|
||||
#### Parameters
|
||||
- `id` always 0, only one UART supported
|
||||
- `id` uart id
|
||||
- `data1`... string or byte to send via UART
|
||||
|
||||
#### Returns
|
||||
|
|
Loading…
Reference in New Issue