zephyr: Re-implement the Zephyr console in non-blocking mode.
The standard Zephyr console implementation doesn't make use of `tty_set_rx_timeout()` and therefore all the functions to receive characters block indefinitely until data is received (including `console_read()`). This commit also releases the GIL where it applies, e.g. the REPL and the time sleep functions. Signed-off-by: danicampora <danicampora@gmail.com>
This commit is contained in:
parent
6833f3dda9
commit
d68d8fcf90
@ -51,12 +51,15 @@ void mp_hal_wait_sem(struct k_sem *sem, uint32_t timeout_ms) {
|
||||
k_poll_event_init(&wait_events[1], K_POLL_TYPE_SEM_AVAILABLE, K_POLL_MODE_NOTIFY_ONLY, sem);
|
||||
}
|
||||
for (;;) {
|
||||
mp_handle_pending(true);
|
||||
MP_THREAD_GIL_EXIT();
|
||||
k_timeout_t wait;
|
||||
if (timeout_ms == (uint32_t)-1) {
|
||||
wait = K_FOREVER;
|
||||
} else {
|
||||
uint32_t dt = mp_hal_ticks_ms() - t0;
|
||||
if (dt >= timeout_ms) {
|
||||
MP_THREAD_GIL_ENTER();
|
||||
return;
|
||||
}
|
||||
wait = K_MSEC(timeout_ms - dt);
|
||||
@ -65,9 +68,9 @@ void mp_hal_wait_sem(struct k_sem *sem, uint32_t timeout_ms) {
|
||||
if (wait_events[0].state == K_POLL_STATE_SIGNALED) {
|
||||
wait_events[0].signal->signaled = 0;
|
||||
wait_events[0].state = K_POLL_STATE_NOT_READY;
|
||||
mp_handle_pending(true);
|
||||
} else if (sem && wait_events[1].state == K_POLL_STATE_SEM_AVAILABLE) {
|
||||
wait_events[1].state = K_POLL_STATE_NOT_READY;
|
||||
MP_THREAD_GIL_ENTER();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -269,6 +269,7 @@ int mp_thread_mutex_lock(mp_thread_mutex_t *mutex, int wait) {
|
||||
|
||||
void mp_thread_mutex_unlock(mp_thread_mutex_t *mutex) {
|
||||
k_sem_give(&mutex->handle);
|
||||
k_yield();
|
||||
}
|
||||
|
||||
void mp_thread_deinit(void) {
|
||||
|
||||
@ -50,14 +50,16 @@ static int console_irq_input_hook(uint8_t ch) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t zephyr_getchar(void) {
|
||||
mp_hal_wait_sem(&uart_sem, -1);
|
||||
k_sem_take(&uart_sem, K_FOREVER);
|
||||
unsigned int key = irq_lock();
|
||||
uint8_t c = uart_ringbuf[i_get++];
|
||||
i_get &= UART_BUFSIZE - 1;
|
||||
irq_unlock(key);
|
||||
return c;
|
||||
int zephyr_getchar(void) {
|
||||
mp_hal_wait_sem(&uart_sem, 0);
|
||||
if (k_sem_take(&uart_sem, K_MSEC(0)) == 0) {
|
||||
unsigned int key = irq_lock();
|
||||
int c = (int)uart_ringbuf[i_get++];
|
||||
i_get &= UART_BUFSIZE - 1;
|
||||
irq_unlock(key);
|
||||
return c;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void zephyr_getchar_init(void) {
|
||||
|
||||
@ -17,4 +17,4 @@
|
||||
#include <stdint.h>
|
||||
|
||||
void zephyr_getchar_init(void);
|
||||
uint8_t zephyr_getchar(void);
|
||||
int zephyr_getchar(void);
|
||||
|
||||
@ -24,14 +24,14 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include <zephyr/zephyr.h>
|
||||
#include <zephyr/console/console.h>
|
||||
#include "zephyr_getchar.h"
|
||||
|
||||
int real_main(void);
|
||||
int mp_console_init(void);
|
||||
|
||||
void main(void) {
|
||||
#ifdef CONFIG_CONSOLE_SUBSYS
|
||||
console_init();
|
||||
mp_console_init();
|
||||
#else
|
||||
zephyr_getchar_init();
|
||||
#endif
|
||||
|
||||
@ -25,10 +25,28 @@
|
||||
*/
|
||||
#include <unistd.h>
|
||||
#include "py/mpconfig.h"
|
||||
#include "py/runtime.h"
|
||||
#include "src/zephyr_getchar.h"
|
||||
// Zephyr headers
|
||||
#include <zephyr/drivers/uart.h>
|
||||
#include <zephyr/zephyr.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/console/console.h>
|
||||
#include <zephyr/console/tty.h>
|
||||
#include <zephyr/drivers/uart.h>
|
||||
|
||||
|
||||
#ifdef CONFIG_CONSOLE_SUBSYS
|
||||
|
||||
static int mp_console_putchar(char c);
|
||||
static int mp_console_getchar(void);
|
||||
|
||||
|
||||
static struct tty_serial mp_console_serial;
|
||||
|
||||
static uint8_t mp_console_rxbuf[CONFIG_CONSOLE_GETCHAR_BUFSIZE];
|
||||
static uint8_t mp_console_txbuf[CONFIG_CONSOLE_PUTCHAR_BUFSIZE];
|
||||
|
||||
#endif // CONFIG_CONSOLE_SUBSYS
|
||||
|
||||
/*
|
||||
* Core UART functions to implement for a port
|
||||
@ -36,11 +54,18 @@
|
||||
|
||||
// Receive single character
|
||||
int mp_hal_stdin_rx_chr(void) {
|
||||
#ifdef CONFIG_CONSOLE_SUBSYS
|
||||
return console_getchar();
|
||||
#else
|
||||
return zephyr_getchar();
|
||||
#endif
|
||||
for (;;) {
|
||||
int _chr;
|
||||
#ifdef CONFIG_CONSOLE_SUBSYS
|
||||
_chr = mp_console_getchar();
|
||||
#else
|
||||
_chr = zephyr_getchar();
|
||||
#endif
|
||||
if (_chr >= 0) {
|
||||
return _chr;
|
||||
}
|
||||
MICROPY_EVENT_POLL_HOOK
|
||||
}
|
||||
}
|
||||
|
||||
// Send string of given length
|
||||
@ -49,8 +74,8 @@ mp_uint_t mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
|
||||
#ifdef CONFIG_CONSOLE_SUBSYS
|
||||
while (len--) {
|
||||
char c = *str++;
|
||||
while (console_putchar(c) == -1) {
|
||||
k_msleep(1);
|
||||
while (mp_console_putchar(c) == -1) {
|
||||
MICROPY_EVENT_POLL_HOOK
|
||||
}
|
||||
}
|
||||
#else
|
||||
@ -63,3 +88,58 @@ mp_uint_t mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_CONSOLE_SUBSYS
|
||||
|
||||
int mp_console_init(void) {
|
||||
|
||||
const struct device *uart_dev;
|
||||
int ret;
|
||||
|
||||
uart_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
|
||||
if (!device_is_ready(uart_dev)) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = tty_init(&mp_console_serial, uart_dev);
|
||||
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Checks device driver supports for interrupt driven data transfers. */
|
||||
if (CONFIG_CONSOLE_GETCHAR_BUFSIZE + CONFIG_CONSOLE_PUTCHAR_BUFSIZE) {
|
||||
const struct uart_driver_api *api =
|
||||
(const struct uart_driver_api *)uart_dev->api;
|
||||
if (!api->irq_callback_set) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
tty_set_tx_buf(&mp_console_serial, mp_console_txbuf, sizeof(mp_console_txbuf));
|
||||
tty_set_rx_buf(&mp_console_serial, mp_console_rxbuf, sizeof(mp_console_rxbuf));
|
||||
|
||||
tty_set_rx_timeout(&mp_console_serial, 0);
|
||||
tty_set_tx_timeout(&mp_console_serial, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mp_console_putchar(char c) {
|
||||
return tty_write(&mp_console_serial, &c, 1);
|
||||
}
|
||||
|
||||
static int mp_console_getchar(void) {
|
||||
uint8_t c;
|
||||
int res;
|
||||
|
||||
res = tty_read(&mp_console_serial, &c, 1);
|
||||
if (res < 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
#endif // CONFIG_CONSOLE_SUBSYS
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user