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:
Gregory Nutt 2018-05-22 15:28:28 -06:00
parent 890656f043
commit db0cdfc407
4 changed files with 183 additions and 95 deletions

View File

@ -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.

View File

@ -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)

View File

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

View File

@ -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