Sfoglia il codice sorgente

gpio: Fix the bug that gpio interrupt cannot be triggered on app cpu on ESP32S3

Closes https://github.com/espressif/esp-idf/issues/7885

(cherry picked from commit 91f1159f9c74a120dcacec46fbc7f66f48e169cb)
songruojing 4 anni fa
parent
commit
41e452e7d8

+ 38 - 1
components/driver/test/test_gpio.c

@@ -20,6 +20,7 @@
 #include "sdkconfig.h"
 #include "esp_rom_uart.h"
 #include "esp_rom_sys.h"
+#include "test_utils.h"
 
 
 #define WAKE_UP_IGNORE 1  // gpio_wakeup function development is not completed yet, set it deprecated.
@@ -100,7 +101,7 @@ static gpio_config_t init_io(gpio_num_t num)
 __attribute__((unused)) static void gpio_isr_edge_handler(void *arg)
 {
     uint32_t gpio_num = (uint32_t) arg;
-    esp_rom_printf("GPIO[%d] intr, val: %d\n", gpio_num, gpio_get_level(gpio_num));
+    esp_rom_printf("GPIO[%d] intr on core %d, val: %d\n", gpio_num, cpu_hal_get_core_id(), gpio_get_level(gpio_num));
     edge_intr_times++;
 }
 
@@ -408,6 +409,42 @@ TEST_CASE("GPIO enable and disable interrupt test", "[gpio][test_env=UT_T1_GPIO]
 }
 #endif //DISABLED_FOR_TARGETS(ESP32S2, ESP32S3, ESP32C3)
 
+#if !CONFIG_FREERTOS_UNICORE
+static void install_isr_service_task(void *arg)
+{
+    uint32_t gpio_num = (uint32_t) arg;
+    //rising edge intr
+    TEST_ESP_OK(gpio_set_intr_type(gpio_num, GPIO_INTR_POSEDGE));
+    TEST_ESP_OK(gpio_install_isr_service(0));
+    gpio_isr_handler_add(gpio_num, gpio_isr_edge_handler, (void *) gpio_num);
+    vTaskSuspend(NULL);
+}
+
+TEST_CASE("GPIO interrupt on other CPUs test", "[gpio]")
+{
+    TaskHandle_t gpio_task_handle;
+    gpio_config_t input_output_io = init_io(TEST_GPIO_EXT_OUT_IO);
+    input_output_io.mode = GPIO_MODE_INPUT_OUTPUT;
+    input_output_io.pull_up_en = 1;
+    TEST_ESP_OK(gpio_config(&input_output_io));
+
+    for (int cpu_num = 1; cpu_num < portNUM_PROCESSORS; ++cpu_num) {
+        // We assume unit-test task is running on core 0, so we install gpio interrupt on other cores
+        edge_intr_times = 0;
+        TEST_ESP_OK(gpio_set_level(TEST_GPIO_EXT_OUT_IO, 0));
+        xTaskCreatePinnedToCore(install_isr_service_task, "install_isr_service_task", 2048, (void *) TEST_GPIO_EXT_OUT_IO, 1, &gpio_task_handle, cpu_num);
+
+        vTaskDelay(200 / portTICK_RATE_MS);
+        TEST_ESP_OK(gpio_set_level(TEST_GPIO_EXT_OUT_IO, 1));
+        vTaskDelay(100 / portTICK_RATE_MS);
+        TEST_ASSERT_EQUAL_INT(edge_intr_times, 1);
+        gpio_isr_handler_remove(TEST_GPIO_EXT_OUT_IO);
+        gpio_uninstall_isr_service();
+        test_utils_task_delete(gpio_task_handle);
+    }
+}
+#endif //!CONFIG_FREERTOS_UNICORE
+
 // ESP32 Connect GPIO18 with GPIO19, ESP32-S2 Connect GPIO17 with GPIO21,
 // ESP32-S3 Connect GPIO17 with GPIO21, ESP32C3 Connect GPIO2 with GPIO3
 // use multimeter to test the voltage, so it is ignored in CI

+ 9 - 5
components/hal/esp32s3/include/hal/gpio_ll.h

@@ -29,8 +29,9 @@ extern "C" {
 // Get GPIO hardware instance with giving gpio num
 #define GPIO_LL_GET_HW(num) (((num) == 0) ? (&GPIO) : NULL)
 
-#define GPIO_LL_PRO_CPU_INTR_ENA      (BIT(0))
-#define GPIO_LL_PRO_CPU_NMI_INTR_ENA  (BIT(1))
+// On ESP32S3, pro cpu and app cpu shares the same interrupt enable bit
+#define GPIO_LL_INTR_ENA      (BIT(0))
+#define GPIO_LL_NMI_INTR_ENA  (BIT(1))
 
 /**
   * @brief Enable pull-up on GPIO.
@@ -97,6 +98,8 @@ static inline void gpio_ll_set_intr_type(gpio_dev_t *hw, gpio_num_t gpio_num, gp
   */
 static inline void gpio_ll_get_intr_status(gpio_dev_t *hw, uint32_t core_id, uint32_t *status)
 {
+    // On ESP32S3, pcpu_int register represents GPIO0-31 interrupt status on both cores
+    (void)core_id;
     *status = hw->pcpu_int;
 }
 
@@ -109,6 +112,8 @@ static inline void gpio_ll_get_intr_status(gpio_dev_t *hw, uint32_t core_id, uin
   */
 static inline void gpio_ll_get_intr_status_high(gpio_dev_t *hw, uint32_t core_id, uint32_t *status)
 {
+    // On ESP32S3, pcpu_int1 register represents GPIO32-48 interrupt status on both cores
+    (void)core_id;
     *status = hw->pcpu_int1.intr;
 }
 
@@ -143,9 +148,8 @@ static inline void gpio_ll_clear_intr_status_high(gpio_dev_t *hw, uint32_t mask)
  */
 static inline void gpio_ll_intr_enable_on_core(gpio_dev_t *hw, uint32_t core_id, gpio_num_t gpio_num)
 {
-    if (core_id == 0) {
-        GPIO.pin[gpio_num].int_ena = GPIO_LL_PRO_CPU_INTR_ENA;     //enable pro cpu intr
-    }
+    (void)core_id;
+    GPIO.pin[gpio_num].int_ena = GPIO_LL_INTR_ENA;     //enable intr
 }
 
 /**

+ 10 - 17
components/soc/esp32s3/include/soc/gpio_struct.h

@@ -1,16 +1,9 @@
-// Copyright 2017-2021 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
 #ifndef _SOC_GPIO_STRUCT_H_
 #define _SOC_GPIO_STRUCT_H_
 
@@ -116,19 +109,19 @@ typedef volatile struct gpio_dev_s {
         };
         uint32_t val;
     } status1_w1tc;
-    uint32_t pcpu_int;
-    uint32_t pcpu_nmi_int;
+    uint32_t pcpu_int;                                            /*GPIO0~31 PRO & APP CPU interrupt status*/
+    uint32_t pcpu_nmi_int;                                        /*GPIO0~31 PRO & APP CPU non-maskable interrupt status*/
     uint32_t cpusdio_int;
     union {
         struct {
-            uint32_t intr                          :    22;
+            uint32_t intr                          :    22;       /*GPIO32-48 PRO & APP CPU interrupt status*/
             uint32_t reserved22                    :    10;
         };
         uint32_t val;
     } pcpu_int1;
     union {
         struct {
-            uint32_t intr                          :    22;
+            uint32_t intr                          :    22;       /*GPIO32-48 PRO & APP CPU non-maskable interrupt status*/
             uint32_t reserved22                    :    10;
         };
         uint32_t val;