How to write DMA code for new eDMA?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How to write DMA code for new eDMA?

1,857 Views
fasihahmed
Contributor IV

I have a source code for DMA on older mc56f82748 DSC, and now have to port the same feature to new mc56f83763 DSC which use eDMA..

The registers and ioctl calls are named completely different, which makes it hard to re-write the code originally working on legacy source code. 

Can someone help with it?  I have attached the legacy source code, and will need some guidance how to write it for the new DSC

 

void DMA_Init(void)
{
ioctl(DMA, DMA_INIT, NULL);
ioctl(DMA_0, DMA_INIT, NULL);
ioctl(DMA_0, DMA_SET_PERIPHERAL_REQUEST, DMA_DISABLE); // Disable peripheral request before modifying DMA registers

ioctl(DMA_0, DMA_WRITE_DSR_BCR, 6*2); // 12 bytes on DMA0 (12-bit result register ADC_RA)
uw32Address = (UWord32)&(w16IphaseArray[0]);
// set destination address to first member of the structure //
ioctl(DMA_0, DMA_SET_DESTINATION_ADDRESS, uw32Address<<1);
ioctl(DMA_0, DMA_SET_SOURCE_ADDRESS, 0x1CA1C);
// clear interrupt flag and enable next transfer by writing BCR registers
ioctl(DMA_0, DMA_SET_PERIPHERAL_REQUEST, DMA_ENABLE); // Enable peripheral request to initiate the DMA transfer

}

 

@ZhangJennie @xianduidong @xiangjun_rong 

0 Kudos
4 Replies

1,835 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Fasih,

Unfortunately, as you know that the eDMA is the IP which is the same as that of Kinetis K family, and i.mxrt10xx family, so you can refer to Kinetis or i.mxrt for the source code of eDMA.

This is the source code based on FRDM-K64 I have developed, which can transfer from memory to memory, you can refer to it.

BR

XiangJun Rong

#include "MK64F12.h"
#define N 100
static void DmaInit(void);
void PollFlag(void);

uint32_t sArray[N],dArray[N];
uint32_t i,j,k;
int main(void)
{

/* Write your code here */
for(i=0; i<N; i++)
{
sArray[i]=i;
}
DmaInit();
PollFlag();
/* This for loop should be replaced. By default this loop allows a single stepping. */
for (;;) {
j++;
}
/* Never leave main */
return 0;
}

static void DmaInit(void)
{
//enable DMA gated clock
SIM_SCGC7|=0x02;
SIM_SCGC6|=0x02;
//set the DMA triggering channel, channel63 is always triggering
DMAMUX_CHCFG0|=63;
DMA_CR|=0x80;
//source address
DMA_TCD0_SADDR=(uint32_t)&sArray[0];
//source offset
DMA_TCD0_SOFF=0x04;
DMA_TCD0_ATTR=0x0202;
//minor loop count number
DMA_TCD0_NBYTES_MLOFFYES=(1<<31)|((4*N)<<10)|(4*N);
DMA_TCD0_SLAST=0x00;
DMA_TCD0_DADDR=(uint32_t)&dArray[0];
DMA_TCD0_DOFF=0x04;
//major counter
DMA_TCD0_CITER_ELINKNO=0x01;
DMA_TCD0_DLASTSGA=0x00;
DMA_TCD0_BITER_ELINKNO=0x01;
//enable DMA trigger
DMAMUX_CHCFG0|=0x80;
//start DMA
DMA_TCD0_CSR|=0x01;
//while(!(DMA_TCD0_CSR&0x80)) {}
//__asm("nop");

}
void PollFlag(void)
{
while(!(DMA_TCD0_CSR&0x80)) {}
__asm("nop");
}
////////////////////////////////////////////////////////////////////////////////
// EOF
////////////////////////////////////////////////////////////////////////////////

0 Kudos

1,813 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Fasih,

I will try to develop the code, the PIT is used to trigger ADC based on MC56F83000-EVK board, the ADC end of scan event can trigger eDMA.

maybe I can post the code at the end of this week.

BR

XiangJun Rong

1,805 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Fasih,

I have tried to use the code to test the PIT/ADC/eDMA, it appears it works fine. I develop the code under CW for mcu ver11.x, MC56F83000-EVK. But it is not fully tested.

BR

XiangJun Rong

#define N 100
#define CHANNEL_NUMBER_EACH_TRIGGER 4

void eDMA_ADC_MultipleChannel(void);

void ADCPit0TriggereMultipleChannelDMA(void);

 

uint16_t sample[N];

void main(void)
{

INTC->VBA = (uint16_t)(&vba_vector_addr);
__EI(0); // enable interrupts of all priorities
LED0_Init();

configADCPins();

ADCPit0TriggereMultipleChannelDMA();
eDMA_ADC_MultipleChannel();

// memTomem_eDMA();
while(1) {}

}

 

 

//ADC will sample CH0/CH1/CH2/CH3, total 4 channel
void ADCPit0TriggereMultipleChannelDMA(void)
{
//PIT0 init
SIM->PCE2|=1<<3;
//PIT0 prescaler is 32768, the PIT0 cycl;e time is (100 000 000/32768)=3051
PIT0->CTRL=0x0F<<3;
PIT0->MOD=5;
//PIT0->CTRL|=0x01;

//set up crossbar so that the PIT0 can trigger ADC
//XBAR_OUT12 ADCA_TRIG ADCA (Cyclic ADC) Trigger
//PIT0_SYNC_OUT PIT0 Sync Output XBAR_IN44

XBARA->SEL6=44;
//ADC init
//enable ADC gated clock
SIM->PCE2|=1<<7;
//init ADC module
//using hardware to start ADC, enable ADC end of scan interrupt
//Triggered sequential mode
ADC->CTRL1=0x9004;
//ADC clock is 100MHz/6=16.67MHz
ADC->CTRL2=0x02;
//ADC will sample CH0/CH1/CH2/CH3, total 4 channel
ADC->CLIST1=0x3210;
//sinfgle channel is sampled
ADC->SDIS=0xFFF0;
//configure ADC PWR reg
ADC->PWR2=0x200;
ADC->PWR=0x304;
//Poll id the ADC is powered up, the delay time is 0x30 clock cycles
while(ADC->PWR&0x400) {}

//set up voltage reference
ADC->CAL=0x00;
i=0;
//start PIT0
PIT0->CTRL|=0x01;
__asm(NOP);
}

 

void eDMA_ADC_MultipleChannel(void)
{
uint32_t temp;
//set up eDMA channel0 interrupt
INTC->IPR3|=0xC0;
DMA->INT|=0x01;
//enable EDMA channel 0 interrupt
//enable always channel

SIM->CTRL&=~(0x1C0);
SIM->CTRL|=0x1C0;
//reset DMAMUX
SIM->PSWR3|=0x200;
__asm(NOP);
__asm(NOP);
SIM->PSWR3&=~(0x200);
//48 ADCA_ES ADCA End of Scan
DMAMUX->CHCFG[0]=48;
//initalize the eDMA module
//enable minor loop and debug mode
DMA->CR|=0x82;
//word address &ADC->RSLT[0]=0xE500+E=0xE50E, byte address is 0x1CA1C
DMA->TCD[0].SADDR=(uint32_t)&ADC->RSLT[0]<<1;
//source offset 2 bytes
DMA->TCD[0].SOFF=0x02;
//two bytes for each transfer
DMA->TCD[0].ATTR=0x0101;
//minor loop count number
temp=(-2*CHANNEL_NUMBER_EACH_TRIGGER)<<10;
temp&=0x3FFFFC00;
temp|=0x80000000;
temp|=2*CHANNEL_NUMBER_EACH_TRIGGER;
DMA->TCD[0].NBYTES_MLOFFYES=temp;
__asm(nop); //break point, check the DMA->TCD[0].NBYTES_MLOFFYES reg
DMA->TCD[0].SLAST=0x00;
DMA->TCD[0].DADDR=(uint32_t)&sample[0]<<1;
DMA->TCD[0].DOFF=0x02;
//major counter
DMA->TCD[0].CITER_ELINKNO=N/4;
DMA->TCD[0].DLASTSGA=0x00;
DMA->TCD[0].BITER_ELINKNO=N/4;
//enable DMA trigger
DMAMUX->CHCFG[0]|=0x80;
//DMA->ERQ|=0x01;
//enable eDMA channel 0 interrupt
DMA->TCD[0].CSR|=0x02;
DMA->ERQ=0x01;
//start DMA for software trigger
//DMA->TCD[0].CSR|=0x01;
// while(!(DMA->TCD[0].CSR&0x80)) {}
__asm(nop);

}

 

//GPIOA0/A1/A2/A3 become ANA0/ANA1/ANA2/ANA3
void configADCPins(void)
{
//enable GPIOA gated clock
SIM->PCE0|=0x40;
GPIOA->PER|=0x0F;
}

#pragma interrupt on
void eDMA_0_ISR(void)
{
//clear DONE flag of eDMA channel 0
// DMA->TCD[0].BITER_ELINKNO=N/4;
// DMA->TCD[0].CITER_ELINKNO=N/4;
DMA->CDNE=0x40;
//clear DONE bit
DMA->TCD[0].CSR|=0x80;
PIT0->CTRL&=~(0x01);
__asm(NOP);
}
#pragma interrupt off

 

 

 

in the MC56F83xxx_Vectors.c

extern void eDMA_0_ISR(void);

volatile asm void _vect(void) {
JMP >_EntryPoint /* Interrupt no. 0 (Used)*/
JMP >_EntryPoint /* Interrupt no. 1 (Used)*/
JSR >ivINT_ILLEGAL_OP /* Interrupt no. 2*/
JSR >ivINT_SWI3 /* Interrupt no. 3*/
JSR >ivINT_OVERFLOW /* Interrupt no. 4*/
JSR >ivINT_MISALIGNED /* Interrupt no. 5*/
JSR >ivINT_STPCNT /* Interrupt no. 6*/
JSR >ivINT_BKPT /* Interrupt no. 7*/
JSR >ivINT_TRBUF /* Interrupt no. 8*/

....

JSR >eDMA_0_ISR //ivINT_DMA0 /* Interrupt no. 36*/

...

}

 

0 Kudos

1,792 Views
fasihahmed
Contributor IV

.

0 Kudos