fix(dma): abort the axi dma gracefully on CPU SW reset

This commit is contained in:
morris
2025-01-03 14:27:19 +08:00
parent e4762af4bb
commit 418768ebc7
8 changed files with 119 additions and 20 deletions

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -27,6 +27,10 @@
#include "soc/hp_sys_clkrst_reg.h"
#include "soc/lp_clkrst_reg.h"
#include "soc/hp_system_reg.h"
#include "hal/gdma_ll.h"
#include "hal/axi_dma_ll.h"
#include "hal/dw_gdma_ll.h"
#include "hal/dma2d_ll.h"
void IRAM_ATTR esp_system_reset_modules_on_exit(void)
{
@@ -37,6 +41,32 @@ void IRAM_ATTR esp_system_reset_modules_on_exit(void)
}
}
// Note: AXI bus doesn't allow an undergoing transaction to be interrupted in the middle
// If you want to reset a AXI master, you should make sure that the master is in IDLE first
if (gdma_ll_is_bus_clock_enabled(1)) {
for (int i = 0; i < GDMA_LL_AXI_PAIRS_PER_GROUP; i++) {
axi_dma_ll_tx_abort(AXI_DMA_LL_GET_HW(0), i, true);
axi_dma_ll_rx_abort(AXI_DMA_LL_GET_HW(0), i, true);
while (!axi_dma_ll_tx_is_reset_avail(AXI_DMA_LL_GET_HW(0), i));
while (!axi_dma_ll_rx_is_reset_avail(AXI_DMA_LL_GET_HW(0), i));
}
}
if (dma2d_ll_is_bus_clock_enabled(0)) {
for (int i = 0; i < SOC_DMA2D_RX_CHANNELS_PER_GROUP; i++) {
dma2d_ll_rx_abort(DMA2D_LL_GET_HW(0), i, true);
while (!dma2d_ll_rx_is_reset_avail(DMA2D_LL_GET_HW(0), i));
}
for (int i = 0; i < SOC_DMA2D_TX_CHANNELS_PER_GROUP; i++) {
dma2d_ll_tx_abort(DMA2D_LL_GET_HW(0), i, true);
while (!dma2d_ll_tx_is_reset_avail(DMA2D_LL_GET_HW(0), i));
}
}
if (dw_gdma_ll_is_bus_clock_enabled(0)) {
for (int i = 0; i < DW_GDMA_LL_CHANNELS_PER_GROUP; i++) {
dw_gdma_ll_channel_abort(DW_GDMA_LL_GET_HW(0), i);
}
}
// Set Peripheral clk rst
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_TIMERGRP1);
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_STIMER);
@@ -47,7 +77,6 @@ void IRAM_ATTR esp_system_reset_modules_on_exit(void)
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART2_CORE);
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART3_CORE);
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART4_CORE);
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_GDMA);
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN2_REG, HP_SYS_CLKRST_REG_RST_EN_ADC);
// Clear Peripheral clk rst
@@ -60,7 +89,6 @@ void IRAM_ATTR esp_system_reset_modules_on_exit(void)
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART2_CORE);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART3_CORE);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART4_CORE);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_GDMA);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN2_REG, HP_SYS_CLKRST_REG_RST_EN_ADC);
#if CONFIG_ESP32P4_REV_MIN_FULL <= 100