From 621afc48b19662de608738dcc6b6dc1384c02b46 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 22 May 2023 20:57:31 +0200 Subject: [PATCH] feat(system): add esp_intr_dump function to debug interrupt alloc esp_intr_dump function can be used to print the list of allocated and free interrupts. It can be used as a debugging aid when interrupt allocation fails. --- .../esp_hw_support/include/esp_intr_alloc.h | 8 ++ components/esp_hw_support/intr_alloc.c | 84 +++++++++++++++++++ 2 files changed, 92 insertions(+) diff --git a/components/esp_hw_support/include/esp_intr_alloc.h b/components/esp_hw_support/include/esp_intr_alloc.h index a800c94fe8..e60b841988 100644 --- a/components/esp_hw_support/include/esp_intr_alloc.h +++ b/components/esp_hw_support/include/esp_intr_alloc.h @@ -8,6 +8,7 @@ #include #include +#include #include "esp_err.h" #ifdef __cplusplus @@ -307,6 +308,13 @@ static inline int esp_intr_flags_to_level(int flags) return __builtin_ffs((flags & ESP_INTR_FLAG_LEVELMASK) >> 1) + 1; } +/** + * @brief Dump the status of allocated interrupts + * @param stream The stream to dump to, if NULL then stdout is used + * @return ESP_OK on success + */ +esp_err_t esp_intr_dump(FILE *stream); + /**@}*/ diff --git a/components/esp_hw_support/intr_alloc.c b/components/esp_hw_support/intr_alloc.c index abcee04358..3e01108d1b 100644 --- a/components/esp_hw_support/intr_alloc.c +++ b/components/esp_hw_support/intr_alloc.c @@ -22,6 +22,9 @@ #include "esp_attr.h" #include "esp_cpu.h" #include "esp_private/rtc_ctrl.h" +#include "soc/interrupts.h" +#include "soc/soc_caps.h" +#include "sdkconfig.h" #if !CONFIG_FREERTOS_UNICORE #include "esp_ipc.h" @@ -902,3 +905,84 @@ void IRAM_ATTR esp_intr_disable_source(int inum) { esp_cpu_intr_disable(1 << inum); } + +esp_err_t esp_intr_dump(FILE *stream) +{ + if (stream == NULL) { + stream = stdout; + } +#ifdef CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE + const int cpu_num = 1; +#else + const int cpu_num = SOC_CPU_CORES_NUM; +#endif + + int general_use_ints_free = 0; + int shared_ints = 0; + + for (int cpu = 0; cpu < cpu_num; ++cpu) { + fprintf(stream, "CPU %d interrupt status:\n", cpu); + fprintf(stream, " Int Level Type Status\n"); + for (int i_num = 0; i_num < 32; ++i_num) { + fprintf(stream, " %2d ", i_num); + esp_cpu_intr_desc_t intr_desc; + esp_cpu_intr_get_desc(cpu, i_num, &intr_desc); + bool is_general_use = true; + vector_desc_t *vd = find_desc_for_int(i_num, cpu); + +#ifndef SOC_CPU_HAS_FLEXIBLE_INTC + fprintf(stream, " %d %s ", + intr_desc.priority, + intr_desc.type == ESP_CPU_INTR_TYPE_EDGE ? "Edge " : "Level"); + + is_general_use = (intr_desc.type == ESP_CPU_INTR_TYPE_LEVEL) && (intr_desc.priority <= XCHAL_EXCM_LEVEL); +#else // SOC_CPU_HAS_FLEXIBLE_INTC + if (vd == NULL) { + fprintf(stream, " * * "); + } else { + // esp_cpu_intr_get_* functions need to be extended with cpu parameter. + // Showing info for the current cpu only, in the meantime. + if (esp_cpu_get_core_id() == cpu) { + fprintf(stream, " %d %s ", + esp_cpu_intr_get_priority(i_num), + esp_cpu_intr_get_type(i_num) == ESP_CPU_INTR_TYPE_EDGE ? "Edge " : "Level"); + } else { + fprintf(stream, " ? ? "); + } + } +#endif // SOC_CPU_HAS_FLEXIBLE_INTC + + if (intr_desc.flags & ESP_CPU_INTR_DESC_FLAG_RESVD) { + fprintf(stream, "Reserved"); + } else if (intr_desc.flags & ESP_CPU_INTR_DESC_FLAG_SPECIAL) { + fprintf(stream, "CPU-internal"); + } else { + if (vd == NULL || (vd->flags & (VECDESC_FL_RESERVED | VECDESC_FL_NONSHARED | VECDESC_FL_SHARED)) == 0) { + fprintf(stream, "Free"); + if (is_general_use) { + ++general_use_ints_free; + } else { + fprintf(stream, " (not general-use)"); + } + } else if (vd->flags & VECDESC_FL_RESERVED) { + fprintf(stream, "Reserved (run-time)"); + } else if (vd->flags & VECDESC_FL_NONSHARED) { + fprintf(stream, "Used: %s", esp_isr_names[vd->source]); + } else if (vd->flags & VECDESC_FL_SHARED) { + fprintf(stream, "Shared: "); + for (shared_vector_desc_t *svd = vd->shared_vec_info; svd != NULL; svd = svd->next) { + fprintf(stream, "%s ", esp_isr_names[svd->source]); + } + ++shared_ints; + } else { + fprintf(stream, "Unknown, flags = 0x%x", vd->flags); + } + } + + fprintf(stream, "\n"); + } + } + fprintf(stream, "Interrupts available for general use: %d\n", general_use_ints_free); + fprintf(stream, "Shared interrupts: %d\n", shared_ints); + return ESP_OK; +}