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- which case only the TCD channel registers will be used and scatter-
will not be supported. 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 config IMXRT_EDMA_ERCA
bool "Round Robin Channel Arbitration" bool "Round Robin Channel Arbitration"
default n default n

View File

@ -93,7 +93,7 @@
/* DMAMUX Register Addresses ********************************************************/ /* 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_CHCFG0 (IMXRT_DMAMUX_BASE + IMXRT_DMAMUX_CHCFG0_OFFSET)
# define IMXRT_DMAMUX_CHCFG1 (IMXRT_DMAMUX_BASE + IMXRT_DMAMUX_CHCFG1_OFFSET) # define IMXRT_DMAMUX_CHCFG1 (IMXRT_DMAMUX_BASE + IMXRT_DMAMUX_CHCFG1_OFFSET)
# define IMXRT_DMAMUX_CHCFG2 (IMXRT_DMAMUX_BASE + IMXRT_DMAMUX_CHCFG2_OFFSET) # define IMXRT_DMAMUX_CHCFG2 (IMXRT_DMAMUX_BASE + IMXRT_DMAMUX_CHCFG2_OFFSET)

View File

@ -352,55 +352,17 @@ static inline void imxrt_tcd_initialize(void)
* *
************************************************************************************/ ************************************************************************************/
static void imxrt_tcd_chanlink(uint8_t flags, uint8_t chan, #ifdef CONFIG_IMXRT_EDMA_ELINK
static inline void imxrt_tcd_chanlink(uint8_t flags, struct imxrt_dmach_s *linkch,
struct imxrt_edmatcd_s *tcd) struct imxrt_edmatcd_s *tcd)
{
switch (flags & EDMA_CONFIG_LINKTYPE_MASK)
{
case EDMA_CONFIG_LINKTYPE_MINORLINK: /* Minor link config */
{ {
uint16_t regval16; uint16_t regval16;
/* Enable minor link */ flags &= EDMA_CONFIG_LINKTYPE_MASK;
tcd->citer |= EDMA_TCD_CITER_ELINK_ELINK; if (linkch == NULL || flags == EDMA_CONFIG_LINKTYPE_LINKNONE)
tcd->biter |= EDMA_TCD_BITER_ELINK_ELINK;
/* Set linked channel */
regval16 = tcd->citer;
regval16 &= ~EDMA_TCD_CITER_ELINK_LINKCH_MASK;
regval16 |= EDMA_TCD_CITER_ELINK_LINKCH(chan);
tcd->citer = regval16;
regval16 = tcd->biter;
regval16 &= ~EDMA_TCD_BITER_ELINK_LINKCH_MASK;
regval16 |= EDMA_TCD_BITER_ELINK_LINKCH(chan);
tcd->biter = regval16;
}
break;
case EDMA_CONFIG_LINKTYPE_MAJORLINK: /* Major link config */
{
uint16_t regval16;
/* Enable major link */
regval16 = tcd->csr;
regval16 |= EDMA_TCD_CSR_MAJORELINK;
tcd->csr = regval16;
/* 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:
{ {
/* No link or no link channel provided */
/* Disable minor links */ /* Disable minor links */
tcd->citer &= ~EDMA_TCD_CITER_ELINK; tcd->citer &= ~EDMA_TCD_CITER_ELINK;
@ -410,9 +372,41 @@ static void imxrt_tcd_chanlink(uint8_t flags, uint8_t chan,
tcd->csr &= ~EDMA_TCD_CSR_MAJORELINK; tcd->csr &= ~EDMA_TCD_CSR_MAJORELINK;
} }
break; else if (flags == EDMA_CONFIG_LINKTYPE_MINORLINK) /* Minor link config */
{
/* Enable minor link */
tcd->citer |= EDMA_TCD_CITER_ELINK_ELINK;
tcd->biter |= EDMA_TCD_BITER_ELINK_ELINK;
/* Set linked channel */
regval16 = tcd->citer;
regval16 &= ~EDMA_TCD_CITER_ELINK_LINKCH_MASK;
regval16 |= EDMA_TCD_CITER_ELINK_LINKCH(linkch->chan);
tcd->citer = regval16;
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;
/* Set major linked channel */
regval16 &= ~EDMA_TCD_CSR_MAJORLINKCH_MASK;
regval16 |= EDMA_TCD_CSR_MAJORLINKCH(linkch->chan);
tcd->csr = regval16;
} }
} }
#endif
/**************************************************************************** /****************************************************************************
* Name: imxrt_tcd_configure * Name: imxrt_tcd_configure
@ -435,14 +429,19 @@ static inline void imxrt_tcd_configure(struct imxrt_edmatcd_s *tcd,
tcd->slast = tcd->slast; tcd->slast = tcd->slast;
tcd->daddr = config->daddr; tcd->daddr = config->daddr;
tcd->doff = config->doff; tcd->doff = config->doff;
tcd->citer = config->iter; tcd->citer = config->iter & EDMA_TCD_CITER_CITER_MASK;
tcd->biter = config->iter; tcd->biter = config->iter & EDMA_TCD_BITER_BITER_MASK;
tcd->csr = EDMA_TCD_CSR_DREQ; /* Assume last transfer */ tcd->csr = EDMA_TCD_CSR_DREQ; /* Assume last transfer */
tcd->dlastsga = 0; tcd->dlastsga = 0;
/* And special case flags */ /* 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) * DMAMUX_CHCFG_ENBL DMA Mux Channel Enable (required)
* *
* A value of zero will disable the DMAMUX channel. * 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: * Returned Value:
* If a DMA channel is available, this function returns a non-NULL, void* * 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; struct imxrt_dmach_s *dmach;
unsigned int chndx; unsigned int chndx;

View File

@ -43,6 +43,56 @@
#ifndef __ARCH_ARM_SRC_IMXRT_IMXRT_EDMAC_H #ifndef __ARCH_ARM_SRC_IMXRT_IMXRT_EDMAC_H
#define __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 * Included Files
************************************************************************************/ ************************************************************************************/
@ -59,9 +109,8 @@
/* Configuration flags. /* Configuration flags.
* *
* REVISIT: Many missing options that should be represented as flags: * REVISIT: Many missing options that should be represented as flags:
* 1. DCHPRIO priority, pre-emption flags * 1. Bandwidth
* 2. Bandwidth * 2. Source/Destination modulo
* 3. Source/Destination modulo
*/ */
#define EDMA_CONFIG_LINKTYPE_SHIFT (0) /* Bits 0-1: Link type */ #define EDMA_CONFIG_LINKTYPE_SHIFT (0) /* Bits 0-1: Link type */
@ -99,12 +148,14 @@ struct imxrt_edma_xfrconfig_s
uint8_t ssize; /* Source data transfer size (see TCD_ATTR_SIZE_* definitions in chip/. */ uint8_t ssize; /* Source data transfer size (see TCD_ATTR_SIZE_* definitions in chip/. */
uint8_t dsize; /* Destination data transfer size. */ uint8_t dsize; /* Destination data transfer size. */
uint8_t ttype; /* Transfer type (see enum imxrt_edma_xfrtype_e). */ uint8_t ttype; /* Transfer type (see enum imxrt_edma_xfrtype_e). */
uint8_t linkch; /* Link channel (With EDMA_CONFIG_LINKTYPE_* flags) */
#ifdef CONFIG_IMXRT_EDMA_EMLIM #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 #else
uint32_t nbytes; /* Bytes to transfer in a minor loop */ uint32_t nbytes; /* Bytes to transfer in a minor loop */
#endif #endif
#ifdef CONFIG_IMXRT_EDMA_ELINK
DMACH_HANDLE linkch; /* Link channel (With EDMA_CONFIG_LINKTYPE_* flags) */
#endif
}; };
/* The following is used for sampling DMA registers when CONFIG DEBUG_DMA is selected */ /* The following is used for sampling DMA registers when CONFIG DEBUG_DMA is selected */
@ -171,7 +222,7 @@ extern "C"
* Public Function Prototypes * Public Function Prototypes
************************************************************************************/ ************************************************************************************/
/************************************************************************************ /****************************************************************************
* Name: imxrt_dmach_alloc * Name: imxrt_dmach_alloc
* *
* Allocate a DMA channel. This function sets aside a DMA channel, * 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) * DMAMUX_CHCFG_ENBL DMA Mux Channel Enable (required)
* *
* A value of zero will disable the DMAMUX channel. * 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: * Returned Value:
* If a DMA channel is available, this function returns a non-NULL, void* * If a DMA channel is available, this function returns a non-NULL, void*
* DMA channel handle. NULL is returned on any failure. * 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 * Name: imxrt_dmach_free