espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
13.06k stars 7.14k forks source link

[ESP32S3] v4.4 Interrupt mapping mismatch with reference manual (IDFGH-11724) #12832

Open KonssnoK opened 7 months ago

KonssnoK commented 7 months ago

Answers checklist.

General issue report

Hello, following the issue https://github.com/espressif/esp-idf/issues/12830

i started looking at documentation and code for the 32 theoretic interrupts available PER CORE in ESP32-S3

in the doc it is pretty straight-forward: https://www.espressif.com/sites/default/files/documentation/esp32-s3_technical_reference_manual_en.pdf

image

If it is not reserved, it s a level-triggered interrupt.

In the code instead: interrupt_descriptor_table.c

const static int_desc_t interrupt_descriptor_table [32]={
    { 1, INTTP_LEVEL, {INTDESC_RESVD,  INTDESC_RESVD } }, //0
    { 1, INTTP_LEVEL, {INTDESC_RESVD,  INTDESC_RESVD } }, //1
    { 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //2
    { 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //3
    { 1, INTTP_LEVEL, {INTDESC_RESVD,  INTDESC_NORMAL} }, //4
    { 1, INTTP_LEVEL, {INTDESC_RESVD,  INTDESC_RESVD } }, //5
    { 1, INTTP_NA,    {INT6RES,        INT6RES       } }, //6
    { 1, INTTP_NA,    {INTDESC_SPECIAL,INTDESC_SPECIAL}}, //7
    { 1, INTTP_LEVEL, {INTDESC_RESVD,  INTDESC_RESVD } }, //8
    { 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //9
    { 1, INTTP_EDGE , {INTDESC_NORMAL, INTDESC_NORMAL} }, //10
    { 3, INTTP_NA,    {INTDESC_SPECIAL,INTDESC_SPECIAL}}, //11
    { 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //12
    { 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //13
    { 7, INTTP_LEVEL, {INTDESC_RESVD,  INTDESC_RESVD } }, //14, NMI
    { 3, INTTP_NA,    {INT15RES,       INT15RES      } }, //15
    { 5, INTTP_NA,    {INTDESC_SPECIAL,INTDESC_SPECIAL} }, //16
    { 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //17
    { 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //18
    { 2, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //19
    { 2, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //20
    { 2, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //21
    { 3, INTTP_EDGE,  {INTDESC_RESVD,  INTDESC_NORMAL} }, //22
    { 3, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //23
    { 4, INTTP_LEVEL, {INTDESC_RESVD,  INTDESC_NORMAL} }, //24
    { 4, INTTP_LEVEL, {INTDESC_RESVD,  INTDESC_RESVD } }, //25
    { 5, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_RESVD } }, //26
    { 3, INTTP_LEVEL, {INTDESC_RESVD,  INTDESC_RESVD } }, //27
    { 4, INTTP_EDGE,  {INTDESC_NORMAL, INTDESC_NORMAL} }, //28
    { 3, INTTP_NA,    {INTDESC_SPECIAL,INTDESC_SPECIAL}}, //29
    { 4, INTTP_EDGE,  {INTDESC_RESVD,  INTDESC_RESVD } }, //30
    { 5, INTTP_LEVEL, {INTDESC_RESVD,  INTDESC_RESVD } }, //31
};

both EDGE and LEVEL interrupts are defined. I am used to chipset having a register to define if an interrupts should be level or edge, but the esp32s3 doesn t seems to have one.

What is the truth? Is the documentation wrong or is the code a copypaste from the code of esp32 ?

Thanks

ESP-Marius commented 7 months ago

@KonssnoK Hi, you are right that these tables do indeed contain some information that is no longer correct on later chips.

Cleaning this up is a high-priority task in our backlog and we should get to it soon. I'll make sure to link and close this issue as well when we create that fix.

KonssnoK commented 7 months ago

hello @ESP-Marius , could you give a us a preview with the correct table for esp32s3 core0?

we are currently blocked because updating the master branch of v4.4 consumed an additional interrupt which we didnt expect.

Or at least tell us if there are more level-trigger interrupts available, like 10, 22.

KonssnoK commented 7 months ago

This would be the table according to the technical reference manual

//This is basically a software-readable version of the interrupt usage table in include/soc/soc.h
const static int_desc_t interrupt_descriptor_table [32]={
    { 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //0
    { 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //1
    { 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //2
    { 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //3
    { 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //4
    { 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //5
    { 1, INTTP_NA,    {INT6RES,        INT6RES       } }, //6
    { 1, INTTP_NA,    {INTDESC_SPECIAL,INTDESC_SPECIAL}}, //7
    { 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL } }, //8
    { 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //9
    { 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //10
    { 3, INTTP_NA,    {INTDESC_SPECIAL,INTDESC_SPECIAL}}, //11
    { 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //12
    { 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //13
    { 7, INTTP_LEVEL, {INTDESC_RESVD,  INTDESC_RESVD } }, //14, NMI
    { 3, INTTP_NA,    {INT15RES,       INT15RES      } }, //15
    { 5, INTTP_NA,    {INTDESC_SPECIAL,INTDESC_SPECIAL}}, //16
    { 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //17
    { 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //18
    { 2, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //19
    { 2, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //20
    { 2, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //21
    { 3, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //22
    { 3, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //23
    { 4, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //24
    { 4, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //25
    { 5, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //26
    { 3, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //27
    { 4, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //28
    { 3, INTTP_NA,    {INTDESC_SPECIAL,INTDESC_SPECIAL}}, //29
    { 4, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //30
    { 5, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //31
};

EDIT: apparently the CORE1 has int0 1 as reserved, the wifi doesn't work if they are used for peripherals.

This means that both the document and the code are wrong..

KonssnoK commented 7 months ago

New table based on soc.h

Please note that in this table, the amount of interrupts that can be allocated with intr_alloc is the same as the original table, which means you cannot allocate more than 11 interrupts (-3 for RTOS, -2 for WDT). Basically the customer has 6 interrupts (out of 32) available on core0


//This is basically a software-readable version of the interrupt usage table in include/soc/soc.h
const static int_desc_t interrupt_descriptor_table [32]={
    { 1, INTTP_LEVEL, {INTDESC_RESVD,  INTDESC_RESVD } }, //0  WMAC                    Reserved
    { 1, INTTP_LEVEL, {INTDESC_RESVD,  INTDESC_RESVD } }, //1  BT/BLE Host HCI DMA     BT/BLE Host HCI DMA
    { 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //2
    { 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //3
    { 1, INTTP_LEVEL, {INTDESC_RESVD,  INTDESC_NORMAL} }, //4  WBB
    { 1, INTTP_LEVEL, {INTDESC_RESVD,  INTDESC_RESVD } }, //5  BT/BLE Controller       BT/BLE Controller
    { 1, INTTP_NA,    {INT6RES,        INT6RES       } }, //6  FreeRTOS Tick(L1)       FreeRTOS Tick(L1)
    { 1, INTTP_NA,    {INTDESC_SPECIAL,INTDESC_SPECIAL}}, //7  BT/BLE VHCI             BT/BLE VHCI
    { 1, INTTP_LEVEL, {INTDESC_RESVD,  INTDESC_RESVD } }, //8  BT/BLE BB(RX/TX)        BT/BLE BB(RX/TX)
    { 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //9
    { 1, INTTP_EDGE,  {INTDESC_NORMAL, INTDESC_NORMAL} }, //10
    { 3, INTTP_NA,    {INTDESC_SPECIAL,INTDESC_SPECIAL}}, //11
    { 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //12
    { 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //13
    { 7, INTTP_LEVEL, {INTDESC_RESVD,  INTDESC_RESVD } }, //14 NMI Reserved                Reserved
    { 3, INTTP_NA,    {INT15RES,       INT15RES      } }, //15 FreeRTOS Tick(L3)       FreeRTOS Tick(L3)
    { 5, INTTP_NA,    {INTDESC_SPECIAL,INTDESC_SPECIAL}}, //16
    { 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //17
    { 1, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //18
    { 2, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //19
    { 2, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //20
    { 2, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //21
    { 3, INTTP_EDGE , {INTDESC_NORMAL, INTDESC_NORMAL} }, //22
    { 3, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //23
    { 4, INTTP_LEVEL, {INTDESC_RESVD,  INTDESC_NORMAL} }, //24 TG1_WDT
    { 4, INTTP_LEVEL, {INTDESC_RESVD,  INTDESC_NORMAL} }, //25 CACHEERR
    { 5, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //26
    { 3, INTTP_LEVEL, {INTDESC_RESVD,  INTDESC_RESVD } }, //27 Reserved                Reserved
    { 4, INTTP_EDGE,  {INTDESC_RESVD,  INTDESC_RESVD } }, //28 IPC_ISR                 IPC_ISR
    { 3, INTTP_NA,    {INTDESC_SPECIAL,INTDESC_SPECIAL}}, //29 Reserved                Reserved
    { 4, INTTP_EDGE,  {INTDESC_RESVD,  INTDESC_RESVD } }, //30 Reserved                Reserved
    { 5, INTTP_LEVEL, {INTDESC_NORMAL, INTDESC_NORMAL} }, //31
};
KonssnoK commented 6 months ago

is there any update on this issue?

igrr commented 6 months ago

Just 2c, I think the TRM might be incorrect here, considering these definitions — they were auto-generated at the time the CPU was configured, and it's unlikely there is a mistake there.

Sharing the interrupts between multiple peripherals is probably the best option to try if you are running out of interrupts. For more info, please see this section of the docs: https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/system/intr_alloc.html#troubleshooting-interrupt-allocation.

KonssnoK commented 6 months ago

Just 2c, I think the TRM might be incorrect here, considering these definitions — they were auto-generated at the time the CPU was configured, and it's unlikely there is a mistake there.

Sharing the interrupts between multiple peripherals is probably the best option to try if you are running out of interrupts. For more info, please see this section of the docs: https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/system/intr_alloc.html#troubleshooting-interrupt-allocation.

sharing interrupts becomes difficult when we use a lot of esp-idf components. All these components use interrupts which are not set as shared, and to change this we need to touch esp-idf. The quickest way we have to solve the issue we currently face is to revert part of your changes that take exclusive interrupts for SPI event when they are not necessary.

Here is a list of our interrupts, to show that we don t really have much custom stuff:

 (cpu 0)    ETS_SYSTIMER_TARGET2_EDGE_INTR_SOURCE       freeRTOS
 (cpu 0)    ETS_FROM_CPU_INTR0_SOURCE                   freeRTOS
 (cpu 0)    ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE       freeRTOS
 (cpu 1)    ETS_FROM_CPU_INTR1_SOURCE                   freeRTOS
 (cpu 1)    ETS_SYSTIMER_TARGET1_EDGE_INTR_SOURCE       freeRTOS
 (cpu 0)    ETS_TG0_WDT_LEVEL_INTR_SOURCE               esp_task_wdt_init
 (cpu 0)    ETS_GPIO_INTR_SOURCE                        gpio_isr_register   gpio_install_isr_service
 (cpu 0)    ETS_I2C_EXT0_INTR_SOURCE                    i2c
 (cpu 0)    ETS_DMA_IN_CH0_INTR_SOURCE                  metering_init -> custom
 (cpu 0)    ETS_SPI3_INTR_SOURCE                        NAND spi interrupt -> not used
 (cpu 0)    ETS_DMA_OUT_CH2_INTR_SOURCE                 NAND DMA
 (cpu 0)    ETS_DMA_IN_CH3_INTR_SOURCE                  NAND DMA
 (cpu 0)    ETS_RTC_CORE_INTR_SOURCE                    rtc_isr_register    esp_xt_wdt_init     startup
 (cpu 1)    ETS_UART1_INTR_SOURCE                       esp_modem
 (cpu 1)    ETS_UART1_INTR_SOURCE                       esp_modem
KonssnoK commented 6 months ago

in alternative we will have to try to allocate more interrupts on the second core, but that is more architecturally demanding

Also please note that the esp-idf drivers do not allow allocation of interrupts higher than level 3, meaning that some available interrupts are not actually used.

KonssnoK commented 6 months ago

Any update on this? we had to solve by creating a CORE1 init task that initializes part of our system putting interrupts on CORE1

Dazza0 commented 6 months ago

@KonssnoK

What is the truth? Is the documentation wrong or is the code a copypaste from the code of esp32 ?

In this case, the soc.h is the source of truth regarding level vs edge triggered interrupts on the ESP32-S3. The XCHAL_INTTYPE_MASK_EXTERN_EDGE bit mask indicates which of the 32 interrupts on the Xtensa core are edge triggered. This mask matches the information in soc.h. I'll pend a fix for the TRM.

Also please note that the esp-idf drivers do not allow allocation of interrupts higher than level 3, meaning that some available interrupts are not actually used.

This is intentional. On Xtensa arch ESP32 targets, critical sections do not mask out interrupts higher than level 3. Thus they are reserved for either low latency user interrupts written in assembly or internal system use.

Any update on this? we had to solve by creating a CORE1 init task that initializes part of our system putting interrupts on CORE1

If you are unable to share interrupts between various drivers/system services, then this will be the only solution.

However, sharing interrupts between drivers/system services is the easier option. Some system services (e.g., TWDT) won't share interrupts due to latency reasons. However, most drivers can be configured to share interrupts on install. Look for the intr_alloc_flags argument passed to the driver's install function. Setting the ESP_INTR_FLAG_SHARED flag will instruct the driver to use a shared interrupt.

For example

#include "esp_intr_alloc.h"
#include "driver/uart.h"
#include "driver/i2c.h

uart_driver_install(..., intr_alloc_flags=ESP_INTR_FLAG_SHARED, ...);

i2c_driver_install(..., intr_alloc_flags=ESP_INTR_FLAG_SHARED, ...);
KonssnoK commented 6 months ago

thanks @Dazza0 , we will look into the shared interrupts, but the main focus of the issue is on knowing with certainty which are the interrupts of the device we have in production. As said in my previous post, the allocation of the interrupts is solved for now, distributing to the second core some of the allocations.

o-marshmallow commented 3 weeks ago

Hello @KonssnoK ,

This has been fixed on master, the interrupt types and usage are now correct for all the chips, including the ESP32-S3. Please check this file: https://github.com/espressif/esp-idf/blob/master/components/esp_hw_support/port/esp32s3/esp_cpu_intr.c

KonssnoK commented 3 weeks ago

thanks @o-marshmallow , i'll check it out. I expect this to be propagated to all branches including 4.4, please let me know if not.