Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DNM] Px4 firmware nuttx 10.3.0+ serial fixes testing #285

Draft
wants to merge 8 commits into
base: px4_firmware_nuttx-10.3.0+
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 27 additions & 4 deletions arch/arm/src/imxrt/imxrt_edma.c
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,8 @@ static void imxrt_dmaterminate(struct imxrt_dmach_s *dmach, int result)
uintptr_t regaddr;
uint8_t regval8;
uint8_t chan;
edma_callback_t callback;
void *arg;

/* Disable channel ERROR interrupts */

Expand Down Expand Up @@ -511,14 +513,17 @@ static void imxrt_dmaterminate(struct imxrt_dmach_s *dmach, int result)

/* Perform the DMA complete callback */

if (dmach->callback)
{
dmach->callback((DMACH_HANDLE)dmach, dmach->arg, true, result);
}
callback = dmach->callback;
arg = dmach->arg;

dmach->callback = NULL;
dmach->arg = NULL;
dmach->state = IMXRT_DMA_IDLE;

if (callback)
{
callback((DMACH_HANDLE)dmach, arg, true, result);
}
}

/****************************************************************************
Expand Down Expand Up @@ -1312,6 +1317,24 @@ unsigned int imxrt_dmach_getcount(DMACH_HANDLE handle)
return remaining;
}

/****************************************************************************
* Name: imxrt_dmach_idle
*
* Description:
* This function checks if the dma is idle
*
* Returned Value:
* 0 - if idle
* !0 - not
*
****************************************************************************/

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;
}

/****************************************************************************
* Name: imxrt_dmasample
*
Expand Down
14 changes: 14 additions & 0 deletions arch/arm/src/imxrt/imxrt_edma.h
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,20 @@ void imxrt_dmach_stop(DMACH_HANDLE handle);

unsigned int imxrt_dmach_getcount(DMACH_HANDLE handle);

/****************************************************************************
* Name: imxrt_dmach_idle
*
* Description:
* This function checks if the dma is idle
*
* Returned Value:
* 0 - if idle
* !0 - not
*
****************************************************************************/

unsigned int imxrt_dmach_idle(DMACH_HANDLE handle);

/****************************************************************************
* Name: imxrt_dmasample
*
Expand Down
78 changes: 57 additions & 21 deletions arch/arm/src/imxrt/imxrt_serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -760,7 +760,6 @@ struct imxrt_uart_s
#ifdef SERIAL_HAVE_TXDMA
const unsigned int dma_txreqsrc; /* DMAMUX source of TX DMA request */
DMACH_HANDLE txdma; /* currently-open trasnmit DMA stream */
sem_t txdmasem; /* Indicate TX DMA completion */
#endif

/* RX DMA state */
Expand All @@ -770,6 +769,10 @@ struct imxrt_uart_s
DMACH_HANDLE rxdma; /* currently-open receive DMA stream */
bool rxenable; /* DMA-based reception en/disable */
uint32_t rxdmanext; /* Next byte in the DMA buffer to be read */
#ifdef CONFIG_ARMV7M_DCACHE
uint32_t rxdmaavail; /* Number of bytes available without need to
* to invalidate the data cache */
#endif
char *const rxfifo; /* Receive DMA buffer */
#endif
};
Expand Down Expand Up @@ -1056,7 +1059,7 @@ static char g_lpuart8rxbuffer[CONFIG_LPUART8_RXBUFSIZE];
static char g_lpuart8txbuffer[LPUART8_TXBUFSIZE_ADJUSTED] \
LPUART8_TXBUFSIZE_ALGN;
#endif

#ifdef CONFIG_IMXRT_LPUART9
static char g_lpuart9rxbuffer[CONFIG_LPUART9_RXBUFSIZE];
static char g_lpuart9txbuffer[LPUART9_TXBUFSIZE_ADJUSTED]
Expand Down Expand Up @@ -2018,9 +2021,6 @@ static int imxrt_dma_setup(struct uart_dev_s *dev)
{
return -EBUSY;
}

nxsem_init(&priv->txdmasem, 0, 1);
nxsem_set_protocol(&priv->txdmasem, SEM_PRIO_NONE);
}

/* Enable Tx DMA for the UART */
Expand Down Expand Up @@ -2075,6 +2075,9 @@ static int imxrt_dma_setup(struct uart_dev_s *dev)
*/

priv->rxdmanext = 0;
#ifdef CONFIG_ARMV7M_DCACHE
priv->rxdmaavail = 0;
#endif

/* Enable receive Rx DMA for the UART */

Expand Down Expand Up @@ -2221,7 +2224,6 @@ static void imxrt_dma_shutdown(struct uart_dev_s *dev)

imxrt_dmach_free(priv->txdma);
priv->txdma = NULL;
nxsem_destroy(&priv->txdmasem);
}
#endif
}
Expand Down Expand Up @@ -2895,25 +2897,56 @@ static bool imxrt_rxflowcontrol(struct uart_dev_s *dev,
static int imxrt_dma_receive(struct uart_dev_s *dev, unsigned int *status)
{
struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
static uint32_t last_nextrx = -1;
uint32_t nextrx = imxrt_dma_nextrx(priv);
int c = 0;

/* Check if more data is available */

if (nextrx != priv->rxdmanext)
{
/* Now we must ensure the cache is updated if the DMA has
* updated again.
#ifdef CONFIG_ARMV7M_DCACHE
/* If the data cache is enabled, then we will also need to manage
* cache coherency. Are any bytes available in the currently coherent
* region of the data cache?
*/

if (last_nextrx != nextrx)
if (priv->rxdmaavail == 0)
{
up_invalidate_dcache((uintptr_t)priv->rxfifo,
(uintptr_t)priv->rxfifo + RXDMA_BUFFER_SIZE);
last_nextrx = nextrx;
uint32_t rxdmaavail;
uintptr_t addr;

/* No.. then we will have to invalidate additional space in the Rx
* DMA buffer.
*/

if (nextrx > priv->rxdmanext)
{
/* Number of available bytes */

rxdmaavail = nextrx - priv->rxdmanext;
}
else
{
/* Number of available bytes up to the end of RXDMA buffer */

rxdmaavail = RXDMA_BUFFER_SIZE - priv->rxdmanext;
}

/* Invalidate the DMA buffer range */

addr = (uintptr_t)&priv->rxfifo[priv->rxdmanext];
up_invalidate_dcache(addr, addr + rxdmaavail);

/* We don't need to invalidate the data cache for the next
* rxdmaavail number of next bytes.
*/

priv->rxdmaavail = rxdmaavail;
}

priv->rxdmaavail--;
#endif

/* Now read from the DMA buffer */

c = priv->rxfifo[priv->rxdmanext];
Expand Down Expand Up @@ -2978,6 +3011,9 @@ static void imxrt_dma_reenable(struct imxrt_uart_s *priv)
*/

priv->rxdmanext = 0;
#ifdef CONFIG_ARMV7M_DCACHE
priv->rxdmaavail = 0;
#endif

/* Start the DMA channel, and arrange for callbacks at the half and
* full points in the FIFO. This ensures that we have half a FIFO
Expand Down Expand Up @@ -3042,8 +3078,9 @@ static bool imxrt_dma_rxavailable(struct uart_dev_s *dev)
* Name: imxrt_dma_txcallback
*
* Description:
* This function clears dma buffer at complete of DMA transfer and wakes up
* threads waiting for space in buffer.
* This function clears dma buffer at completion of DMA transfer. It wakes
* up threads waiting for space in buffer and restarts the DMA if there is
* more data to send.
*
****************************************************************************/

Expand All @@ -3052,19 +3089,20 @@ static void imxrt_dma_txcallback(DMACH_HANDLE handle, void *arg, bool done,
int result)
{
struct imxrt_uart_s *priv = (struct imxrt_uart_s *)arg;

/* Update 'nbytes' indicating number of bytes actually transferred by DMA.
* This is important to free TX buffer space by 'uart_xmitchars_done'.
*/

priv->dev.dmatx.nbytes = priv->dev.dmatx.length + priv->dev.dmatx.nlength;

/* Adjust the pointers */
/* Adjust the pointers and unblock writers */

uart_xmitchars_done(&priv->dev);

/* Release waiter */
/* Send more data if available */

nxsem_post(&priv->txdmasem);
imxrt_dma_txavailable(&priv->dev);
}
#endif

Expand All @@ -3083,9 +3121,7 @@ static void imxrt_dma_txavailable(struct uart_dev_s *dev)

/* Only send when the DMA is idle */

int rv = nxsem_trywait(&priv->txdmasem);

if (rv == 0)
if (imxrt_dmach_idle(priv->txdma) == 0)
{
uart_xmitchars_dma(dev);
}
Expand Down
33 changes: 28 additions & 5 deletions arch/arm/src/s32k3xx/s32k3xx_edma.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/****************************************************************************
* arch/arm/src/s32k3xx/s32k3xx_edma.c
*
* Copyright (C) 2019, 2021 Gregory Nutt. All rights reserved.
* Copyright (C) 2019, 2021, 2023 Gregory Nutt. All rights reserved.
* Copyright 2022 NXP
* Authors: Gregory Nutt <[email protected]>
* David Sidrane <[email protected]>
Expand Down Expand Up @@ -733,6 +733,8 @@ static void s32k3xx_dmaterminate(struct s32k3xx_dmach_s *dmach, int result)
struct s32k3xx_edmatcd_s *next;
#endif
uint8_t chan;
edma_callback_t callback;
void *arg;

chan = dmach->chan;

Expand Down Expand Up @@ -774,14 +776,17 @@ static void s32k3xx_dmaterminate(struct s32k3xx_dmach_s *dmach, int result)

/* Perform the DMA complete callback */

if (dmach->callback)
{
dmach->callback((DMACH_HANDLE)dmach, dmach->arg, true, result);
}
callback = dmach->callback;
arg = dmach->arg;

dmach->callback = NULL;
dmach->arg = NULL;
dmach->state = S32K3XX_DMA_IDLE;

if (callback)
{
callback((DMACH_HANDLE)dmach, arg, true, result);
}
}

/****************************************************************************
Expand Down Expand Up @@ -1532,6 +1537,24 @@ unsigned int s32k3xx_dmach_getcount(DMACH_HANDLE *handle)
return remaining;
}

/****************************************************************************
* Name: s32k3xx_dmach_idle
*
* Description:
* This function checks if the dma is idle
*
* Returned Value:
* 0 - if idle
* !0 - not
*
****************************************************************************/

unsigned int s32k3xx_dmach_idle(DMACH_HANDLE handle)
{
struct s32k3xx_dmach_s *dmach = (struct s32k3xx_dmach_s *)handle;
return dmach->state == S32K3XX_DMA_IDLE ? 0 : -1;
}

/****************************************************************************
* Name: s32k3xx_dmasample
*
Expand Down
16 changes: 15 additions & 1 deletion arch/arm/src/s32k3xx/s32k3xx_edma.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/****************************************************************************
* arch/arm/src/s32k3xx/s32k3xx_edma.h
*
* Copyright (C) 2019, 2021 Gregory Nutt. All rights reserved.
* Copyright (C) 2019, 2021, 2023 Gregory Nutt. All rights reserved.
* Copyright 2022 NXP
* Authors: Gregory Nutt <[email protected]>
* David Sidrane <[email protected]>
Expand Down Expand Up @@ -431,6 +431,20 @@ void s32k3xx_dmach_stop(DMACH_HANDLE handle);

unsigned int s32k3xx_dmach_getcount(DMACH_HANDLE *handle);

/****************************************************************************
* Name: s32k3xx_dmach_idle
*
* Description:
* This function checks if the dma is idle
*
* Returned Value:
* 0 - if idle
* !0 - not
*
****************************************************************************/

unsigned int s32k3xx_dmach_idle(DMACH_HANDLE handle);

/****************************************************************************
* Name: s32k3xx_dmasample
*
Expand Down
Loading