Просмотр исходного кода

Merge branch 'bugfix/dport_access_iram' into 'master'

dport: Bigfix dport_read code move to IRAM

See merge request idf/esp-idf!2427
Angus Gratton 7 лет назад
Родитель
Сommit
67fb34fa4e

+ 74 - 0
components/esp32/dport_access.c

@@ -236,3 +236,77 @@ void IRAM_ATTR esp_dport_access_read_buffer(uint32_t *buff_out, uint32_t address
     }
     DPORT_INTERRUPT_RESTORE();
 }
+
+/**
+ * @brief Read value from register, SMP-safe version.
+ *
+ * This method uses the pre-reading of the APB register before reading the register of the DPORT.
+ * This implementation is useful for reading DORT registers for single reading without stall other CPU.
+ * There is disable/enable interrupt.
+ *
+ * @param reg Register address
+ * @return Value
+ */
+uint32_t IRAM_ATTR esp_dport_access_reg_read(uint32_t reg)
+{
+#if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM)
+    return _DPORT_REG_READ(reg);
+#else
+    uint32_t apb;
+    unsigned int intLvl;
+    __asm__ __volatile__ (\
+                  "movi %[APB], "XTSTR(0x3ff40078)"\n"\
+                  "rsil %[LVL], "XTSTR(3)"\n"\
+                  "l32i %[APB], %[APB], 0\n"\
+                  "l32i %[REG], %[REG], 0\n"\
+                  "wsr  %[LVL], "XTSTR(PS)"\n"\
+                  "rsync\n"\
+                  : [APB]"=a"(apb), [REG]"+a"(reg), [LVL]"=a"(intLvl)\
+                  : \
+                  : "memory" \
+                  );
+    return reg;
+#endif
+}
+
+/**
+ * @brief Read value from register, NOT SMP-safe version.
+ *
+ * This method uses the pre-reading of the APB register before reading the register of the DPORT.
+ * There is not disable/enable interrupt.
+ * The difference from DPORT_REG_READ() is that the user himself must disable interrupts while DPORT reading.
+ * This implementation is useful for reading DORT registers in loop without stall other CPU. Note the usage example.
+ * The recommended way to read registers sequentially without stall other CPU
+ * is to use the method esp_dport_read_buffer(buff_out, address, num_words). It allows you to read registers in the buffer.
+ *
+ * \code{c}
+ * // This example shows how to use it.
+ * { // Use curly brackets to limit the visibility of variables in macros DPORT_INTERRUPT_DISABLE/RESTORE.
+ *     DPORT_INTERRUPT_DISABLE(); // Disable interrupt only on current CPU.
+ *     for (i = 0; i < max; ++i) {
+ *        array[i] = esp_dport_access_sequence_reg_read(Address + i * 4); // reading DPORT registers
+ *     }
+ *     DPORT_INTERRUPT_RESTORE(); // restore the previous interrupt level
+ * }
+ * \endcode
+ *
+ * @param reg Register address
+ * @return Value
+ */
+uint32_t IRAM_ATTR esp_dport_access_sequence_reg_read(uint32_t reg)
+{
+#if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM)
+    return _DPORT_REG_READ(reg);
+#else
+    uint32_t apb;
+    __asm__ __volatile__ (\
+                  "movi %[APB], "XTSTR(0x3ff40078)"\n"\
+                  "l32i %[APB], %[APB], 0\n"\
+                  "l32i %[REG], %[REG], 0\n"\
+                  : [APB]"=a"(apb), [REG]"+a"(reg)\
+                  : \
+                  : "memory" \
+                  );
+    return reg;
+#endif
+}

+ 2 - 1
components/esp32/include/esp_dport_access.h

@@ -27,6 +27,8 @@ void esp_dport_access_int_init(void);
 void esp_dport_access_int_pause(void);
 void esp_dport_access_int_resume(void);
 void esp_dport_access_read_buffer(uint32_t *buff_out, uint32_t address, uint32_t num_words);
+uint32_t esp_dport_access_reg_read(uint32_t reg);
+uint32_t esp_dport_access_sequence_reg_read(uint32_t reg);
 //This routine does not stop the dport routines in any way that is recoverable. Please
 //only call in case of panic().
 void esp_dport_access_int_abort(void);
@@ -34,7 +36,6 @@ void esp_dport_access_int_abort(void);
 #if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM)
 #define DPORT_STALL_OTHER_CPU_START()
 #define DPORT_STALL_OTHER_CPU_END()
-#define DPORT_STALL_OTHER_CPU_START()
 #define DPORT_INTERRUPT_DISABLE()
 #define DPORT_INTERRUPT_RESTORE()
 #else

+ 9 - 44
components/soc/esp32/include/soc/dport_access.h

@@ -73,23 +73,10 @@ extern "C" {
  */
 static inline uint32_t IRAM_ATTR DPORT_REG_READ(uint32_t reg)
 {
-#ifndef CONFIG_FREERTOS_UNICORE
-    uint32_t apb;
-    unsigned int intLvl;
-    __asm__ __volatile__ (\
-                  "movi %[APB], "XTSTR(0x3ff40078)"\n"\
-                  "rsil %[LVL], "XTSTR(3)"\n"\
-                  "l32i %[APB], %[APB], 0\n"\
-                  "l32i %[REG], %[REG], 0\n"\
-                  "wsr  %[LVL], "XTSTR(PS)"\n"\
-                  "rsync\n"\
-                  : [APB]"=a"(apb), [REG]"+a"(reg), [LVL]"=a"(intLvl)\
-                  : \
-                  : "memory" \
-                  );
-    return reg;
-#else
+#if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM)
     return _DPORT_REG_READ(reg);
+#else
+    return esp_dport_access_reg_read(reg);
 #endif
 }
 
@@ -119,19 +106,10 @@ static inline uint32_t IRAM_ATTR DPORT_REG_READ(uint32_t reg)
  */
 static inline uint32_t IRAM_ATTR DPORT_SEQUENCE_REG_READ(uint32_t reg)
 {
-#ifndef CONFIG_FREERTOS_UNICORE
-    uint32_t apb;
-    __asm__ __volatile__ (\
-                  "movi %[APB], "XTSTR(0x3ff40078)"\n"\
-                  "l32i %[APB], %[APB], 0\n"\
-                  "l32i %[REG], %[REG], 0\n"\
-                  : [APB]"=a"(apb), [REG]"+a"(reg)\
-                  : \
-                  : "memory" \
-                  );
-    return reg;
-#else
+#if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM)
     return _DPORT_REG_READ(reg);
+#else
+    return esp_dport_access_sequence_reg_read(reg);
 #endif
 }
 
@@ -188,23 +166,10 @@ static inline uint32_t IRAM_ATTR DPORT_SEQUENCE_REG_READ(uint32_t reg)
  */
 static inline uint32_t IRAM_ATTR DPORT_READ_PERI_REG(uint32_t reg)
 {
-#ifndef CONFIG_FREERTOS_UNICORE
-    uint32_t apb;
-    unsigned int intLvl;
-    __asm__ __volatile__ (\
-                  "movi %[APB], "XTSTR(0x3ff40078)"\n"\
-                  "rsil %[LVL], "XTSTR(3)"\n"\
-                  "l32i %[APB], %[APB], 0\n"\
-                  "l32i %[REG], %[REG], 0\n"\
-                  "wsr  %[LVL], "XTSTR(PS)"\n"\
-                  "rsync\n"\
-                  : [APB]"=a"(apb), [REG]"+a"(reg), [LVL]"=a"(intLvl)\
-                  : \
-                  : "memory" \
-                  );
-    return reg;
+#if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM)
+    return _DPORT_REG_READ(reg);
 #else
-    return _DPORT_READ_PERI_REG(reg);
+    return esp_dport_access_reg_read(reg);
 #endif
 }