Add an argument to ISRs. Disable interrupts while masking them.

This commit is contained in:
Our Air Quality 2017-07-22 22:09:09 +10:00
parent ec5dabd237
commit 5583543f14
16 changed files with 87 additions and 59 deletions

View file

@ -58,17 +58,17 @@ void gpio_set_pullup(uint8_t gpio_num, bool enabled, bool enabled_during_sleep)
static gpio_interrupt_handler_t gpio_interrupt_handlers[16] = { 0 };
void __attribute__((weak)) IRAM gpio_interrupt_handler(void)
void __attribute__((weak)) IRAM gpio_interrupt_handler(void *arg)
{
uint32_t status_reg = GPIO.STATUS;
GPIO.STATUS_CLEAR = status_reg;
uint8_t gpio_idx;
while((gpio_idx = __builtin_ffs(status_reg)))
while ((gpio_idx = __builtin_ffs(status_reg)))
{
gpio_idx--;
status_reg &= ~BIT(gpio_idx);
if(FIELD2VAL(GPIO_CONF_INTTYPE, GPIO.CONF[gpio_idx])) {
if (FIELD2VAL(GPIO_CONF_INTTYPE, GPIO.CONF[gpio_idx])) {
gpio_interrupt_handler_t handler = gpio_interrupt_handlers[gpio_idx];
if (handler) {
handler(gpio_idx);
@ -82,8 +82,8 @@ void gpio_set_interrupt(const uint8_t gpio_num, const gpio_inttype_t int_type, g
gpio_interrupt_handlers[gpio_num] = handler;
GPIO.CONF[gpio_num] = SET_FIELD(GPIO.CONF[gpio_num], GPIO_CONF_INTTYPE, int_type);
if(int_type != GPIO_INTTYPE_NONE) {
_xt_isr_attach(INUM_GPIO, gpio_interrupt_handler);
if (int_type != GPIO_INTTYPE_NONE) {
_xt_isr_attach(INUM_GPIO, gpio_interrupt_handler, NULL);
_xt_isr_unmask(1<<INUM_GPIO);
}
}

View file

@ -7,13 +7,19 @@
*/
#include <esp/interrupts.h>
_xt_isr isr[16];
typedef struct _xt_isr_entry_ {
_xt_isr handler;
void *arg;
} _xt_isr_entry;
_xt_isr_entry isr[16];
bool esp_in_isr;
void IRAM _xt_isr_attach(uint8_t i, _xt_isr func)
void IRAM _xt_isr_attach(uint8_t i, _xt_isr func, void *arg)
{
isr[i] = func;
isr[i].handler = func;
isr[i].arg = arg;
}
/* Generic ISR handler.
@ -25,17 +31,20 @@ uint16_t IRAM _xt_isr_handler(uint16_t intset)
esp_in_isr = true;
/* WDT has highest priority (occasional WDT resets otherwise) */
if(intset & BIT(INUM_WDT)) {
if (intset & BIT(INUM_WDT)) {
_xt_clear_ints(BIT(INUM_WDT));
isr[INUM_WDT]();
isr[INUM_WDT].handler(NULL);
intset -= BIT(INUM_WDT);
}
while(intset) {
while (intset) {
uint8_t index = __builtin_ffs(intset) - 1;
uint16_t mask = BIT(index);
_xt_clear_ints(mask);
isr[index]();
_xt_isr handler = isr[index].handler;
if (handler) {
handler(isr[index].arg);
}
intset -= mask;
}

View file

@ -150,7 +150,7 @@ typedef void (* gpio_interrupt_handler_t)(uint8_t gpio_num);
*
* Example:
*
* void IRAM gpio_interrupt_handler(void) {
* void IRAM gpio_interrupt_handler(void *arg) {
* // check GPIO.STATUS
* // write GPIO.STATUS_CLEAR
* // Do something when GPIO changes

View file

@ -35,19 +35,37 @@ typedef enum {
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_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);
/* The normal running level is 0.
* The system tick isr, timer frc2_isr, sv_isr etc run at level 1.
* Debug exceptions run at level 2?
* The wdev nmi runs at level 3.
*/
static inline uint32_t _xt_get_intlevel(void)
{
uint32_t level;
__asm__ volatile("rsr %0, intlevel" : "=a"(level));
return level;
__asm__ volatile("rsr %0, ps" : "=a"(level));
return level & 0xf;
}
/*
* There are conflicting definitions for XCHAL_EXCM_LEVEL. Newlib
* defines it to be 1 and xtensa_rtos.h defines it to be 3. Don't want
* 3 as that is for the NMI and might want to check that the OS apis
* are not entered in level 3. Setting the interrupt level to 3 does
* not disable the NMI anyway. So set the level to 2.
*/
#ifdef XCHAL_EXCM_LEVEL
#undef XCHAL_EXCM_LEVEL
#define XCHAL_EXCM_LEVEL 2
#endif
/* Disable interrupts and return the old ps value, to pass into
_xt_restore_interrupts later.
@ -68,25 +86,27 @@ static inline 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 */
static inline void _xt_isr_unmask(uint32_t unmask)
static inline uint32_t _xt_isr_unmask(uint32_t unmask)
{
uint32_t old_level = _xt_disable_interrupts();
uint32_t intenable;
asm volatile ("rsr %0, intenable" : "=a" (intenable));
intenable |= unmask;
asm volatile ("wsr %0, intenable; esync" :: "a" (intenable));
asm volatile ("wsr %0, intenable;" :: "a" (intenable | unmask));
_xt_restore_interrupts(old_level);
return intenable;
}
static inline void _xt_isr_mask (uint32_t mask)
static inline uint32_t _xt_isr_mask(uint32_t mask)
{
uint32_t old_level = _xt_disable_interrupts();
uint32_t intenable;
asm volatile ("rsr %0, intenable" : "=a" (intenable));
intenable &= ~mask;
asm volatile ("wsr %0, intenable; esync" :: "a" (intenable));
asm volatile ("wsr %0, intenable;" :: "a" (intenable & ~mask));
_xt_restore_interrupts(old_level);
return intenable;
}
static inline uint32_t _xt_read_ints (void)
static inline uint32_t _xt_read_ints(void)
{
uint32_t interrupt;
asm volatile ("rsr %0, interrupt" : "=a" (interrupt));
@ -98,9 +118,7 @@ static inline 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);
typedef void (* _xt_isr)(void *arg);
void _xt_isr_attach (uint8_t i, _xt_isr func, void *arg);
#endif