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);
void IRAM SV_ISR(void)
void IRAM SV_ISR(void *arg)
{
portBASE_TYPE xHigherPriorityTaskWoken=pdFALSE ;
if(pending_maclayer_sv)
@ -185,11 +185,11 @@ void xPortSysTickHandle (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));
/* 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));
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 };
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;
@ -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);
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);
}
}

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.
@ -27,7 +33,7 @@ uint16_t IRAM _xt_isr_handler(uint16_t intset)
/* WDT has highest priority (occasional WDT resets otherwise) */
if (intset & BIT(INUM_WDT)) {
_xt_clear_ints(BIT(INUM_WDT));
isr[INUM_WDT]();
isr[INUM_WDT].handler(NULL);
intset -= BIT(INUM_WDT);
}
@ -35,7 +41,10 @@ uint16_t IRAM _xt_isr_handler(uint16_t 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

@ -38,16 +38,34 @@ typedef enum {
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_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,22 +86,24 @@ 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)
@ -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

View file

@ -17,13 +17,13 @@ const int freq_frc2 = 10;
static volatile uint32_t frc1_count;
static volatile uint32_t frc2_count;
void frc1_interrupt_handler(void)
void frc1_interrupt_handler(void *arg)
{
frc1_count++;
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 */
timer_set_frequency(FRC2, freq_frc2);
@ -47,8 +47,8 @@ void user_init(void)
timer_set_run(FRC2, false);
/* set up ISRs */
_xt_isr_attach(INUM_TIMER_FRC1, frc1_interrupt_handler);
_xt_isr_attach(INUM_TIMER_FRC2, frc2_interrupt_handler);
_xt_isr_attach(INUM_TIMER_FRC1, frc1_interrupt_handler, NULL);
_xt_isr_attach(INUM_TIMER_FRC2, frc2_interrupt_handler, NULL);
/* configure timer frequencies */
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_last_count_val = TIMER(0).COUNT;
@ -106,7 +106,7 @@ IRAM void frc1_handler(void)
//TIMER_FRC1_MATCH_REG = frc1_last_count_val + 0x100000;
}
void frc2_handler(void)
void frc2_handler(void *arg)
{
frc2_handler_call_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);
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_attach(INUM_TIMER_FRC2, frc2_handler);
_xt_isr_attach(INUM_TIMER_FRC2, frc2_handler, NULL);
_xt_isr_unmask(1<<INUM_TIMER_FRC2);
TIMER(0).CTRL |= TIMER_CTRL_RUN;

View file

@ -237,7 +237,7 @@ static volatile bool frc1_ran;
static volatile bool frc1_finished;
static volatile char frc1_buf[80];
static void frc1_interrupt_handler(void)
static void frc1_interrupt_handler(void *arg)
{
frc1_ran = true;
timer_set_run(FRC1, false);
@ -250,7 +250,7 @@ static void test_isr()
printf("Testing behaviour inside ISRs...\r\n");
timer_set_interrupts(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_interrupts(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.
static void dma_isr_handler(void)
static void dma_isr_handler(void *args)
{
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_dma_init(dma_isr_handler, clock_div, i2s_pins);
i2s_dma_init(dma_isr_handler, NULL, clock_div, i2s_pins);
while (1) {
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)
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
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);
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);
SLC.INT_CLEAR = 0xFFFFFFFF;
_xt_isr_unmask(1<<INUM_SLC);

View file

@ -32,7 +32,7 @@
extern "C" {
#endif
typedef void (*i2s_dma_isr_t)(void);
typedef void (*i2s_dma_isr_t)(void *);
typedef struct dma_descriptor {
uint32_t blocksize:12;
@ -61,10 +61,11 @@ typedef struct {
* Initialize I2S and DMA subsystems.
*
* @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 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.

View file

@ -43,7 +43,7 @@ typedef struct pwmInfoDefinition
static PWMInfo pwmInfo;
static void frc1_interrupt_handler(void)
static void frc1_interrupt_handler(void *arg)
{
uint8_t i = 0;
bool out = true;
@ -97,7 +97,7 @@ void pwm_init(uint8_t npins, const uint8_t* pins)
pwm_stop();
/* 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 */
pwmInfo.running = 0;

View file

@ -44,7 +44,7 @@ static SemaphoreHandle_t uart0_sem = NULL;
static bool inited = false;
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
if (!UART(UART0).INT_STATUS & UART_INT_STATUS_RXFIFO_FULL) {
@ -97,7 +97,7 @@ static void uart0_rx_init(void)
int trig_lvl = 1;
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);
// 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 void dma_isr_handler(void)
static void dma_isr_handler(void *arg)
{
if (i2s_dma_is_eof_interrupt()) {
#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",
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] =

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 current_ccount;
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");
timer_set_interrupts(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_interrupts(FRC1, true);
timer_set_run(FRC1, true);