8000 esp8266: Allow disable of REPL on UART0 by dmkent · Pull Request #3277 · micropython/micropython · GitHub
[go: up one dir, main page]

Skip to content

esp8266: Allow disable of REPL on UART0 #3277

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions esp8266/esp_mphal.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
#include <stdio.h>
#include "ets_sys.h"
#include "etshal.h"
#include "uart.h"
#include "esp_mphal.h"
#include "user_interface.h"
#include "ets_alt_task.h"
Expand All @@ -45,7 +44,7 @@ const mp_print_t mp_debug_print = {NULL, mp_hal_debug_tx_strn_cooked};
void mp_hal_init(void) {
//ets_wdt_disable(); // it's a pain while developing
mp_hal_rtc_init();
uart_init(UART_BIT_RATE_115200, UART_BIT_RATE_115200);
machine_uart_init();
}

void mp_hal_delay_us(uint32_t us) {
Expand Down Expand Up @@ -73,14 +72,14 @@ int mp_hal_stdin_rx_chr(void) {
}

void mp_hal_stdout_tx_char(char c) {
uart_tx_one_char(UART0, c);
uart_maybe_repl_tx_one_char(c);
mp_uos_dupterm_tx_strn(&c, 1);
}

#if 0
void mp_hal_debug_str(const char *str) {
while (*str) {
uart_tx_one_char(UART0, *str++);
uart_maybe_repl_tx_one_char(UART0, *str++);
}
uart_flush(UART0);
}
Expand Down Expand Up @@ -111,9 +110,9 @@ void mp_hal_debug_tx_strn_cooked(void *env, const char *str, uint32_t len) {
(void)env;
while (len--) {
if (*str == '\n') {
uart_tx_one_char(UART0, '\r');
uart_maybe_repl_tx_one_char('\r');
}
uart_tx_one_char(UART0, *str++);
uart_maybe_repl_tx_one_char(*str++);
}
}

Expand Down Expand Up @@ -146,6 +145,7 @@ void mp_hal_signal_input(void) {
#endif
}


static int call_dupterm_read(void) {
if (MP_STATE_PORT(term_obj) == NULL) {
return -1;
Expand Down
105 changes: 96 additions & 9 deletions esp8266/machine_uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,14 @@
#include <string.h>

#include "ets_sys.h"
#include "user_interface.h"
#include "uart.h"
#include "esp_mphal.h"

#include "py/runtime.h"
#include "py/stream.h"
#include "py/mperrno.h"
#include "py/ringbuf.h"
#include "modmachine.h"

// UartDev is defined and initialized in rom code.
Expand All @@ -48,22 +51,36 @@ typedef struct _pyb_uart_obj_t {
uint32_t baudrate;
uint16_t timeout; // timeout waiting for first char (in ms)
uint16_t timeout_char; // timeout waiting between chars (in ms)
uint16_t rxbuflen;
ringbuf_t rxbuf;
byte *buf;
uint8_t use_repl;
} pyb_uart_obj_t;

pyb_uart_obj_t pyb_uart_objs[2];

STATIC const char *_parity_name[] = {"None", "1", "0"};

/******************************************************************************/
// MicroPython bindings for UART

void machine_uart_init (void) {
uart_init(UART_BIT_RATE_115200, UART_BIT_RATE_115200);

// save references of the UART objects, to prevent the read buffers from being trashed by the gc
MP_STATE_PORT(pyb_uart_objs)[0] = &pyb_uart_objs[0];
MP_STATE_PORT(pyb_uart_objs)[1] = &pyb_uart_objs[1];
}

STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, timeout=%u, timeout_char=%u)",
mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, timeout=%u, timeout_char=%u, rxbuflen=%u, use_repl=%u)",
self->uart_id, self->baudrate, self->bits, _parity_name[self->parity],
self->stop, self->timeout, self->timeout_char);
self->stop, self->timeout, self->timeout_char, self->rxbuflen, self->use_repl);
}

STATIC void pyb_uart_init_helper(pyb_uart_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_timeout, ARG_timeout_char };
enum { ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_timeout, ARG_timeout_char, ARG_rxbuflen, ARG_use_repl };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_bits, MP_ARG_INT, {.u_int = 0} },
Expand All @@ -73,6 +90,8 @@ STATIC void pyb_uart_init_helper(pyb_uart_obj_t *self, size_t n_args, const mp_o
//{ MP_QSTR_rx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_rxbuflen, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 16} },
{ MP_QSTR_use_repl, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
Expand Down Expand Up @@ -155,6 +174,23 @@ STATIC void pyb_uart_init_helper(pyb_uart_obj_t *self, size_t n_args, const mp_o
self->timeout_char = min_timeout_char;
}

if (args[ARG_rxbuflen].u_int != self->rxbuflen) {
self->rxbuflen = args[ARG_rxbuflen].u_int;
if (self->buf) {
m_free(self->buf);
}
self->buf = m_malloc(self->rxbuflen);
}
self->rxbuf.buf = self->buf;
self->rxbuf.size = self->rxbuflen;
self->rxbuf.iget = self->rxbuf.iput=0;

if (args[ARG_use_repl].u_int == 0) {
self->use_repl = 0;
} else {
self->use_repl = 1;
}

// setup
uart_setup(self->uart_id);
}
Expand All @@ -169,7 +205,7 @@ STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, size_t n_args, size
}

// create instance
pyb_uart_obj_t *self = m_new_obj(pyb_uart_obj_t);
pyb_uart_obj_t *self = &pyb_uart_objs[uart_id];
self->base.type = &pyb_uart_type;
self->uart_id = uart_id;
self->baudrate = 115200;
Expand All @@ -182,6 +218,7 @@ STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, size_t n_args, size
// init the peripheral
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);

pyb_uart_init_helper(self, n_args - 1, args + 1, &kw_args);

return MP_OBJ_FROM_PTR(self);
Expand All @@ -195,7 +232,11 @@ MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_init_obj, 1, pyb_uart_init);

STATIC mp_obj_t pyb_uart_any(mp_obj_t self_in) {
pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
return MP_OBJ_NEW_SMALL_INT(uart_rx_any(self->uart_id));
if (self->rxbuf.iput != self->rxbuf.iget) {
return mp_const_true;
} else {
return mp_const_false;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_any_obj, pyb_uart_any);

Expand All @@ -211,6 +252,50 @@ STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = {

STATIC MP_DEFINE_CONST_DICT(pyb_uart_locals_dict, pyb_uart_locals_dict_table);

void uart_handle_rx() {
int ch;
pyb_uart_obj_t *self = &pyb_uart_objs[0];
bool is_uart_repl = self->use_repl;

while (uart_rx_any(0)) {
ch = uart_rx_one_char(0);
ringbuf_put(&self->rxbuf, ch);
if (is_uart_repl) {
if (ch == mp_interrupt_char) {
mp_keyboard_interrupt();
} else {
ringbuf_put(&input_buf, ch);
}
}
}
if (is_uart_repl) {
mp_hal_signal_input();
}
}

void uart_maybe_repl_tx_one_char(char c) {
pyb_uart_obj_t *uart = &pyb_uart_objs[0];
if (uart->use_repl) {
uart_tx_one_char(UART0, c);
}
}

// Waits at most timeout microseconds for at least 1 char to become ready for reading.
// Returns true if something available, false if not.
STATIC bool uart_rx_wait(pyb_uart_obj_t *self, uint32_t timeout_us) {
uint32_t start = system_get_time();

for (;;) {
if (self->rxbuf.iput != self->rxbuf.iget) {
return true; // have at least 1 char ready for reading
}
if (timeout_us && system_get_time() - start >= timeout_us) {
return false; // timeout
}
ets_event_poll();
}
}

STATIC mp_uint_t pyb_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);

Expand All @@ -224,16 +309,18 @@ STATIC mp_uint_t pyb_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, i
}

// wait for first char to become available
if (!uart_rx_wait(self->timeout * 1000)) {
if (!uart_rx_wait(self, self->timeout * 1000)) {
*errcode = MP_EAGAIN;
return MP_STREAM_ERROR;
}

// read the data
uint8_t *buf = buf_in;
for (;;) {
*buf++ = uart_rx_char();
if (--size == 0 || !uart_rx_wait(self->timeout_char * 1000)) {
char ch = ringbuf_get(&self->rxbuf);
int avail = uart_rx_wait(self, self->timeout_char * 1000);
*buf++ = ch;
if (--size == 0 || !avail) {
// return number of bytes read
return buf - (uint8_t*)buf_in;
}
Expand Down Expand Up @@ -267,7 +354,7 @@ STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t a
if (request == MP_STREAM_POLL) {
mp_uint_t flags = arg;
ret = 0;
if ((flags & MP_STREAM_POLL_RD) && uart_rx_any(self->uart_id)) {
if ((flags & MP_STREAM_POLL_RD) && self->rxbuf.iget != self->rxbuf.iput) {
ret |= MP_STREAM_POLL_RD;
}
if ((flags & MP_STREAM_POLL_WR) && uart_tx_any_room(self->uart_id)) {
Expand Down
3 changes: 3 additions & 0 deletions esp8266/modmachine.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,7 @@ void pyb_rtc_set_us_since_2000(uint64_t nowus);
uint64_t pyb_rtc_get_us_since_2000();
void rtc_prepare_deepsleep(uint64_t sleep_us);

void uart_maybe_repl_tx_one_char(char c);
void machine_uart_init();

#endif // MICROPY_INCLUDED_ESP8266_MODMACHINE_H
2 changes: 2 additions & 0 deletions esp8266/modules/inisetup.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,7 @@ def setup():
#import webrepl
#webrepl.start()
gc.collect()
from machine import UART
uart0 = UART(0)
""")
return vfs
1 change: 1 addition & 0 deletions esp8266/mpconfigport.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ extern const struct _mp_obj_module_t mp_module_onewire;
#define MICROPY_PORT_ROOT_POINTERS \
const char *readline_hist[8]; \
mp_obj_t pin_irq_handler[16]; \
struct _pyb_uart_obj_t *pyb_uart_objs[2]; \

// We need to provide a declaration/definition of alloca()
#include <alloca.h>
Expand Down
38 changes: 6 additions & 32 deletions esp8266/uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ static void uart0_rx_intr_handler(void *para);

void soft_reset(void);
void mp_keyboard_interrupt(void);
void uart_handle_rx();

/******************************************************************************
* FunctionName : uart_config
Expand Down Expand Up @@ -168,57 +169,30 @@ static void uart0_rx_intr_handler(void *para) {
read_chars:
ETS_UART_INTR_DISABLE();

while (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) {
uint8 RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xff;
if (RcvChar == mp_interrupt_char) {
mp_keyboard_interrupt();
} else {
ringbuf_put(&input_buf, RcvChar);
}
}

mp_hal_signal_input();
uart_handle_rx();

// Clear pending FIFO interrupts
WRITE_PERI_REG(UART_INT_CLR(UART_REPL), UART_RXFIFO_TOUT_INT_CLR | UART_RXFIFO_FULL_INT_ST);
ETS_UART_INTR_ENABLE();
}
}

// Waits at most timeout microseconds for at least 1 char to become ready for reading.
// Returns true if something available, false if not.
bool uart_rx_wait(uint32_t timeout_us) {
uint32_t start = system_get_time();
for (;;) {
if (input_buf.iget != input_buf.iput) {
return true; // have at least 1 char ready for reading
}
if (system_get_time() - start >= timeout_us) {
return false; // timeout
}
ets_event_poll();
}
}

int uart_rx_any(uint8 uart) {
if (input_buf.iget != input_buf.iput) {
int uart_rx_any(uint8 uart_no) {
if (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) {
return true; // have at least 1 char ready for reading
}
return false;
}

int uart_tx_any_room(uint8 uart) {
uint32_t fifo_cnt = READ_PERI_REG(UART_STATUS(uart)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S);
int uart_tx_any_room(uint8 uart_no) {
uint32_t fifo_cnt = READ_PERI_REG(UART_STATUS(uart_no)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S);
if ((fifo_cnt >> UART_TXFIFO_CNT_S & UART_TXFIFO_CNT) >= 126) {
return false;
}
return true;
}

// Returns char from the input buffer, else -1 if buffer is empty.
int uart_rx_char(void) {
return ringbuf_get(&input_buf);
}

int uart_rx_one_char(uint8 uart_no) {
if (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) {
Expand Down
3 changes: 1 addition & 2 deletions esp8266/uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,7 @@ typedef struct {

void uart_init(UartBautRate uart0_br, UartBautRate uart1_br);
int uart0_rx(void);
bool uart_rx_wait(uint32_t timeout_us);
int uart_rx_char(void);
int uart_rx_one_char(uint8 uart);
void uart_tx_one_char(uint8 uart, uint8 TxChar);
void uart_flush(uint8 uart);
void uart_os_config(int uart);
Expand Down
0