Skip to content

Commit d120859

Browse files
committed
zephyr: Run scheduled callbacks at REPL and during mp_hal_delay_ms.
And ctrl-C can now interrupt a time.sleep call. This uses Zephyr's k_poll API to wait efficiently for an event signal, and an optional semaphore. Signed-off-by: Damien George <[email protected]>
1 parent 916c3fd commit d120859

8 files changed

+90
-1
lines changed

ports/zephyr/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ set(MICROPY_SOURCE_PORT
4646
modutime.c
4747
modzephyr.c
4848
modzsensor.c
49+
mphalport.c
4950
uart_core.c
5051
zephyr_storage.c
5152
)

ports/zephyr/main.c

+2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include "py/runtime.h"
4646
#include "py/repl.h"
4747
#include "py/gc.h"
48+
#include "py/mphal.h"
4849
#include "py/stackctrl.h"
4950
#include "lib/utils/pyexec.h"
5051
#include "lib/mp-readline/readline.h"
@@ -123,6 +124,7 @@ int real_main(void) {
123124
mp_stack_set_limit(CONFIG_MAIN_STACK_SIZE - 512);
124125

125126
init_zephyr();
127+
mp_hal_init();
126128

127129
#ifdef TEST
128130
static const char *argv[] = {"test"};

ports/zephyr/mpconfigport.h

+3
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@
9696
#define MICROPY_COMP_CONST (0)
9797
#define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (0)
9898

99+
void mp_hal_signal_event(void);
100+
#define MICROPY_SCHED_HOOK_SCHEDULED mp_hal_signal_event()
101+
99102
#define MICROPY_PY_SYS_PLATFORM "zephyr"
100103

101104
#ifdef CONFIG_BOARD

ports/zephyr/mphalport.c

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2021 Damien P. George
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include "py/runtime.h"
28+
#include "py/mphal.h"
29+
30+
static struct k_poll_signal wait_signal;
31+
static struct k_poll_event wait_events[2] = {
32+
K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
33+
K_POLL_MODE_NOTIFY_ONLY,
34+
&wait_signal),
35+
K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_SEM_AVAILABLE,
36+
K_POLL_MODE_NOTIFY_ONLY,
37+
NULL, 0),
38+
};
39+
40+
void mp_hal_init(void) {
41+
k_poll_signal_init(&wait_signal);
42+
}
43+
44+
void mp_hal_signal_event(void) {
45+
k_poll_signal_raise(&wait_signal, 0);
46+
}
47+
48+
void mp_hal_wait_sem(struct k_sem *sem, uint32_t timeout_ms) {
49+
mp_uint_t t0 = mp_hal_ticks_ms();
50+
if (sem) {
51+
k_poll_event_init(&wait_events[1], K_POLL_TYPE_SEM_AVAILABLE, K_POLL_MODE_NOTIFY_ONLY, sem);
52+
}
53+
for (;;) {
54+
k_timeout_t wait;
55+
if (timeout_ms == (uint32_t)-1) {
56+
wait = K_FOREVER;
57+
} else {
58+
uint32_t dt = mp_hal_ticks_ms() - t0;
59+
if (dt >= timeout_ms) {
60+
return;
61+
}
62+
wait = K_MSEC(timeout_ms - dt);
63+
}
64+
k_poll(wait_events, sem ? 2 : 1, wait);
65+
if (wait_events[0].state == K_POLL_STATE_SIGNALED) {
66+
wait_events[0].signal->signaled = 0;
67+
wait_events[0].state = K_POLL_STATE_NOT_READY;
68+
mp_handle_pending(true);
69+
} else if (sem && wait_events[1].state == K_POLL_STATE_SEM_AVAILABLE) {
70+
wait_events[1].state = K_POLL_STATE_NOT_READY;
71+
return;
72+
}
73+
}
74+
}

ports/zephyr/mphalport.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#include <zephyr.h>
22
#include "lib/utils/interrupt_char.h"
33

4+
void mp_hal_init(void);
5+
void mp_hal_wait_sem(struct k_sem *sem, uint32_t timeout_ms);
6+
47
static inline mp_uint_t mp_hal_ticks_us(void) {
58
return k_cyc_to_ns_floor64(k_cycle_get_32()) / 1000;
69
}
@@ -21,7 +24,7 @@ static inline void mp_hal_delay_us(mp_uint_t delay) {
2124
}
2225

2326
static inline void mp_hal_delay_ms(mp_uint_t delay) {
24-
k_msleep(delay);
27+
mp_hal_wait_sem(NULL, delay);
2528
}
2629

2730
static inline uint64_t mp_hal_time_ns(void) {

ports/zephyr/prj.conf

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ CONFIG_CONSOLE_PUTCHAR_BUFSIZE=128
1313
CONFIG_NEWLIB_LIBC=y
1414
CONFIG_FPU=y
1515
CONFIG_MAIN_STACK_SIZE=4736
16+
CONFIG_POLL=y
1617

1718
# Enable sensor subsystem (doesn't add code if not used).
1819
# Specific sensors should be enabled per-board.

ports/zephyr/prj_minimal.conf

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
CONFIG_NEWLIB_LIBC=y
22
CONFIG_FPU=y
33
CONFIG_MAIN_STACK_SIZE=4096
4+
CONFIG_POLL=y
45

56
CONFIG_UART_INTERRUPT_DRIVEN=y
67
CONFIG_CONSOLE_SUBSYS=y

ports/zephyr/src/zephyr_getchar.c

+4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
extern int mp_interrupt_char;
2424
void mp_sched_keyboard_interrupt(void);
25+
void mp_hal_signal_event(void);
26+
void mp_hal_wait_sem(struct k_sem *sem, uint32_t timeout_ms);
2527

2628
static struct k_sem uart_sem;
2729
#define UART_BUFSIZE 256
@@ -36,6 +38,7 @@ static int console_irq_input_hook(uint8_t ch)
3638
return 1;
3739
}
3840
if (ch == mp_interrupt_char) {
41+
mp_hal_signal_event();
3942
mp_sched_keyboard_interrupt();
4043
return 1;
4144
} else {
@@ -49,6 +52,7 @@ static int console_irq_input_hook(uint8_t ch)
4952
}
5053

5154
uint8_t zephyr_getchar(void) {
55+
mp_hal_wait_sem(&uart_sem, -1);
5256
k_sem_take(&uart_sem, K_FOREVER);
5357
unsigned int key = irq_lock();
5458
uint8_t c = uart_ringbuf[i_get++];

0 commit comments

Comments
 (0)