This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit d9a2e4225d945c2661092de1b4ae218f7368a968 Author: Sarthak Pandey <[email protected]> AuthorDate: Thu Oct 22 23:02:10 2026 +0530 arch/arm/imxrt: fix eDMA NCE error caused by zero-length split transfer - In imxrt_dma_send(), verify dev->dmatx.nlength > 0 before setting up a chained TCD. Chaining a TCD with iter == 0 causes eDMA NCE errors and halts the eDMA engine when HOE is enabled. - In imxrt_dmaterminate(), clear CITER and BITER registers so residual zero-iteration states do not trigger repeated NCE errors on channel re-activation. - In imxrt_dmach_xfrsetup(), return -EINVAL if config->iter is 0. Fixes #20881 Signed-off-by: Sarthak Pandey <[email protected]> --- arch/arm/src/imxrt/imxrt_edma.c | 20 +++++++++++++++++--- arch/arm/src/imxrt/imxrt_serial.c | 2 +- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/arch/arm/src/imxrt/imxrt_edma.c b/arch/arm/src/imxrt/imxrt_edma.c index 52e0149f887..1f787509c0c 100644 --- a/arch/arm/src/imxrt/imxrt_edma.c +++ b/arch/arm/src/imxrt/imxrt_edma.c @@ -472,6 +472,14 @@ static void imxrt_dmaterminate(struct imxrt_dmach_s *dmach, int result) regaddr = IMXRT_EDMA_TCD_DLASTSGA(chan); putreg32(0, regaddr); + /* Clear CITER and BITER to remove error source */ + + regaddr = IMXRT_EDMA_TCD_CITER_ELINK(chan); + putreg16(0, regaddr); + + regaddr = IMXRT_EDMA_TCD_BITER_ELINK(chan); + putreg16(0, regaddr); + #if CONFIG_IMXRT_EDMA_NTCD > 0 /* Return all allocated TCDs to the free list */ @@ -481,10 +489,10 @@ static void imxrt_dmaterminate(struct imxrt_dmach_s *dmach, int result) * if not continue to free tcds in chain */ - next = dmach->flags & EDMA_CONFIG_LOOPDEST ? - NULL : (struct imxrt_edmatcd_s *)tcd->dlastsga; + next = dmach->flags & EDMA_CONFIG_LOOPDEST ? + NULL : (struct imxrt_edmatcd_s *)tcd->dlastsga; - imxrt_tcd_free_nolock(tcd); + imxrt_tcd_free_nolock(tcd); } dmach->head = NULL; @@ -992,6 +1000,11 @@ int imxrt_dmach_xfrsetup(DMACH_HANDLE handle, DEBUGASSERT(dmach != NULL); dmainfo("dmach%u: %p config: %p\n", dmach->chan, dmach, config); + if (config->iter == 0) + { + return -EINVAL; + } + dmach->flags = config->flags; #if CONFIG_IMXRT_EDMA_NTCD > 0 @@ -1299,6 +1312,7 @@ unsigned int imxrt_dmach_getcount(DMACH_HANDLE handle) unsigned int imxrt_dmach_idle(DMACH_HANDLE handle) { struct imxrt_dmach_s *dmach = (struct imxrt_dmach_s *)handle; + return dmach->state == IMXRT_DMA_IDLE ? 0 : -1; } diff --git a/arch/arm/src/imxrt/imxrt_serial.c b/arch/arm/src/imxrt/imxrt_serial.c index 2f4a0872c3f..905ff1188c7 100644 --- a/arch/arm/src/imxrt/imxrt_serial.c +++ b/arch/arm/src/imxrt/imxrt_serial.c @@ -3604,7 +3604,7 @@ static void imxrt_dma_send(struct uart_dev_s *dev) #if CONFIG_IMXRT_EDMA_NTCD > 1 /* Is this a split transfer? */ - if (dev->dmatx.nbuffer) + if (dev->dmatx.nbuffer && dev->dmatx.nlength > 0) { config.iter = priv->dev.dmatx.nlength; config.saddr = (uint32_t) priv->dev.dmatx.nbuffer;
