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

@ -153,7 +153,7 @@ void IRAM PendSV(enum SVC_ReqType req)
*/ */
extern portBASE_TYPE sdk_MacIsrSigPostDefHdl(void); extern portBASE_TYPE sdk_MacIsrSigPostDefHdl(void);
void IRAM SV_ISR(void) void IRAM SV_ISR(void *arg)
{ {
portBASE_TYPE xHigherPriorityTaskWoken=pdFALSE ; portBASE_TYPE xHigherPriorityTaskWoken=pdFALSE ;
if(pending_maclayer_sv) if(pending_maclayer_sv)
@ -185,11 +185,11 @@ void xPortSysTickHandle (void)
*/ */
portBASE_TYPE xPortStartScheduler( void ) portBASE_TYPE xPortStartScheduler( void )
{ {
_xt_isr_attach(INUM_SOFT, SV_ISR); _xt_isr_attach(INUM_SOFT, SV_ISR, NULL);
_xt_isr_unmask(BIT(INUM_SOFT)); _xt_isr_unmask(BIT(INUM_SOFT));
/* Initialize system tick timer interrupt and schedule the first tick. */ /* Initialize system tick timer interrupt and schedule the first tick. */
_xt_isr_attach(INUM_TICK, sdk__xt_timer_int); _xt_isr_attach(INUM_TICK, sdk__xt_timer_int, NULL);
_xt_isr_unmask(BIT(INUM_TICK)); _xt_isr_unmask(BIT(INUM_TICK));
sdk__xt_tick_timer_init(); sdk__xt_tick_timer_init();

View file

@ -58,7 +58,7 @@ void gpio_set_pullup(uint8_t gpio_num, bool enabled, bool enabled_during_sleep)
static gpio_interrupt_handler_t gpio_interrupt_handlers[16] = { 0 }; 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; uint32_t status_reg = GPIO.STATUS;
GPIO.STATUS_CLEAR = status_reg; GPIO.STATUS_CLEAR = status_reg;
@ -83,7 +83,7 @@ void gpio_set_interrupt(const uint8_t gpio_num, const gpio_inttype_t int_type, g
GPIO.CONF[gpio_num] = SET_FIELD(GPIO.CONF[gpio_num], GPIO_CONF_INTTYPE, int_type); GPIO.CONF[gpio_num] = SET_FIELD(GPIO.CONF[gpio_num], GPIO_CONF_INTTYPE, int_type);
if (int_type != GPIO_INTTYPE_NONE) { if (int_type != GPIO_INTTYPE_NONE) {
_xt_isr_attach(INUM_GPIO, gpio_interrupt_handler); _xt_isr_attach(INUM_GPIO, gpio_interrupt_handler, NULL);
_xt_isr_unmask(1<<INUM_GPIO); _xt_isr_unmask(1<<INUM_GPIO);
} }
} }

View file

@ -7,13 +7,19 @@
*/ */
#include <esp/interrupts.h> #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; 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. /* Generic ISR handler.
@ -27,7 +33,7 @@ uint16_t IRAM _xt_isr_handler(uint16_t intset)
/* WDT has highest priority (occasional WDT resets otherwise) */ /* WDT has highest priority (occasional WDT resets otherwise) */
if (intset & BIT(INUM_WDT)) { if (intset & BIT(INUM_WDT)) {
_xt_clear_ints(BIT(INUM_WDT)); _xt_clear_ints(BIT(INUM_WDT));
isr[INUM_WDT](); isr[INUM_WDT].handler(NULL);
intset -= BIT(INUM_WDT); intset -= BIT(INUM_WDT);
} }
@ -35,7 +41,10 @@ uint16_t IRAM _xt_isr_handler(uint16_t intset)
uint8_t index = __builtin_ffs(intset) - 1; uint8_t index = __builtin_ffs(intset) - 1;
uint16_t mask = BIT(index); uint16_t mask = BIT(index);
_xt_clear_ints(mask); _xt_clear_ints(mask);
isr[index](); _xt_isr handler = isr[index].handler;
if (handler) {
handler(isr[index].arg);
}
intset -= mask; intset -= mask;
} }

View file

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

View file

@ -38,16 +38,34 @@ typedef enum {
void sdk__xt_int_exit(void); void sdk__xt_int_exit(void);
void _xt_user_exit(void); void _xt_user_exit(void);
void sdk__xt_tick_timer_init(void); void sdk__xt_tick_timer_init(void);
void sdk__xt_timer_int(void); void sdk__xt_timer_int(void *);
void sdk__xt_timer_int1(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) static inline uint32_t _xt_get_intlevel(void)
{ {
uint32_t level; uint32_t level;
__asm__ volatile("rsr %0, intlevel" : "=a"(level)); __asm__ volatile("rsr %0, ps" : "=a"(level));
return 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 /* Disable interrupts and return the old ps value, to pass into
_xt_restore_interrupts later. _xt_restore_interrupts later.
@ -68,22 +86,24 @@ static inline void _xt_restore_interrupts(uint32_t new_ps)
__asm__ volatile ("wsr %0, ps; rsync" :: "a" (new_ps)); __asm__ volatile ("wsr %0, ps; rsync" :: "a" (new_ps));
} }
/* ESPTODO: the mask/unmask functions aren't thread safe */ static inline uint32_t _xt_isr_unmask(uint32_t unmask)
static inline void _xt_isr_unmask(uint32_t unmask)
{ {
uint32_t old_level = _xt_disable_interrupts();
uint32_t intenable; uint32_t intenable;
asm volatile ("rsr %0, intenable" : "=a" (intenable)); asm volatile ("rsr %0, intenable" : "=a" (intenable));
intenable |= unmask; asm volatile ("wsr %0, intenable;" :: "a" (intenable | unmask));
asm volatile ("wsr %0, intenable; esync" :: "a" (intenable)); _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; uint32_t intenable;
asm volatile ("rsr %0, intenable" : "=a" (intenable)); asm volatile ("rsr %0, intenable" : "=a" (intenable));
intenable &= ~mask; asm volatile ("wsr %0, intenable;" :: "a" (intenable & ~mask));
asm volatile ("wsr %0, intenable; esync" :: "a" (intenable)); _xt_restore_interrupts(old_level);
return intenable;
} }
static inline uint32_t _xt_read_ints(void) static inline uint32_t _xt_read_ints(void)
@ -98,9 +118,7 @@ static inline void _xt_clear_ints(uint32_t mask)
asm volatile ("wsr %0, intclear; esync" :: "a" (mask)); asm volatile ("wsr %0, intclear; esync" :: "a" (mask));
} }
typedef void (* _xt_isr)(void); typedef void (* _xt_isr)(void *arg);
/* This function is implemeneted in FreeRTOS port.c at the moment, void _xt_isr_attach (uint8_t i, _xt_isr func, void *arg);
should be moved or converted to an inline */
void _xt_isr_attach (uint8_t i, _xt_isr func);
#endif #endif

View file

@ -17,13 +17,13 @@ const int freq_frc2 = 10;
static volatile uint32_t frc1_count; static volatile uint32_t frc1_count;
static volatile uint32_t frc2_count; static volatile uint32_t frc2_count;
void frc1_interrupt_handler(void) void frc1_interrupt_handler(void *arg)
{ {
frc1_count++; frc1_count++;
gpio_toggle(gpio_frc1); gpio_toggle(gpio_frc1);
} }
void frc2_interrupt_handler(void) void frc2_interrupt_handler(void *arg)
{ {
/* FRC2 needs the match register updated on each timer interrupt */ /* FRC2 needs the match register updated on each timer interrupt */
timer_set_frequency(FRC2, freq_frc2); timer_set_frequency(FRC2, freq_frc2);
@ -47,8 +47,8 @@ void user_init(void)
timer_set_run(FRC2, false); timer_set_run(FRC2, false);
/* set up ISRs */ /* set up ISRs */
_xt_isr_attach(INUM_TIMER_FRC1, frc1_interrupt_handler); _xt_isr_attach(INUM_TIMER_FRC1, frc1_interrupt_handler, NULL);
_xt_isr_attach(INUM_TIMER_FRC2, frc2_interrupt_handler); _xt_isr_attach(INUM_TIMER_FRC2, frc2_interrupt_handler, NULL);
/* configure timer frequencies */ /* configure timer frequencies */
timer_set_frequency(FRC1, freq_frc1); timer_set_frequency(FRC1, freq_frc1);

View file

@ -97,7 +97,7 @@ void timerRegTask(void *pvParameters)
} }
} }
IRAM void frc1_handler(void) IRAM void frc1_handler(void *arg)
{ {
frc1_handler_call_count++; frc1_handler_call_count++;
frc1_last_count_val = TIMER(0).COUNT; frc1_last_count_val = TIMER(0).COUNT;
@ -106,7 +106,7 @@ IRAM void frc1_handler(void)
//TIMER_FRC1_MATCH_REG = frc1_last_count_val + 0x100000; //TIMER_FRC1_MATCH_REG = frc1_last_count_val + 0x100000;
} }
void frc2_handler(void) void frc2_handler(void *arg)
{ {
frc2_handler_call_count++; frc2_handler_call_count++;
frc2_last_count_val = TIMER(1).COUNT; frc2_last_count_val = TIMER(1).COUNT;
@ -127,9 +127,9 @@ void user_init(void)
TIMER(1).LOAD = VAL2FIELD(TIMER_CTRL_CLKDIV, TIMER_CLKDIV_256); TIMER(1).LOAD = VAL2FIELD(TIMER_CTRL_CLKDIV, TIMER_CLKDIV_256);
DPORT.INT_ENABLE |= DPORT_INT_ENABLE_TIMER0 | DPORT_INT_ENABLE_TIMER1; DPORT.INT_ENABLE |= DPORT_INT_ENABLE_TIMER0 | DPORT_INT_ENABLE_TIMER1;
_xt_isr_attach(INUM_TIMER_FRC1, frc1_handler); _xt_isr_attach(INUM_TIMER_FRC1, frc1_handler, NULL);
_xt_isr_unmask(1<<INUM_TIMER_FRC1); _xt_isr_unmask(1<<INUM_TIMER_FRC1);
_xt_isr_attach(INUM_TIMER_FRC2, frc2_handler); _xt_isr_attach(INUM_TIMER_FRC2, frc2_handler, NULL);
_xt_isr_unmask(1<<INUM_TIMER_FRC2); _xt_isr_unmask(1<<INUM_TIMER_FRC2);
TIMER(0).CTRL |= TIMER_CTRL_RUN; TIMER(0).CTRL |= TIMER_CTRL_RUN;

View file

@ -237,7 +237,7 @@ static volatile bool frc1_ran;
static volatile bool frc1_finished; static volatile bool frc1_finished;
static volatile char frc1_buf[80]; static volatile char frc1_buf[80];
static void frc1_interrupt_handler(void) static void frc1_interrupt_handler(void *arg)
{ {
frc1_ran = true; frc1_ran = true;
timer_set_run(FRC1, false); timer_set_run(FRC1, false);
@ -250,7 +250,7 @@ static void test_isr()
printf("Testing behaviour inside ISRs...\r\n"); printf("Testing behaviour inside ISRs...\r\n");
timer_set_interrupts(FRC1, false); timer_set_interrupts(FRC1, false);
timer_set_run(FRC1, false); timer_set_run(FRC1, false);
_xt_isr_attach(INUM_TIMER_FRC1, frc1_interrupt_handler); _xt_isr_attach(INUM_TIMER_FRC1, frc1_interrupt_handler, NULL);
timer_set_frequency(FRC1, 1000); timer_set_frequency(FRC1, 1000);
timer_set_interrupts(FRC1, true); timer_set_interrupts(FRC1, true);
timer_set_run(FRC1, true); timer_set_run(FRC1, true);

View file

@ -88,7 +88,7 @@ static inline void init_descriptors_list()
} }
// DMA interrupt handler. It is called each time a DMA block is finished processing. // DMA interrupt handler. It is called each time a DMA block is finished processing.
static void dma_isr_handler(void) static void dma_isr_handler(void *args)
{ {
portBASE_TYPE task_awoken = pdFALSE; portBASE_TYPE task_awoken = pdFALSE;
@ -168,7 +168,7 @@ void play_task(void *pvParameters)
i2s_pins_t i2s_pins = {.data = true, .clock = true, .ws = true}; i2s_pins_t i2s_pins = {.data = true, .clock = true, .ws = true};
i2s_dma_init(dma_isr_handler, clock_div, i2s_pins); i2s_dma_init(dma_isr_handler, NULL, clock_div, i2s_pins);
while (1) { while (1) {
init_descriptors_list(); init_descriptors_list();

View file

@ -62,7 +62,7 @@ void sdk_rom_i2c_writeReg_Mask(uint32_t block, uint32_t host_id,
reg_add##_lsb, indata) reg_add##_lsb, indata)
void i2s_dma_init(i2s_dma_isr_t isr, i2s_clock_div_t clock_div, i2s_pins_t pins) void i2s_dma_init(i2s_dma_isr_t isr, void *arg, i2s_clock_div_t clock_div, i2s_pins_t pins)
{ {
// reset DMA // reset DMA
SET_MASK_BITS(SLC.CONF0, SLC_CONF0_RX_LINK_RESET); SET_MASK_BITS(SLC.CONF0, SLC_CONF0_RX_LINK_RESET);
@ -83,7 +83,7 @@ void i2s_dma_init(i2s_dma_isr_t isr, i2s_clock_div_t clock_div, i2s_pins_t pins)
SLC_RX_DESCRIPTOR_CONF_RX_EOF_MODE | SLC_RX_DESCRIPTOR_CONF_RX_FILL_MODE); SLC_RX_DESCRIPTOR_CONF_RX_EOF_MODE | SLC_RX_DESCRIPTOR_CONF_RX_FILL_MODE);
if (isr) { if (isr) {
_xt_isr_attach(INUM_SLC, isr); _xt_isr_attach(INUM_SLC, isr, arg);
SET_MASK_BITS(SLC.INT_ENABLE, SLC_INT_ENABLE_RX_EOF); SET_MASK_BITS(SLC.INT_ENABLE, SLC_INT_ENABLE_RX_EOF);
SLC.INT_CLEAR = 0xFFFFFFFF; SLC.INT_CLEAR = 0xFFFFFFFF;
_xt_isr_unmask(1<<INUM_SLC); _xt_isr_unmask(1<<INUM_SLC);

View file

@ -32,7 +32,7 @@
extern "C" { extern "C" {
#endif #endif
typedef void (*i2s_dma_isr_t)(void); typedef void (*i2s_dma_isr_t)(void *);
typedef struct dma_descriptor { typedef struct dma_descriptor {
uint32_t blocksize:12; uint32_t blocksize:12;
@ -61,10 +61,11 @@ typedef struct {
* Initialize I2S and DMA subsystems. * Initialize I2S and DMA subsystems.
* *
* @param isr ISR handler. Can be NULL if interrupt handling is not needed. * @param isr ISR handler. Can be NULL if interrupt handling is not needed.
* @param arg ISR handler arg.
* @param clock_div I2S clock configuration. * @param clock_div I2S clock configuration.
* @param pins I2S pin configuration. Specifies which pins are enabled in I2S. * @param pins I2S pin configuration. Specifies which pins are enabled in I2S.
*/ */
void i2s_dma_init(i2s_dma_isr_t isr, i2s_clock_div_t clock_div, i2s_pins_t pins); void i2s_dma_init(i2s_dma_isr_t isr, void *arg, i2s_clock_div_t clock_div, i2s_pins_t pins);
/** /**
* Calculate I2S dividers for the specified frequency. * Calculate I2S dividers for the specified frequency.

View file

@ -43,7 +43,7 @@ typedef struct pwmInfoDefinition
static PWMInfo pwmInfo; static PWMInfo pwmInfo;
static void frc1_interrupt_handler(void) static void frc1_interrupt_handler(void *arg)
{ {
uint8_t i = 0; uint8_t i = 0;
bool out = true; bool out = true;
@ -97,7 +97,7 @@ void pwm_init(uint8_t npins, const uint8_t* pins)
pwm_stop(); pwm_stop();
/* set up ISRs */ /* set up ISRs */
_xt_isr_attach(INUM_TIMER_FRC1, frc1_interrupt_handler); _xt_isr_attach(INUM_TIMER_FRC1, frc1_interrupt_handler, NULL);
/* Flag not running */ /* Flag not running */
pwmInfo.running = 0; pwmInfo.running = 0;

View file

@ -44,7 +44,7 @@ static SemaphoreHandle_t uart0_sem = NULL;
static bool inited = false; static bool inited = false;
static void uart0_rx_init(void); static void uart0_rx_init(void);
IRAM void uart0_rx_handler(void) IRAM void uart0_rx_handler(void *arg)
{ {
// TODO: Handle UART1, see reg 0x3ff20020, bit2, bit0 represents uart1 and uart0 respectively // TODO: Handle UART1, see reg 0x3ff20020, bit2, bit0 represents uart1 and uart0 respectively
if (!UART(UART0).INT_STATUS & UART_INT_STATUS_RXFIFO_FULL) { if (!UART(UART0).INT_STATUS & UART_INT_STATUS_RXFIFO_FULL) {
@ -97,7 +97,7 @@ static void uart0_rx_init(void)
int trig_lvl = 1; int trig_lvl = 1;
uart0_sem = xSemaphoreCreateCounting(UART0_RX_SIZE, 0); uart0_sem = xSemaphoreCreateCounting(UART0_RX_SIZE, 0);
_xt_isr_attach(INUM_UART, uart0_rx_handler); _xt_isr_attach(INUM_UART, uart0_rx_handler, NULL);
_xt_isr_unmask(1 << INUM_UART); _xt_isr_unmask(1 << INUM_UART);
// reset the rx fifo // reset the rx fifo

View file

@ -60,7 +60,7 @@ volatile uint32_t dma_isr_counter = 0;
static volatile bool i2s_dma_processing = false; static volatile bool i2s_dma_processing = false;
static void dma_isr_handler(void) static void dma_isr_handler(void *arg)
{ {
if (i2s_dma_is_eof_interrupt()) { if (i2s_dma_is_eof_interrupt()) {
#ifdef WS2812_I2S_DEBUG #ifdef WS2812_I2S_DEBUG
@ -145,7 +145,7 @@ void ws2812_i2s_init(uint32_t pixels_number)
debug("i2s clock dividers, bclk=%d, clkm=%d\n", debug("i2s clock dividers, bclk=%d, clkm=%d\n",
clock_div.bclk_div, clock_div.clkm_div); clock_div.bclk_div, clock_div.clkm_div);
i2s_dma_init(dma_isr_handler, clock_div, i2s_pins); i2s_dma_init(dma_isr_handler, NULL, clock_div, i2s_pins);
} }
const IRAM_DATA int16_t bitpatterns[16] = const IRAM_DATA int16_t bitpatterns[16] =

View file

@ -69,7 +69,7 @@ void IRAM sdk__xt_int_exit(void) {
"); ");
} }
void IRAM sdk__xt_timer_int(void) { void IRAM sdk__xt_timer_int(void *arg) {
uint32_t trigger_ccount; uint32_t trigger_ccount;
uint32_t current_ccount; uint32_t current_ccount;
uint32_t ccount_interval = portTICK_PERIOD_MS * sdk_os_get_cpu_frequency() * 1000; uint32_t ccount_interval = portTICK_PERIOD_MS * sdk_os_get_cpu_frequency() * 1000;

View file

@ -290,7 +290,7 @@ static void a_03_byte_load_test_isr()
printf("Testing behaviour inside ISRs...\r\n"); printf("Testing behaviour inside ISRs...\r\n");
timer_set_interrupts(FRC1, false); timer_set_interrupts(FRC1, false);
timer_set_run(FRC1, false); timer_set_run(FRC1, false);
_xt_isr_attach(INUM_TIMER_FRC1, frc1_interrupt_handler); _xt_isr_attach(INUM_TIMER_FRC1, frc1_interrupt_handler, NULL);
timer_set_frequency(FRC1, 1000); timer_set_frequency(FRC1, 1000);
timer_set_interrupts(FRC1, true); timer_set_interrupts(FRC1, true);
timer_set_run(FRC1, true); timer_set_run(FRC1, true);