89c481c606
RTOS Timer tick handler is now the same as any other ISR. This causes a few subtle behaviour changes that seem OK but are worth noting: * RTOS tick handler sdk__xt_timer_int() is now called from one stack frame deeper (inside _xt_isr_handler()), whereas before it was called from the level above in UserHandleInterrupt. I can't see any way that the extra ~40 bytes of stack use here hurt, though. * sdk__xt_timer_int() was previous called after all other interrupts flagged in the handler, now it's called before the TIMER FRC1 & FRC2 handlers. The tick handler doesn't appear to do anything particularly timing intensive, though. * GPIO interrupt (value 3) is now lower priority than the SPI interrupt (value 2), whereas before it would have been called before SPI if both interrupts triggered at once.
103 lines
2.8 KiB
C
103 lines
2.8 KiB
C
/* ESP8266 Xtensa interrupt management functions
|
|
*
|
|
* Some (w/ sdk_ prefix) are implemented in binary libs, rest are
|
|
* inlines replacing functions in the binary libraries.
|
|
*
|
|
* Part of esp-open-rtos
|
|
* Copyright (C) 2015 Superhouse Automation Pty Ltd
|
|
* BSD Licensed as described in the file LICENSE
|
|
*/
|
|
#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>
|
|
|
|
/* Interrupt numbers for level 1 exception handler. */
|
|
typedef enum {
|
|
INUM_SPI = 2,
|
|
INUM_GPIO = 4,
|
|
INUM_UART = 5,
|
|
INUM_TICK = 6, /* RTOS timer tick, possibly xtensa CPU CCOMPARE0(?) */
|
|
INUM_SOFT = 7,
|
|
INUM_WDT = 8,
|
|
INUM_TIMER_FRC1 = 9,
|
|
|
|
/* FRC2 default handler. Configured by sdk_ets_timer_init, which
|
|
runs as part of default libmain.a startup code, assigns
|
|
interrupt handler to sdk_vApplicationTickHook+0x68
|
|
*/
|
|
INUM_TIMER_FRC2 = 10,
|
|
} xt_isr_num_t;
|
|
|
|
void sdk__xt_int_exit (void);
|
|
void _xt_user_exit (void);
|
|
void sdk__xt_tick_timer_init (void);
|
|
void sdk__xt_timer_int(void);
|
|
void sdk__xt_timer_int1(void);
|
|
|
|
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));
|
|
intenable |= unmask;
|
|
asm volatile ("wsr %0, intenable; esync" :: "a" (intenable));
|
|
}
|
|
|
|
INLINED void _xt_isr_mask (uint32_t mask)
|
|
{
|
|
uint32_t intenable;
|
|
asm volatile ("rsr %0, intenable" : "=a" (intenable));
|
|
intenable &= ~mask;
|
|
asm volatile ("wsr %0, intenable; esync" :: "a" (intenable));
|
|
}
|
|
|
|
INLINED uint32_t _xt_read_ints (void)
|
|
{
|
|
uint32_t interrupt;
|
|
asm volatile ("rsr %0, interrupt" : "=a" (interrupt));
|
|
return interrupt;
|
|
}
|
|
|
|
INLINED void _xt_clear_ints(uint32_t mask)
|
|
{
|
|
asm volatile ("wsr %0, intclear; esync" :: "a" (mask));
|
|
}
|
|
|
|
typedef void (* _xt_isr)(void);
|
|
/* This function is implemeneted in FreeRTOS port.c at the moment,
|
|
should be moved or converted to an inline */
|
|
void _xt_isr_attach (uint8_t i, _xt_isr func);
|
|
|
|
#endif
|