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 <stdint.h>
-#include    <xtruntime.h>
 #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 <stdint.h>
+#include <stdbool.h>
+#include <xtruntime.h>
 #include <xtensa/hal.h>
+#include <common_macros.h>
 
 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));