diff --git a/components/esp32/dport_access.c b/components/esp32/dport_access.c index 4e5d5b177..731bdb7ec 100644 --- a/components/esp32/dport_access.c +++ b/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 +} diff --git a/components/esp32/include/esp_dport_access.h b/components/esp32/include/esp_dport_access.h index 1a46fa00c..adbb82820 100644 --- a/components/esp32/include/esp_dport_access.h +++ b/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 diff --git a/components/soc/esp32/include/soc/dport_access.h b/components/soc/esp32/include/soc/dport_access.h index db3908241..00e7c8381 100644 --- a/components/soc/esp32/include/soc/dport_access.h +++ b/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 }