mirror of
https://github.com/apache/nuttx.git
synced 2026-05-22 22:20:01 +08:00
arch/arm/stm32h7: Fix UART TX DMA getting stuck
When closing a serial port an ongoing TX DMA transfer will be stopped. This can cause one (or multiple) the following: - dev->dmatx.length != 0 - dev->dmatx.nlength != 0 - stm32_dmaresidual returning a non-zero residual This is caused by length/nlength not being set to 0 at startup or during closing. In addition the DMA_SxNDTR register is not set to 0 at startup or during closing. This commit solves the issue by setting the variables and register to 0 during closing. Signed-off-by: Alexander Lerach <alexander@auterion.com> arch/arm/stm32h7: Add review feedback regarding style Removed non-needed spaces. Aligned style of documentation. Signed-off-by: Alexander Lerach <alexander@auterion.com>
This commit is contained in:
committed by
Xiang Xiao
parent
fca1010a5b
commit
a9b258aa68
@@ -159,6 +159,10 @@ struct stm32_dma_ops_s
|
||||
|
||||
void (*dma_setup)(DMA_HANDLE handle, stm32_dmacfg_t *cfg);
|
||||
|
||||
/* Free the DMA */
|
||||
|
||||
void (*dma_free)(DMA_HANDLE handle);
|
||||
|
||||
/* Start the DMA */
|
||||
|
||||
void (*dma_start)(DMA_HANDLE handle, dma_callback_t callback,
|
||||
@@ -185,6 +189,7 @@ struct stm32_dma_ops_s
|
||||
static void stm32_mdma_disable(DMA_CHANNEL dmachan);
|
||||
static int stm32_mdma_interrupt(int irq, void *context, void *arg);
|
||||
static void stm32_mdma_setup(DMA_HANDLE handle, stm32_dmacfg_t *cfg);
|
||||
static void stm32_mdma_free(DMA_HANDLE handle);
|
||||
static void stm32_mdma_start(DMA_HANDLE handle, dma_callback_t callback,
|
||||
void *arg, bool half);
|
||||
static size_t stm32_mdma_residual(DMA_HANDLE handle);
|
||||
@@ -200,6 +205,7 @@ static void stm32_mdma_dump(DMA_HANDLE handle, const char *msg);
|
||||
static void stm32_sdma_disable(DMA_CHANNEL dmachan);
|
||||
static int stm32_sdma_interrupt(int irq, void *context, void *arg);
|
||||
static void stm32_sdma_setup(DMA_HANDLE handle, stm32_dmacfg_t *cfg);
|
||||
static void stm32_sdma_free(DMA_HANDLE handle);
|
||||
static void stm32_sdma_start(DMA_HANDLE handle, dma_callback_t callback,
|
||||
void *arg, bool half);
|
||||
static size_t stm32_sdma_residual(DMA_HANDLE handle);
|
||||
@@ -215,6 +221,7 @@ static void stm32_sdma_dump(DMA_HANDLE handle, const char *msg);
|
||||
static void stm32_bdma_disable(DMA_CHANNEL dmachan);
|
||||
static int stm32_bdma_interrupt(int irq, void *context, void *arg);
|
||||
static void stm32_bdma_setup(DMA_HANDLE handle, stm32_dmacfg_t *cfg);
|
||||
static void stm32_bdma_free(DMA_HANDLE handle);
|
||||
static void stm32_bdma_start(DMA_HANDLE handle, dma_callback_t callback,
|
||||
void *arg, bool half);
|
||||
static size_t stm32_bdma_residual(DMA_HANDLE handle);
|
||||
@@ -265,6 +272,7 @@ struct stm32_dma_ops_s g_dma_ops[DMA_CONTROLLERS] =
|
||||
.dma_disable = stm32_mdma_disable,
|
||||
.dma_interrupt = stm32_mdma_interrupt,
|
||||
.dma_setup = stm32_mdma_setup,
|
||||
.dma_free = stm32_mdma_free,
|
||||
.dma_start = stm32_mdma_start,
|
||||
.dma_residual = stm32_mdma_residual,
|
||||
#ifdef CONFIG_STM32H7_DMACAPABLE
|
||||
@@ -287,6 +295,7 @@ struct stm32_dma_ops_s g_dma_ops[DMA_CONTROLLERS] =
|
||||
.dma_disable = stm32_sdma_disable,
|
||||
.dma_interrupt = stm32_sdma_interrupt,
|
||||
.dma_setup = stm32_sdma_setup,
|
||||
.dma_free = stm32_sdma_free,
|
||||
.dma_start = stm32_sdma_start,
|
||||
.dma_residual = stm32_sdma_residual,
|
||||
#ifdef CONFIG_STM32H7_DMACAPABLE
|
||||
@@ -309,6 +318,7 @@ struct stm32_dma_ops_s g_dma_ops[DMA_CONTROLLERS] =
|
||||
.dma_disable = stm32_sdma_disable,
|
||||
.dma_interrupt = stm32_sdma_interrupt,
|
||||
.dma_setup = stm32_sdma_setup,
|
||||
.dma_free = stm32_sdma_free,
|
||||
.dma_start = stm32_sdma_start,
|
||||
.dma_residual = stm32_sdma_residual,
|
||||
#ifdef CONFIG_STM32H7_DMACAPABLE
|
||||
@@ -331,6 +341,7 @@ struct stm32_dma_ops_s g_dma_ops[DMA_CONTROLLERS] =
|
||||
.dma_disable = stm32_bdma_disable,
|
||||
.dma_interrupt = stm32_bdma_interrupt,
|
||||
.dma_setup = stm32_bdma_setup,
|
||||
.dma_free = stm32_bdma_free,
|
||||
.dma_start = stm32_bdma_start,
|
||||
.dma_residual = stm32_bdma_residual,
|
||||
#ifdef CONFIG_STM32H7_DMACAPABLE
|
||||
@@ -959,6 +970,21 @@ static void stm32_mdma_setup(DMA_HANDLE handle, stm32_dmacfg_t *cfg)
|
||||
#warning stm32_mdma_setup not implemented
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_mdma_free
|
||||
*
|
||||
* Description:
|
||||
* Free master DMA
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void stm32_mdma_free(DMA_HANDLE handle)
|
||||
{
|
||||
DMA_CHANNEL dmachan = (DMA_CHANNEL)handle;
|
||||
|
||||
dmachan_putreg(dmachan, STM32_BDMACH_CNDTR_OFFSET, 0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_mdma_start
|
||||
*
|
||||
@@ -1393,6 +1419,21 @@ static void stm32_sdma_setup(DMA_HANDLE handle, stm32_dmacfg_t *cfg)
|
||||
dmachan_putreg(dmachan, STM32_DMA_SCR_OFFSET, regval);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_sdma_sfree
|
||||
*
|
||||
* Description:
|
||||
* Free master DMA
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void stm32_sdma_free(DMA_HANDLE handle)
|
||||
{
|
||||
DMA_CHANNEL dmachan = (DMA_CHANNEL)handle;
|
||||
|
||||
dmachan_putreg(dmachan, STM32_DMA_SNDTR_OFFSET, 0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_sdma_start
|
||||
*
|
||||
@@ -1961,6 +2002,21 @@ static void stm32_bdma_setup(DMA_HANDLE handle, stm32_dmacfg_t *cfg)
|
||||
dmachan_putreg(dmachan, STM32_BDMACH_CCR_OFFSET, regval);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_bdma_sfree
|
||||
*
|
||||
* Description:
|
||||
* Free master DMA
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void stm32_bdma_free(DMA_HANDLE handle)
|
||||
{
|
||||
DMA_CHANNEL dmachan = (DMA_CHANNEL)handle;
|
||||
|
||||
dmachan_putreg(dmachan, STM32_BDMACH_CNDTR_OFFSET, 0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32_bdma_start
|
||||
*
|
||||
@@ -2471,6 +2527,10 @@ void stm32_dmafree(DMA_HANDLE handle)
|
||||
controller = dmachan->ctrl;
|
||||
DEBUGASSERT(controller >= MDMA && controller <= BDMA);
|
||||
|
||||
/* Do controller specific free */
|
||||
|
||||
g_dma_ops[controller].dma_free(handle);
|
||||
|
||||
/* Get DMAMUX associated with DMA controller */
|
||||
|
||||
dmamux = g_dma[controller].dmamux;
|
||||
|
||||
@@ -2382,6 +2382,9 @@ static void up_dma_shutdown(struct uart_dev_s *dev)
|
||||
|
||||
stm32_dmafree(priv->txdma);
|
||||
priv->txdma = NULL;
|
||||
|
||||
dev->dmatx.length = 0;
|
||||
dev->dmatx.nlength = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user