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
				
			
		|  | @ -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(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -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); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -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; | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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
 | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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(); | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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. | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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
 | ||||
|  |  | |||
|  | @ -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] = | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue