8000 zephyr: run async/scheduled events during REPL and sleep by dpgeorge · Pull Request #7177 · micropython/micropython · GitHub
[go: up one dir, main page]

Skip to content

zephyr: run async/scheduled events during REPL and sleep #7177

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

Merged
merged 4 commits into from
Apr 30, 2021
Merged
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
1 change: 1 addition & 0 deletions ports/zephyr/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ set(MICROPY_SOURCE_PORT
modutime.c
modzephyr.c
modzsensor.c
mphalport.c
uart_core.c
zephyr_storage.c
)
Expand Down
2 changes: 2 additions & 0 deletions ports/zephyr/boards/nucleo_wb55rg.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CONFIG_CONSOLE_SUBSYS=n
CONFIG_NETWORKING=n
2 changes: 2 additions & 0 deletions ports/zephyr/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "py/runtime.h"
#include "py/repl.h"
#include "py/gc.h"
#include "py/mphal.h"
#include "py/stackctrl.h"
#include "lib/utils/pyexec.h"
#include "lib/mp-readline/readline.h"
Expand Down Expand Up @@ -123,6 +124,7 @@ int real_main(void) {
mp_stack_set_limit(CONFIG_MAIN_STACK_SIZE - 512);

init_zephyr();
mp_hal_init();

#ifdef TEST
static const char *argv[] = {"test"};
Expand Down
7 changes: 7 additions & 0 deletions ports/zephyr/modmachine.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,19 @@ STATIC mp_obj_t machine_reset_cause(void) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause);

STATIC mp_obj_t machine_idle(void) {
k_yield();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_idle_obj, machine_idle);

STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) },
#ifdef CONFIG_REBOOT
{ MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) },
#endif
{ MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) },
{ MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&machine_idle_obj) },

#if MICROPY_PY_MACHINE_I2C
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_hard_i2c_type) },
Expand Down
3 changes: 3 additions & 0 deletions ports/zephyr/mpconfigport.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@
#define MICROPY_COMP_CONST (0)
#define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (0)

void mp_hal_signal_event(void);
#define MICROPY_SCHED_HOOK_SCHEDULED mp_hal_signal_event()

#define MICROPY_PY_SYS_PLATFORM "zephyr"

#ifdef CONFIG_BOARD
Expand Down
74 changes: 74 additions & 0 deletions ports/zephyr/mphalport.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#include "py/runtime.h"
#include "py/mphal.h"

static struct k_poll_signal wait_signal;
static struct k_poll_event wait_events[2] = {
K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
K_POLL_MODE_NOTIFY_ONLY,
&wait_signal),
K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_SEM_AVAILABLE,
K_POLL_MODE_NOTIFY_ONLY,
NULL, 0),
};

void mp_hal_init(void) {
k_poll_signal_init(&wait_signal);
}

void mp_hal_signal_event(void) {
k_poll_signal_raise(&wait_signal, 0);
}

void mp_hal_wait_sem(struct k_sem *sem, uint32_t timeout_ms) {
mp_uint_t t0 = mp_hal_ticks_ms();
if (sem) {
k_poll_event_init(&wait_events[1], K_POLL_TYPE_SEM_AVAILABLE, K_POLL_MODE_NOTIFY_ONLY, sem);
}
for (;;) {
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) {
return;
}
wait = K_MSEC(timeout_ms - dt);
}
k_poll(wait_events, sem ? 2 : 1, wait);
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;
return;
}
}
}
5 changes: 4 additions & 1 deletion ports/zephyr/mphalport.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#include <zephyr.h>
#include "lib/utils/interrupt_char.h"

void mp_hal_init(void);
void mp_hal_wait_sem(struct k_sem *sem, uint32_t timeout_ms);

static inline mp_uint_t mp_hal_ticks_us(void) {
return k_cyc_to_ns_floor64(k_cycle_get_32()) / 1000;
}
Expand All @@ -21,7 +24,7 @@ static inline void mp_hal_delay_us(mp_uint_t delay) {
}

static inline void mp_hal_delay_ms(mp_uint_t delay) {
k_msleep(delay);
mp_hal_wait_sem(NULL, delay);
}

static inline uint64_t mp_hal_time_ns(void) {
Expand Down
1 change: 1 addition & 0 deletions ports/zephyr/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ CONFIG_CONSOLE_PUTCHAR_BUFSIZE=128
CONFIG_NEWLIB_LIBC=y
CONFIG_FPU=y
CONFIG_MAIN_STACK_SIZE=4736
CONFIG_POLL=y

# Enable sensor subsystem (doesn't add code if not used).
# Specific sensors should be enabled per-board.
Expand Down
1 change: 1 addition & 0 deletions ports/zephyr/prj_minimal.conf
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
CONFIG_NEWLIB_LIBC=y
CONFIG_FPU=y
CONFIG_MAIN_STACK_SIZE=4096
CONFIG_POLL=y

CONFIG_UART_INTERRUPT_DRIVEN=y
CONFIG_CONSOLE_SUBSYS=y
Expand Down
4 changes: 4 additions & 0 deletions ports/zephyr/src/zephyr_getchar.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

extern int mp_interrupt_char;
void mp_sched_keyboard_interrupt(void);
void mp_hal_signal_event(void);
void mp_hal_wait_sem(struct k_sem *sem, uint32_t timeout_ms);

static struct k_sem uart_sem;
#define UART_BUFSIZE 256
Expand All @@ -36,6 +38,7 @@ static int console_irq_input_hook(uint8_t ch)
return 1;
}
if (ch == mp_interrupt_char) {
mp_hal_signal_event();
mp_sched_keyboard_interrupt();
return 1;
} else {
Expand All @@ -49,6 +52,7 @@ static int console_irq_input_hook(uint8_t ch)
}

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++];
Expand Down
6 changes: 6 additions & 0 deletions py/mpconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,12 @@
#define MICROPY_VM_HOOK_RETURN
#endif

// Hook for mp_sched_schedule when a function gets scheduled on sched_queue
// (this macro executes within an atomic section)
#ifndef MICROPY_SCHED_HOOK_SCHEDULED
#define MICROPY_SCHED_HOOK_SCHEDULED
#endif

// Whether to include the garbage collector
#ifndef MICROPY_ENABLE_GC
#define MICROPY_ENABLE_GC (0)
Expand Down
1 change: 1 addition & 0 deletions py/scheduler.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ bool MICROPY_WRAP_MP_SCHED_SCHEDULE(mp_sched_schedule)(mp_obj_t function, mp_obj
uint8_t iput = IDX_MASK(MP_STATE_VM(sched_idx) + MP_STATE_VM(sched_len)++);
MP_STATE_VM(sched_queue)[iput].func = function;
MP_STATE_VM(sched_queue)[iput].arg = arg;
MICROPY_SCHED_HOOK_SCHEDULED;
ret = true;
} else {
// schedule queue is full
Expand Down
0