arch/arm/src/imxrt: A little more eDMA logic. Slow progress.
This commit is contained in:
parent
1acc765156
commit
fe364ba1f4
@ -258,14 +258,44 @@ static void imxrt_dmaterminate(struct imxrt_dmach_s *dmach, int result)
|
|||||||
|
|
||||||
static void imxrt_dmach_interrupt(struct imxrt_dmach_s *dmach)
|
static void imxrt_dmach_interrupt(struct imxrt_dmach_s *dmach)
|
||||||
{
|
{
|
||||||
|
uintptr_t regaddr;
|
||||||
|
uint16_t regval16;
|
||||||
|
uint8_t regval8;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
/* Is (or was) DMA active on this channel? */
|
||||||
|
|
||||||
|
if (dmach->state == IMXRT_DMA_ACTIVE)
|
||||||
|
{
|
||||||
|
/* Yes.. Get the eDMA TCD Control and Status register value. */
|
||||||
|
|
||||||
|
regaddr = IMXRT_EDMA_TCD_CSR(dmach->chan);
|
||||||
|
|
||||||
|
/* Check if the transfer is done */
|
||||||
|
|
||||||
|
if ((regaddr & EDMA_TCD_CSR_DONE) != 0)
|
||||||
|
{
|
||||||
|
/* Clear the pending DONE interrupt status. */
|
||||||
|
|
||||||
|
regval8 = EDMA_CDNE(dmach->chan);
|
||||||
|
putreg8(regval8, IMXRT_EDMA_CDNE);
|
||||||
|
result = OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if any errors have occurred. */
|
||||||
#warning Missing logic
|
#warning Missing logic
|
||||||
/* Get the eDMA status register value. Ignore all masked interrupt
|
|
||||||
* status bits.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Check if the any transfer has completed or any errors have occurred. */
|
{
|
||||||
|
/* Clear the pending error interrupt status. */
|
||||||
|
#warning Missing logic
|
||||||
|
|
||||||
imxrt_dmaterminate(dmach);
|
result = -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Terminate the transfer */
|
||||||
|
|
||||||
|
imxrt_dmaterminate(dmach, result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -295,21 +325,14 @@ static int imxrt_edma_interrupt(int irq, void *context, FAR void *arg)
|
|||||||
|
|
||||||
/* Check for an interrupt on the lower numbered DMA channel */
|
/* Check for an interrupt on the lower numbered DMA channel */
|
||||||
|
|
||||||
if (dmach->state == IMXRT_DMA_ACTIVE)
|
imxrt_dmach_interrupt(dmach);
|
||||||
{
|
|
||||||
imxrt_dmach_interrupt(dmach);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for an interrupt on the lower numbered DMA channel */
|
/* Check for an interrupt on the higher numbered DMA channel */
|
||||||
|
|
||||||
chan += 16;
|
chan += 16;
|
||||||
DEBUGASSERT(chan < IMXRT_EDMA_NCHANNELS);
|
DEBUGASSERT(chan < IMXRT_EDMA_NCHANNELS);
|
||||||
dmach = &g_edma.dmach[chan];
|
dmach = &g_edma.dmach[chan];
|
||||||
|
imxrt_dmach_interrupt(dmach);
|
||||||
if (dmach->state == IMXRT_DMA_ACTIVE)
|
|
||||||
{
|
|
||||||
imxrt_dmach_interrupt(dmach);
|
|
||||||
}
|
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@ -498,16 +521,16 @@ void imxrt_dmafree(DMA_HANDLE handle)
|
|||||||
*
|
*
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
int imxrt_dmasetup(DMA_HANDLE handle, uint8_t pchan, uint32_t maddr, size_t nbytes,
|
int imxrt_dmasetup(DMA_HANDLE handle, uint32_t saddr, uint32_t daddr, size_t nbytes,
|
||||||
uint32_t chflags)
|
uint32_t chflags);
|
||||||
{
|
{
|
||||||
struct imxrt_dmach_s *dmach = (struct imxrt_dmach_s *)handle;
|
struct imxrt_dmach_s *dmach = (struct imxrt_dmach_s *)handle;
|
||||||
int ret = OK;
|
int ret = OK;
|
||||||
|
|
||||||
DEBUGASSERT(dmach != NULL);
|
DEBUGASSERT(dmach != NULL);
|
||||||
dmainfo("dmach%u: %p pchan: %u maddr: %08x nbytes: %d chflags %08x\n",
|
dmainfo("dmach%u: %p saddr: %08lx maddr: %08lx nbytes: %lu chflags %08x\n",
|
||||||
dmach, dmach->chan, (int)pchan, (int)maddr, (int)nbytes,
|
dmach, dmach->chan, (unsigned long)pchan, (unsigned long)maddr,
|
||||||
(unsigned int)chflags);
|
(unsigned long)nbytes, (unsigned int)chflags);
|
||||||
|
|
||||||
/* To initialize the eDMA:
|
/* To initialize the eDMA:
|
||||||
*
|
*
|
||||||
@ -516,6 +539,13 @@ int imxrt_dmasetup(DMA_HANDLE handle, uint8_t pchan, uint32_t maddr, size_t nbyt
|
|||||||
* configuration other than the default is desired.
|
* configuration other than the default is desired.
|
||||||
* 3. Enable error interrupts in the EEI register if so desired.
|
* 3. Enable error interrupts in the EEI register if so desired.
|
||||||
* 4. Write the 32-byte TCD for each channel that may request service.
|
* 4. Write the 32-byte TCD for each channel that may request service.
|
||||||
|
*
|
||||||
|
* To perform a simple transfer of n bytes of data with one activation, set
|
||||||
|
* the major loop to one (TCDn_CITER = TCDn_BITER = 1). The data transfer
|
||||||
|
* begins after the channel service request is acknowledged and the channel
|
||||||
|
* is selected to execute. After the transfer is complete, the TCDn_CSR[DONE]
|
||||||
|
* bit is set and an interrupt generates if properly enabled.
|
||||||
|
*
|
||||||
* 5. Enable any hardware service requests via the ERQ register.
|
* 5. Enable any hardware service requests via the ERQ register.
|
||||||
* 6. Request channel service via either:
|
* 6. Request channel service via either:
|
||||||
* - Software: setting the TCDn_CSR[START]
|
* - Software: setting the TCDn_CSR[START]
|
||||||
@ -566,24 +596,48 @@ int imxrt_dmasetup(DMA_HANDLE handle, uint8_t pchan, uint32_t maddr, size_t nbyt
|
|||||||
int imxrt_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg)
|
int imxrt_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg)
|
||||||
{
|
{
|
||||||
struct imxrt_dmach_s *dmach = (struct imxrt_dmach_s *)handle;
|
struct imxrt_dmach_s *dmach = (struct imxrt_dmach_s *)handle;
|
||||||
int ret = -EINVAL;
|
irqstate_t flags;
|
||||||
|
uintptr_t regaddr;
|
||||||
|
uint16_t regval16;
|
||||||
|
uint8_t regval8;
|
||||||
|
uint8_t chan;
|
||||||
|
|
||||||
dmainfo("dmach: %p callback: %p arg: %p\n", dmach, callback, arg);
|
|
||||||
DEBUGASSERT(dmach != NULL && dmach->state == IMXRT_DMA_CONFIGURED);
|
DEBUGASSERT(dmach != NULL && dmach->state == IMXRT_DMA_CONFIGURED);
|
||||||
|
chan = dmach->chan;
|
||||||
/* Verify that the DMA has been setup (i.e., at least one entry in the
|
dmainfo("dmach%u: %p callback: %p arg: %p\n", dmach, chan, callback, arg);
|
||||||
* link list).
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Save the callback info. This will be invoked whent the DMA commpletes */
|
/* Save the callback info. This will be invoked whent the DMA commpletes */
|
||||||
|
|
||||||
|
flags = spin_lock_irqsave();
|
||||||
dmach->callback = callback;
|
dmach->callback = callback;
|
||||||
dmach->arg = arg;
|
dmach->arg = arg;
|
||||||
dmach->state = IMXRT_DMA_ACTIVE;
|
dmach->state = IMXRT_DMA_ACTIVE;
|
||||||
|
|
||||||
|
/* Enable the DONE interrupt when the major interation count completes. */
|
||||||
#warning Missing logic
|
#warning Missing logic
|
||||||
|
|
||||||
return ret;
|
/* Enable channel ERROR interrupts */
|
||||||
|
#warning Missing logic
|
||||||
|
|
||||||
|
/* Enable the DMA request for this channel */
|
||||||
|
|
||||||
|
regval8 = EDMA_SERQ(chan);
|
||||||
|
putreg8(regval8, IMXRT_EDMA_SERQ_OFFSET);
|
||||||
|
|
||||||
|
/* Request channel service via either:
|
||||||
|
* - Software: setting the TCDn_CSR[START]
|
||||||
|
* - Hardware: slave device asserting its eDMA peripheral request signal
|
||||||
|
*
|
||||||
|
* REVISIT: Which case do we need to do the software interrupt?
|
||||||
|
*/
|
||||||
|
|
||||||
|
regaddr = IMXRT_EDMA_TCD_CSR(chan);
|
||||||
|
regval16 = getreg16(regaddr);
|
||||||
|
regval16 |= EDMA_TCD_CSR_START;
|
||||||
|
putreg16(regval16, regaddr);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(flags);
|
||||||
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -153,7 +153,7 @@ struct imxrt_dmaregs_s
|
|||||||
uint32_t req; /* Interrupt Request */
|
uint32_t req; /* Interrupt Request */
|
||||||
uint32_t err; /* Error */
|
uint32_t err; /* Error */
|
||||||
uint32_t hrs; /* Hardware Request Status */
|
uint32_t hrs; /* Hardware Request Status */
|
||||||
uint32_t ears; /* Enable Asynchronous Request in Stop */
|
uint32_t ears; /* Enable Asynchronous Request in Stop */
|
||||||
|
|
||||||
/* eDMA Channel registers */
|
/* eDMA Channel registers */
|
||||||
|
|
||||||
@ -248,7 +248,7 @@ void imxrt_dmafree(DMA_HANDLE handle);
|
|||||||
*
|
*
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
int imxrt_dmasetup(DMA_HANDLE handle, uint8_t pchan, uint32_t maddr, size_t nbytes,
|
int imxrt_dmasetup(DMA_HANDLE handle, uint32_t saddr, uint32_t daddr, size_t nbytes,
|
||||||
uint32_t chflags);
|
uint32_t chflags);
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
|
Loading…
Reference in New Issue
Block a user