ports: Move definitions of ATOMIC_SECTION macros to mphalport.h.

Also move MICROPY_PY_PENDSV_ENTER/REENTER/EXIT to mphalport.h, for ports
where these are not already there.

This helps separate the hardware implementation of these macros from the
MicroPython configuration (eg for renesas-ra and stm32, the IRQ static
inline helper functions can now be moved to irq.h).

Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
Damien George 2023-12-01 13:29:42 +11:00
parent bfdf500ea5
commit ad806df857
27 changed files with 124 additions and 120 deletions

View File

@ -30,6 +30,10 @@
#include "hal/utils.h"
#include "hal/systick.h"
// assembly functions to handle critical sections, interrupt
// disabling/enabling and sleep mode enter/exit
#include "cc3200_asm.h"
/******************************************************************************
DEFINE CONSTANTS
******************************************************************************/
@ -55,6 +59,9 @@
" isb \n"); \
}
#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq()
#define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state)
/******************************************************************************
DECLARE PUBLIC FUNCTIONS
******************************************************************************/

View File

@ -25,7 +25,7 @@
* THE SOFTWARE.
*/
#include "py/mpconfig.h"
#include "py/mphal.h"
#include "py/obj.h"
#include "py/runtime.h"
#include "py/mperrno.h"

View File

@ -161,14 +161,8 @@ typedef int32_t mp_int_t; // must be pointer size
typedef unsigned int mp_uint_t; // must be pointer size
typedef long mp_off_t;
#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq()
#define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state)
#define MICROPY_EVENT_POLL_HOOK __WFI();
// assembly functions to handle critical sections, interrupt
// disabling/enabling and sleep mode enter/exit
#include "cc3200_asm.h"
// We need to provide a declaration/definition of alloca()
#include <alloca.h>

View File

@ -187,13 +187,6 @@ void *esp_native_code_commit(void *, size_t, void *);
#define MP_PLAT_COMMIT_EXEC(buf, len, reloc) esp_native_code_commit(buf, len, reloc)
#define MP_SSIZE_MAX (0x7fffffff)
// Note: these "critical nested" macros do not ensure cross-CPU exclusion,
// the only disable interrupts on the current CPU. To full manage exclusion
// one should use portENTER_CRITICAL/portEXIT_CRITICAL instead.
#include "freertos/FreeRTOS.h"
#define MICROPY_BEGIN_ATOMIC_SECTION() portSET_INTERRUPT_MASK_FROM_ISR()
#define MICROPY_END_ATOMIC_SECTION(state) portCLEAR_INTERRUPT_MASK_FROM_ISR(state)
#if MICROPY_PY_SOCKET_EVENTS
#define MICROPY_PY_SOCKET_EVENTS_HANDLER extern void socket_events_handler(void); socket_events_handler();
#else

View File

@ -63,6 +63,13 @@ void check_esp_err_(esp_err_t code);
void check_esp_err_(esp_err_t code, const char *func, const int line, const char *file);
#endif
// Note: these "critical nested" macros do not ensure cross-CPU exclusion,
// the only disable interrupts on the current CPU. To full manage exclusion
// one should use portENTER_CRITICAL/portEXIT_CRITICAL instead.
#include "freertos/FreeRTOS.h"
#define MICROPY_BEGIN_ATOMIC_SECTION() portSET_INTERRUPT_MASK_FROM_ISR()
#define MICROPY_END_ATOMIC_SECTION(state) portCLEAR_INTERRUPT_MASK_FROM_ISR(state)
uint32_t mp_hal_ticks_us(void);
__attribute__((always_inline)) static inline uint32_t mp_hal_ticks_cpu(void) {
uint32_t ccount;

View File

@ -29,6 +29,9 @@
#include "shared/runtime/interrupt_char.h"
#include "xtirq.h"
#define MICROPY_BEGIN_ATOMIC_SECTION() esp_disable_irq()
#define MICROPY_END_ATOMIC_SECTION(state) esp_enable_irq(state)
void mp_sched_keyboard_interrupt(void);
struct _mp_print_t;
@ -66,6 +69,9 @@ uint32_t mp_hal_get_cpu_freq(void);
void uart_task_init();
void dupterm_task_init();
uint32_t esp_disable_irq(void);
void esp_enable_irq(uint32_t state);
void ets_event_poll(void);
#define ETS_POLL_WHILE(cond) { while (cond) ets_event_poll(); }

View File

@ -127,9 +127,6 @@
#define MICROPY_VM_HOOK_LOOP MICROPY_VM_HOOK_POLL
#define MICROPY_VM_HOOK_RETURN MICROPY_VM_HOOK_POLL
#define MICROPY_BEGIN_ATOMIC_SECTION() esp_disable_irq()
#define MICROPY_END_ATOMIC_SECTION(state) esp_enable_irq(state)
// type definitions for the specific machine
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((mp_uint_t)(p)))
@ -173,6 +170,3 @@ extern const struct _mp_print_t mp_debug_print;
#define WDEV_HWRNG ((volatile uint32_t *)0x3ff20e44)
#define _assert(expr) ((expr) ? (void)0 : __assert_func(__FILE__, __LINE__, __func__, #expr))
uint32_t esp_disable_irq(void);
void esp_enable_irq(uint32_t state);

View File

@ -151,30 +151,8 @@ uint32_t trng_random_u32(void);
#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-mimxrt"
#endif
// For regular code that wants to prevent "background tasks" from running.
// These background tasks (LWIP, Bluetooth) run in PENDSV context.
// TODO: Check for the settings of the STM32 port in irq.h
#define NVIC_PRIORITYGROUP_4 ((uint32_t)0x00000003)
#define IRQ_PRI_PENDSV NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 15, 0)
#define MICROPY_PY_PENDSV_ENTER uint32_t atomic_state = raise_irq_pri(IRQ_PRI_PENDSV);
#define MICROPY_PY_PENDSV_REENTER atomic_state = raise_irq_pri(IRQ_PRI_PENDSV);
#define MICROPY_PY_PENDSV_EXIT restore_irq_pri(atomic_state);
// Hooks to add builtins
__attribute__((always_inline)) static inline void enable_irq(uint32_t state) {
__set_PRIMASK(state);
}
__attribute__((always_inline)) static inline uint32_t disable_irq(void) {
uint32_t state = __get_PRIMASK();
__disable_irq();
return state;
}
#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq()
#define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state)
#if defined(IOMUX_TABLE_ENET)
extern const struct _mp_obj_type_t network_lan_type;
#define MICROPY_HW_NIC_ETH { MP_ROM_QSTR(MP_QSTR_LAN), MP_ROM_PTR(&network_lan_type) },

View File

@ -36,6 +36,18 @@
#define MICROPY_HAL_VERSION "2.8.0"
#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq()
#define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state)
// For regular code that wants to prevent "background tasks" from running.
// These background tasks (LWIP, Bluetooth) run in PENDSV context.
// TODO: Check for the settings of the STM32 port in irq.h
#define NVIC_PRIORITYGROUP_4 ((uint32_t)0x00000003)
#define IRQ_PRI_PENDSV NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 15, 0)
#define MICROPY_PY_PENDSV_ENTER uint32_t atomic_state = raise_irq_pri(IRQ_PRI_PENDSV);
#define MICROPY_PY_PENDSV_REENTER atomic_state = raise_irq_pri(IRQ_PRI_PENDSV);
#define MICROPY_PY_PENDSV_EXIT restore_irq_pri(atomic_state);
#define MICROPY_HW_USB_CDC_TX_TIMEOUT (500)
#define MP_HAL_PIN_FMT "%q"
@ -82,6 +94,16 @@ extern ringbuf_t stdin_ringbuf;
#define mp_hal_quiet_timing_enter() raise_irq_pri(1)
#define mp_hal_quiet_timing_exit(irq_state) restore_irq_pri(irq_state)
__attribute__((always_inline)) static inline void enable_irq(uint32_t state) {
__set_PRIMASK(state);
}
__attribute__((always_inline)) static inline uint32_t disable_irq(void) {
uint32_t state = __get_PRIMASK();
__disable_irq();
return state;
}
void mp_hal_set_interrupt_char(int c);
static inline mp_uint_t mp_hal_ticks_ms(void) {

View File

@ -54,11 +54,26 @@ extern uint32_t irq_stats[IRQ_STATS_MAX];
#define IRQ_EXIT(irq)
#endif
// 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.
static inline uint32_t query_irq(void) {
return __get_PRIMASK();
}
// enable_irq and disable_irq are defined inline in mpconfigport.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;
}
#if __CORTEX_M >= 0x03

View File

@ -250,27 +250,6 @@ typedef unsigned int 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.
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)
#if MICROPY_HW_ENABLE_USBDEV
#define MICROPY_HW_USBDEV_TASK_HOOK extern void mp_usbd_task(void); mp_usbd_task();
#define MICROPY_VM_HOOK_COUNT (10)

View File

@ -29,6 +29,9 @@
#include "pin.h"
#include "py/ringbuf.h"
#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq()
#define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state)
#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)

View File

@ -24,6 +24,7 @@
* THE SOFTWARE.
*/
#include "py/mphal.h"
#include "py/runtime.h"
#include "drivers/dht/dht.h"
#include "modrp2.h"

View File

@ -244,12 +244,6 @@ extern const struct _mp_obj_type_t mod_network_nic_type_wiznet5k;
#define MICROPY_HW_BOOTSEL_DELAY_US 8
#endif
// Entering a critical section.
extern uint32_t mp_thread_begin_atomic_section(void);
extern void mp_thread_end_atomic_section(uint32_t);
#define MICROPY_BEGIN_ATOMIC_SECTION() mp_thread_begin_atomic_section()
#define MICROPY_END_ATOMIC_SECTION(state) mp_thread_end_atomic_section(state)
// Prevent the "lwIP task" from running when unsafe to do so.
#define MICROPY_PY_LWIP_ENTER lwip_lock_acquire();
#define MICROPY_PY_LWIP_REENTER lwip_lock_acquire();

View File

@ -36,12 +36,19 @@
#define SYSTICK_MAX (0xffffff)
#define MICROPY_HW_USB_CDC_TX_TIMEOUT (500)
// Entering a critical section.
#define MICROPY_BEGIN_ATOMIC_SECTION() mp_thread_begin_atomic_section()
#define MICROPY_END_ATOMIC_SECTION(state) mp_thread_end_atomic_section(state)
#define MICROPY_PY_PENDSV_ENTER pendsv_suspend()
#define MICROPY_PY_PENDSV_EXIT pendsv_resume()
extern int mp_interrupt_char;
extern ringbuf_t stdin_ringbuf;
uint32_t mp_thread_begin_atomic_section(void);
void mp_thread_end_atomic_section(uint32_t);
void mp_hal_set_interrupt_char(int c);
void mp_hal_time_ns_set_from_rtc(void);

View File

@ -26,6 +26,7 @@
#include "py/runtime.h"
#include "py/gc.h"
#include "py/mphal.h"
#include "py/mpthread.h"
#include "pico/stdlib.h"
#include "pico/multicore.h"

View File

@ -26,6 +26,7 @@
#include <string.h>
#include "py/mphal.h"
#include "py/runtime.h"
#include "extmod/vfs.h"
#include "modrp2.h"

View File

@ -177,18 +177,6 @@
#endif // !defined(MICROPY_HW_MCUFLASH) ....
// Miscellaneous settings
__attribute__((always_inline)) static inline void enable_irq(uint32_t state) {
__set_PRIMASK(state);
}
__attribute__((always_inline)) static inline uint32_t disable_irq(void) {
uint32_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_EVENT_POLL_HOOK \
do { \

View File

@ -35,6 +35,9 @@
#include "hpl_time_measure.h"
#include "sam.h"
#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq()
#define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state)
#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)
@ -46,6 +49,16 @@ uint64_t mp_hal_ticks_us_64(void);
void mp_hal_set_interrupt_char(int c);
__attribute__((always_inline)) static inline void enable_irq(uint32_t state) {
__set_PRIMASK(state);
}
__attribute__((always_inline)) static inline uint32_t disable_irq(void) {
uint32_t state = __get_PRIMASK();
__disable_irq();
return state;
}
#define mp_hal_delay_us_fast mp_hal_delay_us
static inline uint64_t mp_hal_ticks_ms_64(void) {

View File

@ -52,11 +52,26 @@ extern uint32_t irq_stats[IRQ_STATS_MAX];
#define IRQ_EXIT(irq)
#endif
// 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.
static inline uint32_t query_irq(void) {
return __get_PRIMASK();
}
// enable_irq and disable_irq are defined inline in mpconfigport.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;
}
#if __CORTEX_M >= 0x03

View File

@ -239,27 +239,6 @@ typedef unsigned int 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.
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)
#if MICROPY_PY_THREAD
#define MICROPY_EVENT_POLL_HOOK \
do { \
@ -289,12 +268,6 @@ static inline mp_uint_t disable_irq(void) {
// Configuration for shared/runtime/softtimer.c.
#define MICROPY_SOFT_TIMER_TICKS_MS uwTick
// For regular code that wants to prevent "background tasks" from running.
// These background tasks (LWIP, Bluetooth) run in PENDSV context.
#define MICROPY_PY_PENDSV_ENTER uint32_t atomic_state = raise_irq_pri(IRQ_PRI_PENDSV);
#define MICROPY_PY_PENDSV_REENTER atomic_state = raise_irq_pri(IRQ_PRI_PENDSV);
#define MICROPY_PY_PENDSV_EXIT restore_irq_pri(atomic_state);
// Prevent the "LWIP task" from running.
#define MICROPY_PY_LWIP_ENTER MICROPY_PY_PENDSV_ENTER
#define MICROPY_PY_LWIP_REENTER MICROPY_PY_PENDSV_REENTER

View File

@ -40,10 +40,21 @@ static inline int mp_hal_status_to_neg_errno(HAL_StatusTypeDef status) {
NORETURN void mp_hal_raise(HAL_StatusTypeDef status);
void mp_hal_set_interrupt_char(int c); // -1 to disable
// timing functions
// Atomic section helpers.
#include "irq.h"
#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq()
#define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state)
// For regular code that wants to prevent "background tasks" from running.
// These background tasks (LWIP, Bluetooth) run in PENDSV context.
#define MICROPY_PY_PENDSV_ENTER uint32_t atomic_state = raise_irq_pri(IRQ_PRI_PENDSV);
#define MICROPY_PY_PENDSV_REENTER atomic_state = raise_irq_pri(IRQ_PRI_PENDSV);
#define MICROPY_PY_PENDSV_EXIT restore_irq_pri(atomic_state);
// Timing functions.
#if __CORTEX_M == 0
// Don't have raise_irq_pri on Cortex-M0 so keep IRQs enabled to have SysTick timing
#define mp_hal_quiet_timing_enter() (1)

View File

@ -26,6 +26,8 @@
#ifndef MICROPY_INCLUDED_STM32_MPU_H
#define MICROPY_INCLUDED_STM32_MPU_H
#include "irq.h"
#if (defined(STM32F4) && defined(MICROPY_HW_ETH_MDC)) || defined(STM32F7) || defined(STM32H7) || defined(STM32WB)
#define MPU_REGION_ETH (MPU_REGION_NUMBER0)

View File

@ -221,12 +221,6 @@ static inline unsigned long mp_random_seed_init(void) {
#include <stdio.h>
#endif
// If threading is enabled, configure the atomic section.
#if MICROPY_PY_THREAD
#define MICROPY_BEGIN_ATOMIC_SECTION() (mp_thread_unix_begin_atomic_section(), 0xffffffff)
#define MICROPY_END_ATOMIC_SECTION(x) (void)x; mp_thread_unix_end_atomic_section()
#endif
// In lieu of a WFI(), slow down polling from being a tight loop.
#ifndef MICROPY_EVENT_POLL_HOOK
#define MICROPY_EVENT_POLL_HOOK \

View File

@ -30,6 +30,12 @@
#define CHAR_CTRL_C (3)
#endif
// If threading is enabled, configure the atomic section.
#if MICROPY_PY_THREAD
#define MICROPY_BEGIN_ATOMIC_SECTION() (mp_thread_unix_begin_atomic_section(), 0xffffffff)
#define MICROPY_END_ATOMIC_SECTION(x) (void)x; mp_thread_unix_end_atomic_section()
#endif
void mp_hal_set_interrupt_char(char c);
#define mp_hal_stdio_poll unused // this is not implemented, nor needed

View File

@ -139,6 +139,3 @@ typedef long mp_off_t;
// extra built in names to add to the global namespace
#define MICROPY_PORT_BUILTINS \
{ MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) },
#define MICROPY_BEGIN_ATOMIC_SECTION irq_lock
#define MICROPY_END_ATOMIC_SECTION irq_unlock

View File

@ -1,6 +1,9 @@
#include <zephyr/zephyr.h>
#include "shared/runtime/interrupt_char.h"
#define MICROPY_BEGIN_ATOMIC_SECTION irq_lock
#define MICROPY_END_ATOMIC_SECTION irq_unlock
void mp_hal_init(void);
void mp_hal_wait_sem(struct k_sem *sem, uint32_t timeout_ms);