mirror of
https://github.com/espressif/esp-idf
synced 2025-03-09 17:19:09 -04:00
fix(dma): abort the axi dma gracefully on CPU SW reset
This commit is contained in:
parent
5bb41c4932
commit
605fb6e894
@ -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
|
||||
*/
|
||||
@ -28,6 +28,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)
|
||||
{
|
||||
@ -38,6 +42,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);
|
||||
@ -48,7 +78,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
|
||||
@ -61,7 +90,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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -14,16 +14,16 @@ void dma2d_hal_init(dma2d_hal_context_t *hal, int group_id)
|
||||
|
||||
void dma2d_hal_tx_reset_channel(dma2d_hal_context_t *hal, uint32_t channel)
|
||||
{
|
||||
dma2d_ll_tx_disable_cmd(hal->dev, channel, true);
|
||||
dma2d_ll_tx_abort(hal->dev, channel, true);
|
||||
while (!dma2d_ll_tx_is_reset_avail(hal->dev, channel));
|
||||
dma2d_ll_tx_reset_channel(hal->dev, channel);
|
||||
dma2d_ll_tx_disable_cmd(hal->dev, channel, false);
|
||||
dma2d_ll_tx_abort(hal->dev, channel, false);
|
||||
}
|
||||
|
||||
void dma2d_hal_rx_reset_channel(dma2d_hal_context_t *hal, uint32_t channel)
|
||||
{
|
||||
dma2d_ll_rx_disable_cmd(hal->dev, channel, true);
|
||||
dma2d_ll_rx_abort(hal->dev, channel, true);
|
||||
while (!dma2d_ll_rx_is_reset_avail(hal->dev, channel));
|
||||
dma2d_ll_rx_reset_channel(hal->dev, channel);
|
||||
dma2d_ll_rx_disable_cmd(hal->dev, channel, false);
|
||||
dma2d_ll_rx_abort(hal->dev, channel, false);
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
void dw_gdma_hal_init(dw_gdma_hal_context_t *hal, const dw_gdma_hal_config_t *config)
|
||||
{
|
||||
hal->dev = DW_GDMA_LL_GET_HW();
|
||||
hal->dev = DW_GDMA_LL_GET_HW(0);
|
||||
dw_gdma_ll_reset(hal->dev);
|
||||
dw_gdma_ll_enable_controller(hal->dev, true);
|
||||
dw_gdma_ll_enable_intr_global(hal->dev, true);
|
||||
|
@ -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
|
||||
*/
|
||||
@ -195,6 +195,15 @@ static inline void axi_dma_ll_rx_stop(axi_dma_dev_t *dev, uint32_t channel)
|
||||
dev->in[channel].conf.in_link1.inlink_stop_chn = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort the RX channel, stop the undergoing transfer immediately
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void axi_dma_ll_rx_abort(axi_dma_dev_t *dev, uint32_t channel, bool abort)
|
||||
{
|
||||
dev->in[channel].conf.in_conf0.in_cmd_disable_chn = abort;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Restart a new inlink right after the last descriptor
|
||||
*/
|
||||
@ -291,6 +300,15 @@ static inline void axi_dma_ll_rx_enable_ext_mem_ecc_aes_access(axi_dma_dev_t *de
|
||||
dev->in[channel].conf.in_conf0.in_ecc_aes_en_chn = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return if the channel is ready to be reset
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline bool axi_dma_ll_rx_is_reset_avail(axi_dma_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
return dev->in_reset_avail_chn[channel].in_reset_avail_chn;
|
||||
}
|
||||
|
||||
///////////////////////////////////// TX /////////////////////////////////////////
|
||||
/**
|
||||
* @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)
|
||||
dev->out[channel].conf.out_link1.outlink_stop_chn = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort the TX channel, stop the undergoing transfer immediately
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void axi_dma_ll_tx_abort(axi_dma_dev_t *dev, uint32_t channel, bool abort)
|
||||
{
|
||||
dev->out[channel].conf.out_conf0.out_cmd_disable_chn = abort;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Restart a new outlink right after the last descriptor
|
||||
*/
|
||||
@ -507,6 +534,15 @@ static inline void axi_dma_ll_tx_enable_ext_mem_ecc_aes_access(axi_dma_dev_t *de
|
||||
dev->out[channel].conf.out_conf0.out_ecc_aes_en_chn = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return if the channel is ready to be reset
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline bool axi_dma_ll_tx_is_reset_avail(axi_dma_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
return dev->out_reset_avail_chn[channel].out_reset_avail_chn;
|
||||
}
|
||||
|
||||
///////////////////////////////////// CRC-TX /////////////////////////////////////////
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -105,6 +105,16 @@ static inline void dma2d_ll_reset_register(int group_id)
|
||||
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
|
||||
#define dma2d_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; dma2d_ll_reset_register(__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Check if the bus clock is enabled for the DMA module
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline bool dma2d_ll_is_bus_clock_enabled(int group_id)
|
||||
{
|
||||
(void) group_id;
|
||||
return HP_SYS_CLKRST.soc_clk_ctrl1.reg_dma2d_sys_clk_en;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable 2D-DMA module
|
||||
*/
|
||||
@ -278,7 +288,7 @@ static inline bool dma2d_ll_rx_is_reset_avail(dma2d_dev_t *dev, uint32_t channel
|
||||
* @brief Disable 2D-DMA RX channel via a command
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void dma2d_ll_rx_disable_cmd(dma2d_dev_t *dev, uint32_t channel, bool disable)
|
||||
static inline void dma2d_ll_rx_abort(dma2d_dev_t *dev, uint32_t channel, bool disable)
|
||||
{
|
||||
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);
|
||||
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
|
||||
* @brief Disable 2D-DMA TX channel via a command
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void dma2d_ll_tx_disable_cmd(dma2d_dev_t *dev, uint32_t channel, bool disable)
|
||||
static inline void dma2d_ll_tx_abort(dma2d_dev_t *dev, uint32_t channel, bool disable)
|
||||
{
|
||||
dev->out_channel[channel].out_conf0.out_cmd_disable_chn = disable;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -15,7 +15,7 @@
|
||||
#include "soc/hp_sys_clkrst_struct.h"
|
||||
#include "soc/reg_base.h"
|
||||
|
||||
#define DW_GDMA_LL_GET_HW() (&DW_GDMA)
|
||||
#define DW_GDMA_LL_GET_HW(id) (((id) == 0) ? (&DW_GDMA) : NULL)
|
||||
|
||||
#define DW_GDMA_LL_GROUPS 1 // there's one DW-GDMA instance connected to the AXI bus
|
||||
#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)
|
||||
/**
|
||||
* @brief Reset the DMA module
|
||||
*/
|
||||
static inline void dw_gdma_ll_reset_register(int group_id)
|
||||
static inline void _dw_gdma_ll_reset_register(int group_id)
|
||||
{
|
||||
(void)group_id;
|
||||
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)
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
|
||||
#define dw_gdma_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; dw_gdma_ll_reset_register(__VA_ARGS__)
|
||||
#define dw_gdma_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; _dw_gdma_ll_reset_register(__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Check if the bus clock is enabled for the DMA module
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline bool dw_gdma_ll_is_bus_clock_enabled(int group_id)
|
||||
{
|
||||
(void) group_id;
|
||||
return HP_SYS_CLKRST.soc_clk_ctrl1.reg_gdma_sys_clk_en && HP_SYS_CLKRST.soc_clk_ctrl0.reg_gdma_cpu_clk_en;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
* @param dev Pointer to the DW_GDMA registers
|
||||
* @param channel Channel number
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void dw_gdma_ll_channel_abort(dw_gdma_dev_t *dev, uint8_t channel)
|
||||
{
|
||||
// the abort bit clears itself after the abort is done
|
||||
dev->chen1.val = 0x101 << channel;
|
||||
while (dev->chen1.val & (0x101 << channel));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
*/
|
||||
@ -108,6 +108,19 @@ static inline void _gdma_ll_enable_bus_clock(int group_id, bool enable)
|
||||
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
|
||||
#define gdma_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _gdma_ll_enable_bus_clock(__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Check if the bus clock is enabled for the DMA module
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline bool gdma_ll_is_bus_clock_enabled(int group_id)
|
||||
{
|
||||
if (group_id == 0) {
|
||||
return HP_SYS_CLKRST.soc_clk_ctrl1.reg_ahb_pdma_sys_clk_en;
|
||||
} else {
|
||||
return HP_SYS_CLKRST.soc_clk_ctrl1.reg_axi_pdma_sys_clk_en;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the DMA module
|
||||
*/
|
||||
|
@ -63,7 +63,7 @@ static inline void lcd_ll_enable_bus_clock(int group_id, bool enable)
|
||||
*
|
||||
* @param group_id Group ID
|
||||
*/
|
||||
static inline void lcd_ll_reset_register(int group_id)
|
||||
static inline void _lcd_ll_reset_register(int group_id)
|
||||
{
|
||||
(void)group_id;
|
||||
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)
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_RC_ATOMIC_ENV variable in advance
|
||||
#define lcd_ll_reset_register(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; lcd_ll_reset_register(__VA_ARGS__)
|
||||
#define lcd_ll_reset_register(...) (void)__DECLARE_RCC_RC_ATOMIC_ENV; _lcd_ll_reset_register(__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Enable clock gating
|
||||
|
Loading…
x
Reference in New Issue
Block a user