ESP32: add support for RS485 (#2559)

* ESP32: add support for RS485

This commit adds support for switching UART mode to RS485/IRDA.
Also included are patches for memory leaks then handling UART events other than data.

* ESP32: Documentation for uart.setmode()
This commit is contained in:
Skirmantas Lauzikas 2018-11-30 13:07:05 +02:00 committed by Marcel Stör
parent 794a07bb51
commit 3257e557d4
4 changed files with 72 additions and 1 deletions

View File

@ -172,6 +172,20 @@ static int uart_setup( lua_State* L )
return 1;
}
static int uart_setmode(lua_State* L)
{
unsigned id, mode;
uint32_t res;
id = luaL_checkinteger( L, 1 );
MOD_CHECK_ID( uart, id );
mode = luaL_checkinteger( L, 2 );
platform_uart_setmode(id, mode);
return 0;
}
// Lua: write( id, string1, [string2], ..., [stringn] )
static int uart_write( lua_State* L )
{
@ -231,6 +245,7 @@ static const LUA_REG_TYPE uart_map[] = {
{ LSTRKEY( "start" ), LFUNCVAL( uart_start ) },
{ LSTRKEY( "stop" ), LFUNCVAL( uart_stop ) },
{ LSTRKEY( "on" ), LFUNCVAL( uart_on ) },
{ LSTRKEY( "setmode" ), LFUNCVAL( uart_setmode ) },
{ LSTRKEY( "STOPBITS_1" ), LNUMVAL( PLATFORM_UART_STOPBITS_1 ) },
{ LSTRKEY( "STOPBITS_1_5" ), LNUMVAL( PLATFORM_UART_STOPBITS_1_5 ) },
{ LSTRKEY( "STOPBITS_2" ), LNUMVAL( PLATFORM_UART_STOPBITS_2 ) },
@ -240,6 +255,11 @@ static const LUA_REG_TYPE uart_map[] = {
{ LSTRKEY( "FLOWCTRL_NONE" ), LNUMVAL( PLATFORM_UART_FLOW_NONE ) },
{ LSTRKEY( "FLOWCTRL_CTS" ), LNUMVAL( PLATFORM_UART_FLOW_CTS ) },
{ LSTRKEY( "FLOWCTRL_RTS" ), LNUMVAL( PLATFORM_UART_FLOW_RTS ) },
{ LSTRKEY( "MODE_UART" ), LNUMVAL( PLATFORM_UART_MODE_UART ) },
{ LSTRKEY( "MODE_RS485_COLLISION_DETECT" ), LNUMVAL( PLATFORM_UART_MODE_RS485_COLLISION_DETECT ) },
{ LSTRKEY( "MODE_RS485_APP_CONTROL" ), LNUMVAL( PLATFORM_UART_MODE_RS485_APP_CONTROL ) },
{ LSTRKEY( "MODE_RS485_HALF_DUPLEX" ), LNUMVAL( PLATFORM_UART_MODE_HALF_DUPLEX ) },
{ LSTRKEY( "MODE_IRDA" ), LNUMVAL( PLATFORM_UART_MODE_IRDA ) },
{ LNILKEY, LNILVAL }
};

View File

@ -50,6 +50,15 @@ int platform_gpio_output_exists( unsigned gpio );
#define UART_BUFFER_SIZE 512
enum
{
PLATFORM_UART_MODE_UART = 0x0,
PLATFORM_UART_MODE_RS485_COLLISION_DETECT = 0x1,
PLATFORM_UART_MODE_RS485_APP_CONTROL = 0x2,
PLATFORM_UART_MODE_HALF_DUPLEX = 0x3,
PLATFORM_UART_MODE_IRDA = 0x4
};
// Parity
enum
{
@ -107,6 +116,7 @@ typedef struct {
// 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, uart_pins_t* pins );
void platform_uart_setmode(unsigned id, unsigned mode);
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 );

View File

@ -76,7 +76,6 @@ void uart_event_task( task_param_t param, task_prio_t prio ) {
}
free(post->data);
free(post);
} else {
char *err;
switch(post->type) {
@ -92,6 +91,7 @@ void uart_event_task( task_param_t param, task_prio_t prio ) {
}
uart_on_error_cb(id, err, strlen(err));
}
free(post);
}
static void task_uart( void *pvParameters ){
@ -130,6 +130,7 @@ static void task_uart( void *pvParameters ){
}
post->id = id;
post->type = PLATFORM_UART_EVENT_BREAK;
break;
case UART_FIFO_OVF:
case UART_BUFFER_FULL:
case UART_PARITY_ERR:
@ -242,6 +243,26 @@ uint32_t platform_uart_setup( unsigned id, uint32_t baud, int databits, int pari
}
}
void platform_uart_setmode(unsigned id, unsigned mode)
{
uart_mode_t uartMode;
switch(mode)
{
case PLATFORM_UART_MODE_IRDA:
uartMode = UART_MODE_IRDA; break;
case PLATFORM_UART_MODE_RS485_COLLISION_DETECT:
uartMode = UART_MODE_RS485_COLLISION_DETECT; break;
case PLATFORM_UART_MODE_RS485_APP_CONTROL:
uartMode = UART_MODE_RS485_APP_CTRL; break;
case PLATFORM_UART_MODE_HALF_DUPLEX:
uartMode = UART_MODE_RS485_HALF_DUPLEX; break;
case PLATFORM_UART_MODE_UART:
default:
uartMode = UART_MODE_UART; break;
}
uart_set_mode(id, uartMode);
}
void platform_uart_send_multi( unsigned id, const char *data, size_t len )
{

View File

@ -131,6 +131,26 @@ Stop the UART. You should not call `stop()` on the console uart.
`nil`
## uart.setmode()
Set UART controllers communication mode
#### Syntax
`uart.setmode(id, mode)`
#### Parameters
- `id` uart id
- `mode` value should be one of
- `uart.MODE_UART` default UART mode, is set after uart.setup() call
- `uart.MODE_RS485_COLLISION_DETECT` receiver must be always enabled, transmitter is automatically switched using RTS pin, collision is detected by UART hardware (note: no event is generated on collision, limitation of esp-idf)
- `uart.MODE_RS485_APP_CONTROL` receiver/transmitter control is left to the application
- `uart.MODE_RS485_HALF_DUPLEX` receiver/transmitter are controlled by RTS pin
- `uart.MODE_IRDA`
#### Returns
`nil`
## uart.write()
Write string or byte to the UART.