Hi All,
Looking for some guidance on porting my TCD-DMA configuration to the KSDK v2.0 using the eDMA driver API. My code transfer data from buffer to SPI over DMA.
static uint32_t SPI_data_patterns[] =
{
DSPI_PUSHR_PCS0 | DSPI_PUSHR_CTAS(0) | DSPI_PUSHR_CONT | DSPI_PUSHR_TXDATA(0x0ec0),
DSPI_PUSHR_PCS0 | DSPI_PUSHR_CTAS(0) | DSPI_PUSHR_EOQ | DSPI_PUSHR_TXDATA(0x0000)
};
static uint32_t *p_SPI_data_patterns = SPI_data_patterns;
static uint32_t SPI_data_patterns_size = sizeof(SPI_data_patterns);
void test(void)
{
...
/* Load address of source data */
DMA_0.TCD[16].SADDR.R = p_SPI_data_patterns;
/* Read 4 bytes per transfer */
DMA_0.TCD[16].ATTR.B.SSIZE = kEDMA_TransferSize4Bytes;
/* After transfer, add 4 to src addr */
DMA_0.TCD[16].SOFF.B.SOFF = 4;
/* After major loop, reset src addr */
DMA_0.TCD[16].SLAST.B.SLAST = -SPI_data_patterns_size;
/* Source modulo feature not used */
DMA_0.TCD[16].ATTR.B.SMOD = 0;
/* Load address of destination */
DMA_0.TCD[16].DADDR.B.DADDR = &SPI0.PUSHR.R;
/* Write 4 bytes per transfer */
DMA_0.TCD[16].ATTR.B.DSIZE = kEDMA_TransferSize4Bytes;
/* After transfer, add 0 to dest addr */
DMA_0.TCD[16].DOFF.B.DOFF = 0;
/* After major loop, reset dest addr */
DMA_0.TCD[16].DLASTSGA.B.DLASTSGA = 0;
/* Destination modulo feature not used */
DMA_0.TCD[16].ATTR.B.DMOD = 0;
/* Transfer 4 bytes per minor loop */
DMA_0.TCD[16].NBYTES.MLNO.B.NBYTES = 4;
/* Initialize the begining and current major loop iteration counts */
DMA_0.TCD[16].BITER.ELINKNO.B.BITER = SPI_data_patterns_size / 4;
DMA_0.TCD[16].CITER.ELINKNO.B.CITER = SPI_data_patterns_size / 4;
DMA_0.TCD[16].BITER.ELINKNO.B.ELINK = 0;
DMA_0.TCD[16].CITER.ELINKNO.B.ELINK = 0;
DMA_0.TCD[16].CSR.B.DREQ = 1;
DMA_0.TCD[16].CSR.B.INTHALF = 0;
DMA_0.TCD[16].CSR.B.INTMAJOR = 0;
DMA_0.TCD[16].CSR.B.MAJORELINK = 0;
DMA_0.TCD[16].CSR.B.ESG = 0
DMA_0.TCD[16].CSR.B.BWC = 0;
DMA_0.TCD[16].CSR.B.START = 0;
DMA_0.TCD[16].CSR.B.DONE = 0;
DMA_0.TCD[16].CSR.B.ACTIVE = 0;
/*eDMA request signal for channel 16 is enabled, start DMA/SPI transfer*/
DMA_0.ERQ.B.ERQ16 = 1U;
...
}
void my10msISR(void)
{
...
if (SPI_0.SR.B.EOQF){
/*clear EOQF, so next frames are TXed by DMA*/
SPI_0.SR.R = DSPI_SR_EOQF;
DMA_0.ERQ.B.ERQ16 = 1U;
}
...
}
Best regards,
Pat
Solved! Go to Solution.
Hi Pat,
I do not see a specific EDMA API for modifying the LAST.
I tested below code in the edma scatter gather for frdm-k64f using KSDK_v2.
EDMA_CreateHandle(&g_EDMA_Handle, DMA0, 0);
#if 1 //DES 1=test, 0=default code
edma_tcd_t *tcdRegs;
tcdRegs = (edma_tcd_t *)(&g_EDMA_Handle.base->TCD[g_EDMA_Handle.channel]);
tcdRegs->SLAST = -4;
#endif
Regards,
David
Hi, Pat,
do you want to develop code for DMA and SPI module based on SDK2.0? The SDK2.0 has the example for spi plus DMA.
For example, this is the directory of example for DMA and SPI based on K64.
C:\Freescale\SDK2.0_FRDM_K64F\boards\frdmk64f\driver_examples\dspi\edma_transfer\kdsp:
you can download SDK2.0 from the link:
Hope it can help you
BR
XiangJun Rong
Hi XiangJun,
I already downloaded and saw the examples provided in KSDK2.0 which unfortunately don't match with my working "simple" DMA-SPI Tx tranfer. The TCD configuration is done just one time during initialisation. During runtime I only have to enable the corresponding DMA channel in order to send my data and DMA stop automatically, and waiting for a new activation, and so on.
Anyway, I would like porting my TCD configuration to the KSDK v2.0 using the eDMA driver API. For example, I'm facing a problem when I would like set the SLAST field, it seems that it's not covered by the eDMA API ?!
Best regards,
Pat
Hi Pat,
I do not see a specific EDMA API for modifying the LAST.
I tested below code in the edma scatter gather for frdm-k64f using KSDK_v2.
EDMA_CreateHandle(&g_EDMA_Handle, DMA0, 0);
#if 1 //DES 1=test, 0=default code
edma_tcd_t *tcdRegs;
tcdRegs = (edma_tcd_t *)(&g_EDMA_Handle.base->TCD[g_EDMA_Handle.channel]);
tcdRegs->SLAST = -4;
#endif
Regards,
David
Hi David,
Thank you for the workaround. I was wondering if it's the rignt way to set the TCD because I have to call EDMA_TcdDisableInterrupts() in order to clear the INTMAJOR previously enabled by EDMA_SubmitTransfer() ?
edma_handle_t g_EDMA_Handle;
EDMA_GetDefaultConfig(&userConfig);
EDMA_Init(DMA0, &userConfig);
EDMA_CreateHandle(&g_EDMA_Handle, DMA0, 0);
{
edma_tcd_t *tcdRegs;
tcdRegs = (edma_tcd_t *)(&g_EDMA_Handle.base->TCD[g_EDMA_Handle.channel]);
tcdRegs->SLAST = -sizeof(SPI_data_patterns);
}
EDMA_PrepareTransfer(&transferConfig, SPI_data_patterns, sizeof(SPI_data_patterns[0]),
(void *)&SPI0->PUSHR, sizeof(SPI0->PUSHR),
sizeof(SPI_data_patterns[0]), sizeof(SPI_data_patterns),
kEDMA_MemoryToPeripheral);
EDMA_SubmitTransfer(&g_EDMA_Handle, &transferConfig);
/*Disable TCD[n].CSR.INTMAJOR because it has been previously set by EDMA_SubmitTransfer(),
and the corresponding NVIC interrupt is still enabled by EDMA_CreateHandle()*/
EDMA_TcdDisableInterrupts((edma_tcd_t *)(&g_EDMA_Handle.base->TCD[g_EDMA_Handle.channel]),
(uint32_t)(kEDMA_MajorInterruptEnable));
for(;;){
wait20ms();
EDMA_StartTransfer(&g_EDMA_Handle);
/* Wait for SPI0 finish */
while (!(DSPI_GetStatusFlags(SPI0) & kDSPI_EndOfQueueFlag))
{
}
...
}
Best regards,
Pat
Hi Pat,
Since the LAST was initialized to 0 and there is not a standard API function call to change it, this is just one way to do it.
You could go implement this into your own API call as well.
Regards,
David