Squashed commit of the following:
arch/arm/src/imxrt: May eDMA channel linking a configuration option. Add support to select the DMA channel priority and pre-emption controls. arch/arm/src/imxrt: Update some HowTo comments in the eDMA header file. arch/arm/src/imxrt: Fix a logic error in parmater passing. Caller does not know actual channel number when setting up linked channel, only the channel handler.
This commit is contained in:
parent
890656f043
commit
db0cdfc407
@ -345,6 +345,26 @@ config IMXRT_EDMA_NTCD
|
||||
which case only the TCD channel registers will be used and scatter-
|
||||
will not be supported.
|
||||
|
||||
config IMXRT_EDMA_ELINK
|
||||
bool "Channeling Linking"
|
||||
default n
|
||||
---help---
|
||||
This option enables optional minor or major loop channel linking:
|
||||
|
||||
Minor loop channel linking: As the channel completes the minor
|
||||
loop, this flag enables linking to another channel. The link target
|
||||
channel initiates a channel service request via an internal
|
||||
mechanism that sets the TCDn_CSR[START] bit of the specified
|
||||
channel.
|
||||
|
||||
If minor loop channel linking is disabled, this link mechanism is
|
||||
suppressed in favor of the major loop channel linking.
|
||||
|
||||
Major loop channel linking: As the channel completes the minor
|
||||
loop, this option enables the linking to another channel. The link
|
||||
target channel initiates a channel service request via an internal
|
||||
mechanism that sets the TCDn_CSR[START] bit of the linked channel.
|
||||
|
||||
config IMXRT_EDMA_ERCA
|
||||
bool "Round Robin Channel Arbitration"
|
||||
default n
|
||||
@ -379,7 +399,7 @@ config IMXRT_EDMA_EMLIM
|
||||
---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
|
||||
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.
|
||||
|
@ -93,7 +93,7 @@
|
||||
|
||||
/* DMAMUX Register Addresses ********************************************************/
|
||||
|
||||
#define IMXRT_DMAMUX_CHCF(n) (IMXRT_DMAMUX_BASE + IMXRT_DMAMUX_CHCFG_OFFSET(n))
|
||||
#define IMXRT_DMAMUX_CHCFG(n) (IMXRT_DMAMUX_BASE + IMXRT_DMAMUX_CHCFG_OFFSET(n))
|
||||
# define IMXRT_DMAMUX_CHCFG0 (IMXRT_DMAMUX_BASE + IMXRT_DMAMUX_CHCFG0_OFFSET)
|
||||
# define IMXRT_DMAMUX_CHCFG1 (IMXRT_DMAMUX_BASE + IMXRT_DMAMUX_CHCFG1_OFFSET)
|
||||
# define IMXRT_DMAMUX_CHCFG2 (IMXRT_DMAMUX_BASE + IMXRT_DMAMUX_CHCFG2_OFFSET)
|
||||
|
@ -352,67 +352,61 @@ static inline void imxrt_tcd_initialize(void)
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
static void imxrt_tcd_chanlink(uint8_t flags, uint8_t chan,
|
||||
struct imxrt_edmatcd_s *tcd)
|
||||
#ifdef CONFIG_IMXRT_EDMA_ELINK
|
||||
static inline void imxrt_tcd_chanlink(uint8_t flags, struct imxrt_dmach_s *linkch,
|
||||
struct imxrt_edmatcd_s *tcd)
|
||||
{
|
||||
switch (flags & EDMA_CONFIG_LINKTYPE_MASK)
|
||||
uint16_t regval16;
|
||||
|
||||
flags &= EDMA_CONFIG_LINKTYPE_MASK;
|
||||
|
||||
if (linkch == NULL || flags == EDMA_CONFIG_LINKTYPE_LINKNONE)
|
||||
{
|
||||
case EDMA_CONFIG_LINKTYPE_MINORLINK: /* Minor link config */
|
||||
{
|
||||
uint16_t regval16;
|
||||
/* No link or no link channel provided */
|
||||
/* Disable minor links */
|
||||
|
||||
/* Enable minor link */
|
||||
tcd->citer &= ~EDMA_TCD_CITER_ELINK;
|
||||
tcd->biter &= ~EDMA_TCD_BITER_ELINK;
|
||||
|
||||
tcd->citer |= EDMA_TCD_CITER_ELINK_ELINK;
|
||||
tcd->biter |= EDMA_TCD_BITER_ELINK_ELINK;
|
||||
/* Disable major link */
|
||||
|
||||
/* Set linked channel */
|
||||
tcd->csr &= ~EDMA_TCD_CSR_MAJORELINK;
|
||||
}
|
||||
else if (flags == EDMA_CONFIG_LINKTYPE_MINORLINK) /* Minor link config */
|
||||
{
|
||||
/* Enable minor link */
|
||||
|
||||
regval16 = tcd->citer;
|
||||
regval16 &= ~EDMA_TCD_CITER_ELINK_LINKCH_MASK;
|
||||
regval16 |= EDMA_TCD_CITER_ELINK_LINKCH(chan);
|
||||
tcd->citer = regval16;
|
||||
tcd->citer |= EDMA_TCD_CITER_ELINK_ELINK;
|
||||
tcd->biter |= EDMA_TCD_BITER_ELINK_ELINK;
|
||||
|
||||
regval16 = tcd->biter;
|
||||
regval16 &= ~EDMA_TCD_BITER_ELINK_LINKCH_MASK;
|
||||
regval16 |= EDMA_TCD_BITER_ELINK_LINKCH(chan);
|
||||
tcd->biter = regval16;
|
||||
}
|
||||
break;
|
||||
/* Set linked channel */
|
||||
|
||||
case EDMA_CONFIG_LINKTYPE_MAJORLINK: /* Major link config */
|
||||
{
|
||||
uint16_t regval16;
|
||||
regval16 = tcd->citer;
|
||||
regval16 &= ~EDMA_TCD_CITER_ELINK_LINKCH_MASK;
|
||||
regval16 |= EDMA_TCD_CITER_ELINK_LINKCH(linkch->chan);
|
||||
tcd->citer = regval16;
|
||||
|
||||
/* Enable major link */
|
||||
regval16 = tcd->biter;
|
||||
regval16 &= ~EDMA_TCD_BITER_ELINK_LINKCH_MASK;
|
||||
regval16 |= EDMA_TCD_BITER_ELINK_LINKCH(linkch->chan);
|
||||
tcd->biter = regval16;
|
||||
}
|
||||
else /* if (flags == EDMA_CONFIG_LINKTYPE_MAJORLINK) Major link config */
|
||||
{
|
||||
/* Enable major link */
|
||||
|
||||
regval16 = tcd->csr;
|
||||
regval16 |= EDMA_TCD_CSR_MAJORELINK;
|
||||
tcd->csr = regval16;
|
||||
regval16 = tcd->csr;
|
||||
regval16 |= EDMA_TCD_CSR_MAJORELINK;
|
||||
tcd->csr = regval16;
|
||||
|
||||
/* Set major linked channel */
|
||||
/* Set major linked channel */
|
||||
|
||||
regval16 &= ~EDMA_TCD_CSR_MAJORLINKCH_MASK;
|
||||
regval16 |= EDMA_TCD_CSR_MAJORLINKCH(chan);
|
||||
tcd->csr = regval16;
|
||||
}
|
||||
break;
|
||||
|
||||
case EDMA_CONFIG_LINKTYPE_LINKNONE: /* link none */
|
||||
default:
|
||||
{
|
||||
/* Disable minor links */
|
||||
|
||||
tcd->citer &= ~EDMA_TCD_CITER_ELINK;
|
||||
tcd->biter &= ~EDMA_TCD_BITER_ELINK;
|
||||
|
||||
/* Disable major link */
|
||||
|
||||
tcd->csr &= ~EDMA_TCD_CSR_MAJORELINK;
|
||||
}
|
||||
break;
|
||||
regval16 &= ~EDMA_TCD_CSR_MAJORLINKCH_MASK;
|
||||
regval16 |= EDMA_TCD_CSR_MAJORLINKCH(linkch->chan);
|
||||
tcd->csr = regval16;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: imxrt_tcd_configure
|
||||
@ -435,14 +429,19 @@ static inline void imxrt_tcd_configure(struct imxrt_edmatcd_s *tcd,
|
||||
tcd->slast = tcd->slast;
|
||||
tcd->daddr = config->daddr;
|
||||
tcd->doff = config->doff;
|
||||
tcd->citer = config->iter;
|
||||
tcd->biter = config->iter;
|
||||
tcd->citer = config->iter & EDMA_TCD_CITER_CITER_MASK;
|
||||
tcd->biter = config->iter & EDMA_TCD_BITER_BITER_MASK;
|
||||
tcd->csr = EDMA_TCD_CSR_DREQ; /* Assume last transfer */
|
||||
tcd->dlastsga = 0;
|
||||
|
||||
/* And special case flags */
|
||||
|
||||
imxrt_tcd_chanlink(config->flags, config->linkch, tcd);
|
||||
#ifdef CONFIG_IMXRT_EDMA_ELINK
|
||||
/* Configure major/minor link mapping */
|
||||
|
||||
imxrt_tcd_chanlink(config->flags, (struct imxrt_dmach_s *)config->linkch,
|
||||
tcd);
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -841,6 +840,15 @@ void weak_function up_dmainitialize(void)
|
||||
* DMAMUX_CHCFG_ENBL DMA Mux Channel Enable (required)
|
||||
*
|
||||
* A value of zero will disable the DMAMUX channel.
|
||||
* dchpri - DCHPRI channel priority configuration. See DCHPRI channel
|
||||
* configuration register bit-field definitions in
|
||||
* chip/imxrt_edma.h. Meaningful settings include:
|
||||
*
|
||||
* EDMA_DCHPRI_CHPRI Channel Arbitration Priority
|
||||
* DCHPRI_DPA Disable Preempt Ability
|
||||
* DCHPRI_ECP Enable Channel Preemption
|
||||
*
|
||||
* The power-on default, 0x05, is a reasonable choice.
|
||||
*
|
||||
* Returned Value:
|
||||
* If a DMA channel is available, this function returns a non-NULL, void*
|
||||
@ -848,7 +856,7 @@ void weak_function up_dmainitialize(void)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
DMACH_HANDLE imxrt_dmach_alloc(uint32_t dmamux)
|
||||
DMACH_HANDLE imxrt_dmach_alloc(uint32_t dmamux, uint8_t dchpri)
|
||||
{
|
||||
struct imxrt_dmach_s *dmach;
|
||||
unsigned int chndx;
|
||||
|
@ -43,6 +43,56 @@
|
||||
#ifndef __ARCH_ARM_SRC_IMXRT_IMXRT_EDMAC_H
|
||||
#define __ARCH_ARM_SRC_IMXRT_IMXRT_EDMAC_H
|
||||
|
||||
/* General Usage:
|
||||
*
|
||||
* 1. Allocate a DMA channel
|
||||
*
|
||||
* DMACH_HANDLE handle;
|
||||
* handle = edma_dmach_alloc(dmamux, dchpri);
|
||||
*
|
||||
* Where 'dmamux' is the channel DMAMUX configuration register setting and
|
||||
* 'dchpri' is the channel DCHPRIO priority register setting.
|
||||
*
|
||||
* 2. Create the transfer configuration:
|
||||
*
|
||||
* struct imxrt_edma_xfrconfig_s config;
|
||||
* config.saddr = ..;
|
||||
* config.daddr = ..;
|
||||
* etc.
|
||||
*
|
||||
* 3. Setup the transfer in hardware:
|
||||
*
|
||||
* int ret;
|
||||
* ret = imxrt_dmach_xfrsetup(handle, &config);
|
||||
*
|
||||
* 4. If you are setting up a scatter gather DMA (with CONFIG_IMXRT_EDMA_NTCD > 0),
|
||||
* then repeat steps 2 and 3 for each segment of the transfer.
|
||||
*
|
||||
* 5. Start the DMA:
|
||||
*
|
||||
* ret = imxrt_dmach_start(handle, my_callback_func, priv);
|
||||
*
|
||||
* Where my_callback_func() is called when the DMA completes or an error occurs.
|
||||
* 'priv' represents some internal driver state that will be provided with the
|
||||
* callback.
|
||||
*
|
||||
* 6. If you need to stop the DMA and free resources (such as if a timeout occurs),
|
||||
* then:
|
||||
*
|
||||
* i mxrt_dmach_stop(handle);
|
||||
*
|
||||
* 7. The callback will be received when the DMA completes (or an error occurs).
|
||||
* After that, you may free the DMA channel, or re-use it on subsequent DMAs.
|
||||
*
|
||||
* imxrt_dmach_free(handle);
|
||||
*
|
||||
* Almost non-invasive debug instrumentation is available. You may call
|
||||
* imxrt_dmasample() to save the current state of the eDMA registers at any given
|
||||
* point in time. At some later, postmortem analysis, you can dump the content of
|
||||
* the buffered registers with imxrt_dmadump(). imxrt_dmasample() is also available
|
||||
* for monitoring DMA progress.
|
||||
*/
|
||||
|
||||
/************************************************************************************
|
||||
* Included Files
|
||||
************************************************************************************/
|
||||
@ -59,9 +109,8 @@
|
||||
/* Configuration flags.
|
||||
*
|
||||
* REVISIT: Many missing options that should be represented as flags:
|
||||
* 1. DCHPRIO priority, pre-emption flags
|
||||
* 2. Bandwidth
|
||||
* 3. Source/Destination modulo
|
||||
* 1. Bandwidth
|
||||
* 2. Source/Destination modulo
|
||||
*/
|
||||
|
||||
#define EDMA_CONFIG_LINKTYPE_SHIFT (0) /* Bits 0-1: Link type */
|
||||
@ -81,29 +130,31 @@ typedef void (*edma_callback_t)(DMACH_HANDLE handle, void *arg, bool done, int r
|
||||
|
||||
enum imxrt_edma_xfrtype_e
|
||||
{
|
||||
eDMA_MEM2MEM = 0, /* Transfer from memory to memory */
|
||||
eDMA_PERIPH2MEM, /* Transfer from peripheral to memory */
|
||||
eDMA_MEM2PERIPH, /* Transfer from memory to peripheral */
|
||||
eDMA_MEM2MEM = 0, /* Transfer from memory to memory */
|
||||
eDMA_PERIPH2MEM, /* Transfer from peripheral to memory */
|
||||
eDMA_MEM2PERIPH, /* 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. */
|
||||
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. */
|
||||
uint8_t flags; /* See EDMA_CONFIG_* definitions */
|
||||
uint8_t ssize; /* Source data transfer size (see TCD_ATTR_SIZE_* definitions in chip/. */
|
||||
uint8_t dsize; /* Destination data transfer size. */
|
||||
uint8_t ttype; /* Transfer type (see enum imxrt_edma_xfrtype_e). */
|
||||
uint8_t linkch; /* Link channel (With EDMA_CONFIG_LINKTYPE_* flags) */
|
||||
uint32_t saddr; /* Source data address. */
|
||||
uint32_t daddr; /* Destination data address. */
|
||||
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. */
|
||||
uint8_t flags; /* See EDMA_CONFIG_* definitions */
|
||||
uint8_t ssize; /* Source data transfer size (see TCD_ATTR_SIZE_* definitions in chip/. */
|
||||
uint8_t dsize; /* Destination data transfer size. */
|
||||
uint8_t ttype; /* Transfer type (see enum imxrt_edma_xfrtype_e). */
|
||||
#ifdef CONFIG_IMXRT_EDMA_EMLIM
|
||||
uint16_t nbytes; /* Bytes to transfer in a minor loop */
|
||||
uint16_t nbytes; /* Bytes to transfer in a minor loop */
|
||||
#else
|
||||
uint32_t nbytes; /* Bytes to transfer in a minor loop */
|
||||
uint32_t nbytes; /* Bytes to transfer in a minor loop */
|
||||
#endif
|
||||
#ifdef CONFIG_IMXRT_EDMA_ELINK
|
||||
DMACH_HANDLE linkch; /* Link channel (With EDMA_CONFIG_LINKTYPE_* flags) */
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -112,39 +163,39 @@ struct imxrt_edma_xfrconfig_s
|
||||
#ifdef CONFIG_DEBUG_DMA
|
||||
struct imxrt_dmaregs_s
|
||||
{
|
||||
uint8_t chan; /* Sampled channel */
|
||||
uint8_t chan; /* Sampled channel */
|
||||
|
||||
/* eDMA Global Registers */
|
||||
|
||||
uint32_t cr; /* Control */
|
||||
uint32_t es; /* Error Status */
|
||||
uint32_t erq; /* Enable Request */
|
||||
uint32_t req; /* Interrupt Request */
|
||||
uint32_t err; /* Error */
|
||||
uint32_t hrs; /* Hardware Request Status */
|
||||
uint32_t ears; /* Enable Asynchronous Request in Stop */
|
||||
uint32_t cr; /* Control */
|
||||
uint32_t es; /* Error Status */
|
||||
uint32_t erq; /* Enable Request */
|
||||
uint32_t req; /* Interrupt Request */
|
||||
uint32_t err; /* Error */
|
||||
uint32_t hrs; /* Hardware Request Status */
|
||||
uint32_t ears; /* Enable Asynchronous Request in Stop */
|
||||
|
||||
/* eDMA Channel registers */
|
||||
|
||||
uint8_t dchpri; /* Channel priority */
|
||||
uint8_t dchpri; /* Channel priority */
|
||||
|
||||
/* eDMA TCD */
|
||||
|
||||
uint32_t saddr; /* TCD Source Address */
|
||||
uint16_t soff; /* TCD Signed Source Address Offset */
|
||||
uint16_t attr; /* TCD Transfer Attributes */
|
||||
uint32_t nbml; /* TCD Signed Minor Loop Offset / Byte Count */
|
||||
uint32_t slast; /* TCD Last Source Address Adjustment */
|
||||
uint32_t daddr; /* TCD Destination Address */
|
||||
uint16_t doff; /* TCD Signed Destination Address Offset */
|
||||
uint16_t citer; /* TCD Current Minor Loop Link, Major Loop Count */
|
||||
uint32_t dlastsga; /* TCD Last Destination Address Adjustment/Scatter Gather Address */
|
||||
uint16_t csr; /* TCD Control and Status */
|
||||
uint16_t biter; /* TCD Beginning Minor Loop Link, Major Loop Count */
|
||||
uint32_t saddr; /* TCD Source Address */
|
||||
uint16_t soff; /* TCD Signed Source Address Offset */
|
||||
uint16_t attr; /* TCD Transfer Attributes */
|
||||
uint32_t nbml; /* TCD Signed Minor Loop Offset / Byte Count */
|
||||
uint32_t slast; /* TCD Last Source Address Adjustment */
|
||||
uint32_t daddr; /* TCD Destination Address */
|
||||
uint16_t doff; /* TCD Signed Destination Address Offset */
|
||||
uint16_t citer; /* TCD Current Minor Loop Link, Major Loop Count */
|
||||
uint32_t dlastsga; /* TCD Last Destination Address Adjustment/Scatter Gather Address */
|
||||
uint16_t csr; /* TCD Control and Status */
|
||||
uint16_t biter; /* TCD Beginning Minor Loop Link, Major Loop Count */
|
||||
|
||||
/* DMAMUX registers */
|
||||
|
||||
uint32_t dmamux; /* Channel configuration */
|
||||
uint32_t dmamux; /* Channel configuration */
|
||||
};
|
||||
#endif /* CONFIG_DEBUG_DMA */
|
||||
|
||||
@ -171,7 +222,7 @@ extern "C"
|
||||
* Public Function Prototypes
|
||||
************************************************************************************/
|
||||
|
||||
/************************************************************************************
|
||||
/****************************************************************************
|
||||
* Name: imxrt_dmach_alloc
|
||||
*
|
||||
* Allocate a DMA channel. This function sets aside a DMA channel,
|
||||
@ -188,14 +239,23 @@ extern "C"
|
||||
* DMAMUX_CHCFG_ENBL DMA Mux Channel Enable (required)
|
||||
*
|
||||
* A value of zero will disable the DMAMUX channel.
|
||||
* dchpri - DCHPRI channel priority configuration. See DCHPRI channel
|
||||
* configuration register bit-field definitions in
|
||||
* chip/imxrt_edma.h. Meaningful settings include:
|
||||
*
|
||||
* EDMA_DCHPRI_CHPRI Channel Arbitration Priority
|
||||
* DCHPRI_DPA Disable Preempt Ability
|
||||
* DCHPRI_ECP Enable Channel Preemption
|
||||
*
|
||||
* The power-on default, 0x05, is a reasonable choice.
|
||||
*
|
||||
* Returned Value:
|
||||
* If a DMA channel is available, this function returns a non-NULL, void*
|
||||
* DMA channel handle. NULL is returned on any failure.
|
||||
*
|
||||
************************************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
DMACH_HANDLE imxrt_dmach_alloc(uint32_t dmamux);
|
||||
DMACH_HANDLE imxrt_dmach_alloc(uint32_t dmamux, uint8_t dchpri);
|
||||
|
||||
/************************************************************************************
|
||||
* Name: imxrt_dmach_free
|
||||
|
Loading…
Reference in New Issue
Block a user