From 6ff6468968248ec3ffabba789f88f2e7e6d873c2 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Wed, 27 Mar 2024 08:05:31 +1100 Subject: [PATCH] nrf/soft_timer: Bring in soft timer and penbdsv. Signed-off-by: Andrew Leech --- ports/nrf/Makefile | 6 ++-- ports/nrf/main.c | 5 +++ ports/nrf/mpconfigport.h | 13 +++++--- ports/nrf/mphalport.c | 13 ++++++++ ports/nrf/mphalport.h | 37 +++++++++++++++++++++ ports/nrf/pendsv.c | 70 ++++++++++++++++++++++++++++++++++++++++ ports/nrf/pendsv.h | 42 ++++++++++++++++++++++++ 7 files changed, 180 insertions(+), 6 deletions(-) create mode 100644 ports/nrf/pendsv.c create mode 100644 ports/nrf/pendsv.h diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 94d6403a59..70dd4703ac 100644 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -191,6 +191,7 @@ SRC_SHARED_C += $(addprefix shared/,\ libc/string0.c \ readline/readline.c \ runtime/pyexec.c \ + runtime/softtimer.c \ runtime/sys_stdio_mphal.c \ runtime/interrupt_char.c \ tinyusb/mp_cdc_common.c \ @@ -208,13 +209,13 @@ endif SRC_NRFX += $(addprefix lib/nrfx/drivers/src/,\ prs/nrfx_prs.c \ nrfx_uart.c \ - nrfx_uarte.c \ + nrfx_uarte.c \ nrfx_adc.c \ nrfx_saadc.c \ nrfx_temp.c \ nrfx_rng.c \ nrfx_twi.c \ - nrfx_twim.c \ + nrfx_twim.c \ nrfx_spi.c \ nrfx_spim.c \ nrfx_rtc.c \ @@ -229,6 +230,7 @@ SRC_NRFX += $(addprefix lib/nrfx/drivers/src/,\ SRC_C += \ main.c \ mphalport.c \ + pendsv.c \ help.c \ gccollect.c \ pin_named_pins.c \ diff --git a/ports/nrf/main.c b/ports/nrf/main.c index e24c2f15d8..032f2e7264 100644 --- a/ports/nrf/main.c +++ b/ports/nrf/main.c @@ -40,6 +40,7 @@ #include "py/compile.h" #include "extmod/modmachine.h" #include "shared/runtime/pyexec.h" +#include "shared/runtime/softtimer.h" #include "readline.h" #include "gccollect.h" #include "modmachine.h" @@ -54,6 +55,7 @@ #include "adc.h" #include "rtcounter.h" #include "mphalport.h" +#include "pendsv.h" #if MICROPY_PY_BLUETOOTH #include "extmod/modbluetooth.h" @@ -123,6 +125,8 @@ void NORETURN _start(void) { soft_reset: + pendsv_init(); + #if MICROPY_PY_TIME_TICKS rtc1_init_time_ticks(); #endif @@ -309,6 +313,7 @@ soft_reset: mp_bluetooth_deinit(); #endif + soft_timer_deinit(); mp_deinit(); printf("MPY: soft reboot\n"); diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index e8b1a1d948..88bc4cca9a 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -155,7 +155,6 @@ #define MICROPY_USE_INTERNAL_ERRNO (1) #if MICROPY_HW_USB_CDC_1200BPS_TOUCH #define MICROPY_HW_ENABLE_USBDEV (1) -#define MICROPY_ENABLE_SCHEDULER (1) #define MICROPY_SCHEDULER_STATIC_NODES (1) #endif #define MICROPY_PY_FUNCTION_ATTRS (1) @@ -180,9 +179,8 @@ #define MICROPY_PY_MACHINE_BOOTLOADER (1) #define MICROPY_PY_MACHINE_PULSE (0) #define MICROPY_PY_MACHINE_SOFTI2C (MICROPY_PY_MACHINE_I2C) -#ifndef MICROPY_ENABLE_SCHEDULER -#define MICROPY_ENABLE_SCHEDULER (1) -#endif +#define MICROPY_ENABLE_SCHEDULER (1) +#define MICROPY_SCHEDULER_STATIC_NODES (1) #ifndef MICROPY_HW_LED_COUNT #define MICROPY_HW_LED_COUNT (0) @@ -391,6 +389,13 @@ static inline mp_uint_t disable_irq(void) { #endif +#define MICROPY_SOFT_TIMER_TICKS_MS uwTick + +// Additional entries for use with pendsv_schedule_dispatch. +#ifndef MICROPY_BOARD_PENDSV_ENTRIES +#define MICROPY_BOARD_PENDSV_ENTRIES +#endif + #ifndef MICROPY_BOARD_STARTUP #define MICROPY_BOARD_STARTUP() #endif diff --git a/ports/nrf/mphalport.c b/ports/nrf/mphalport.c index 566680edd6..e48dc16803 100644 --- a/ports/nrf/mphalport.c +++ b/ports/nrf/mphalport.c @@ -34,12 +34,25 @@ #include "uart.h" #include "nrfx_errors.h" #include "nrfx_config.h" +#include "pendsv.h" +#include "shared/runtime/softtimer.h" #if MICROPY_PY_TIME_TICKS #include "nrfx_rtc.h" #include "nrf_clock.h" #endif +volatile uint32_t uwTick = 0; + +void SysTick_Handler(void) { + uint32_t next_tick = uwTick + 1; + uwTick = next_tick; + + if (soft_timer_next == next_tick) { + pendsv_schedule_dispatch(PENDSV_DISPATCH_SOFT_TIMER, soft_timer_handler); + } +} + #if MICROPY_PY_TIME_TICKS // Use RTC1 for time ticks generation (ms and us) with 32kHz tick resolution diff --git a/ports/nrf/mphalport.h b/ports/nrf/mphalport.h index 1ba4b6e70f..c71428d74b 100644 --- a/ports/nrf/mphalport.h +++ b/ports/nrf/mphalport.h @@ -54,6 +54,43 @@ void mp_hal_delay_us(mp_uint_t us); const char *nrfx_error_code_lookup(uint32_t err_code); +#define MICROPY_PY_PENDSV_ENTER uint32_t atomic_state = raise_irq_pri(IRQ_PRI_PENDSV) +#define MICROPY_PY_PENDSV_EXIT restore_irq_pri(atomic_state) + +#if defined(NRF51) + +static inline uint32_t raise_irq_pri(uint32_t pri) { + (void)pri; + return 0; +} + +static inline void restore_irq_pri(uint32_t basepri) { + (void)basepri; +} +#define IRQ_PRI_PENDSV ((1 << __NVIC_PRIO_BITS) - 1) + +#else +#define NVIC_PRIORITYGROUP_4 ((uint32_t)0x00000003) +#define IRQ_PRI_PENDSV NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 7, 0) + +static inline uint32_t raise_irq_pri(uint32_t pri) { + uint32_t basepri = __get_BASEPRI(); + // If non-zero, the processor does not process any exception with a + // priority value greater than or equal to BASEPRI. + // When writing to BASEPRI_MAX the write goes to BASEPRI only if either: + // - Rn is non-zero and the current BASEPRI value is 0 + // - Rn is non-zero and less than the current BASEPRI value + pri <<= (8 - __NVIC_PRIO_BITS); + __ASM volatile ("msr basepri_max, %0" : : "r" (pri) : "memory"); + return basepri; +} + +// "basepri" should be the value returned from raise_irq_pri +static inline void restore_irq_pri(uint32_t basepri) { + __set_BASEPRI(basepri); +} +#endif + #define MP_HAL_PIN_FMT "%q" #define mp_hal_pin_obj_t const pin_obj_t * #define mp_hal_get_pin_obj(o) pin_find(o) diff --git a/ports/nrf/pendsv.c b/ports/nrf/pendsv.c new file mode 100644 index 0000000000..96bfaa8fc9 --- /dev/null +++ b/ports/nrf/pendsv.c @@ -0,0 +1,70 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 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 + +#include "py/runtime.h" +#include "shared/runtime/interrupt_char.h" +#include "mphalport.h" +#include "pendsv.h" + +#if defined(PENDSV_DISPATCH_NUM_SLOTS) +uint32_t pendsv_dispatch_active; +pendsv_dispatch_t pendsv_dispatch_table[PENDSV_DISPATCH_NUM_SLOTS]; +#endif + +void pendsv_init(void) { + #if defined(PENDSV_DISPATCH_NUM_SLOTS) + pendsv_dispatch_active = false; + #endif + + // set PendSV interrupt at lowest priority + NVIC_SetPriority(PendSV_IRQn, IRQ_PRI_PENDSV); +} + +#if defined(PENDSV_DISPATCH_NUM_SLOTS) +void pendsv_schedule_dispatch(size_t slot, pendsv_dispatch_t f) { + pendsv_dispatch_table[slot] = f; + pendsv_dispatch_active = true; + SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; +} + +void pendsv_dispatch_handler(void) { + for (size_t i = 0; i < PENDSV_DISPATCH_NUM_SLOTS; ++i) { + if (pendsv_dispatch_table[i] != NULL) { + pendsv_dispatch_t f = pendsv_dispatch_table[i]; + pendsv_dispatch_table[i] = NULL; + f(); + } + } +} + +void PendSV_Handler(void) { + if (pendsv_dispatch_active) { + pendsv_dispatch_handler(); + } +} +#endif diff --git a/ports/nrf/pendsv.h b/ports/nrf/pendsv.h new file mode 100644 index 0000000000..3f5c0c6ad6 --- /dev/null +++ b/ports/nrf/pendsv.h @@ -0,0 +1,42 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 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. + */ +#ifndef MICROPY_INCLUDED_NRF_PENDSV_H +#define MICROPY_INCLUDED_NRF_PENDSV_H + +enum { + PENDSV_DISPATCH_SOFT_TIMER, // For later & for having at least one entry + MICROPY_BOARD_PENDSV_ENTRIES + PENDSV_DISPATCH_MAX +}; + +#define PENDSV_DISPATCH_NUM_SLOTS PENDSV_DISPATCH_MAX + +typedef void (*pendsv_dispatch_t)(void); + +void pendsv_init(void); +void pendsv_schedule_dispatch(size_t slot, pendsv_dispatch_t f); + +#endif // MICROPY_INCLUDED_NRF_PENDSV_H