diff --git a/FreeRTOS/Source/portable/esp8266/portmacro.h b/FreeRTOS/Source/portable/esp8266/portmacro.h index 242c253..c7f0501 100644 --- a/FreeRTOS/Source/portable/esp8266/portmacro.h +++ b/FreeRTOS/Source/portable/esp8266/portmacro.h @@ -73,7 +73,6 @@ extern "C" { #include "esp8266.h" #include "espressif/esp8266/ets_sys.h" #include -#include #include "xtensa_rtos.h" #include "xtensa_interrupts.h" @@ -144,33 +143,31 @@ extern char sdk_NMIIrqIsOn; extern char level1_int_disabled; extern unsigned cpu_sr; -/* ESPTODO: Currently we store the old interrupt level (ps) in a - global variable cpu_sr. It may not be necessary to do this, - especially as lx106 has only one real interrupt level + NMI, but it - all depends on how the blob libraries call into these functions. +/* Disable interrupts, store old ps level in global variable cpu_sr. + + Note: cpu_sr is also referenced by the binary SDK. + + Where possible (and when writing non-FreeRTOS specific code), + prefer to _xt_disable_interrupts & _xt_enable_interrupts and store + the ps value in a local variable - that approach is recursive-safe + and generally better. */ -inline static __attribute__((always_inline)) void _esp_disable_interrupts(void) +inline static __attribute__((always_inline)) void portDISABLE_INTERRUPTS(void) { if(!sdk_NMIIrqIsOn && !level1_int_disabled) { - __asm__ volatile ("rsil %0, " XTSTR(XCHAL_EXCM_LEVEL) : "=a" (cpu_sr) :: "memory"); + cpu_sr = _xt_disable_interrupts(); level1_int_disabled = 1; } } -inline static __attribute__((always_inline)) void _esp_enable_interrupts(void) +inline static __attribute__((always_inline)) void portENABLE_INTERRUPTS(void) { if(!sdk_NMIIrqIsOn && level1_int_disabled) { level1_int_disabled = 0; - __asm__ volatile ("wsr %0, ps" :: "a" (cpu_sr) : "memory"); + _xt_restore_interrupts(cpu_sr); } } -/* Disable interrupts, saving previous state in cpu_sr */ -#define portDISABLE_INTERRUPTS() _esp_disable_interrupts() - -/* Restore interrupts to previous level saved in cpu_sr */ -#define portENABLE_INTERRUPTS() _esp_enable_interrupts() - /* Critical section management. */ void vPortEnterCritical( void ); void vPortExitCritical( void ); diff --git a/include/xtensa_interrupts.h b/include/xtensa_interrupts.h index f2c75f8..4a39bb9 100644 --- a/include/xtensa_interrupts.h +++ b/include/xtensa_interrupts.h @@ -10,14 +10,46 @@ #ifndef _XTENSA_INTERRUPTS_H #define _XTENSA_INTERRUPTS_H #include +#include +#include #include +#include void sdk__xt_int_exit (void); void sdk__xt_user_exit (void); void sdk__xt_tick_timer_init (void); void sdk__xt_timer_int1(void); -INLINED void _xt_isr_unmask (uint32_t unmask) +INLINED uint32_t _xt_get_intlevel(void) +{ + uint32_t level; + __asm__ volatile("rsr %0, intlevel" : "=a"(level)); + return level; +} + +/* Disable interrupts and return the old ps value, to pass into + _xt_restore_interrupts later. + + This is desirable to use in place of + portDISABLE_INTERRUPTS/portENABLE_INTERRUPTS for + non-FreeRTOS & non-portable code. +*/ +INLINED uint32_t _xt_disable_interrupts(void) +{ + uint32_t old_level; + __asm__ volatile ("rsil %0, " XTSTR(XCHAL_EXCM_LEVEL) : "=a" (old_level)); + return old_level; +} + +/* Restore PS level. Intended to be used with _xt_disable_interrupts */ +INLINED void _xt_restore_interrupts(uint32_t new_ps) +{ + __asm__ volatile ("wsr %0, ps; rsync" :: "a" (new_ps)); +} + +/* ESPTODO: the mask/unmask functions aren't thread safe */ + +INLINED void _xt_isr_unmask(uint32_t unmask) { uint32_t intenable; asm volatile ("rsr %0, intenable" : "=a" (intenable));