Skip to content
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

pbio/os: Prototype simpler and unified async OS. #298

Merged
merged 19 commits into from
Apr 8, 2025
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
7 changes: 3 additions & 4 deletions bricks/_common/micropython.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include <pbio/button.h>
#include <pbio/main.h>
#include <pbio/os.h>
#include <pbio/util.h>
#include <pbio/protocol.h>
#include <pbsys/main.h>
Expand Down Expand Up @@ -39,14 +40,12 @@
// Implementation for MICROPY_EVENT_POLL_HOOK
void pb_event_poll_hook(void) {

// Drive pbio event loop.
while (pbio_do_one_event()) {
while (pbio_os_run_processes_once()) {
}

mp_handle_pending(true);

// Platform-specific code to run on completing the poll hook.
pb_event_poll_hook_leave();
pbio_os_run_processes_and_wait_for_event();
}

// callback for when stop button is pressed in IDE or on hub
Expand Down
1 change: 1 addition & 0 deletions bricks/_common/sources.mk
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ PBIO_SRC_C = $(addprefix lib/pbio/,\
src/motor_process.c \
src/motor/servo_settings.c \
src/observer.c \
src/os.c \
src/parent.c \
src/port.c \
src/port_dcm_pup.c \
Expand Down
26 changes: 5 additions & 21 deletions bricks/_common_stm32/mpconfigport.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,31 +24,15 @@ typedef unsigned mp_uint_t; // must be pointer size

typedef long mp_off_t;

// We have inlined IRQ functions for efficiency (they are generally
// 1 machine instruction).
//
// Note on IRQ state: you should not need to know the specific
// value of the state variable, but rather just pass the return
// value from disable_irq back to enable_irq. If you really need
// to know the machine-specific values, see irq.h.
#include "pbio_os_config.h"

static inline void enable_irq(mp_uint_t state) {
__set_PRIMASK(state);
}

static inline mp_uint_t disable_irq(void) {
mp_uint_t state = __get_PRIMASK();
__disable_irq();
return state;
}

#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq()
#define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state)
#define MICROPY_BEGIN_ATOMIC_SECTION() pbio_os_hook_disable_irq()
#define MICROPY_END_ATOMIC_SECTION(state) pbio_os_hook_enable_irq(state)

#define MICROPY_VM_HOOK_LOOP \
do { \
extern int pbio_do_one_event(void); \
pbio_do_one_event(); \
extern bool pbio_os_run_processes_once(void); \
pbio_os_run_processes_once(); \
} while (0);

#define MICROPY_GC_HOOK_LOOP(i) do { \
Expand Down
13 changes: 0 additions & 13 deletions bricks/_common_stm32/mphalport.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,6 @@ void pb_stack_get_info(char **sstack, char **estack) {
*estack = (char *)&_estack;
}

void pb_event_poll_hook_leave(void) {
// There is a possible race condition where an interrupt occurs and sets the
// Contiki poll_requested flag after all events have been processed. So we
// have a critical section where we disable interrupts and check see if there
// are any last second events. If not, we can call __WFI(), which still wakes
// up the CPU on interrupt even though interrupts are otherwise disabled.
mp_uint_t state = disable_irq();
if (!process_nevents()) {
__WFI();
}
enable_irq(state);
}

// using "internal" pbdrv variable
extern volatile uint32_t pbdrv_clock_ticks;

Expand Down
13 changes: 5 additions & 8 deletions bricks/ev3/mpconfigport.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,18 +79,15 @@ typedef unsigned mp_uint_t; // must be pointer size

typedef long mp_off_t;

#define CPSR_IRQ_MASK (1 << 7) // IRQ disable
#define CPSR_FIQ_MASK (1 << 6) // FIQ disable
#include "pbio_os_config.h"

#include <tiam1808/armv5/am1808/interrupt.h>

#define MICROPY_BEGIN_ATOMIC_SECTION() IntDisable()
#define MICROPY_END_ATOMIC_SECTION(state) IntEnable(state)
#define MICROPY_BEGIN_ATOMIC_SECTION() pbio_os_hook_disable_irq()
#define MICROPY_END_ATOMIC_SECTION(state) pbio_os_hook_enable_irq(state)

#define MICROPY_VM_HOOK_LOOP \
do { \
extern int pbio_do_one_event(void); \
pbio_do_one_event(); \
extern bool pbio_os_run_processes_once(void); \
pbio_os_run_processes_once(); \
} while (0);

#define MICROPY_GC_HOOK_LOOP(i) do { \
Expand Down
22 changes: 0 additions & 22 deletions bricks/ev3/mphalport.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,28 +25,6 @@ void pb_stack_get_info(char **sstack, char **estack) {
*estack = (char *)&_estack;
}

static inline int arm_wfi(void) {
__asm volatile (
"mov r0, #0\n"
"mcr p15, 0, r0, c7, c0, 4\n" /* wait for interrupt */
::: "r0"
);
return 0;
}

void pb_event_poll_hook_leave(void) {
// There is a possible race condition where an interrupt occurs and sets the
// Contiki poll_requested flag after all events have been processed. So we
// have a critical section where we disable interrupts and check see if there
// are any last second events. If not, we can call __WFI(), which still wakes
// up the CPU on interrupt even though interrupts are otherwise disabled.
mp_uint_t state = MICROPY_BEGIN_ATOMIC_SECTION();
if (!process_nevents()) {
arm_wfi();
}
MICROPY_END_ATOMIC_SECTION(state);
}

// Core delay function that does an efficient sleep and may switch thread context.
// If IRQs are enabled then we must have the GIL.
void mp_hal_delay_ms(mp_uint_t Delay) {
Expand Down
17 changes: 11 additions & 6 deletions bricks/nxt/mpconfigport.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,18 +79,23 @@ typedef long mp_off_t;
// We need to provide a declaration/definition of alloca()
#include <alloca.h>

uint32_t nx_interrupts_disable(void);
void nx_interrupts_enable(uint32_t);
#include "pbio_os_config.h"

#define MICROPY_BEGIN_ATOMIC_SECTION() nx_interrupts_disable()
#define MICROPY_END_ATOMIC_SECTION(state) nx_interrupts_enable(state)
#define MICROPY_BEGIN_ATOMIC_SECTION() pbio_os_hook_disable_irq()
#define MICROPY_END_ATOMIC_SECTION(state) pbio_os_hook_enable_irq(state)

#define MICROPY_VM_HOOK_LOOP \
do { \
extern int pbio_do_one_event(void); \
pbio_do_one_event(); \
extern bool pbio_os_run_processes_once(void); \
pbio_os_run_processes_once(); \
} while (0);

#define MICROPY_GC_HOOK_LOOP(i) do { \
if (((i) & 0xf) == 0) { \
MICROPY_VM_HOOK_LOOP \
} \
} while (0)

#define MICROPY_EVENT_POLL_HOOK \
do { \
extern void pb_event_poll_hook(void); \
Expand Down
19 changes: 0 additions & 19 deletions bricks/nxt/mphalport.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@

#include <stdint.h>

#include <at91sam7s256.h>
#include <contiki.h>

#include <nxos/interrupts.h>
#include <nxos/drivers/systick.h>
#include <nxos/drivers/bt.h>

Expand All @@ -20,23 +18,6 @@
#include "py/mpconfig.h"
#include "py/stream.h"

void pb_event_poll_hook_leave(void) {
// There is a possible race condition where an interrupt occurs and sets
// the Contiki poll_requested flag after all events have been processed. So
// we have a critical section where we disable interrupts and check see if
// there are any last second events. If not, we can enter Idle Mode, which
// still wakes up the CPU on interrupt even though interrupts are otherwise
// disabled.
uint32_t state = nx_interrupts_disable();

if (!process_nevents()) {
// disable the processor clock which puts it in Idle Mode.
AT91C_BASE_PMC->PMC_SCDR = AT91C_PMC_PCK;
}

nx_interrupts_enable(state);
}

void pb_stack_get_info(char **sstack, char **estack) {
extern uint32_t __stack_start__;
extern uint32_t __stack_end__;
Expand Down
52 changes: 21 additions & 31 deletions bricks/virtualhub/mp_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@

#include <contiki.h>

#include "pbio_os_config.h"

#include <pbio/main.h>
#include <pbio/os.h>
#include <pbsys/core.h>
#include <pbsys/program_stop.h>
#include <pbsys/status.h>
Expand Down Expand Up @@ -72,7 +75,8 @@ void pb_virtualhub_port_init(void) {
pbsys_init();

pbsys_status_set(PBIO_PYBRICKS_STATUS_USER_PROGRAM_RUNNING);
while (pbio_do_one_event()) {

while (pbio_os_run_processes_once()) {
}

pb_package_pybricks_init(true);
Expand All @@ -84,62 +88,48 @@ void pb_virtualhub_port_deinit(void) {
pb_package_pybricks_deinit();
}

// MICROPY_VM_HOOK_LOOP
void pb_virtualhub_poll(void) {
while (pbio_do_one_event()) {
// Implementation for MICROPY_EVENT_POLL_HOOK
void pb_event_poll_hook(void) {

while (pbio_os_run_processes_once()) {
}
}

// MICROPY_EVENT_POLL_HOOK
void pb_virtualhub_event_poll(void) {
start:
mp_handle_pending(true);

int events_handled = 0;

while (pbio_do_one_event()) {
events_handled++;
}

// If there were any pbio events handled, don't sleep because there may
// be something waiting on one of the events that was just handled.
if (events_handled) {
return;
}
pbio_os_run_processes_and_wait_for_event();
}

pbio_os_irq_flags_t pbio_os_hook_disable_irq(void) {
sigset_t sigmask;
sigfillset(&sigmask);

// disable "interrupts"
sigset_t origmask;
pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);
return origmask;
}

if (process_nevents()) {
// something was scheduled since the event loop above
pthread_sigmask(SIG_SETMASK, &origmask, NULL);
goto start;
}
void pbio_os_hook_enable_irq(pbio_os_irq_flags_t flags) {
sigset_t origmask = (sigset_t)flags;
pthread_sigmask(SIG_SETMASK, &origmask, NULL);
}

void pbio_os_hook_wait_for_interrupt(pbio_os_irq_flags_t flags) {
struct timespec timeout = {
.tv_sec = 0,
.tv_nsec = 100000,
};

// "sleep" with "interrupts" enabled
sigset_t origmask = flags;
MP_THREAD_GIL_EXIT();
pselect(0, NULL, NULL, NULL, &timeout, &origmask);
MP_THREAD_GIL_ENTER();

// restore "interrupts"
pthread_sigmask(SIG_SETMASK, &origmask, NULL);
}


void pb_virtualhub_delay_us(mp_uint_t us) {
mp_uint_t start = mp_hal_ticks_us();

while (mp_hal_ticks_us() - start < us) {
pb_virtualhub_poll();
MICROPY_VM_HOOK_LOOP;
}
}

Expand Down
8 changes: 4 additions & 4 deletions bricks/virtualhub/mpconfigvariant.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@
} while (0)

#define MICROPY_VM_HOOK_LOOP do { \
extern void pb_virtualhub_poll(void); \
pb_virtualhub_poll(); \
extern bool pbio_os_run_processes_once(void); \
pbio_os_run_processes_once(); \
} while (0);

#define MICROPY_GC_HOOK_LOOP(i) do { \
Expand All @@ -108,6 +108,6 @@
} while (0)

#define MICROPY_EVENT_POLL_HOOK do { \
extern void pb_virtualhub_event_poll(void); \
pb_virtualhub_event_poll(); \
extern void pb_event_poll_hook(void); \
pb_event_poll_hook(); \
} while (0);
Loading