Add an argument to ISRs. Disable interrupts while masking them.
This commit is contained in:
		
							parent
							
								
									ec5dabd237
								
							
						
					
					
						commit
						5583543f14
					
				
					 16 changed files with 87 additions and 59 deletions
				
			
		| 
						 | 
				
			
			@ -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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue