diff --git a/arch/xtensa/include/esp32/irq.h b/arch/xtensa/include/esp32/irq.h index 36fce7d4e58..4221f30b20d 100644 --- a/arch/xtensa/include/esp32/irq.h +++ b/arch/xtensa/include/esp32/irq.h @@ -50,29 +50,6 @@ * Pre-processor Definitions ****************************************************************************/ -/* Exceptions - * - * IRAM Offset Description - * 0x0000 Windows - * 0x0180 Level 2 interrupt - * 0x01c0 Level 3 interrupt - * 0x0200 Level 4 interrupt - * 0x0240 Level 5 interrupt - * 0x0280 Debug exception - * 0x02c0 NMI exception - * 0x0300 Kernel exception - * 0x0340 User exception - * 0x03c0 Double exception - * - * REVISIT: In more architectures supported by NuttX, exception errors - * tie into the normal interrupt handling via special IRQ numbers. I - * is still to be determined what will be done for the ESP32. - */ - -#define XTENSA_IRQ_TIMER0 0 /* INTERRUPT, bit 6 */ -#define XTENSA_IRQ_TIMER1 1 /* INTERRUPT, bit 15 */ -#define XTENSA_IRQ_TIMER2 2 /* INTERRUPT, bit 16 */ - /* Interrupt Matrix * * The Interrupt Matrix embedded in the ESP32 independently allocates @@ -102,94 +79,285 @@ /* PRO_INTR_STATUS_REG_0 / APP_INTR_STATUS_REG_0 */ -#define XTENSA_IRQ_SREG0 3 -#define XTENSA_IRQ_MAC 3 /* INTR_STATUS_REG_0, bit 0 */ -#define XTENSA_IRQ_MAC_NMI 4 /* INTR_STATUS_REG_0, bit 1 */ -#define XTENSA_IRQ_BB 5 /* INTR_STATUS_REG_0, bit 2 */ -#define XTENSA_IRQ_BB_MAC 6 /* INTR_STATUS_REG_0, bit 3 */ -#define XTENSA_IRQ_BT_BB 7 /* INTR_STATUS_REG_0, bit 4 */ -#define XTENSA_IRQ_BT_BB_NMI 8 /* INTR_STATUS_REG_0, bit 5 */ -#define XTENSA_IRQ_RWBT_IRQ 9 /* INTR_STATUS_REG_0, bit 6 */ -#define XTENSA_IRQ_RWBLE_IRQ 10 /* INTR_STATUS_REG_0, bit 7 */ -#define XTENSA_IRQ_RWBT_NMI 11 /* INTR_STATUS_REG_0, bit 8 */ -#define XTENSA_IRQ_RWBLE_NMI 12 /* INTR_STATUS_REG_0, bit 9 */ +#define ESP32_PERIPH_MAC 0 /* INTR_STATUS_REG_0, bit 0 */ +#define ESP32_PERIPH_MAC_NMI 1 /* INTR_STATUS_REG_0, bit 1 */ +#define ESP32_PERIPH_BB 2 /* INTR_STATUS_REG_0, bit 2 */ +#define ESP32_PERIPH_BB_MAC 3 /* INTR_STATUS_REG_0, bit 3 */ +#define ESP32_PERIPH_BT_BB 4 /* INTR_STATUS_REG_0, bit 4 */ +#define ESP32_PERIPH_BT_BB_NMI 5 /* INTR_STATUS_REG_0, bit 5 */ +#define ESP32_PERIPH_RWBT_IRQ 6 /* INTR_STATUS_REG_0, bit 6 */ +#define ESP32_PERIPH_RWBLE_IRQ 7 /* INTR_STATUS_REG_0, bit 7 */ +#define ESP32_PERIPH_RWBT_NMI 8 /* INTR_STATUS_REG_0, bit 8 */ +#define ESP32_PERIPH_RWBLE_NMI 9 /* INTR_STATUS_REG_0, bit 9 */ -#define XTENSA_IRQ_SLC0 13 /* INTR_STATUS_REG_0, bit 10 */ -#define XTENSA_IRQ_SLC1 14 /* INTR_STATUS_REG_0, bit 11 */ -#define XTENSA_IRQ_UHCI0 15 /* INTR_STATUS_REG_0, bit 12 */ -#define XTENSA_IRQ_UHCI1 16 /* INTR_STATUS_REG_0, bit 13 */ -#define XTENSA_IRQ_TG_T0_LEVEL 17 /* INTR_STATUS_REG_0, bit 14 */ -#define XTENSA_IRQ_TG_T1_LEVEL 18 /* INTR_STATUS_REG_0, bit 15 */ -#define XTENSA_IRQ_TG_WDT_LEVEL 19 /* INTR_STATUS_REG_0, bit 16 */ -#define XTENSA_IRQ_TG_LACT_LEVEL 20 /* INTR_STATUS_REG_0, bit 17 */ -#define XTENSA_IRQ_TG1_T0_LEVEL 21 /* INTR_STATUS_REG_0, bit 18 */ -#define XTENSA_IRQ_TG1_T1_LEVEL 22 /* INTR_STATUS_REG_0, bit 19 */ +#define ESP32_PERIPH_SLC0 10 /* INTR_STATUS_REG_0, bit 10 */ +#define ESP32_PERIPH_SLC1 11 /* INTR_STATUS_REG_0, bit 11 */ +#define ESP32_PERIPH_UHCI0 12 /* INTR_STATUS_REG_0, bit 12 */ +#define ESP32_PERIPH_UHCI1 13 /* INTR_STATUS_REG_0, bit 13 */ +#define ESP32_PERIPH_TG_T0_LEVEL 14 /* INTR_STATUS_REG_0, bit 14 */ +#define ESP32_PERIPH_TG_T1_LEVEL 15 /* INTR_STATUS_REG_0, bit 15 */ +#define ESP32_PERIPH_TG_WDT_LEVEL 16 /* INTR_STATUS_REG_0, bit 16 */ +#define ESP32_PERIPH_TG_LACT_LEVEL 17 /* INTR_STATUS_REG_0, bit 17 */ +#define ESP32_PERIPH_TG1_T0_LEVEL 18 /* INTR_STATUS_REG_0, bit 18 */ +#define ESP32_PERIPH_TG1_T1_LEVEL 19 /* INTR_STATUS_REG_0, bit 19 */ -#define XTENSA_IRQ_TG1_WDT_LEVEL 23 /* INTR_STATUS_REG_0, bit 20 */ -#define XTENSA_IRQ_G1_LACT_LEVEL 24 /* INTR_STATUS_REG_0, bit 21 */ -#define XTENSA_IRQ_CPU_GPIO 25 /* INTR_STATUS_REG_0, bit 22 */ -#define XTENSA_IRQ_CPU_NMI 26 /* INTR_STATUS_REG_0, bit 23 */ -#define XTENSA_IRQ_CPU_CPU0 27 /* INTR_STATUS_REG_0, bit 24 */ -#define XTENSA_IRQ_CPU_CPU1 28 /* INTR_STATUS_REG_0, bit 25 */ -#define XTENSA_IRQ_CPU_CPU2 29 /* INTR_STATUS_REG_0, bit 26 */ -#define XTENSA_IRQ_CPU_CPU3 30 /* INTR_STATUS_REG_0, bit 27 */ -#define XTENSA_IRQ_SPI0 31 /* INTR_STATUS_REG_0, bit 28 */ -#define XTENSA_IRQ_SPI1 32 /* INTR_STATUS_REG_0, bit 29 */ +#define ESP32_PERIPH_TG1_WDT_LEVEL 20 /* INTR_STATUS_REG_0, bit 20 */ +#define ESP32_PERIPH_G1_LACT_LEVEL 21 /* INTR_STATUS_REG_0, bit 21 */ +#define ESP32_PERIPH_CPU_GPIO 22 /* INTR_STATUS_REG_0, bit 22 */ +#define ESP32_PERIPH_CPU_NMI 23 /* INTR_STATUS_REG_0, bit 23 */ +#define ESP32_PERIPH_CPU_CPU0 24 /* INTR_STATUS_REG_0, bit 24 */ +#define ESP32_PERIPH_CPU_CPU1 25 /* INTR_STATUS_REG_0, bit 25 */ +#define ESP32_PERIPH_CPU_CPU2 26 /* INTR_STATUS_REG_0, bit 26 */ +#define ESP32_PERIPH_CPU_CPU3 27 /* INTR_STATUS_REG_0, bit 27 */ +#define ESP32_PERIPH_SPI0 28 /* INTR_STATUS_REG_0, bit 28 */ +#define ESP32_PERIPH_SPI1 29 /* INTR_STATUS_REG_0, bit 29 */ -#define XTENSA_IRQ_SPI2 33 /* INTR_STATUS_REG_0, bit 30 */ -#define XTENSA_IRQ_SPI3 34 /* INTR_STATUS_REG_0, bit 31 */ +#define ESP32_PERIPH_SPI2 30 /* INTR_STATUS_REG_0, bit 30 */ +#define ESP32_PERIPH_SPI3 31 /* INTR_STATUS_REG_0, bit 31 */ /* PRO_INTR_STATUS_REG_1 / APP_INTR_STATUS_REG_1 */ -#define XTENSA_IRQ_SREG1 35 -#define XTENSA_IRQ_I2S0 35 /* INTR_STATUS_REG_1, bit 0 */ -#define XTENSA_IRQ_I2S1 36 /* INTR_STATUS_REG_1, bit 1 */ -#define XTENSA_IRQ_UART 37 /* INTR_STATUS_REG_1, bit 2 */ -#define XTENSA_IRQ_UART1 38 /* INTR_STATUS_REG_1, bit 3 */ -#define XTENSA_IRQ_UART2 39 /* INTR_STATUS_REG_1, bit 4 */ -#define XTENSA_IRQ_SDIO_HOST 40 /* INTR_STATUS_REG_1, bit 5 */ -#define XTENSA_IRQ_EMAC 41 /* INTR_STATUS_REG_1, bit 6 */ -#define XTENSA_IRQ_PWM0 42 /* INTR_STATUS_REG_1, bit 7 */ -#define XTENSA_IRQ_PWM1 43 /* INTR_STATUS_REG_1, bit 8 */ -#define XTENSA_IRQ_PWM2 44 /* INTR_STATUS_REG_1, bit 9 */ +#define ESP32_PERIPH_I2S0 32 /* INTR_STATUS_REG_1, bit 0 */ +#define ESP32_PERIPH_I2S1 33 /* INTR_STATUS_REG_1, bit 1 */ +#define ESP32_PERIPH_UART 34 /* INTR_STATUS_REG_1, bit 2 */ +#define ESP32_PERIPH_UART1 35 /* INTR_STATUS_REG_1, bit 3 */ +#define ESP32_PERIPH_UART2 36 /* INTR_STATUS_REG_1, bit 4 */ +#define ESP32_PERIPH_SDIO_HOST 37 /* INTR_STATUS_REG_1, bit 5 */ +#define ESP32_PERIPH_EMAC 38 /* INTR_STATUS_REG_1, bit 6 */ +#define ESP32_PERIPH_PWM0 39 /* INTR_STATUS_REG_1, bit 7 */ +#define ESP32_PERIPH_PWM1 40 /* INTR_STATUS_REG_1, bit 8 */ +#define ESP32_PERIPH_PWM2 41 /* INTR_STATUS_REG_1, bit 9 */ -#define XTENSA_IRQ_PWM3 45 /* INTR_STATUS_REG_1, bit 10 */ -#define XTENSA_IRQ_LEDC 46 /* INTR_STATUS_REG_1, bit 11 */ -#define XTENSA_IRQ_EFUSE 47 /* INTR_STATUS_REG_1, bit 12 */ -#define XTENSA_IRQ_CAN 48 /* INTR_STATUS_REG_1, bit 13 */ -#define XTENSA_IRQ_RTC_CORE 49 /* INTR_STATUS_REG_1, bit 14 */ -#define XTENSA_IRQ_RMT 50 /* INTR_STATUS_REG_1, bit 15 */ -#define XTENSA_IRQ_PCNT 51 /* INTR_STATUS_REG_1, bit 16 */ -#define XTENSA_IRQ_I2C_EXT0 52 /* INTR_STATUS_REG_1, bit 17 */ -#define XTENSA_IRQ_I2C_EXT1 53 /* INTR_STATUS_REG_1, bit 18 */ -#define XTENSA_IRQ_RSA 54 /* INTR_STATUS_REG_1, bit 19 */ +#define ESP32_PERIPH_PWM3 42 /* INTR_STATUS_REG_1, bit 10 */ +#define ESP32_PERIPH_LEDC 43 /* INTR_STATUS_REG_1, bit 11 */ +#define ESP32_PERIPH_EFUSE 44 /* INTR_STATUS_REG_1, bit 12 */ +#define ESP32_PERIPH_CAN 45 /* INTR_STATUS_REG_1, bit 13 */ +#define ESP32_PERIPH_RTC_CORE 46 /* INTR_STATUS_REG_1, bit 14 */ +#define ESP32_PERIPH_RMT 47 /* INTR_STATUS_REG_1, bit 15 */ +#define ESP32_PERIPH_PCNT 48 /* INTR_STATUS_REG_1, bit 16 */ +#define ESP32_PERIPH_I2C_EXT0 49 /* INTR_STATUS_REG_1, bit 17 */ +#define ESP32_PERIPH_I2C_EXT1 50 /* INTR_STATUS_REG_1, bit 18 */ +#define ESP32_PERIPH_RSA 51 /* INTR_STATUS_REG_1, bit 19 */ -#define XTENSA_IRQ_SPI1_DMA 55 /* INTR_STATUS_REG_1, bit 20 */ -#define XTENSA_IRQ_SPI2_DMA 56 /* INTR_STATUS_REG_1, bit 21 */ -#define XTENSA_IRQ_SPI3_DMA 57 /* INTR_STATUS_REG_1, bit 22 */ -#define XTENSA_IRQ_WDG 58 /* INTR_STATUS_REG_1, bit 23 */ -#define XTENSA_IRQ_TIMER1 59 /* INTR_STATUS_REG_1, bit 24 */ -#define XTENSA_IRQ_TIMER2 60 /* INTR_STATUS_REG_1, bit 25 */ -#define XTENSA_IRQ_TG_T0_EDGE 61 /* INTR_STATUS_REG_1, bit 26 */ -#define XTENSA_IRQ_TG_T1_EDGE 62 /* INTR_STATUS_REG_1, bit 27 */ -#define XTENSA_IRQ_TG_WDT_EDGE 63 /* INTR_STATUS_REG_1, bit 28 */ -#define XTENSA_IRQ_TG_LACT_EDGE 64 /* INTR_STATUS_REG_1, bit 29 */ +#define ESP32_PERIPH_SPI1_DMA 52 /* INTR_STATUS_REG_1, bit 20 */ +#define ESP32_PERIPH_SPI2_DMA 53 /* INTR_STATUS_REG_1, bit 21 */ +#define ESP32_PERIPH_SPI3_DMA 54 /* INTR_STATUS_REG_1, bit 22 */ +#define ESP32_PERIPH_WDG 55 /* INTR_STATUS_REG_1, bit 23 */ +#define ESP32_PERIPH_TIMER1 56 /* INTR_STATUS_REG_1, bit 24 */ +#define ESP32_PERIPH_TIMER2 57 /* INTR_STATUS_REG_1, bit 25 */ +#define ESP32_PERIPH_TG_T0_EDGE 58 /* INTR_STATUS_REG_1, bit 26 */ +#define ESP32_PERIPH_TG_T1_EDGE 59 /* INTR_STATUS_REG_1, bit 27 */ +#define ESP32_PERIPH_TG_WDT_EDGE 60 /* INTR_STATUS_REG_1, bit 28 */ +#define ESP32_PERIPH_TG_LACT_EDGE 61 /* INTR_STATUS_REG_1, bit 29 */ -#define XTENSA_IRQ_TG1_T0_EDGE 65 /* INTR_STATUS_REG_1, bit 30 */ -#define XTENSA_IRQ_TG1_T1_EDGE 66 /* INTR_STATUS_REG_1, bit 31 */ +#define ESP32_PERIPH_TG1_T0_EDGE 62 /* INTR_STATUS_REG_1, bit 30 */ +#define ESP32_PERIPH_TG1_T1_EDGE 63 /* INTR_STATUS_REG_1, bit 31 */ /* PRO_INTR_STATUS_REG_2 / APP_INTR_STATUS_REG_2 */ -#define XTENSA_IRQ_SREG2 67 -#define XTENSA_IRQ_TG1_WDT_EDGE 67 /* INTR_STATUS_REG_2, bit 0 */ -#define XTENSA_IRQ_TG1_LACT_EDGE 68 /* INTR_STATUS_REG_2, bit 1 */ -#define XTENSA_IRQ_MMU_IA 69 /* INTR_STATUS_REG_2, bit 2 */ -#define XTENSA_IRQ_MPU_IA 70 /* INTR_STATUS_REG_2, bit 3 */ -#define XTENSA_IRQ_CACHE_IA 71 /* INTR_STATUS_REG_2, bit 4 */ +#define ESP32_PERIPH_TG1_WDT_EDGE 64 /* INTR_STATUS_REG_2, bit 0 */ +#define ESP32_PERIPH_TG1_LACT_EDGE 65 /* INTR_STATUS_REG_2, bit 1 */ +#define ESP32_PERIPH_MMU_IA 66 /* INTR_STATUS_REG_2, bit 2 */ +#define ESP32_PERIPH_MPU_IA 67 /* INTR_STATUS_REG_2, bit 3 */ +#define ESP32_PERIPH_CACHE_IA 68 /* INTR_STATUS_REG_2, bit 4 */ + +/* Total number of peripherals */ + +#define NR_PERIPHERALS 69 + +/* Exceptions + * + * IRAM Offset Description + * 0x0000 Windows + * 0x0180 Level 2 interrupt + * 0x01c0 Level 3 interrupt + * 0x0200 Level 4 interrupt + * 0x0240 Level 5 interrupt + * 0x0280 Debug exception + * 0x02c0 NMI exception + * 0x0300 Kernel exception + * 0x0340 User exception + * 0x03c0 Double exception + * + * REVISIT: In more architectures supported by NuttX, exception errors + * tie into the normal interrupt handling via special IRQ numbers. I + * is still to be determined what will be done for the ESP32. + */ + +/* IRQ numbers for internal interrupts that are dispatched like peripheral + * interrupts + */ + +#define XTENSA_IRQ_TIMER0 0 /* INTERRUPT, bit 6 */ +#define XTENSA_IRQ_TIMER1 1 /* INTERRUPT, bit 15 */ +#define XTENSA_IRQ_TIMER2 2 /* INTERRUPT, bit 16 */ + +#define XTENSA_IRQ_FIRSTPERIPH 3 /* First peripheral IRQ number */ + +/* IRQ numbers for peripheral interrupts coming throught the Interrupt + * Matrix. + */ + +#define ESP32_IRQ2PERIPH(irq) ((irq)-XTENSA_IRQ_FIRSTPERIPH) + +/* PRO_INTR_STATUS_REG_0 / APP_INTR_STATUS_REG_0 */ + +#define ESP32_IRQ_MAC (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_MAC) +#define ESP32_IRQ_MAC_NMI (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_MAC_NMI) +#define ESP32_IRQ_BB (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_BB) +#define ESP32_IRQ_BB_MAC (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_BB_MAC) +#define ESP32_IRQ_BT_BB (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_BT_BB) +#define ESP32_IRQ_BT_BB_NMI (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_BT_BB_NMI) +#define ESP32_IRQ_RWBT_IRQ (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_RWBT_IRQ) +#define ESP32_IRQ_RWBLE_IRQ (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_RWBLE_IRQ) +#define ESP32_IRQ_RWBT_NMI (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_RWBT_NMI) +#define ESP32_IRQ_RWBLE_NMI (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_RWBLE_NMI) +#define ESP32_IRQ_SLC0 (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_SLC0) +#define ESP32_IRQ_SLC1 (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_SLC1) +#define ESP32_IRQ_UHCI0 (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_UHCI0) +#define ESP32_IRQ_UHCI1 (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_UHCI1) +#define ESP32_IRQ_TG_T0_LEVEL (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_TG_T0_LEVEL) +#define ESP32_IRQ_TG_T1_LEVEL (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_TG_T1_LEVEL) +#define ESP32_IRQ_TG_WDT_LEVEL (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_TG_WDT_LEVEL) +#define ESP32_IRQ_TG_LACT_LEVEL (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_TG_LACT_LEVEL) +#define ESP32_IRQ_TG1_T0_LEVEL (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_TG1_T0_LEVEL) +#define ESP32_IRQ_TG1_T1_LEVEL (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_TG1_T1_LEVEL) +#define ESP32_IRQ_TG1_WDT_LEVEL (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_TG1_WDT_LEVEL) +#define ESP32_IRQ_G1_LACT_LEVEL (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_G1_LACT_LEVEL) +#define ESP32_IRQ_CPU_GPIO (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_CPU_GPIO) +#define ESP32_IRQ_CPU_NMI (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_CPU_NMI) +#define ESP32_IRQ_CPU_CPU0 (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_CPU_CPU0) +#define ESP32_IRQ_CPU_CPU1 (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_CPU_CPU1) +#define ESP32_IRQ_CPU_CPU2 (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_CPU_CPU2) +#define ESP32_IRQ_CPU_CPU3 (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_CPU_CPU3) +#define ESP32_IRQ_SPI0 (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_SPI0) +#define ESP32_IRQ_SPI1 (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_SPI1 +#define ESP32_IRQ_SPI2 (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_SPI2) +#define ESP32_IRQ_SPI3 (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_SPI3 + +#define ESP32_IRQ_SREG0 ESP32_IRQ_MAC +#define ESP32_NIRQS_SREG0 32 + +/* PRO_INTR_STATUS_REG_1 / APP_INTR_STATUS_REG_1 */ + +#define ESP32_IRQ_I2S0 (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_I2S0) +#define ESP32_IRQ_I2S1 (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_I2S1) +#define ESP32_IRQ_UART (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_UART) +#define ESP32_IRQ_UART1 (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_UART1) +#define ESP32_IRQ_UART2 (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_UART2) +#define ESP32_IRQ_SDIO_HOST (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_SDIO_HOST) +#define ESP32_IRQ_EMAC (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_EMAC) +#define ESP32_IRQ_PWM0 (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_PWM0) +#define ESP32_IRQ_PWM1 (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_PWM1) +#define ESP32_IRQ_PWM2 (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_PWM2) +#define ESP32_IRQ_PWM3 (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_PWM3) +#define ESP32_IRQ_LEDC (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_LEDC) +#define ESP32_IRQ_EFUSE (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_EFUSE) +#define ESP32_IRQ_CAN (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_CAN) +#define ESP32_IRQ_RTC_CORE (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_RTC_CORE) +#define ESP32_IRQ_RMT (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_RMT) +#define ESP32_IRQ_PCNT (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_PCNT) +#define ESP32_IRQ_I2C_EXT0 (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_I2C_EXT0) +#define ESP32_IRQ_I2C_EXT1 (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_I2C_EXT1) +#define ESP32_IRQ_RSA (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_RSA) +#define ESP32_IRQ_SPI1_DMA (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_SPI1_DMA) +#define ESP32_IRQ_SPI2_DMA (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_SPI2_DMA) +#define ESP32_IRQ_SPI3_DMA (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_SPI3_DMA) +#define ESP32_IRQ_WDG (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_WDG) +#define ESP32_IRQ_TIMER1 (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_TIMER1) +#define ESP32_IRQ_TIMER2 (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_TIMER2) +#define ESP32_IRQ_TG_T0_EDGE (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_TG_T0_EDGE) +#define ESP32_IRQ_TG_T1_EDGE (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_TG_T1_EDGE) +#define ESP32_IRQ_TG_WDT_EDGE (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_TG_WDT_EDGE) +#define ESP32_IRQ_TG_LACT_EDGE (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_TG_LACT_EDGE) +#define ESP32_IRQ_TG1_T0_EDGE (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_TG1_T0_EDGE) +#define ESP32_IRQ_TG1_T1_EDGE (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_TG1_T1_EDGE) + +#define ESP32_IRQ_SREG1 ESP32_IRQ_I2S0 +#define ESP32_NIRQS_SREG1 32 + +/* PRO_INTR_STATUS_REG_2 / APP_INTR_STATUS_REG_2 */ + +#define ESP32_IRQ_TG1_WDT_EDGE (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_TG1_WDT_EDGE) +#define ESP32_IRQ_TG1_LACT_EDGE (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_TG1_LACT_EDGE) +#define ESP32_IRQ_MMU_IA (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_MMU_IA) +#define ESP32_IRQ_MPU_IA (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_MPU_IA) +#define ESP32_IRQ_CACHE_IA (XTENSA_IRQ_FIRSTPERIPH+ESP32_PERIPH_CACHE_IA) + +#define ESP32_IRQ_SREG2 ESP32_IRQ_TG1_WDT_EDGE +#define ESP32_NIRQS_SREG2 5 /* Total number of interrupts */ -#define NR_IRQS 72 +#define NR_IRQS (ESP32_IRQ_CACHE_IA+1) + +/* CPU Interrupts. + * + * Each of the two CPUs (PRO and APP) have 32 interrupts each, of which + * 26 can be mapped to peripheral interrupts: + * + * Level triggered peripherals (21 total): + * 0-5, 8-9, 12-13, 17-21, 23-27, 31 + * Edge triggered peripherals (4 total): + * 10, 22, 28, 30 + * NMI (1 total): + * 14 + * + * CPU peripheral interrupts can be a assigned to a CPU interrupt using the + * PRO_*_MAP_REG or APP_*_MAP_REG. There are a pair of these registers for + * each peripheral source. Multiple peripheral interrupt sources can be + * mapped to the same. + * + * The remaining, five, internal CPU interrupts are: + * + * 6 Timer0 + * 7 Software + * 15 Timer1 + * 16 Timer2 + * 29 Software + * + * A peripheral interrupt can be disabled + */ + +#define ESP32_CPUINT_LEVELPERIPH_0 0 +#define ESP32_CPUINT_LEVELPERIPH_1 1 +#define ESP32_CPUINT_LEVELPERIPH_2 2 +#define ESP32_CPUINT_LEVELPERIPH_3 3 +#define ESP32_CPUINT_LEVELPERIPH_4 4 +#define ESP32_CPUINT_LEVELPERIPH_5 5 +#define ESP32_CPUINT_LEVELPERIPH_6 8 +#define ESP32_CPUINT_LEVELPERIPH_7 9 +#define ESP32_CPUINT_LEVELPERIPH_8 12 +#define ESP32_CPUINT_LEVELPERIPH_9 13 +#define ESP32_CPUINT_LEVELPERIPH_10 17 +#define ESP32_CPUINT_LEVELPERIPH_11 18 +#define ESP32_CPUINT_LEVELPERIPH_12 19 +#define ESP32_CPUINT_LEVELPERIPH_13 20 +#define ESP32_CPUINT_LEVELPERIPH_14 21 +#define ESP32_CPUINT_LEVELPERIPH_15 23 +#define ESP32_CPUINT_LEVELPERIPH_16 24 +#define ESP32_CPUINT_LEVELPERIPH_17 25 +#define ESP32_CPUINT_LEVELPERIPH_18 26 +#define ESP32_CPUINT_LEVELPERIPH_19 27 +#define ESP32_CPUINT_LEVELPERIPH_20 31 +#define ESP32_CPUINT_NLEVELPERIPHS 21 + +#define ESP32_CPUINT_EDGEPERIPH_0 10 +#define ESP32_CPUINT_EDGEPERIPH_1 22 +#define ESP32_CPUINT_EDGEPERIPH_2 28 +#define ESP32_CPUINT_EDGEPERIPH_3 30 +#define ESP32_CPUINT_NEDGEPERIPHS 4 + +#define ESP32_CPUINT_TIMER0 6 +#define ESP32_CPUINT_SOFTWARE0 7 +#define ESP32_CPUINT_TIMER1 15 +#define ESP32_CPUINT_TIMER2 16 +#define ESP32_CPUINT_SOFTWARE1 29 +#define ESP32_CPUINT_NINTERNAL 5 + +#define ESP32_CPUINT_MAX 31 +#define EPS32_CPUINT_PERIPHSET 0xdffe7f3f +#define EPS32_CPUINT_INTERNALSET 0x200180c0 /**************************************************************************** * Public Types diff --git a/arch/xtensa/src/common/xtensa.h b/arch/xtensa/src/common/xtensa.h index fb13a8150a8..bde2eaba5f8 100644 --- a/arch/xtensa/src/common/xtensa.h +++ b/arch/xtensa/src/common/xtensa.h @@ -156,13 +156,6 @@ extern volatile uint32_t *g_current_regs[1]; #endif -/* This is the beginning of heap as provided from *_head.S. This is the - * first address in DRAM after the loaded program+bss+idle stack. The end - * of the heap is CONFIG_RAM_END - */ - -extern uint32_t g_idle_topstack; - /* Address of the saved user stack pointer */ #if CONFIG_ARCH_INTERRUPTSTACK > 3 @@ -243,6 +236,8 @@ void xtensa_dumpstate(void); uint32_t *xtensa_int_decode(uint32_t *regs); uint32_t *xtensa_irq_dispatch(int irq, uint32_t *regs); +uint32_t xtensa_enable_cpuint(uint32_t *shadow, uint32_t intmask); +uint32_t xtensa_disable_cpuint(uint32_t *shadow, uint32_t intmask); /* Software interrupt handler */ diff --git a/arch/xtensa/src/common/xtensa_cpuint.S b/arch/xtensa/src/common/xtensa_cpuint.S new file mode 100644 index 00000000000..8d5b9dd33f9 --- /dev/null +++ b/arch/xtensa/src/common/xtensa_cpuint.S @@ -0,0 +1,128 @@ +/**************************************************************************** + * arch/xtensa/src/common/xtensa_cpuint.S + * + * Adapted from use in NuttX by: + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Derives from logic originally provided by Cadence Design Systems Inc. + * + * Copyright (c) 2006-2015 Cadence Design Systems Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ****************************************************************************/ + + .file "xtensa_cpuint.S" + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "xtensa_context.h" + +#if XCHAL_HAVE_INTERRUPTS + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: xtensa_enable_cpuint + * + * C Prototype: + * uint32_t xtensa_enable_cpuint(uint32_t *shadow, unsigned int intmask) + * + * Description: + * Enables a set of interrupts. Does not simply set INTENABLE directly, + * but operates on a shadow copy of the CPU INTENABLE register then + * writes that value to the hardware INTENABLE register. Can be called + * from interrupt handlers. + * + * NOTE: It is possible only to enable interrupts on the current CPU + * because there is an INTENABLE register implemented in each CPU. + * + ****************************************************************************/ + + .text + .global xtensa_enable_cpuint + .type xtensa_enable_cpuint, @function + .align 4 + +xtensa_enable_cpuint: + + movi a4, 0 + xsr a4, INTENABLE /* Disables all interrupts */ + rsync + + l32i a4, a2, 0 /* a4 = value of INTENABLE shadow */ + or a5, a4, a3 /* a5 = shadow | mask */ + s32i a5, a2, 0 /* shadow |= mask */ + + wsr a5, INTENABLE /* Set CPU INTENABLE to shadow */ + mov a3, a4 /* Return previous shadow content */ + ret + + .size xtensa_enable_cpuint, . - xtensa_enable_cpuint + +/**************************************************************************** + * Name: xtensa_disable_cpuint + * + * C Prototype: + * uint32_t xtensa_disable_cpuint(uint32_t *shadow, unsigned int intmask) + * + * Description: + * Disables a set of interrupts. Does not simply set INTENABLE directly, + * but operates on a shadow copy of the CPU INTENABLE register then + * writes that value to the hardware INTENABLE register. Can be called + * from interrupt handlers. + * + * NOTE: It is possible only to enable interrupts on the current CPU + * because there is an INTENABLE register implemented in each CPU. + * + ****************************************************************************/ + + .text + .globa xtensa_disable_cpuint + .type xtensa_disable_cpuint, @function + .align 4 + +xtensa_disable_cpuint: + + movi a4, 0 + xsr a4, INTENABLE /* Disables all interrupts */ + rsync + + l32i a4, a2, 0 /* a4 = value of INTENABLE shadow */ + or a5, a4, a3 /* a5 = shadow | mask */ + xor a5, a5, a3 /* a5 = shadow & ~mask */ + s32i a5, a2, 0 /* shadow &= ~mask */ + + wsr a5, INTENABLE /* Set CPU INTENABLE to shadow */ + mov a3, a4 /* Return previous shadow content */ + ret + + .size xtensa_disable_cpuint, . - xtensa_disable_cpuint + +#endif /* XCHAL_HAVE_INTERRUPTS */ diff --git a/arch/xtensa/src/esp32/Make.defs b/arch/xtensa/src/esp32/Make.defs index 993965dac87..d904abdc6ca 100644 --- a/arch/xtensa/src/esp32/Make.defs +++ b/arch/xtensa/src/esp32/Make.defs @@ -44,14 +44,15 @@ CMN_ASRCS = xtensa_context.S xtensa_vectors.S xtensa_inthandlers.S CMN_ASRCS += xtensa_nmihandler.S CMN_CSRCS = xtensa_assert.c xtensa_blocktask.c xtensa_copystate.c -CMN_CSRCS += xtensa_createstack.c xtensa_exit.c xtensa_idle.c -CMN_CSRCS += xtensa_initialize.c xtensa_initialstate.c -CMN_CSRCS += xtensa_interruptcontext.c xtensa_irqdispatch.c xtensa_lowputs.c -CMN_CSRCS += xtensa_mdelay.c xtensa_modifyreg8.c xtensa_modifyreg16.c -CMN_CSRCS += xtensa_modifyreg32.c xtensa_puts.c xtensa_releasepending.c -CMN_CSRCS += xtensa_releasestack.c xtensa_reprioritizertr.c -CMN_CSRCS += xtensa_schedsigaction.c xtensa_sigdeliver.c xtensa_stackframe.c -CMN_CSRCS += xtensa_udelay.c xtensa_unblocktask.c xtensa_usestack.c +CMN_CSRCS += xtens_cpuint.c xtensa_createstack.c xtensa_exit.c +CMN_CSRCS += xtensa_idle.c xtensa_initialize.c xtensa_initialstate.c +CMN_CSRCS += xtensa_interruptcontext.c xtensa_irqdispatch.c +CMN_CSRCS += xtensa_lowputs.c xtensa_mdelay.c xtensa_modifyreg8.c +CMN_CSRCS += xtensa_modifyreg16.c xtensa_modifyreg32.c xtensa_puts.c +CMN_CSRCS += xtensa_releasepending.c xtensa_releasestack.c +CMN_CSRCS += xtensa_reprioritizertr.c xtensa_schedsigaction.c +CMN_CSRCS += xtensa_sigdeliver.c xtensa_stackframe.c xtensa_udelay.c +CMN_CSRCS += xtensa_unblocktask.c xtensa_usestack.c # Configuration-dependent common XTENSA files @@ -77,8 +78,8 @@ endif # Required ESP32 files (arch/xtensa/src/lx6) CHIP_ASRCS = -CHIP_CSRCS = esp32_allocateheap.c esp32_intdecode.c esp32_irq.c -CHIP_CSRCS += esp32_region.c esp32_start.c esp32_timerisr.c +CHIP_CSRCS = esp32_allocateheap.c esp32_cpuint.c esp32_intdecode.c +CHIP_CSRCS += esp32_irq.c esp32_region.c esp32_start.c esp32_timerisr.c # Configuration-dependent ESP32 files diff --git a/arch/xtensa/src/esp32/esp32_cpuint.c b/arch/xtensa/src/esp32/esp32_cpuint.c new file mode 100644 index 00000000000..119e9917e24 --- /dev/null +++ b/arch/xtensa/src/esp32/esp32_cpuint.c @@ -0,0 +1,303 @@ +/**************************************************************************** + * arch/xtensa/src/esp32/esp32_irq.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include + +#include "xtensa.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ESP32_INTSET(n) ((1 << (n)) - 1) +#define ESP32_LEVEL_SET ESP32_INTSET(ESP32_CPUINT_NLEVELPERIPHS) +#define ESP32_EDGE_SET ESP32_INTSET(ESP32_CPUINT_NEDGEPERIPHS) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* g_intenable[] is a shadow copy of the per-CPU INTENABLE register + * content. + */ + +#ifdef CONFIG_SMP + +static uint32_t *g_intenable[CONFIG_SMP_NCPUS]; + +#else + +static uint32_t *g_intenable[1]; + +#endif + +/* Bitsets for free, unallocated CPU interrupts */ + +status uint32_t g_level_ints = ESP32_LEVEL_SET; +status uint32_t g_edge_ints = ESP32_EDGE_SET; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_disable_irq + * + * Description: + * Disable the CPU interrupt specified by 'cpuint' + * + ****************************************************************************/ + +void up_disable_irq(int cpuint) +{ +#ifdef CONFIG_SMP + int cpu; +#endif + + DEBUGASSERT(cpuint >= 0 && cpuint <= ESP32_CPUINT_MAX); + +#ifdef CONFIG_SMP + cpu = up_cpu_index(); + (void)xtensa_disable_cpuint(&g_intenable[cpu], (1ul << cpuint)) +#else + (void)xtensa_disable_cpuint(&g_intenable[0], (1ul << cpuint)) +#endif +} + +/**************************************************************************** + * Name: up_enable_irq + * + * Description: + * Ensable the CPU interrupt specified by 'cpuint' + * + ****************************************************************************/ + +void up_enable_irq(int cpuint) +{ +#ifdef CONFIG_SMP + int cpu; +#endif + + DEBUGASSERT(cpuint >= 0 && cpuint <= ESP32_CPUINT_MAX); + +#ifdef CONFIG_SMP + cpu = up_cpu_index(); + (void)xtensa_enable_cpuint(&g_intenable[cpu], (1ul << cpuint)) +#else + (void)xtensa_enable_cpuint(&g_intenable[0], (1ul << cpuint)) +#endif +} + +/**************************************************************************** + * Name: esp32_alloc_levelint + * + * Description: + * Allocate a level CPU interrupt + * + * Input Parameters: + * None + * + * Returned Value: + * On success, the allocated level-sensitive, CPU interrupt numbr is + * returned. A negated errno is returned on failure. The only possible + * failure is that all level-sensitive CPU interrupts have already been + * allocated. + * + ****************************************************************************/ + +int esp32_alloc_levelint(void) +{ + irqstate_t flags; + uint32_t mask; + int cpuint; + int ret = -ENOMEM; + + /* Check if there are any level CPU interrupts available */ + + flags = enter_critical_section(); + if ((g_level_ints & ESP32_LEVEL_SET) != 0) + { + /* Search for an unallocated CPU interrupt number in g_level_ints. */ + + for (cpuint = 0; cpuint < ESP32_CPUINT_NLEVELPERIPHS; cpuint++) + { + /* If the bit corresponding to the CPU interrupt is '1', then + * that CPU interrupt is available. + */ + + mask = (1ul << cpuint); + if ((g_level_ints & mask) != 0) + { + /* Got it! */ + + g_level_ints &= ~mask; + ret = cpuint; + break; + } + } + } + + leave_critical_section(flags); + return ret; +} + +/**************************************************************************** + * Name: esp32_free_levelint + * + * Description: + * Free a previoulsy allocated level CPU interrupt + * + * Input Parameters: + * The CPU interrupt number to be freed + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32_free_levelint(int cpuint) +{ + irqstate_t flags; + uint32_t mask; + + DEBUGASSERT(cpuint >= 0 && cpuint < ESP32_CPUINT_NLEVELPERIPHS); + + /* Mark the CPU interrupt as available */ + + mask = (1ul << cpuint); + flags = enter_critical_section(); + DEBUGASSERT((g_level_ints & mask) == 0); + g_level_ints |= mask; + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: esp32_alloc_edgeint + * + * Description: + * Allocate an edge CPU interrupt + * + * Input Parameters: + * None + * + * Returned Value: + * On success, the allocated edge-sensitive, CPU interrupt numbr is + * returned. A negated errno is returned on failure. The only possible + * failure is that all edge-sensitive CPU interrupts have already been + * allocated. + * + ****************************************************************************/ + +int esp32_alloc_edgeint(void) +{ + irqstate_t flags; + uint32_t mask; + int cpuint; + int ret = -ENOMEM; + + /* Check if there are any level CPU interrupts available */ + + flags = enter_critical_section(); + if ((g_edge_ints & ESP32_EDGE_SET) != 0) + { + /* Search for an unallocated CPU interrupt number in g_edge_ints. */ + + for (cpuint = 0; cpuint < ESP32_CPUINT_NEDGEPERIPHS; cpuint++) + { + /* If the bit corresponding to the CPU interrupt is '1', then + * that CPU interrupt is available. + */ + + mask = (1ul << cpuint); + if ((g_edge_ints & mask) != 0) + { + /* Got it! */ + + g_edge_ints &= ~mask; + ret = cpuint; + break; + } + } + } + + leave_critical_section(flags); + return ret; +} + +/**************************************************************************** + * Name: esp32_free_edgeint + * + * Description: + * Free a previoulsy allocated edge CPU interrupt + * + * Input Parameters: + * The CPU interrupt number to be freed + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32_free_edgeint(int cpuint) +{ + irqstate_t flags; + uint32_t mask; + + DEBUGASSERT(cpuint >= 0 && cpuint < ESP32_CPUINT_NEDGEPERIPHS); + + /* Mark the CPU interrupt as available */ + + mask = (1ul << cpuint); + flags = enter_critical_section(); + DEBUGASSERT((g_edge_ints & mask) == 0); + g_edge_ints |= mask; + leave_critical_section(flags); +} diff --git a/arch/xtensa/src/esp32/esp32_cpuint.h b/arch/xtensa/src/esp32/esp32_cpuint.h new file mode 100644 index 00000000000..79aa852096a --- /dev/null +++ b/arch/xtensa/src/esp32/esp32_cpuint.h @@ -0,0 +1,119 @@ +/**************************************************************************** + * arch/xtensa/src/esp32/esp32_cpuint.h + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __ARCH_XTENSA_SRC_ESP32_ESP32_CPUINT_H +#define __ARCH_XTENSA_SRC_ESP32_ESP32_CPUINT_H 1 + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: esp32_alloc_levelint + * + * Description: + * Allocate a level CPU interrupt + * + * Input Parameters: + * None + * + * Returned Value: + * On success, the allocated level-sensitive, CPU interrupt numbr is + * returned. A negated errno is returned on failure. The only possible + * failure is that all level-sensitive CPU interrupts have already been + * allocated. + * + ****************************************************************************/ + +int esp32_alloc_levelint(void); + +/**************************************************************************** + * Name: esp32_free_levelint + * + * Description: + * Free a previoulsy allocated level CPU interrupt + * + * Input Parameters: + * The CPU interrupt number to be freed + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32_free_levelint(int cpuint); + +/**************************************************************************** + * Name: esp32_alloc_edgeint + * + * Description: + * Allocate an edge CPU interrupt + * + * Input Parameters: + * None + * + * Returned Value: + * On success, the allocated edge-sensitive, CPU interrupt numbr is + * returned. A negated errno is returned on failure. The only possible + * failure is that all edge-sensitive CPU interrupts have already been + * allocated. + * + ****************************************************************************/ + +int esp32_alloc_edgeint(void); + +/**************************************************************************** + * Name: esp32_free_edgeint + * + * Description: + * Free a previoulsy allocated edge CPU interrupt + * + * Input Parameters: + * The CPU interrupt number to be freed + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32_free_edgeint(int cpuint); + +#endif /* __ARCH_XTENSA_SRC_ESP32_ESP32_CPUINT_H */ diff --git a/arch/xtensa/src/esp32/esp32_cpustart.c b/arch/xtensa/src/esp32/esp32_cpustart.c index 038a2851c2a..1f4a6d4c015 100644 --- a/arch/xtensa/src/esp32/esp32_cpustart.c +++ b/arch/xtensa/src/esp32/esp32_cpustart.c @@ -83,6 +83,20 @@ static inline void xtensa_registerdump(FAR struct tcb_s *tcb) # define xtensa_registerdump(tcb) #endif +/**************************************************************************** + * Name: xtensa_disable_all + ****************************************************************************/ + +static inline void xtensa_disable_all(void) +{ + __asm__ __volatile__ + ( + "movi a2, 0\n" + "xsr a2, INTENABLE\n" + : : : "a2" + ); +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -127,6 +141,13 @@ int xtensa_start_handler(int irq, FAR void *context) esp32_region_protection(); + /* Disable all PRO CPU interrupts */ + + xtensa_disable_all(); + + /* Disable peripheral sources from all PRO CPU interrupt */ +#warning Missing logic + /* Dump registers so that we can see what is going to happen on return */ xtensa_registerdump(tcb); diff --git a/arch/xtensa/src/esp32/esp32_intdecode.c b/arch/xtensa/src/esp32/esp32_intdecode.c index 5490e614e36..e316274f4b8 100644 --- a/arch/xtensa/src/esp32/esp32_intdecode.c +++ b/arch/xtensa/src/esp32/esp32_intdecode.c @@ -44,6 +44,24 @@ #include "chip/esp32_dport.h" #include "xtensa.h" +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const uint8_t g_baseirq[3] = +{ + ESP32_IRQ_SREG0, + ESP32_IRQ_SREG1, + ESP32_IRQ_SREG2 +}; + +static const uint8_t g_nirqs[3] = +{ + ESP32_NIRQS_SREG0, + ESP32_NIRQS_SREG1, + ESP32_NIRQS_SREG2 +}; + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -94,19 +112,23 @@ uint32_t *xtensa_int_decode(uint32_t *regs) * registers. */ - for (regndx = 0, baseirq = XTENSA_IRQ_SREG0; - regndx < 3; - regndx++, baseirq += 32, regaddr += sizeof(uint32_t)) + for (regndx = 0; regndx < 3; regndx++) { /* Fetch the next register status register */ - regval = getreg32(regaddr); + regval = getreg32(regaddr); + regaddr += sizeof(uint32_t); + + /* Set up the search */ + + baseirq = g_baseirq[regndx]; + nirqs = g_nirqs[regndx] /* Decode and dispatch each pending bit in the interrupt status * register. */ - for (bit = 0; regval != 0 && bit < 32; bit++) + for (bit = 0; regval != 0 && bit < nirqs; bit++) { /* Check if this interrupt is pending */ diff --git a/arch/xtensa/src/esp32/esp32_irq.c b/arch/xtensa/src/esp32/esp32_irq.c index d5cf4b552a4..6394beb8e10 100644 --- a/arch/xtensa/src/esp32/esp32_irq.c +++ b/arch/xtensa/src/esp32/esp32_irq.c @@ -48,10 +48,6 @@ #include "xtensa.h" -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - /**************************************************************************** * Public Data ****************************************************************************/ @@ -62,8 +58,19 @@ * CURRENT_REGS for portability. */ +#ifdef CONFIG_SMP +/* For the case of architectures with multiple CPUs, then there must be one + * such value for each processor that can receive an interrupt. + */ + +volatile uint32_t *g_current_regs[CONFIG_SMP_NCPUS]; + +#else + volatile uint32_t *g_current_regs[1]; +#endif + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -89,6 +96,20 @@ static void esp32_irq_dump(const char *msg, int irq) # define esp32_irq_dump(msg, irq) #endif +/**************************************************************************** + * Name: xtensa_disable_all + ****************************************************************************/ + +static inline void xtensa_disable_all(void) +{ + __asm__ __volatile__ + ( + "movi a2, 0\n" + "xsr a2, INTENABLE\n" + : : : "a2" + ); +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -99,7 +120,11 @@ static void esp32_irq_dump(const char *msg, int irq) void xtensa_irq_initialize(void) { - /* Disable all interrupts */ + /* Disable all PRO CPU interrupts */ + + xtensa_disable_all(); + + /* Disable peripheral sources from all PRO CPU interrupt */ #warning Missing logic #if defined(CONFIG_STACK_COLORATION) && CONFIG_ARCH_INTERRUPTSTACK > 3 @@ -111,72 +136,14 @@ void xtensa_irq_initialize(void) /* Set all interrupts (and exceptions) to the default priority */ #warning Missing logic - /* Attach all other processor exceptions (except reset and sys tick) */ + /* Attach all processor exceptions */ #warning Missing logic esp32_irq_dump("initial", NR_IRQS); #ifndef CONFIG_SUPPRESS_INTERRUPTS - /* And finally, enable interrupts */ up_irq_enable(); #endif } - -/**************************************************************************** - * Name: up_disable_irq - * - * Description: - * Disable the IRQ specified by 'irq' - * - ****************************************************************************/ - -void up_disable_irq(int irq) -{ -#warning Missing logic -} - -/**************************************************************************** - * Name: up_enable_irq - * - * Description: - * Enable the IRQ specified by 'irq' - * - ****************************************************************************/ - -void up_enable_irq(int irq) -{ -#warning Missing logic -} - -/**************************************************************************** - * Name: up_ack_irq - * - * Description: - * Acknowledge the IRQ - * - ****************************************************************************/ - -void up_ack_irq(int irq) -{ -} - -/**************************************************************************** - * Name: up_prioritize_irq - * - * Description: - * Set the priority of an IRQ. - * - * Since this API is not supported on all architectures, it should be - * avoided in common implementations where possible. - * - ****************************************************************************/ - -#ifdef CONFIG_ARCH_IRQPRIO -int up_prioritize_irq(int irq, int priority) -{ -#warning Missing logic - return OK; -} -#endif diff --git a/arch/xtensa/src/esp32/esp32_timerisr.c b/arch/xtensa/src/esp32/esp32_timerisr.c index b5a7871ae49..f809fb45d92 100644 --- a/arch/xtensa/src/esp32/esp32_timerisr.c +++ b/arch/xtensa/src/esp32/esp32_timerisr.c @@ -51,6 +51,14 @@ #include "xtensa_timer.h" #include "xtensa.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#if XT_TIMER_INTEN != ESP32_CPUINT_TIMER0 +# error Mismatch in irq.h and xtensa_timer.h +#endif + /**************************************************************************** * Private data ****************************************************************************/ @@ -62,8 +70,7 @@ static uint32_t g_tick_divisor; ****************************************************************************/ /**************************************************************************** - * Function: xtensa_getcount, xtensa_getcompare, xtensa_setcompare, and - * xtensa_enable_timer + * Function: xtensa_getcount, xtensa_getcompare, and xtensa_setcompare * * Description: * Lower level operations on Xtensa special registers. @@ -108,22 +115,6 @@ static inline void xtensa_setcompare(uint32_t compare) ); } -/* Enable the timer interrupt. NOTE: This is non-atomic but safe in this - * context because this occurs early in the initialization sequence. - */ - -static inline void xtensa_enable_timer(void) -{ - __asm__ __volatile__ - ( - "movi a3, %0\n" - "rsr a2, INTENABLE\n" - "or a2, a2, a3\n" - "wsr a2, INTENABLE\n" - : : "I"(XT_TIMER_INTEN) : "a2", "a3" - ); -} - /**************************************************************************** * Function: esp32_timerisr * @@ -212,9 +203,7 @@ void xtensa_timer_initialize(void) (void)irq_attach(XTENSA_IRQ_TIMER0, (xcpt_t)esp32_timerisr); - /* Enable the timer interrupt at the device level. NOTE: It is un-necessary - * to call up_enable_irq() for timers. - */ + /* Enable the timer 0 CPU interrupt. */ - xtensa_enable_timer(); + up_enable_irq(ESP32_CPUINT_TIMER0); }