Skip to content

Commit

Permalink
zephyr: Re-implement the Zephyr console in non-blocking mode.
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
danicampora authored and dpgeorge committed Sep 6, 2024
1 parent 6833f3d commit d68d8fc
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 20 deletions.
5 changes: 4 additions & 1 deletion ports/zephyr/mphalport.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
}
}
Expand Down
1 change: 1 addition & 0 deletions ports/zephyr/mpthreadport.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
18 changes: 10 additions & 8 deletions ports/zephyr/src/zephyr_getchar.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion ports/zephyr/src/zephyr_getchar.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@
#include <stdint.h>

void zephyr_getchar_init(void);
uint8_t zephyr_getchar(void);
int zephyr_getchar(void);
4 changes: 2 additions & 2 deletions ports/zephyr/src/zephyr_start.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
96 changes: 88 additions & 8 deletions ports/zephyr/uart_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,47 @@
*/
#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
*/

// 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
Expand All @@ -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
Expand All @@ -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

0 comments on commit d68d8fc

Please sign in to comment.