diff --git a/cpu/esp32/include/irq_arch.h b/cpu/esp32/include/irq_arch.h index 20d8caca24..ccf014c76e 100644 --- a/cpu/esp32/include/irq_arch.h +++ b/cpu/esp32/include/irq_arch.h @@ -21,21 +21,12 @@ #ifndef IRQ_ARCH_H #define IRQ_ARCH_H -#include "irq.h" -#include "sched.h" -#include "thread.h" +#include "irq_arch_common.h" #ifdef __cplusplus extern "C" { #endif -/** - * @brief Indicates the interrupt nesting depth - * - * The variable is increment on entry into and decremented on exit from an ISR. - */ -extern volatile uint32_t irq_interrupt_nesting; - /** * @name CPU interrupt numbers * @@ -56,37 +47,6 @@ extern volatile uint32_t irq_interrupt_nesting; #define CPU_INUM_TIMER 19 /**< Level interrupt with medium priority 2 */ /** @} */ -/** - * @name Macros to enter and exit an ISR - * - * Since all the stuff is done in `_frxt_int_enter` and `_frxt_int_exit`, these - * macros are doing nothing and are kept only for source code compatibility. - * - * @{ - */ -#define irq_isr_enter() -#define irq_isr_exit() -/** @} */ - -/** - * @name Macros to enter and exit a critical region - * - * @note: since they use a local variable they can be used only in same function - * - * @{ - */ -#define critical_enter() int _irq_state = irq_disable() -#define critical_exit() irq_restore(_irq_state) -/** @} */ - -/** - * @name Macros to enter and exit a critical region with state variable - * @{ - */ -#define critical_enter_var(m) m = irq_disable() -#define critical_exit_var(m) irq_restore(m) -/** @} */ - #ifdef __cplusplus } #endif diff --git a/cpu/esp32/irq_arch.c b/cpu/esp32/irq_arch.c index 12b2beabb9..fd52da69d1 100644 --- a/cpu/esp32/irq_arch.c +++ b/cpu/esp32/irq_arch.c @@ -21,89 +21,13 @@ #define ENABLE_DEBUG 0 #include "debug.h" -#include -#include - -#include "irq.h" #include "irq_arch.h" -#include "cpu.h" -#include "esp_common.h" #include "esp_err.h" -#include "esp/common_macros.h" -#include "esp/xtensa_ops.h" #include "rom/ets_sys.h" #include "soc/dport_reg.h" -#include "xtensa/xtensa_context.h" #include "xtensa/xtensa_api.h" -extern unsigned _xtos_set_intlevel(unsigned intlevel); - -/** - * @brief Set on entry into and reset on exit from an ISR - */ -volatile uint32_t irq_interrupt_nesting = 0; - -/** - * @brief Disable all maskable interrupts - */ -unsigned int IRAM irq_disable(void) -{ - uint32_t _saved_intlevel; - - /* read and set interrupt level with one asm instruction (RSIL) */ - __asm__ volatile ("rsil %0, " XTSTR(XCHAL_NUM_INTLEVELS+1) : "=a" (_saved_intlevel)); - /* mask out everything else of the PS register that do not belong to - interrupt level (bits 3..0) */ - _saved_intlevel &= 0xf; - - DEBUG ("%s new %08x (old %08x)\n", __func__, - XCHAL_NUM_INTLEVELS + 1, _saved_intlevel); - return _saved_intlevel; -} - -/** - * @brief Enable all maskable interrupts - */ -unsigned int IRAM irq_enable(void) -{ - uint32_t _saved_intlevel; - - /* read and set interrupt level with one asm instruction (RSIL) */ - __asm__ volatile ("rsil %0, 0" : "=a" (_saved_intlevel)); - /* mask out everything else of the PS register that do not belong to - interrupt level (bits 3..0) */ - _saved_intlevel &= 0xf; - - DEBUG ("%s new %08x (old %08x)\n", __func__, 0, _saved_intlevel); - return _saved_intlevel; -} - -/** - * @brief Restore the state of the IRQ flags - */ -void IRAM irq_restore(unsigned int state) -{ - /* restore the interrupt level using a rom function, performance is not - important here */ - #if 0 - __asm__ volatile ("wsr %0, ps; rsync" :: "a" (state)); - DEBUG ("%s %02x\n", __func__, state); - #else - unsigned _saved_intlevel = _xtos_set_intlevel(state); - DEBUG ("%s new %08x (old %08x)\n", __func__, state, _saved_intlevel); - #endif -} - -/** - * @brief See if the current context is inside an ISR - */ -int IRAM irq_is_in(void) -{ - DEBUG("irq_interrupt_nesting = %d\n", irq_interrupt_nesting); - return irq_interrupt_nesting; -} - struct _irq_alloc_table_t { int src; /* peripheral interrupt source */ uint32_t intr; /* interrupt number */ diff --git a/cpu/esp8266/include/irq_arch.h b/cpu/esp8266/include/irq_arch.h index 46626a0818..f6ef6533e9 100644 --- a/cpu/esp8266/include/irq_arch.h +++ b/cpu/esp8266/include/irq_arch.h @@ -21,52 +21,12 @@ #ifndef IRQ_ARCH_H #define IRQ_ARCH_H -#include "irq.h" -#include "sched.h" -#include "thread.h" +#include "irq_arch_common.h" #ifdef __cplusplus extern "C" { #endif -/** - * @brief Indicates the interrupt nesting depth - * - * The variable is increment on entry into and decremented on exit from an ISR. - */ -extern uint32_t irq_interrupt_nesting; - -/** - * @name Macros to enter and exit an ISR - * - * Since all the stuff is done in `_frxt_int_enter` and `_frxt_int_exit`, these - * macros are doing nothing and are kept only for source code compatibility. - * - * @{ - */ -#define irq_isr_enter() -#define irq_isr_exit() -/** @} */ - -/** - * @name Macros to enter and exit a critical region - * - * @note since they use a local variable they can be used only in same function - * - * @{ - */ -#define critical_enter() int _irq_state = irq_disable() -#define critical_exit() irq_restore(_irq_state) -/** @} */ - -/** - * @name Macros to enter and exit a critical region with state variable - * @{ - */ -#define critical_enter_var(m) m = irq_disable() -#define critical_exit_var(m) irq_restore(m) -/** @} */ - /** * @name Software interrupt types * diff --git a/cpu/esp_common/include/irq_arch_common.h b/cpu/esp_common/include/irq_arch_common.h new file mode 100644 index 0000000000..1cd811e5dc --- /dev/null +++ b/cpu/esp_common/include/irq_arch_common.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2019 Gunar Schorcht + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup cpu_esp_common + * @{ + * + * @file + * @brief Implementation of the kernels irq interface + * + * @author Gunar Schorcht + * + * @} + */ + +#ifndef IRQ_ARCH_COMMON_H +#define IRQ_ARCH_COMMON_H + +#include "irq.h" +#include "sched.h" +#include "thread.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Indicates the interrupt nesting depth + * + * The variable is incremented on entry into and decremented on exit from an ISR. + */ +extern volatile uint32_t irq_interrupt_nesting; + +/** + * @name Macros to enter and exit an ISR + * + * Since all the stuff is done in `_frxt_int_enter` and `_frxt_int_exit`, these + * macros are doing nothing and are kept only for source code compatibility. + * + * @{ + */ +#define irq_isr_enter() +#define irq_isr_exit() +/** @} */ + +/** + * @name Macros to enter and exit a critical region + * + * @note: since they use a local variable they can be used only in same function + * + * @{ + */ +#define critical_enter() int _irq_state = irq_disable() +#define critical_exit() irq_restore(_irq_state) +/** @} */ + +/** + * @name Macros to enter and exit a critical region with state variable + * @{ + */ +#define critical_enter_var(m) m = irq_disable() +#define critical_exit_var(m) irq_restore(m) +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* IRQ_ARCH_COMMON_H */ diff --git a/cpu/esp8266/irq_arch.c b/cpu/esp_common/irq_arch.c similarity index 53% rename from cpu/esp8266/irq_arch.c rename to cpu/esp_common/irq_arch.c index c5f902cd99..62d264f3ec 100644 --- a/cpu/esp8266/irq_arch.c +++ b/cpu/esp_common/irq_arch.c @@ -7,7 +7,7 @@ */ /** - * @ingroup cpu_esp8266 + * @ingroup cpu_esp_common * @{ * * @file @@ -42,14 +42,16 @@ volatile uint32_t irq_interrupt_nesting = 0; */ unsigned int IRAM irq_disable(void) { - uint32_t _saved_interrupt_level; + uint32_t state; /* read and set interrupt level (RSIL) */ - __asm__ volatile ("rsil %0, " XTSTR(XCHAL_EXCM_LEVEL) : "=a" (_saved_interrupt_level)); - DEBUG ("%s %02x(%02x)\n", __func__, - (_saved_interrupt_level & 0xfffffff0) | (XCHAL_EXCM_LEVEL), - _saved_interrupt_level); - return _saved_interrupt_level; + __asm__ volatile ("rsil %0, " XTSTR(XCHAL_EXCM_LEVEL) : "=a" (state) :: "memory"); + /* mask out everything else of the PS register that do not belong to + interrupt level (bits 3..0) */ + state &= 0xf; + + DEBUG("%s %02x(%02x)\n", __func__, XCHAL_EXCM_LEVEL, state); + return state; } /** @@ -57,13 +59,16 @@ unsigned int IRAM irq_disable(void) */ unsigned int IRAM irq_enable(void) { - uint32_t _saved_interrupt_level; + uint32_t state; /* read and set interrupt level (RSIL) */ - __asm__ volatile ("rsil %0, 0" : "=a" (_saved_interrupt_level)); - DEBUG ("%s %02x (%02x)\n", __func__, - _saved_interrupt_level & 0xfffffff0, _saved_interrupt_level); - return _saved_interrupt_level; + __asm__ volatile ("rsil %0, 0" : "=a" (state) :: "memory"); + /* mask out everything else of the PS register that do not belong to + interrupt level (bits 3..0) */ + state &= 0xf; + + DEBUG("%s %02x(%02x)\n", __func__, 0, state); + return state; } /** @@ -71,9 +76,19 @@ unsigned int IRAM irq_enable(void) */ void IRAM irq_restore(unsigned int state) { + uint32_t old = 0; + /* write interrupt level and sync */ - DEBUG ("%s %02x\n", __func__, state); - __asm__ volatile ("wsr %0, ps; rsync" :: "a" (state)); + __asm__ volatile ("extui %1, %1, 0, 4 \n" /* mask intlevel bits in param */ + "rsr.ps %0 \n" /* read current PS value */ + "movi.n a4, -16 \n" + "and a4, a4, %0 \n" /* mask out intlevel bits in PS */ + "or a4, a4, %1 \n" /* or intlevel with PS */ + "wsr.ps a4 \n" /* write back PS */ + "rsync \n" + : "+a" (old) : "a" (state) : "memory"); + + DEBUG("%s %02x(%02x)\n", __func__, state, old & 0xf); } /**