Closed EricNRS closed 1 day ago
@sylvioalves
As a temporary work-around to continue development, I have enabled level 2 interrupts for the WiFI using this patch:
commit 19b1cdd240e5f9453a8589ad8bf2609384cd9796 (HEAD)
Author: Eric Holmberg <eric.holmberg@northriversystems.co.nz>
Date: Mon Jun 17 01:08:22 2024 +1200
esp-hal-components: allow WiFi interrupt to use either level 1 or level 2
Level 1 interrupts are failing to register, so enable level 2 interrupts
while original failure is investigated.
Fixes #74368
Signed-off-by: Eric Holmberg <eric.holmberg@northriversystems.co.nz>
diff --git a/components/esp_timer/src/esp_timer_impl_systimer.c b/components/esp_timer/src/esp_timer_impl_systimer.c
index df379a198f..f2581a20ba 100644
--- a/components/esp_timer/src/esp_timer_impl_systimer.c
+++ b/components/esp_timer/src/esp_timer_impl_systimer.c
@@ -154,7 +154,7 @@ esp_err_t esp_timer_impl_early_init(void)
esp_err_t esp_timer_impl_init(intr_handler_t alarm_handler)
{
- int isr_flags = ((1 << 1) & ESP_INTR_FLAG_LEVELMASK)
+ int isr_flags = ((1 << 1 | 1 << 2) & ESP_INTR_FLAG_LEVELMASK)
#if !SOC_SYSTIMER_INT_LEVEL
| ESP_INTR_FLAG_EDGE
#endif
@@ -163,6 +163,7 @@ esp_err_t esp_timer_impl_init(intr_handler_t alarm_handler)
esp_err_t err = esp_intr_alloc(ETS_SYSTIMER_TARGET2_EDGE_INTR_SOURCE, isr_flags,
(ISR_HANDLER)timer_alarm_isr, NULL, NULL);
if (err != ESP_OK) {
+ __ASSERT(0, "esp_intr_alloc failed (0x%x)", err);
ESP_EARLY_LOGE(TAG, "esp_intr_alloc failed (0x%x)", err);
return err;
}
@EricNRS, let me check something in wifi driver that could be related to this..
I've encountered the same issue also within the sample/net/wifi
example by only enabeling the DMA.
add CONFIG_DMA=y
to the prj.conf
and enable the DMA in the dt overlay.
The patch from @EricNRS also fixes it.
Not sure if it is the same issue but even with the patch applied I still could not connect to wifi in my custom application. There I allocated an additional interrupt and forgot to specify the interrupt priority. e.g.
esp_intr_alloc(cfg->irq_source,
0, < ----------
(intr_handler_t)video_esp32_irq_handler,
(void *)dev,
NULL);
Specifying any Interrupt level there (e.g. ESP_INTR_FLAG_LEVEL4
) seems to fix it again.
I more or less copied that from the uart_esp32 driver where it also allocates an interrupt without specifying a priority level. (at least when not in async mode)
I keep stumbling over this problem...
By digging in to it I came across the interrupt_descriptor_table.
Looks like I'm running out of interrupt slots.
However, can someone explain me why almost half of the Pheripheral interrupts are marked as reserved? (e.g. INTDESC_RESVD
)
Reserved by what?
from hal/esp32s3/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
};
When DMA is enabled, it takes at least 6 (up to 10) interrupt slots for all of its rx/tx channels.
In my application I only need one rx channel though.
What ended up working for me is to configure all DMA Channel interrupts to share the same interrupt slot by setting the ESP_INTR_FLAG_SHARED
flag when allocating the interrupts in the dma_esp32_gdma driver.
Are you on an older version of Zephyr? I show interrupt_descriptor_table.c
and interrupt_descriptor_table
as only being in IDF 4.x and not in the latest v5.1 version.
You're right. I was on zephyr 3.6.0.
In the latest hal shipping with 3.7.0-rc1 the table moved to components/esp_hw_support/cpu.c
.
https://github.com/zephyrproject-rtos/hal_espressif/blob/snapshot/1/components/esp_hw_support/cpu.c#L181
However, the issue persists and there are still almost half of all slots marked as "reserved".
@epc-ake - FYI, you may not want to use LEVEL4 interrupts. I ran across this issue which if still relevant, implies that anything higher than XCHAL_EXCM_LEVEL (which is 3) may cause corruption of the stack during window exceptions.
@epc-ake DMA issue is being handled in another PR.
Describe the bug Once 6 other peripheral interrupts are installed, the WiFi "timer_alarm_isr" interrupt allocation fails resulting in loss of WiFi functionality.
Without the watchdog enabled, the WiFi timer interrupt "timer_alarm_isr" is correctly allocated.
With watchdog enabled, WiFi timer ISR fails and is not in the allocation table:
Here is the GDB screenshot showing that the failure is caused by the interrupt controller failing to get an interrupt from the call to
get_available_int()
.To Reproduce On ESP32-S3 WiFi sample, enable additional peripherals. I have enabled:
I have shared an updated version of the interrupt registration patch that was originally shared in the discussion at https://discord.com/channels/720317445772017664/1211822589081550878/1219766247051235449
After booting the system use GDB and enter the following commands to dump the registered interrupts:
Expected behavior Interrupt registration should be successful since there are more interrupts slots available per Table 9-2 in the ESP32-S3 TRM version 1.4.
Impact Functionality loss of either the watchdog or WiFi in this case. [0001-DEBUG-log-interrupt.patch](https://github.com/user-attachments/files/15858065/0001-DEBUG-log-interrupt.patch) Additional context Zephyr v3.6.99 at commit d78a9429450f89de7829c8af7efe41fdb692fd50.