Skip to content

Commit 4393a0d

Browse files
committed
Merge branch 'bugfix/reset_axi_gdma_gracefully' into 'master'
fix(gdma): stop the axi gdma gracefully on CPU SW reset See merge request espressif/esp-idf!36137
2 parents e991442 + fbcbefe commit 4393a0d

File tree

8 files changed

+119
-20
lines changed

8 files changed

+119
-20
lines changed

components/esp_system/port/soc/esp32p4/system_internal.c

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -28,6 +28,10 @@
2828
#include "soc/hp_sys_clkrst_reg.h"
2929
#include "soc/lp_clkrst_reg.h"
3030
#include "soc/hp_system_reg.h"
31+
#include "hal/gdma_ll.h"
32+
#include "hal/axi_dma_ll.h"
33+
#include "hal/dw_gdma_ll.h"
34+
#include "hal/dma2d_ll.h"
3135

3236
void IRAM_ATTR esp_system_reset_modules_on_exit(void)
3337
{
@@ -38,6 +42,32 @@ void IRAM_ATTR esp_system_reset_modules_on_exit(void)
3842
}
3943
}
4044

45+
// Note: AXI bus doesn't allow an undergoing transaction to be interrupted in the middle
46+
// If you want to reset a AXI master, you should make sure that the master is in IDLE first
47+
if (gdma_ll_is_bus_clock_enabled(1)) {
48+
for (int i = 0; i < GDMA_LL_AXI_PAIRS_PER_GROUP; i++) {
49+
axi_dma_ll_tx_abort(AXI_DMA_LL_GET_HW(0), i, true);
50+
axi_dma_ll_rx_abort(AXI_DMA_LL_GET_HW(0), i, true);
51+
while (!axi_dma_ll_tx_is_reset_avail(AXI_DMA_LL_GET_HW(0), i));
52+
while (!axi_dma_ll_rx_is_reset_avail(AXI_DMA_LL_GET_HW(0), i));
53+
}
54+
}
55+
if (dma2d_ll_is_bus_clock_enabled(0)) {
56+
for (int i = 0; i < SOC_DMA2D_RX_CHANNELS_PER_GROUP; i++) {
57+
dma2d_ll_rx_abort(DMA2D_LL_GET_HW(0), i, true);
58+
while (!dma2d_ll_rx_is_reset_avail(DMA2D_LL_GET_HW(0), i));
59+
}
60+
for (int i = 0; i < SOC_DMA2D_TX_CHANNELS_PER_GROUP; i++) {
61+
dma2d_ll_tx_abort(DMA2D_LL_GET_HW(0), i, true);
62+
while (!dma2d_ll_tx_is_reset_avail(DMA2D_LL_GET_HW(0), i));
63+
}
64+
}
65+
if (dw_gdma_ll_is_bus_clock_enabled(0)) {
66+
for (int i = 0; i < DW_GDMA_LL_CHANNELS_PER_GROUP; i++) {
67+
dw_gdma_ll_channel_abort(DW_GDMA_LL_GET_HW(0), i);
68+
}
69+
}
70+
4171
// Set Peripheral clk rst
4272
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_TIMERGRP1);
4373
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_STIMER);
@@ -48,7 +78,6 @@ void IRAM_ATTR esp_system_reset_modules_on_exit(void)
4878
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART2_CORE);
4979
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART3_CORE);
5080
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART4_CORE);
51-
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_GDMA);
5281
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN2_REG, HP_SYS_CLKRST_REG_RST_EN_ADC);
5382

5483
// Clear Peripheral clk rst
@@ -61,7 +90,6 @@ void IRAM_ATTR esp_system_reset_modules_on_exit(void)
6190
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART2_CORE);
6291
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART3_CORE);
6392
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART4_CORE);
64-
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_GDMA);
6593
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN2_REG, HP_SYS_CLKRST_REG_RST_EN_ADC);
6694

6795
#if CONFIG_ESP32P4_REV_MIN_FULL <= 100

components/hal/dma2d_hal.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -14,16 +14,16 @@ void dma2d_hal_init(dma2d_hal_context_t *hal, int group_id)
1414

1515
void dma2d_hal_tx_reset_channel(dma2d_hal_context_t *hal, uint32_t channel)
1616
{
17-
dma2d_ll_tx_disable_cmd(hal->dev, channel, true);
17+
dma2d_ll_tx_abort(hal->dev, channel, true);
1818
while (!dma2d_ll_tx_is_reset_avail(hal->dev, channel));
1919
dma2d_ll_tx_reset_channel(hal->dev, channel);
20-
dma2d_ll_tx_disable_cmd(hal->dev, channel, false);
20+
dma2d_ll_tx_abort(hal->dev, channel, false);
2121
}
2222

2323
void dma2d_hal_rx_reset_channel(dma2d_hal_context_t *hal, uint32_t channel)
2424
{
25-
dma2d_ll_rx_disable_cmd(hal->dev, channel, true);
25+
dma2d_ll_rx_abort(hal->dev, channel, true);
2626
while (!dma2d_ll_rx_is_reset_avail(hal->dev, channel));
2727
dma2d_ll_rx_reset_channel(hal->dev, channel);
28-
dma2d_ll_rx_disable_cmd(hal->dev, channel, false);
28+
dma2d_ll_rx_abort(hal->dev, channel, false);
2929
}

components/hal/dw_gdma_hal.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
void dw_gdma_hal_init(dw_gdma_hal_context_t *hal, const dw_gdma_hal_config_t *config)
1313
{
14-
hal->dev = DW_GDMA_LL_GET_HW();
14+
hal->dev = DW_GDMA_LL_GET_HW(0);
1515
dw_gdma_ll_reset(hal->dev);
1616
dw_gdma_ll_enable_controller(hal->dev, true);
1717
dw_gdma_ll_enable_intr_global(hal->dev, true);

components/hal/esp32p4/include/hal/axi_dma_ll.h

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -195,6 +195,15 @@ static inline void axi_dma_ll_rx_stop(axi_dma_dev_t *dev, uint32_t channel)
195195
dev->in[channel].conf.in_link1.inlink_stop_chn = 1;
196196
}
197197

198+
/**
199+
* @brief Abort the RX channel, stop the undergoing transfer immediately
200+
*/
201+
__attribute__((always_inline))
202+
static inline void axi_dma_ll_rx_abort(axi_dma_dev_t *dev, uint32_t channel, bool abort)
203+
{
204+
dev->in[channel].conf.in_conf0.in_cmd_disable_chn = abort;
205+
}
206+
198207
/**
199208
* @brief Restart a new inlink right after the last descriptor
200209
*/
@@ -291,6 +300,15 @@ static inline void axi_dma_ll_rx_enable_ext_mem_ecc_aes_access(axi_dma_dev_t *de
291300
dev->in[channel].conf.in_conf0.in_ecc_aes_en_chn = enable;
292301
}
293302

303+
/**
304+
* @brief Return if the channel is ready to be reset
305+
*/
306+
__attribute__((always_inline))
307+
static inline bool axi_dma_ll_rx_is_reset_avail(axi_dma_dev_t *dev, uint32_t channel)
308+
{
309+
return dev->in_reset_avail_chn[channel].in_reset_avail_chn;
310+
}
311+
294312
///////////////////////////////////// TX /////////////////////////////////////////
295313
/**
296314
* @brief Get DMA TX channel interrupt status word
@@ -429,6 +447,15 @@ static inline void axi_dma_ll_tx_stop(axi_dma_dev_t *dev, uint32_t channel)
429447
dev->out[channel].conf.out_link1.outlink_stop_chn = 1;
430448
}
431449

450+
/**
451+
* @brief Abort the TX channel, stop the undergoing transfer immediately
452+
*/
453+
__attribute__((always_inline))
454+
static inline void axi_dma_ll_tx_abort(axi_dma_dev_t *dev, uint32_t channel, bool abort)
455+
{
456+
dev->out[channel].conf.out_conf0.out_cmd_disable_chn = abort;
457+
}
458+
432459
/**
433460
* @brief Restart a new outlink right after the last descriptor
434461
*/
@@ -507,6 +534,15 @@ static inline void axi_dma_ll_tx_enable_ext_mem_ecc_aes_access(axi_dma_dev_t *de
507534
dev->out[channel].conf.out_conf0.out_ecc_aes_en_chn = enable;
508535
}
509536

537+
/**
538+
* @brief Return if the channel is ready to be reset
539+
*/
540+
__attribute__((always_inline))
541+
static inline bool axi_dma_ll_tx_is_reset_avail(axi_dma_dev_t *dev, uint32_t channel)
542+
{
543+
return dev->out_reset_avail_chn[channel].out_reset_avail_chn;
544+
}
545+
510546
///////////////////////////////////// CRC-TX /////////////////////////////////////////
511547

512548
/**

components/hal/esp32p4/include/hal/dma2d_ll.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -105,6 +105,16 @@ static inline void dma2d_ll_reset_register(int group_id)
105105
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
106106
#define dma2d_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; dma2d_ll_reset_register(__VA_ARGS__)
107107

108+
/**
109+
* @brief Check if the bus clock is enabled for the DMA module
110+
*/
111+
__attribute__((always_inline))
112+
static inline bool dma2d_ll_is_bus_clock_enabled(int group_id)
113+
{
114+
(void) group_id;
115+
return HP_SYS_CLKRST.soc_clk_ctrl1.reg_dma2d_sys_clk_en;
116+
}
117+
108118
/**
109119
* @brief Enable 2D-DMA module
110120
*/
@@ -278,7 +288,7 @@ static inline bool dma2d_ll_rx_is_reset_avail(dma2d_dev_t *dev, uint32_t channel
278288
* @brief Disable 2D-DMA RX channel via a command
279289
*/
280290
__attribute__((always_inline))
281-
static inline void dma2d_ll_rx_disable_cmd(dma2d_dev_t *dev, uint32_t channel, bool disable)
291+
static inline void dma2d_ll_rx_abort(dma2d_dev_t *dev, uint32_t channel, bool disable)
282292
{
283293
volatile dma2d_in_conf0_chn_reg_t *reg = (volatile dma2d_in_conf0_chn_reg_t *)DMA2D_LL_IN_CHANNEL_GET_REG_ADDR(dev, channel, in_conf0);
284294
reg->in_cmd_disable_chn = disable;
@@ -811,7 +821,7 @@ static inline bool dma2d_ll_tx_is_reset_avail(dma2d_dev_t *dev, uint32_t channel
811821
* @brief Disable 2D-DMA TX channel via a command
812822
*/
813823
__attribute__((always_inline))
814-
static inline void dma2d_ll_tx_disable_cmd(dma2d_dev_t *dev, uint32_t channel, bool disable)
824+
static inline void dma2d_ll_tx_abort(dma2d_dev_t *dev, uint32_t channel, bool disable)
815825
{
816826
dev->out_channel[channel].out_conf0.out_cmd_disable_chn = disable;
817827
}

components/hal/esp32p4/include/hal/dw_gdma_ll.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -15,7 +15,7 @@
1515
#include "soc/hp_sys_clkrst_struct.h"
1616
#include "soc/reg_base.h"
1717

18-
#define DW_GDMA_LL_GET_HW() (&DW_GDMA)
18+
#define DW_GDMA_LL_GET_HW(id) (((id) == 0) ? (&DW_GDMA) : NULL)
1919

2020
#define DW_GDMA_LL_GROUPS 1 // there's one DW-GDMA instance connected to the AXI bus
2121
#define DW_GDMA_LL_CHANNELS_PER_GROUP 4 // there are 4 independent channels in the DW-GDMA
@@ -101,7 +101,7 @@ static inline void dw_gdma_ll_enable_bus_clock(int group_id, bool enable)
101101
/**
102102
* @brief Reset the DMA module
103103
*/
104-
static inline void dw_gdma_ll_reset_register(int group_id)
104+
static inline void _dw_gdma_ll_reset_register(int group_id)
105105
{
106106
(void)group_id;
107107
HP_SYS_CLKRST.hp_rst_en0.reg_rst_en_gdma = 1;
@@ -110,7 +110,17 @@ static inline void dw_gdma_ll_reset_register(int group_id)
110110

111111
/// use a macro to wrap the function, force the caller to use it in a critical section
112112
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
113-
#define dw_gdma_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; dw_gdma_ll_reset_register(__VA_ARGS__)
113+
#define dw_gdma_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; _dw_gdma_ll_reset_register(__VA_ARGS__)
114+
115+
/**
116+
* @brief Check if the bus clock is enabled for the DMA module
117+
*/
118+
__attribute__((always_inline))
119+
static inline bool dw_gdma_ll_is_bus_clock_enabled(int group_id)
120+
{
121+
(void) group_id;
122+
return HP_SYS_CLKRST.soc_clk_ctrl1.reg_gdma_sys_clk_en && HP_SYS_CLKRST.soc_clk_ctrl0.reg_gdma_cpu_clk_en;
123+
}
114124

115125
/**
116126
* @brief Reset the DMA controller by software
@@ -320,10 +330,12 @@ static inline void dw_gdma_ll_channel_suspend(dw_gdma_dev_t *dev, uint8_t channe
320330
* @param dev Pointer to the DW_GDMA registers
321331
* @param channel Channel number
322332
*/
333+
__attribute__((always_inline))
323334
static inline void dw_gdma_ll_channel_abort(dw_gdma_dev_t *dev, uint8_t channel)
324335
{
325336
// the abort bit clears itself after the abort is done
326337
dev->chen1.val = 0x101 << channel;
338+
while (dev->chen1.val & (0x101 << channel));
327339
}
328340

329341
/**

components/hal/esp32p4/include/hal/gdma_ll.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -108,6 +108,19 @@ static inline void _gdma_ll_enable_bus_clock(int group_id, bool enable)
108108
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
109109
#define gdma_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _gdma_ll_enable_bus_clock(__VA_ARGS__)
110110

111+
/**
112+
* @brief Check if the bus clock is enabled for the DMA module
113+
*/
114+
__attribute__((always_inline))
115+
static inline bool gdma_ll_is_bus_clock_enabled(int group_id)
116+
{
117+
if (group_id == 0) {
118+
return HP_SYS_CLKRST.soc_clk_ctrl1.reg_ahb_pdma_sys_clk_en;
119+
} else {
120+
return HP_SYS_CLKRST.soc_clk_ctrl1.reg_axi_pdma_sys_clk_en;
121+
}
122+
}
123+
111124
/**
112125
* @brief Reset the DMA module
113126
*/

components/hal/esp32p4/include/hal/lcd_ll.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ static inline void lcd_ll_enable_bus_clock(int group_id, bool enable)
6363
*
6464
* @param group_id Group ID
6565
*/
66-
static inline void lcd_ll_reset_register(int group_id)
66+
static inline void _lcd_ll_reset_register(int group_id)
6767
{
6868
(void)group_id;
6969
HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_lcdcam = 1;
@@ -72,7 +72,7 @@ static inline void lcd_ll_reset_register(int group_id)
7272

7373
/// use a macro to wrap the function, force the caller to use it in a critical section
7474
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
75-
#define lcd_ll_reset_register(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; lcd_ll_reset_register(__VA_ARGS__)
75+
#define lcd_ll_reset_register(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _lcd_ll_reset_register(__VA_ARGS__)
7676

7777
/**
7878
* @brief Enable clock gating

0 commit comments

Comments
 (0)