]> granicus.if.org Git - esp-idf/commitdiff
esp32: Add UTs for DPORT and Hi-interrupt
authorKonstantin Kondrashov <konstantin@espressif.com>
Fri, 28 Jun 2019 05:34:19 +0000 (13:34 +0800)
committerbot <bot@espressif.com>
Wed, 21 Aug 2019 09:48:16 +0000 (09:48 +0000)
components/esp32/test/CMakeLists.txt
components/esp32/test/component.mk
components/esp32/test/test_dport.c
components/esp32/test/test_dport_xt_highint5.S [new file with mode: 0644]

index b99e2888b6ecbccadea7ae6d09f57019fcbbfcdb..ac687495529eda71a5ed1d6bcdc87977b450fb09 100644 (file)
@@ -34,4 +34,5 @@ add_definitions(-DCOEX_ADAPTER_MD5=\"${COEX_ADAPTER_MD5}\")
 
 add_custom_target(esp32_test_logo DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/test_tjpgd_logo.h")
 
-add_dependencies(${COMPONENT_TARGET} esp32_test_logo)
\ No newline at end of file
+add_dependencies(${COMPONENT_TARGET} esp32_test_logo)
+target_link_libraries(${COMPONENT_TARGET} "-u ld_include_test_dport_xt_highint5")
index 6fb41f30a6ab4c3be3847417dace663a3854e540..8edadc3c0d3b773d1c6a6852847dec629ca0b226 100644 (file)
@@ -4,7 +4,8 @@
 
 COMPONENT_EXTRA_CLEAN := test_tjpgd_logo.h
 
-COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
+COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive \
+                         -u ld_include_test_dport_xt_highint5 \
 
 COMPONENT_SRCDIRS := .
 
index 4520a70aaa9c14aa8a47a8c7e3e49c1c097add26..013f546d9afb4330d4fea76656964184e8086616 100644 (file)
@@ -1,5 +1,7 @@
 #include <stdio.h>
 #include <stdlib.h>
+#include "xtensa/core-macros.h"
+#include "xtensa/hal.h"
 #include "esp_types.h"
 #include "esp_clk.h"
 
 #include "soc/uart_reg.h"
 #include "soc/dport_reg.h"
 #include "soc/rtc.h"
+#include "esp_intr_alloc.h"
+#include "driver/timer.h"
 
 #define MHZ (1000000)
 static volatile bool exit_flag;
 static bool dport_test_result;
 static bool apb_test_result;
+uint32_t volatile apb_intr_test_result;
 
 static void accessDPORT(void *pvParameters)
 {
@@ -60,6 +65,7 @@ static void accessAPB(void *pvParameters)
 
 void run_tasks(const char *task1_description, void (* task1_func)(void *), const char *task2_description, void (* task2_func)(void *), uint32_t delay_ms)
 {
+    apb_intr_test_result = 1;
     int i;
     TaskHandle_t th[2];
     xSemaphoreHandle exit_sema[2];
@@ -95,7 +101,7 @@ void run_tasks(const char *task1_description, void (* task1_func)(void *), const
             vSemaphoreDelete(exit_sema[i]);
         }
     }
-    TEST_ASSERT(dport_test_result == true && apb_test_result == true);
+    TEST_ASSERT(dport_test_result == true && apb_test_result == true && apb_intr_test_result == 1);
 }
 
 TEST_CASE("access DPORT and APB at same time", "[esp32]")
@@ -325,3 +331,88 @@ TEST_CASE("BENCHMARK for DPORT access performance", "[freertos]")
     }
     BENCHMARK_END("_DPORT_REG_READ");
 }
+
+uint32_t xt_highint5_read_apb;
+
+#ifndef CONFIG_FREERTOS_UNICORE
+timer_isr_handle_t inth;
+xSemaphoreHandle sync_sema;
+
+static void init_hi_interrupt(void *arg)
+{
+    printf("init hi_interrupt on CPU%d \n", xPortGetCoreID());
+    TEST_ESP_OK(esp_intr_alloc(ETS_INTERNAL_TIMER2_INTR_SOURCE, ESP_INTR_FLAG_LEVEL5 | ESP_INTR_FLAG_IRAM, NULL, NULL, &inth));
+    while (exit_flag == false);
+    esp_intr_free(inth);
+    printf("disable hi_interrupt on CPU%d \n", xPortGetCoreID());
+    vTaskDelete(NULL);
+}
+
+static void accessDPORT2_stall_other_cpu(void *pvParameters)
+{
+    xSemaphoreHandle *sema = (xSemaphoreHandle *) pvParameters;
+    dport_test_result = true;
+    while (exit_flag == false) {
+        DPORT_STALL_OTHER_CPU_START();
+        XTHAL_SET_CCOMPARE(2, XTHAL_GET_CCOUNT());
+        xt_highint5_read_apb = 1;
+        for (int i = 0; i < 200; ++i) {
+            if (_DPORT_REG_READ(DPORT_DATE_REG) != _DPORT_REG_READ(DPORT_DATE_REG)) {
+                apb_test_result = false;
+                break;
+            }
+        }
+        xt_highint5_read_apb = 0;
+        DPORT_STALL_OTHER_CPU_END();
+    }
+    printf("accessDPORT2_stall_other_cpu finish\n");
+
+    xSemaphoreGive(*sema);
+    vTaskDelete(NULL);
+}
+
+TEST_CASE("Check stall workaround DPORT and Hi-interrupt", "[esp32]")
+{
+    xt_highint5_read_apb = 0;
+    dport_test_result    = false;
+    apb_test_result      = true;
+    TEST_ASSERT(xTaskCreatePinnedToCore(&init_hi_interrupt, "init_hi_intr", 2048, NULL, 6, NULL, 1) == pdTRUE);
+    // Access DPORT(stall other cpu method) - CPU0
+    // STALL                                - CPU1
+    // Hi-interrupt                         - CPU1
+    run_tasks("accessDPORT2_stall_other_cpu", accessDPORT2_stall_other_cpu, " - ", NULL, 10000);
+}
+
+static void accessDPORT2(void *pvParameters)
+{
+    xSemaphoreHandle *sema = (xSemaphoreHandle *) pvParameters;
+    dport_test_result = true;
+
+    TEST_ESP_OK(esp_intr_alloc(ETS_INTERNAL_TIMER2_INTR_SOURCE, ESP_INTR_FLAG_LEVEL5 | ESP_INTR_FLAG_IRAM, NULL, NULL, &inth));
+
+    while (exit_flag == false) {
+        XTHAL_SET_CCOMPARE(2, XTHAL_GET_CCOUNT() + 21);
+        for (int i = 0; i < 200; ++i) {
+            if (DPORT_REG_READ(DPORT_DATE_REG) != DPORT_REG_READ(DPORT_DATE_REG)) {
+                dport_test_result = false;
+                break;
+            }
+        }
+    }
+    esp_intr_free(inth);
+    printf("accessDPORT2 finish\n");
+
+    xSemaphoreGive(*sema);
+    vTaskDelete(NULL);
+}
+
+TEST_CASE("Check pre-read workaround DPORT and Hi-interrupt", "[esp32]")
+{
+    xt_highint5_read_apb = 0;
+    dport_test_result    = false;
+    apb_test_result      = true;
+    // Access DPORT(pre-read method) - CPU1
+    // Hi-interrupt                  - CPU1
+    run_tasks("accessAPB", accessAPB, "accessDPORT2", accessDPORT2, 10000);
+}
+#endif // CONFIG_FREERTOS_UNICORE
diff --git a/components/esp32/test/test_dport_xt_highint5.S b/components/esp32/test/test_dport_xt_highint5.S
new file mode 100644 (file)
index 0000000..965c738
--- /dev/null
@@ -0,0 +1,80 @@
+#include <xtensa/coreasm.h>
+#include <xtensa/corebits.h>
+#include <xtensa/config/system.h>
+#include "freertos/xtensa_context.h"
+
+#include "sdkconfig.h"
+#include "soc/soc.h"
+#include "soc/dport_reg.h"
+
+#ifndef CONFIG_FREERTOS_UNICORE
+
+#define L5_INTR_STACK_SIZE  12
+#define L5_INTR_A2_OFFSET   0
+#define L5_INTR_A3_OFFSET   4
+#define L5_INTR_A4_OFFSET   8
+    .data
+_l5_intr_stack:
+    .space      L5_INTR_STACK_SIZE
+
+    .section .iram1,"ax"
+    .global     xt_highint5
+    .type       xt_highint5,@function
+    .align      4
+xt_highint5:
+
+    movi    a0, xt_highint5_read_apb
+    l32i    a0, a0, 0
+    bnez    a0, .read_apb_reg
+
+// Short interrupt
+    esync
+    rsr a0, CCOUNT
+    addi a0, a0, 27
+    wsr a0, CCOMPARE2
+    esync
+
+    rsr     a0, EXCSAVE_5 // restore a0
+    rfi     5
+
+
+
+// read APB reg 10 time.
+.read_apb_reg:
+    movi    a0, _l5_intr_stack
+    s32i    a2, a0, L5_INTR_A2_OFFSET
+    s32i    a3, a0, L5_INTR_A3_OFFSET
+    s32i    a4, a0, L5_INTR_A4_OFFSET
+
+    movi    a4, 10         // count of reading
+    movi    a0, 0x3ff40078 // read APB reg
+    l32i    a2, a0, 0
+.loop_read_apb_reg:
+    l32i    a3, a0, 0
+    bne     a3, a2, .need_set_apb_test_result
+    addi    a4, a4, -1
+    l32i    a2, a0, 0
+    bnez    a4, .loop_read_apb_reg
+    j       1f
+.need_set_apb_test_result:
+    movi    a0, apb_intr_test_result // set fail
+    movi    a2, 0
+    s32i    a2, a0, 0
+    memw
+1:
+    movi    a0, _l5_intr_stack
+    l32i    a2, a0, L5_INTR_A2_OFFSET
+    l32i    a3, a0, L5_INTR_A3_OFFSET
+    l32i    a4, a0, L5_INTR_A4_OFFSET
+    rsync
+.L_xt_highint5_exit:
+    rsr     a0, EXCSAVE_5                   // restore a0
+    rfi     5
+
+/* The linker has no reason to link in this file; all symbols it exports are already defined
+   (weakly!) in the default int handler. Define a symbol here so we can use it to have the
+   linker inspect this anyway. */
+
+    .global ld_include_test_dport_xt_highint5
+ld_include_test_dport_xt_highint5:
+#endif // CONFIG_FREERTOS_UNICORE