Squashed commit of the following:
arch/arm/src/imxrt: Add structures to support list of TCDs for Scatter/Gather DMA. arch/arm/src/imxrt: Add eDMA imxrt_dmach_initconfig(). arch/arm/src/imxrt: Add eDMA imxrt_tcd_instantiate(). arch/arm/src/imxrt: Replacing some of the logic cloned from SAMv7 XDMAC with eDMA logic from NXP sample code. I am thinking that the eDMA is too complex to force into the same pattern as for other MCUs. arch/arms/src/imxrt/imxrt_edma.c: Add support for in-memory TCDs. arch/arm/src/imxrt/chip: Add an in-memory representation of the TCD in imxrt_edma.h
This commit is contained in:
parent
f837f2231f
commit
1cf676344e
@ -337,25 +337,61 @@ endmenu # Memory Configuration
|
||||
menu "eDMA Configuration"
|
||||
depends on IMXRT_EDMA
|
||||
|
||||
config IMXRT_EDMA_NTCD
|
||||
int "Number of transfer descriptors"
|
||||
default 0
|
||||
---help---
|
||||
Number of pre-allocated transfer descriptors. Needed for scatter-
|
||||
gather DMA. Make to be set to zero to disable in-memory TCDs in
|
||||
which case only the TCD channel registers will be used and scatter-
|
||||
will not be supported.
|
||||
|
||||
config IMXRT_EDMA_ERCA
|
||||
bool "Round Robin Channel Arbitration"
|
||||
default n
|
||||
---help---
|
||||
Normally, a fixed priority arbitration is used for channel
|
||||
selection. If this option is selected, round robin arbitration is
|
||||
used for channel selection.
|
||||
|
||||
config IMXRT_EDMA_HOE
|
||||
bool "Halt On Error"
|
||||
default y
|
||||
---help---
|
||||
Any error causes the HALT bit to set. Subsequently, all service
|
||||
requests are ignored until the HALT bit is cleared.
|
||||
|
||||
config IMXRT_EDMA_CLM
|
||||
bool "Continuous Link Mode"
|
||||
default n
|
||||
---help---
|
||||
By default, A minor loop channel link made to itself goes through
|
||||
channel arbitration before being activated again. If this option is
|
||||
selected, a minor loop channel link made to itself does not go
|
||||
through channel arbitration before being activated again. Upon minor
|
||||
loop completion, the channel activates again if that channel has a
|
||||
minor loop channel link enabled and the link channel is itself. This
|
||||
effectively applies the minor loop offsets and restarts the next
|
||||
minor loop.
|
||||
|
||||
config IMXRT_EDMA_EMLIM
|
||||
bool "Minor Loop Mapping"
|
||||
default n
|
||||
---help---
|
||||
Normally TCD word 2 is a 32-bit NBYTES field. When this option is
|
||||
enabled, TCD word 2 is redefined to include individual enable fields,
|
||||
an offset field, and the NBYTES field. The individual enable fields
|
||||
allow the minor loop offset to be applied to the source address, the
|
||||
destination address, or both. The NBYTES field is reduced when either
|
||||
offset is enabled.
|
||||
|
||||
config IMXRT_EDMA_EDBG
|
||||
bool "Enable Debug"
|
||||
default n
|
||||
---help---
|
||||
When in debug mode, the DMA stalls the start of a new channel. Executing
|
||||
channels are allowed to complete. Channel execution resumes when the
|
||||
system exits debug mode or the EDBG bit is cleared
|
||||
|
||||
endmenu # eDMA Global Configuration
|
||||
endif # ARCH_CHIP_IMXRT
|
||||
|
@ -44,7 +44,7 @@
|
||||
#include "chip/imxrt_memorymap.h"
|
||||
|
||||
/****************************************************************************************************
|
||||
* Pre-processor definitions
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************************************/
|
||||
|
||||
#define IMXRT_EDMA_NCHANNELS 32
|
||||
@ -103,6 +103,8 @@
|
||||
#define IMXRT_EDMA_DCHPRI29_OFFSET 0x011e /* Channel 0 Priority */
|
||||
#define IMXRT_EDMA_DCHPRI28_OFFSET 0x011f /* Channel 1 Priority */
|
||||
|
||||
/* Transfer Control Descriptor (TCD) */
|
||||
|
||||
#define IMXRT_EDMA_TCD_OFFSET(n) (0x1000 + ((n) << 5))
|
||||
#define IMXRT_EDMA_TCD_SADDR_OFFSET 0x0000 /* TCD Source Address */
|
||||
#define IMXRT_EDMA_TCD_SOFF_OFFSET 0x0004 /* TCD Signed Source Address Offset */
|
||||
@ -566,6 +568,8 @@
|
||||
#define IMXRT_EDMA_DCHPRI29 (IMXRT_EDMA_BASE + IMXRT_EDMA_DCHPRI2_OFFSET)
|
||||
#define IMXRT_EDMA_DCHPRI28 (IMXRT_EDMA_BASE + IMXRT_EDMA_DCHPRI3_OFFSET)
|
||||
|
||||
/* Transfer Control Descriptor (TCD) */
|
||||
|
||||
#define IMXRT_EDMA_TCD_BASE(n) (IMXRT_EDMA_BASE + IMXRT_EDMA_TCD_OFFSET(n))
|
||||
#define IMXRT_EDMA_TCD_SADDR(n) (IMXRT_EDMA_TCD_BASE(n) + IMXRT_EDMA_TCD_SADDR_OFFSET)
|
||||
#define IMXRT_EDMA_TCD_SOFF(n) (IMXRT_EDMA_TCD_BASE(n) + IMXRT_EDMA_TCD_SOFF_OFFSET)
|
||||
@ -1125,6 +1129,7 @@
|
||||
|
||||
#define EDMA_TCD_ATTR_DSIZE_SHIFT (0) /* Bits 0-2: Destination data transfer size */
|
||||
#define EDMA_TCD_ATTR_DSIZE_MASK (7 << EDMA_TCD_ATTR_DSIZE_SHIFT)
|
||||
# define EDMA_TCD_ATTR_DSIZE(n) ((uint32_t)(n) << EDMA_TCD_ATTR_DSIZE_SHIFT) /* 8-bit */
|
||||
# define EDMA_TCD_ATTR_DSIZE_8BIT (TCD_ATTR_SIZE_8BIT << EDMA_TCD_ATTR_DSIZE_SHIFT) /* 8-bit */
|
||||
# define EDMA_TCD_ATTR_DSIZE_16BIT (TCD_ATTR_SIZE_16BIT << EDMA_TCD_ATTR_DSIZE_SHIFT) /* 16-bit */
|
||||
# define EDMA_TCD_ATTR_DSIZE_32BIT (TCD_ATTR_SIZE_32BIT << EDMA_TCD_ATTR_DSIZE_SHIFT) /* 32-bit */
|
||||
@ -1135,6 +1140,7 @@
|
||||
# define EDMA_TCD_ATTR_DMOD(n) ((uint32_t)(n) << EDMA_TCD_ATTR_DMOD_SHIFT)
|
||||
#define EDMA_TCD_ATTR_SSIZE_SHIFT (8) /* Bits 8-10: Source data transfer size */
|
||||
#define EDMA_TCD_ATTR_SSIZE_MASK (7 << EDMA_TCD_ATTR_SSIZE_SHIFT)
|
||||
# define EDMA_TCD_ATTR_SSIZE(n) ((uint32_t)(n) << EDMA_TCD_ATTR_SSIZE_SHIFT) /* 8-bit */
|
||||
# define EDMA_TCD_ATTR_SSIZE_8BIT (TCD_ATTR_SIZE_8BIT << EDMA_TCD_ATTR_SSIZE_SHIFT) /* 8-bit */
|
||||
# define EDMA_TCD_ATTR_SSIZE_16BIT (TCD_ATTR_SIZE_16BIT << EDMA_TCD_ATTR_SSIZE_SHIFT) /* 16-bit */
|
||||
# define EDMA_TCD_ATTR_SSIZE_32BIT (TCD_ATTR_SIZE_32BIT << EDMA_TCD_ATTR_SSIZE_SHIFT) /* 32-bit */
|
||||
@ -1237,4 +1243,25 @@
|
||||
#define EDMA_TCD_BITER_ELINK_ELINK (1 << 15) /* Bit 15: Enable channel-to-channel linking
|
||||
* on minor-loop complete */
|
||||
|
||||
/****************************************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************************************/
|
||||
|
||||
/* In-memory representation of the 32-byte Transfer Control Descriptor (TCD) */
|
||||
|
||||
struct imxrt_edmatcd_s
|
||||
{
|
||||
uint32_t saddr; /* Offset: 0x0000 TCD Source Address */
|
||||
uint16_t soff; /* Offset: 0x0004 TCD Signed Source Address Offset */
|
||||
uint16_t attr; /* Offset: 0x0006 TCD Transfer Attributes */
|
||||
uint32_t nbytes; /* Offset: 0x0008 TCD Signed Minor Loop Offset / Byte Count */
|
||||
uint32_t slast; /* Offset: 0x000c TCD Last Source Address Adjustment */
|
||||
uint32_t daddr; /* Offset: 0x0010 TCD Destination Address */
|
||||
uint16_t doff; /* Offset: 0x0014 TCD Signed Destination Address Offset */
|
||||
uint16_t citer; /* Offset: 0x0016 TCD Current Minor Loop Link, Major Loop Count */
|
||||
uint32_t dlastsga; /* Offset: 0x0018 TCD Last Destination Address Adjustment/Scatter Gather Address */
|
||||
uint16_t csr; /* Offset: 0x001c TCD Control and Status */
|
||||
uint16_t biter; /* Offset: 0x001e TCD Beginning Minor Loop Link, Major Loop Count */
|
||||
};
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_IMXRT_CHIP_IMXRT_EDMA_H */
|
||||
|
@ -4,6 +4,13 @@
|
||||
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Portions of the eDMA logic derive from NXP sample code which has a compatible
|
||||
* BSD 3-clause license:
|
||||
*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
@ -43,6 +50,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <semaphore.h>
|
||||
#include <queue.h>
|
||||
#include <debug.h>
|
||||
#include <errno.h>
|
||||
|
||||
@ -66,6 +74,32 @@
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* TCD Alignment.
|
||||
*
|
||||
* eDMA TCDs must be aligned with the D-Cache line boundaries to facilitate
|
||||
* cache operations on the TCDs when the D-Cache is enabled.
|
||||
*
|
||||
* NOTE: The TCDs are 32-bytes in length. We implicitly assume that the
|
||||
* D-Cache line size is also 32-bits. Otherwise, padding would be required
|
||||
* at the ends of the TCDS and buffers to protect data after the end of from
|
||||
* invalidation.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_ARMV7M_DCACHE
|
||||
/* Align to the cache line size which we assume is >= 8 */
|
||||
|
||||
# define EDMA_ALIGN ARMV7M_DCACHE_LINESIZE
|
||||
# define EDMA_ALIGN_MASK (EDMA_ALIGN-1)
|
||||
# define EDMA_ALIGN_UP(n) (((n) + EDMA_ALIGN_MASK) & ~EDMA_ALIGN_MASK)
|
||||
|
||||
#else
|
||||
/* Special alignment is not required in this case, but we will align to 8-bytes */
|
||||
|
||||
# define EDMA_ALIGN 8
|
||||
# define EDMA_ALIGN_MASK 7
|
||||
# define EDMA_ALIGN_UP(n) (((n) + 7) & ~7)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
@ -92,6 +126,16 @@ struct imxrt_dmach_s
|
||||
void *arg; /* Argument passed to callback function */
|
||||
uint32_t rxaddr; /* RX memory address */
|
||||
size_t rxsize; /* Size of RX memory region */
|
||||
|
||||
#if CONFIG_IMXRT_EDMA_NTCD > 0
|
||||
/* That TCD list is linked through the DLAST SGA field. The first transfer
|
||||
* to be performed is at the head of the list. Subsequent TCDs are added at
|
||||
* the tail of the list.
|
||||
*/
|
||||
|
||||
struct imxrt_edmatcd_s *head; /* First TCD in the list */
|
||||
struct imxrt_edmatcd_s *tail; /* Last TCD in the list */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* This structure describes the state of the eDMA controller */
|
||||
@ -101,7 +145,9 @@ struct imxrt_edma_s
|
||||
/* These semaphores protect the DMA channel and descriptor tables */
|
||||
|
||||
sem_t chsem; /* Protects channel table */
|
||||
sem_t dsem; /* Protects descriptor table */
|
||||
#if CONFIG_IMXRT_EDMA_NTCD > 0
|
||||
sem_t dsem; /* Supports wait for free descriptors */
|
||||
#endif
|
||||
|
||||
/* This array describes each DMA channel */
|
||||
|
||||
@ -116,6 +162,17 @@ struct imxrt_edma_s
|
||||
|
||||
static struct imxrt_edma_s g_edma;
|
||||
|
||||
#if CONFIG_IMXRT_EDMA_NTCD > 0
|
||||
/* This is a singly-linked list of free TCDs */
|
||||
|
||||
static sq_queue_t g_tcd_free;
|
||||
|
||||
/* This is a pool of pre-allocated TCDs */
|
||||
|
||||
static struct imxrt_edmatcd_s g_tcd_pool[CONFIG_IMXRT_EDMA_NTCD]
|
||||
__attribute__((aligned(EDMA_ALIGN)));
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
@ -124,7 +181,8 @@ static struct imxrt_edma_s g_edma;
|
||||
* Name: imxrt_takechsem() and imxrt_givechsem()
|
||||
*
|
||||
* Description:
|
||||
* Used to get exclusive access to the DMA channel table
|
||||
* Used to get exclusive access to the DMA channel table for channel
|
||||
* allocation.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
@ -160,6 +218,7 @@ static inline void imxrt_givechsem(void)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_IMXRT_EDMA_NTCD > 0
|
||||
static void imxrt_takedsem(void)
|
||||
{
|
||||
int ret;
|
||||
@ -183,6 +242,36 @@ static inline void imxrt_givedsem(void)
|
||||
{
|
||||
(void)nxsem_post(&g_edma.dsem);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: imxrt_tcd_initialize()
|
||||
*
|
||||
* Description:
|
||||
* Initialize the TCD free list from the pool of pre-allocated TCDs.
|
||||
*
|
||||
* Assumptions:
|
||||
* Called early in the initialization sequence so no special protection is
|
||||
* necessary.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_IMXRT_EDMA_NTCD > 0
|
||||
static inline void imxrt_tcd_initialize(void)
|
||||
{
|
||||
sq_entry_t *tcd;
|
||||
int i;
|
||||
|
||||
/* Add each pre-allocated TCD to the tail of the TCD free list */
|
||||
|
||||
sq_init(&g_tcd_free);
|
||||
for (i = 0; i < CONFIG_IMXRT_EDMA_NTCD; i++)
|
||||
{
|
||||
tcd = (sq_entry_t *)&g_tcd_poll[i];
|
||||
sq_add_last(tcd, &g_tcd_free);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: imxrt_getdmach
|
||||
@ -212,6 +301,130 @@ static inline void imxrt_putdmach(struct imxrt_dmach_s *dmach, uint32_t value,
|
||||
putreg32(value, IMXRT_EDMA_TCD_BASE(dmach->chan) + offset);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: imxrt_tcd_reset
|
||||
*
|
||||
* Description:
|
||||
* Reset all TCD registers to default values. 'tcd' is an 'overlay' that
|
||||
* may refer either to either the TCD register set or to an in-memory TCD
|
||||
* structure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void imxrt_tcd_reset(struct imxrt_edmatcd_s *tcd)
|
||||
{
|
||||
/* Reset channel TCD */
|
||||
|
||||
tcd->saddr = 0;
|
||||
tcd->soff = 0;
|
||||
tcd->attr = 0;
|
||||
tcd->nbytes = 0;
|
||||
tcd->slast = 0;
|
||||
tcd->daddr = 0;
|
||||
tcd->doff = 0;
|
||||
tcd->citer = 0;
|
||||
tcd->dlastsga = 0;
|
||||
|
||||
/* Enable auto disable request feature */
|
||||
|
||||
tcd->csr = EDMA_TCD_CSR_DREQ;
|
||||
tcd->biter = 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: imxrt_tcd_configure
|
||||
*
|
||||
* Description:
|
||||
* Configure all TCD registers to the specified values. 'tcd' is an
|
||||
* 'overlay' that may refer either to either the TCD register set or to an
|
||||
* in-memory TCD structure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_IMXRT_EDMA_NTCD > 0
|
||||
void imxrt_tcd_configure(struct imxrt_edmatcd_s *tcd,
|
||||
const struct imxrt_edma_xfrconfig_s *config,
|
||||
struct imxrt_edmatcd_s *next)
|
||||
#else
|
||||
void imxrt_tcd_configure(struct imxrt_edmatcd_s *tcd,
|
||||
const struct imxrt_edma_xfrconfig_s *config)
|
||||
#endif
|
||||
{
|
||||
tcd->saddr = config->saddr; /* Source Address */
|
||||
tcd->soff = config->soff; /* Signed Source Address Offset */
|
||||
tcd->attr = EDMA_TCD_ATTR_SSIZE(config->ssize) | /* Transfer Attributes */
|
||||
EDMA_TCD_ATTR_DSIZE(config->destTransferSize);
|
||||
tcd->nbytes = config->nbytes; /* Signed Minor Loop Offset / Byte Count */
|
||||
tcd->slast = tcd->slast; /* Last Source Address Adjustment */
|
||||
tcd->daddr = config->daddr; /* Destination Address */
|
||||
tcd->doff = config->doff; /* Signed Destination Address Offset */
|
||||
tcd->citer = config->iter; /* Current Minor Loop Link, Major Loop Count */
|
||||
tcd->biter = config->iter; /* Beginning Minor Loop Link, Major Loop Count */
|
||||
|
||||
#ifdef CONFIG_IMXRT_EDMA_NTCD > 0
|
||||
/* Enable scatter/gather processing */
|
||||
|
||||
if (next != NULL)
|
||||
{
|
||||
uint16_t regval16;
|
||||
|
||||
/* Set the next TCD address */
|
||||
|
||||
tcd->dlastsga = (uint32_t)next;
|
||||
|
||||
/* Before calling imxrt_tcd_configure or imxrt_dmach_setconfig, the
|
||||
* user must call imxrt_tcd_reset or imxrt_dmach_reset which will set
|
||||
* DREQ, so must use "|" or "&" rather than "=".
|
||||
*
|
||||
* Clear the DREQ bit because scatter gather has been enabled, so the
|
||||
* previous transfer is not the last transfer, and channel request should
|
||||
* be enabled at the next transfer(the next TCD).
|
||||
*/
|
||||
|
||||
regval16 = tcd->csr;
|
||||
regval16 &= ~EDMA_TCD_CSR_DREQ;
|
||||
regval16 |= EDMA_TCD_CSR_ESG
|
||||
tcd->csr = regval16;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: imxrt_tcd_instantiate
|
||||
*
|
||||
* Description:
|
||||
* Copy an in-memory TCD into eDMA channel TCD registers
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_IMXRT_EDMA_NTCD > 0
|
||||
static void imxrt_tcd_instantiate(struct imxrt_dmach_s *dmach,
|
||||
const struct imxrt_edmatcd_s *tcd)
|
||||
{
|
||||
uintptr_t base = IMXRT_EDMA_TCD_BASE(dmach->chan);
|
||||
|
||||
/* Push tcd into hardware TCD register */
|
||||
|
||||
putreg32(tcd->saddr, base + IMXRT_EDMA_TCD_SADDR_OFFSET);
|
||||
putreg16(tcd->soff, base + IMXRT_EDMA_TCD_SOFF_OFFSET);
|
||||
putreg16(tcd->attr, base + IMXRT_EDMA_TCD_ATTR_OFFSET);
|
||||
putreg32(tcd->nbytes, base + IMXRT_EDMA_TCD_NBYTES_ML_OFFSET);
|
||||
putreg32(tcd->slast, base + IMXRT_EDMA_TCD_SLAST_OFFSET);
|
||||
putreg32(tcd->daddr, base + IMXRT_EDMA_TCD_DADDR_OFFSET);
|
||||
putreg16(tcd->doff, base + IMXRT_EDMA_TCD_DOFF_OFFSET);
|
||||
putreg16(tcd->citer, base + IMXRT_EDMA_TCD_CITER_ELINK_OFFSET);
|
||||
putreg32(tcd->dlastsga, base + IMXRT_EDMA_TCD_DLASTSGA_OFFSET);
|
||||
|
||||
/* Clear DONE bit first, otherwise ESG cannot be set */
|
||||
|
||||
putreg16(0, base + IMXRT_EDMA_TCD_CSR_OFFSET);
|
||||
putreg16(tcd->csr, base + IMXRT_EDMA_TCD_CSR_OFFSET);
|
||||
|
||||
putreg16(tcd->biter, base + IMXRT_EDMA_TCD_BITER_ELINK_OFFSET);
|
||||
base->TCD[channel].BITER_ELINKNO = tcd->biter;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: imxrt_dmaterminate
|
||||
*
|
||||
@ -224,20 +437,35 @@ static void imxrt_dmaterminate(struct imxrt_dmach_s *dmach, int result)
|
||||
{
|
||||
struct imxrt_edma_s *dmac = imxrt_controller(dmach);
|
||||
|
||||
/* Disable all channel interrupts */
|
||||
/* Disable channel ERROR interrupts */
|
||||
|
||||
regval8 = EDMA_CEEI(chan);
|
||||
putreg8(regval8, IMXRT_EDMA_CEEI);
|
||||
|
||||
/* Disable the DONE interrupt when the major iteration count completes. */
|
||||
/* Disable channel IRQ requests */
|
||||
|
||||
regval8 = EDMA_CERQ(chan);
|
||||
putreg8(regval8, IMXRT_EDMA_CERQ);
|
||||
|
||||
/* Clear CSR to disable channel. Because if the given channel started,
|
||||
* transfer CSR will be not zero. Because if it is the last transfer, DREQ
|
||||
* will be set. If not, ESG will be set.
|
||||
*/
|
||||
|
||||
regaddr = IMXRT_EDMA_TCD_CSR(chan);
|
||||
modifyreg16(regaddr, EDMA_TCD_CSR_INTMAJOR | EDMA_TCD_CSR_INTHALF, 0);
|
||||
putreg16(0, regaddr);
|
||||
|
||||
/* Disable the channel. */
|
||||
/* Cancel all next TCD transfer. */
|
||||
|
||||
regaddr = IMXRT_EDMA_TCD_DLASTSGA(chan);
|
||||
putreg16(0, regaddr);
|
||||
|
||||
#if CONFIG_IMXRT_EDMA_NTCD > 0
|
||||
/* Return all allocated TCDs to the free list */
|
||||
#warning Missing logic
|
||||
|
||||
#endif
|
||||
|
||||
/* If this was an RX DMA (peripheral-to-memory), then invalidate the cache
|
||||
* to force reloads from memory.
|
||||
*/
|
||||
@ -251,7 +479,7 @@ static void imxrt_dmaterminate(struct imxrt_dmach_s *dmach, int result)
|
||||
|
||||
if (dmach->callback)
|
||||
{
|
||||
dmach->callback((DMA_HANDLE)dmach, dmach->arg, result);
|
||||
dmach->callback((DMACH_HANDLE)dmach, dmach->arg, result);
|
||||
}
|
||||
|
||||
dmach->callback = NULL;
|
||||
@ -434,7 +662,19 @@ void weak_function up_dmainitialize(void)
|
||||
/* Initialize semaphores */
|
||||
|
||||
nxsem_init(&g_edma.chsem, 0, 1);
|
||||
nxsem_init(&g_edma.dsem, 0, SAM_NDMACHAN);
|
||||
#if CONFIG_IMXRT_EDMA_NTCD > 0
|
||||
nxsem_init(&g_edma.dsem, 0, CONFIG_IMXRT_EDMA_NTCD);
|
||||
|
||||
/* The 'dsem' is used for signaling rather than mutual exclusion and,
|
||||
* hence, should not have priority inheritance enabled.
|
||||
*/
|
||||
|
||||
nxsem_setprotocol(&g_edma.dsem, SEM_PRIO_NONE);
|
||||
|
||||
/* Initialize the list of of free TCDs from the pool of pre-allocated TCDs. */
|
||||
|
||||
imxrt_tcd_initialize();
|
||||
#endif
|
||||
|
||||
/* Attach DMA interrupt vectors.
|
||||
*
|
||||
@ -514,7 +754,7 @@ void weak_function up_dmainitialize(void)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
DMA_HANDLE imxrt_dmachannel(uint32_t dmamux)
|
||||
DMACH_HANDLE imxrt_dmachannel(uint32_t dmamux)
|
||||
{
|
||||
struct imxrt_dmach_s *dmach;
|
||||
unsigned int chndx;
|
||||
@ -566,7 +806,7 @@ DMA_HANDLE imxrt_dmachannel(uint32_t dmamux)
|
||||
dmaerr("ERROR: Failed allocate eDMA channel\n");
|
||||
}
|
||||
|
||||
return (DMA_HANDLE)dmach;
|
||||
return (DMACH_HANDLE)dmach;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -582,7 +822,7 @@ DMA_HANDLE imxrt_dmachannel(uint32_t dmamux)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void imxrt_dmafree(DMA_HANDLE handle)
|
||||
void imxrt_dmafree(DMACH_HANDLE handle)
|
||||
{
|
||||
struct imxrt_dmach_s *dmach = (struct imxrt_dmach_s *)handle;
|
||||
uintptr_t regaddr;
|
||||
@ -610,6 +850,253 @@ void imxrt_dmafree(DMA_HANDLE handle)
|
||||
putreg32(0, regaddr);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: imxrt_tcd_alloc
|
||||
*
|
||||
* Description:
|
||||
* Allocate an in-memory, TCD
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_IMXRT_EDMA_NTCD > 0
|
||||
struct imxrt_edmatcd_s *imxrt_tcd_alloc(void)
|
||||
{
|
||||
struct imxrt_edmatcd_s *tcd;
|
||||
irqstate_t flags;
|
||||
|
||||
/* Take the 'dsem'. When we hold the the 'dsem', then we know that one
|
||||
* TCD is reserved for us in the free list.
|
||||
*
|
||||
* NOTE: We use a critical section here because we may block waiting for
|
||||
* the 'dsem'. The critical section will be suspended while we are
|
||||
* waiting.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
imxrt_takedsem();
|
||||
|
||||
/* Now there should be a TCD in the free list reserved just for us */
|
||||
|
||||
tcd = (struct imxrt_edmatcd_s *)sq_remfirst(&g_tcd_free);
|
||||
DEBUGASSERT(tcd != NULL);
|
||||
|
||||
leave_critical_section(flags);
|
||||
return tcd;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: imxrt_tcd_free()
|
||||
*
|
||||
* Description:
|
||||
* Free an in-memory, TCD
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_IMXRT_EDMA_NTCD > 0
|
||||
void imxrt_tcd_free(struct imxrt_edmatcd_s *tcd)
|
||||
{
|
||||
irqstate_t flags;
|
||||
|
||||
/* Add the the TCD to the end of the free list and post the 'dsem',
|
||||
* possibly waking up another thread that might be waiting for
|
||||
* a TCD.
|
||||
*/
|
||||
|
||||
flags = spin_lock_irqsave();
|
||||
sq_add_last((sq_entry_t *)tcd, &g_tcd_free);
|
||||
(void)imxrt_givedsem();
|
||||
spin_unlock_irqrestore(flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
* Name: imxrt_dmach_reset
|
||||
*
|
||||
* Description:
|
||||
* Sets all TCD registers to default values..
|
||||
*
|
||||
* NOTE: This function enables the auto stop request feature.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
void imxrt_dmach_reset(DMACH_HANDLE handle)
|
||||
{
|
||||
struct imxrt_dmach_s *dmach = (struct imxrt_dmach_s *)handle;
|
||||
|
||||
dmainfo("dmach: %p\n", dmach);
|
||||
DEBUGASSERT(dmach != NULL && dmach->inuse && dmach->state != IMXRT_DMA_ACTIVE);
|
||||
|
||||
imxrt_tcd_reset((struct imxrt_edmatcd_s *)IMXRT_EDMA_TCD_BASE(dmach->chan));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: imxrt_dmach_initconfig
|
||||
*
|
||||
* Description:
|
||||
* This function initializes the transfer configuration structure according
|
||||
* to the user-provided input configuration.
|
||||
*
|
||||
* Input Parameters:
|
||||
* saddr - eDMA transfer source address.
|
||||
* srcwidth - eDMA transfer source address width(bytes).
|
||||
* daddr - eDMA transfer destination address.
|
||||
* destwidth - eDMA transfer destination address width(bytes).
|
||||
* reqsize - eDMA transfer bytes per channel request.
|
||||
* nbytes - eDMA transfer bytes to be transferred.
|
||||
* type - eDMA transfer type.
|
||||
* config - The user configuration structure of type struct
|
||||
* imxrt_edma_xfrconfig_s.
|
||||
*
|
||||
* NOTE: The data address and the data width must be consistent. For example,
|
||||
* if the SRC is 4 bytes, the source address must be 4 bytes aligned, or it
|
||||
* results in source address error (SAE).
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success; a negated errno value is returned on
|
||||
* any failure.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
int imxrt_dmach_initconfig(void *saddr, uint32_t srcwidth,
|
||||
void *daddr, uint32_t destwidth,
|
||||
uint32_t reqsize, uint32_t nbytes,
|
||||
edma_transfer_type_t type,
|
||||
struct imxrt_edma_xfrconfig_s *config)
|
||||
{
|
||||
config->daddr = (uint32_t)daddr;
|
||||
config->saddr = (uint32_t)saddr;
|
||||
config->nbytes = reqsize;
|
||||
config->iter = nbytes / reqsize;
|
||||
|
||||
switch (srcwidth)
|
||||
{
|
||||
case 1:
|
||||
config->ssize = TCD_ATTR_SIZE_8BIT;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
config->ssize = TCD_ATTR_SIZE_16BIT;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
config->ssize = TCD_ATTR_SIZE_32BIT;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
config->ssize = TCD_ATTR_SIZE_64BIT;
|
||||
break;
|
||||
|
||||
case 32:
|
||||
config->ssize = TCD_ATTR_SIZE_256BIT;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (destwidth)
|
||||
{
|
||||
case 1:
|
||||
config->dsize = TCD_ATTR_SIZE_8BIT;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
config->dsize = TCD_ATTR_SIZE_16BIT;
|
||||
break;
|
||||
|
||||
case 4U
|
||||
config->dsize = TCD_ATTR_SIZE_32BIT;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
config->dsize = TCD_ATTR_SIZE_64BIT;
|
||||
break;
|
||||
|
||||
case 32:
|
||||
config->dsize = TCD_ATTR_SIZE_256BIT;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case kEDMA_MemoryToMemory:
|
||||
config->doff = destwidth;
|
||||
config->soff = srcwidth;
|
||||
break;
|
||||
|
||||
case kEDMA_MemoryToPeripheral:
|
||||
config->doff = 0;
|
||||
config->soff = srcwidth;
|
||||
break;
|
||||
|
||||
case kEDMA_PeripheralToMemory:
|
||||
config->doff = destwidth;
|
||||
config->soff = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: imxrt_dmach_setconfig
|
||||
*
|
||||
* Description:
|
||||
* This function configures the transfer attribute, including source address,
|
||||
* destination address, transfer size, address offset, and so on. It also
|
||||
* configures the scatter gather feature if the user supplies the TCD address.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* edma_transfer_t config;
|
||||
* struct imxrt_edmatcd_s tcd;
|
||||
* config.saddr = ..;
|
||||
* config.daddr = ..;
|
||||
* ...
|
||||
* dmach = imxrt_dmachannel(dmamux);
|
||||
* ...
|
||||
* tcd = imxrt_tcd_alloc(dmach)
|
||||
* ...
|
||||
* imxrt_dmach_setconfig(dmach, &config, &tcd);
|
||||
*
|
||||
* Input Parameters:
|
||||
* handle - DMA channel handle created by imxrt_dmachannel()
|
||||
* channel - eDMA channel number.
|
||||
* config - Pointer to eDMA transfer configuration structure.
|
||||
* next - Points to a TCD structure previously allocated via
|
||||
* imxrt_tcd_alloc(). 'next' can be NULL if the caller does not
|
||||
* wish to enable scatter/gather feature.
|
||||
*
|
||||
* NOTE: If 'next' is not NULL, it means scatter gather feature is enabled
|
||||
* and DREQ bit is cleared in the previous transfer configuration.
|
||||
* That bit was set in imxrt_dmach_reset().
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifdef CONFIG_IMXRT_EDMA_NTCD > 0
|
||||
void imxrt_dmach_setconfig(DMACH_HANDLE handle,
|
||||
const struct imxrt_edma_xfrconfig_s *config,
|
||||
struct imxrt_edmatcd_s *next)
|
||||
{
|
||||
imxrt_tcd_configure((struct imxrt_edmatcd_s *)IMXRT_EDMA_TCD_BASE(dmach->chan)),
|
||||
config, next);
|
||||
}
|
||||
#else
|
||||
void imxrt_dmach_setconfig(DMACH_HANDLE handle,
|
||||
const struct imxrt_edma_xfrconfig_s *config)
|
||||
{
|
||||
imxrt_tcd_configure((struct imxrt_edmatcd_s *)IMXRT_EDMA_TCD_BASE(dmach->chan)),
|
||||
config);
|
||||
}
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
* Name: imxrt_dmasetup
|
||||
*
|
||||
@ -622,8 +1109,8 @@ void imxrt_dmafree(DMA_HANDLE handle)
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
int imxrt_dmasetup(DMA_HANDLE handle, uint32_t saddr, uint32_t daddr, size_t nbytes,
|
||||
uint32_t chflags);
|
||||
int imxrt_dmasetup(DMACH_HANDLE handle, uint32_t saddr, uint32_t daddr,
|
||||
size_t nbytes, uint32_t chflags);
|
||||
{
|
||||
struct imxrt_dmach_s *dmach = (struct imxrt_dmach_s *)handle;
|
||||
int ret = OK;
|
||||
@ -697,7 +1184,7 @@ int imxrt_dmasetup(DMA_HANDLE handle, uint32_t saddr, uint32_t daddr, size_t nby
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int imxrt_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg)
|
||||
int imxrt_dmastart(DMACH_HANDLE handle, dma_callback_t callback, void *arg)
|
||||
{
|
||||
struct imxrt_dmach_s *dmach = (struct imxrt_dmach_s *)handle;
|
||||
irqstate_t flags;
|
||||
@ -764,7 +1251,7 @@ int imxrt_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void imxrt_dmastop(DMA_HANDLE handle)
|
||||
void imxrt_dmastop(DMACH_HANDLE handle)
|
||||
{
|
||||
struct imxrt_dmach_s *dmach = (struct imxrt_dmach_s *)handle;
|
||||
irqstate_t flags;
|
||||
@ -789,7 +1276,7 @@ void imxrt_dmastop(DMA_HANDLE handle)
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_DEBUG_DMA
|
||||
void imxrt_dmasample(DMA_HANDLE handle, struct imxrt_dmaregs_s *regs)
|
||||
void imxrt_dmasample(DMACH_HANDLE handle, struct imxrt_dmaregs_s *regs)
|
||||
{
|
||||
struct imxrt_dmach_s *dmach = (struct imxrt_dmach_s *)handle;
|
||||
uintptr_t regaddr;
|
||||
|
@ -4,6 +4,13 @@
|
||||
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Portions of the eDMA logic derive from NXP sample code which has a compatible
|
||||
* BSD 3-clause license:
|
||||
*
|
||||
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||||
* Copyright 2016-2017 NXP
|
||||
* All rights reserved
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
@ -49,94 +56,39 @@
|
||||
* Pre-processor Definitions
|
||||
************************************************************************************/
|
||||
|
||||
/* eDMA Configuration ***************************************************************/
|
||||
|
||||
/* Flags used to characterize the DMA channel. The naming convention is that one
|
||||
* side is the peripheral and the other is memory (however, the interface could still
|
||||
* be used if, for example, both sides were memory although the naming would be
|
||||
* awkward)
|
||||
*
|
||||
* .... .... .... .... CCCC GGBA DDSS ..TT
|
||||
*
|
||||
* REVISIT: Initially, only vanilla Rx/Tx DMA block transfers are supported.
|
||||
*/
|
||||
|
||||
/* Transfer type:
|
||||
*
|
||||
* .... .... .... .... .... .... .... ..TT
|
||||
*/
|
||||
|
||||
#define TTYPE_M2M (0) /* Memory-to-memory (not supported) */
|
||||
#define TTYPE_M2P (1) /* Memory-to-peripheral (normal Tx) */
|
||||
#define TTYPE_P2M (2) /* Peripheral-to-memory (normal Rx) */
|
||||
#define TTYPE_P2P (3) /* Peripheral-to-peripheral (not supported) */
|
||||
|
||||
#define TTYPE_2P_MASK (1) /* Transfer to peripheral (M2P or P2P) */
|
||||
#define TTYPE_P2_MASK (2) /* Transfer from peripheral (P2M or P2P) */
|
||||
|
||||
#define DMACH_FLAG_TTYPE_SHIFT (0) /* Bits 0-1 Destination transfer size */
|
||||
#define DMACH_FLAG_TTYPE_MASK (3 << DMACH_FLAG_TTYPE_SHIFT)
|
||||
# define DMACH_FLAG_TTYPE_M2M (TTYPE_M2M << DMACH_FLAG_TTYPE_SHIFT) /* Memory-to-memory */
|
||||
# define DMACH_FLAG_TTYPE_M2P (TTYPE_M2P << DMACH_FLAG_TTYPE_SHIFT) /* Memory-to-peripheral */
|
||||
# define DMACH_FLAG_TTYPE_P2M (TTYPE_P2M << DMACH_FLAG_TTYPE_SHIFT) /* Peripheral-to-memory */
|
||||
# define DMACH_FLAG_TTYPE_P2P (TTYPE_P2P << DMACH_FLAG_TTYPE_SHIFT) /* Peripheral-to-peripheral */
|
||||
|
||||
# define DMACH_FLAG_TTYPE_2P_MASK (TTYPE_2P_MASK << DMACH_FLAG_TTYPE_SHIFT) /* Transfer to peripheral */
|
||||
# define DMACH_FLAG_TTYPE_P2_MASK (TTYPE_P2_MASK << DMACH_FLAG_TTYPE_SHIFT) /* Transfer from peripheral */
|
||||
|
||||
/* Source transfer size:
|
||||
*
|
||||
* .... .... .... .... .... .... ..SS ....
|
||||
*/
|
||||
|
||||
#define DMACH_FLAG_SSIZE_SHIFT (4) /* Bits 4-5: Source transfer size */
|
||||
#define DMACH_FLAG_SSIZE_MASK (7 << DMACH_FLAG_SSIZE_SHIFT)
|
||||
# define DMACH_FLAG_SSIZE_8BIT (TCD_ATTR_SIZE_8BIT << DMACH_FLAG_SSIZE_SHIFT) /* 8-bit */
|
||||
# define DMACH_FLAG_SSIZE_16BIT (TCD_ATTR_SIZE_16BIT << DMACH_FLAG_SSIZE_SHIFT) /* 16-bit */
|
||||
# define DMACH_FLAG_SSIZE_32BIT (TCD_ATTR_SIZE_32BIT << DMACH_FLAG_SSIZE_SHIFT) /* 32-bit */
|
||||
# define DMACH_FLAG_SSIZE_64BIT (TCD_ATTR_SIZE_64BIT << DMACH_FLAG_SSIZE_SHIFT) /* 64-bit */
|
||||
# define DMACH_FLAG_SSIZE_256BIT (TCD_ATTR_SIZE_256BIT << DMACH_FLAG_SSIZE_SHIFT) /* 32-byte burst */
|
||||
|
||||
/* Destination transfer size:
|
||||
*
|
||||
* .... .... .... .... .... .... DD.. ....
|
||||
*/
|
||||
|
||||
#define DMACH_FLAG_DSIZE_SHIFT (6) /* Bits 6-7: Destination transfer size */
|
||||
#define DMACH_FLAG_DSIZE_MASK (7 << DMACH_FLAG_DSIZE_SHIFT)
|
||||
# define DMACH_FLAG_DSIZE_8BIT (TCD_ATTR_SIZE_8BIT << DMACH_FLAG_DSIZE_SHIFT) /* 8-bit */
|
||||
# define DMACH_FLAG_DSIZE_16BIT (TCD_ATTR_SIZE_16BIT << DMACH_FLAG_DSIZE_SHIFT) /* 16-bit */
|
||||
# define DMACH_FLAG_DSIZE_32BIT (TCD_ATTR_SIZE_32BIT << DMACH_FLAG_DSIZE_SHIFT) /* 32-bit */
|
||||
# define DMACH_FLAG_DSIZE_64BIT (TCD_ATTR_SIZE_64BIT << DMACH_FLAG_DSIZE_SHIFT) /* 64-bit */
|
||||
# define DMACH_FLAG_DSIZE_256BIT (TCD_ATTR_SIZE_256BIT << DMACH_FLAG_DSIZE_SHIFT) /* 32-byte burst */
|
||||
|
||||
/* Arbitration:
|
||||
*
|
||||
* .... .... .... .... .... ..BA .... ....
|
||||
*/
|
||||
|
||||
#define DMACH_FLAG_CHRR (1 << 8) /* Bit 8: Round Robin Channel Arbitration */
|
||||
#define DMACH_FLAG_GRPRR (1 << 8) /* Bit 9: Round Robin Group Arbitration */
|
||||
|
||||
/* DMA Priorities:
|
||||
*
|
||||
* .... .... .... .... CCCC GG.. .... ....
|
||||
*/
|
||||
|
||||
#define DMACH_FLAG_GPPRI_SHIFT (10) /* Bits 10-11: Channel Group Priority */
|
||||
#define DMACH_FLAG_GRPPRI_MASK (3 << DMACH_FLAG_GPPRI_SHIFT)
|
||||
# define DMACH_FLAG_GRPPRI(n) ((uint32_t)(n) << DMACH_FLAG_GPPRI_SHIFT)
|
||||
|
||||
#define DMACH_FLAG_CHPRI_SHIFT (12) /* Bits 12-15: Channel Arbitration Priority */
|
||||
#define DMACH_FLAG_CHPRI_MASK (15 << DMACH_FLAG_CHPRI_SHIFT)
|
||||
# define DMACH_FLAG_CHPRI(n) ((uint32_t)(n) << DMACH_FLAG_CHPRI_SHIFT)
|
||||
|
||||
/************************************************************************************
|
||||
* Public Types
|
||||
************************************************************************************/
|
||||
|
||||
typedef FAR void *DMA_HANDLE;
|
||||
typedef void (*dma_callback_t)(DMA_HANDLE handle, void *arg, int result);
|
||||
typedef FAR void *DMACH_HANDLE;
|
||||
typedef void (*dma_callback_t)(DMACH_HANDLE handle, void *arg, int result);
|
||||
|
||||
/* eDMA transfer type */
|
||||
|
||||
enum imxrt_edma_xfrtype_e
|
||||
{
|
||||
eDMA_MEMORY2MEMORY = 0, /* Transfer from memory to memory */
|
||||
eDMA_PERIPH2MEMORY, /* Transfer from peripheral to memory */
|
||||
eDMA_MEMORY2PERIPH, /* Transfer from memory to peripheral */
|
||||
};
|
||||
|
||||
/* This structure holds the source/destination transfer attribute configuration. */
|
||||
|
||||
struct imxrt_edma_xfrconfig_s
|
||||
{
|
||||
uint32_t saddr; /* Source data address. */
|
||||
uint32_t daddr; /* Destination data address. */
|
||||
uint8_t ssize; /* Source data transfer size (see TCD_ATTR_SIZE_* definitions in chip/. */
|
||||
uint8_t dsize; /* Destination data transfer size. */
|
||||
int16_t soff; /* Sign-extended offset for current source address. */
|
||||
int16_t doff; /* Sign-extended offset for current destination address. */
|
||||
uint16_t iter; /* Major loop iteration count. */
|
||||
#ifdef CONFIG_IMXRT_EDMA_EMLIM
|
||||
uint16_t nbytes; /* Bytes to transfer in a minor loop */
|
||||
#else
|
||||
uint32_t nbytes; /* Bytes to transfer in a minor loop */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* The following is used for sampling DMA registers when CONFIG DEBUG_DMA is selected */
|
||||
|
||||
@ -202,7 +154,7 @@ extern "C"
|
||||
* Public Function Prototypes
|
||||
************************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
/************************************************************************************
|
||||
* Name: imxrt_dmachannel
|
||||
*
|
||||
* Allocate a DMA channel. This function sets aside a DMA channel,
|
||||
@ -224,9 +176,9 @@ extern "C"
|
||||
* If a DMA channel is available, this function returns a non-NULL, void*
|
||||
* DMA channel handle. NULL is returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
************************************************************************************/
|
||||
|
||||
DMA_HANDLE imxrt_dmachannel(uint32_t dmamux);
|
||||
DMACH_HANDLE imxrt_dmachannel(uint32_t dmamux);
|
||||
|
||||
/************************************************************************************
|
||||
* Name: imxrt_dmafree
|
||||
@ -240,7 +192,121 @@ DMA_HANDLE imxrt_dmachannel(uint32_t dmamux);
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
void imxrt_dmafree(DMA_HANDLE handle);
|
||||
void imxrt_dmafree(DMACH_HANDLE handle);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: imxrt_tcd_alloc
|
||||
*
|
||||
* Description:
|
||||
* Allocate an in-memory, TCD
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_IMXRT_EDMA_NTCD > 0
|
||||
struct imxrt_edmatcd_s *imxrt_tcd_alloc(void);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: imxrt_tcd_free()
|
||||
*
|
||||
* Description:
|
||||
* Free an in-memory, TCD
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_IMXRT_EDMA_NTCD > 0
|
||||
void imxrt_tcd_free(struct imxrt_edmatcd_s *tcd);
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
* Name: imxrt_dmach_reset
|
||||
*
|
||||
* Description:
|
||||
* Sets all TCD registers to default values..
|
||||
*
|
||||
* NOTE: This function enables the auto stop request feature.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
void imxrt_dmach_reset(DMACH_HANDLE handle);
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: imxrt_dmach_initconfig
|
||||
*
|
||||
* Description:
|
||||
* This function initializes the transfer configuration structure according
|
||||
* to the user-provided input configuration.
|
||||
*
|
||||
* Input Parameters:
|
||||
* saddr - eDMA transfer source address.
|
||||
* srcwidth - eDMA transfer source address width(bytes).
|
||||
* daddr - eDMA transfer destination address.
|
||||
* destwidth - eDMA transfer destination address width(bytes).
|
||||
* reqsize - eDMA transfer bytes per channel request.
|
||||
* nbytes - eDMA transfer bytes to be transferred.
|
||||
* type - eDMA transfer type.
|
||||
* config - The user configuration structure of type struct
|
||||
* imxrt_edma_xfrconfig_s.
|
||||
*
|
||||
* NOTE: The data address and the data width must be consistent. For example,
|
||||
* if the SRC is 4 bytes, the source address must be 4 bytes aligned, or it
|
||||
* results in source address error (SAE).
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success; a negated errno value is returned on
|
||||
* any failure.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
int imxrt_dmach_initconfig(void *saddr, uint32_t srcwidth,
|
||||
void *daddr, uint32_t destwidth,
|
||||
uint32_t reqsize, uint32_t nbytes,
|
||||
edma_transfer_type_t type,
|
||||
struct imxrt_edma_xfrconfig_s *config);
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: imxrt_dmach_setconfig
|
||||
*
|
||||
* Description:
|
||||
* This function configures the transfer attribute, including source address,
|
||||
* destination address, transfer size, address offset, and so on. It also
|
||||
* configures the scatter gather feature if the user supplies the TCD address.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* edma_transfer_t config;
|
||||
* struct imxrt_edmatcd_s tcd;
|
||||
* config.saddr = ..;
|
||||
* config.daddr = ..;
|
||||
* ...
|
||||
* dmach = imxrt_dmachannel(dmamux);
|
||||
* ...
|
||||
* tcd = imxrt_tcd_alloc(dmach)
|
||||
* ...
|
||||
* imxrt_dmach_setconfig(dmach, &config, &tcd);
|
||||
*
|
||||
* Input Parameters:
|
||||
* handle - DMA channel handle created by imxrt_dmachannel()
|
||||
* channel - eDMA channel number.
|
||||
* config - Pointer to eDMA transfer configuration structure.
|
||||
* next - Points to a TCD structure previously allocated via
|
||||
* imxrt_tcd_alloc(). 'next' can be NULL if the caller does not
|
||||
* wish to enable scatter/gather feature.
|
||||
*
|
||||
* NOTE: If 'next' is not NULL, it means scatter gather feature is enabled
|
||||
* and DREQ bit is cleared in the previous transfer configuration.
|
||||
* That bit was set in imxrt_dmach_reset().
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifdef CONFIG_IMXRT_EDMA_NTCD > 0
|
||||
void imxrt_dmach_setconfig(DMACH_HANDLE handle,
|
||||
const struct imxrt_edma_xfrconfig_s *config,
|
||||
struct imxrt_edmatcd_s *next);
|
||||
#else
|
||||
void imxrt_dmach_setconfig(DMACH_HANDLE handle,
|
||||
const struct imxrt_edma_xfrconfig_s *config);
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
* Name: imxrt_dmasetup
|
||||
@ -254,8 +320,8 @@ void imxrt_dmafree(DMA_HANDLE handle);
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
int imxrt_dmasetup(DMA_HANDLE handle, uint32_t saddr, uint32_t daddr, size_t nbytes,
|
||||
uint32_t chflags);
|
||||
int imxrt_dmasetup(DMACH_HANDLE handle, uint32_t saddr, uint32_t daddr,
|
||||
size_t nbytes, uint32_t chflags);
|
||||
|
||||
/************************************************************************************
|
||||
* Name: imxrt_dmastart
|
||||
@ -265,7 +331,7 @@ int imxrt_dmasetup(DMA_HANDLE handle, uint32_t saddr, uint32_t daddr, size_t nby
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
int imxrt_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg);
|
||||
int imxrt_dmastart(DMACH_HANDLE handle, dma_callback_t callback, void *arg);
|
||||
|
||||
/************************************************************************************
|
||||
* Name: imxrt_dmastop
|
||||
@ -276,7 +342,7 @@ int imxrt_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg);
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
void imxrt_dmastop(DMA_HANDLE handle);
|
||||
void imxrt_dmastop(DMACH_HANDLE handle);
|
||||
|
||||
/************************************************************************************
|
||||
* Name: imxrt_dmasample
|
||||
@ -287,7 +353,7 @@ void imxrt_dmastop(DMA_HANDLE handle);
|
||||
************************************************************************************/
|
||||
|
||||
#ifdef CONFIG_DEBUG_DMA
|
||||
void imxrt_dmasample(DMA_HANDLE handle, struct imxrt_dmaregs_s *regs);
|
||||
void imxrt_dmasample(DMACH_HANDLE handle, struct imxrt_dmaregs_s *regs);
|
||||
#else
|
||||
# define imxrt_dmasample(handle,regs)
|
||||
#endif
|
||||
|
@ -1598,6 +1598,12 @@ void sam_dmainitialize(struct sam_xdmac_s *xdmac)
|
||||
|
||||
nxsem_init(&xdmac->chsem, 0, 1);
|
||||
nxsem_init(&xdmac->dsem, 0, SAMV7_NDMACHAN);
|
||||
|
||||
/* The 'dsem' is used for signaling rather than mutual exclusion and,
|
||||
* hence, should not have priority inheritance enabled.
|
||||
*/
|
||||
|
||||
nxsem_setprotocol(&xdmac->dsem, SEM_PRIO_NONE);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
Loading…
Reference in New Issue
Block a user