DMA0_IRQHandler doesn't run [s32k144]

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

DMA0_IRQHandler doesn't run [s32k144]

Jump to solution
1,883 Views
electronica2pow
Contributor III

Hi to the community,

I have been trying to run this example, but the "DMA0_IRQHandler" doesn't run. Why is it?

If i look at expressions "counter" is always 0. It should increase its value on each DMA0_IRQ request: counter++;

(DMA is triggered by PDB)

On the other hand, i think that interrupts is enable, because i get some "Error:Target...." when i debug step by step on the for(;;){}. So maybe the DMA0 interruption isn't linked correctly.

Code:

#include "S32K144.h" /* include peripheral declarations S32K144 */


static uint32_t result[4] __attribute__ ((aligned (32)));
uint32_t salidaADC=0;
uint32_t counter=0;

void SCG_Init(void);
void GPIO_Init(void);
void PDB_Init(void);
void ADC_Init(void);
void WDOG_Disable(void);
void PDB_Init(void);
void DMA_init(void);
void DMAMUX_Init(void);
void IRQs_Init(void);
void DMA0_IRQHandler(void);


void SCG_Init(void)
{
// *** System OSC ***
SCG->SOSCDIV=0x00000101; /* SOSCDIV1 & SOSCDIV2 =1: divide by 1 */
SCG->SOSCCFG=0x00000034; /* Range=3: high freq (SOSC betw 8MHz-32MHz)*/
/* HGO=0: Config xtal osc for low power */
/* EREFS=1: Input is external XTAL */
while(SCG->SOSCCSR & SCG_SOSCCSR_LK_MASK); /* Ensure SOSCCSR unlocked */
SCG->SOSCCSR=0x00000001; /* LK=0: SOSCCSR can be written */
/* SOSCCMRE=0: OSC CLK monitor IRQ if enabled */
/* SOSCCM=0: OSC CLK monitor disabled */
/* SOSCERCLKEN=0: Sys OSC 3V ERCLK output clk disabled */
/* SOSCLPEN=0: Sys OSC disabled in VLP modes */
/* SOSCSTEN=0: Sys OSC disabled in Stop modes */
/* SOSCEN=1: Enable oscillator */
while(!(SCG->SOSCCSR & SCG_SOSCCSR_SOSCVLD_MASK)); /* Wait for sys OSC clk valid */

// *** System PLL ***
SCG->SPLLDIV = 0x00000101; /* SOSCPLL1 & SPLLDIV2 =1: divide by 1 */
SCG->SPLLCFG = 0x00180000; /* PREDIV=0: Divide SOSC_CLK by 0+1=1 */
/* MULT=24: Multiply sys pll by 24+16=40 */
/* SPLL_CLK = 8MHz / 1 * 40 / 2 = 160 MHz */
while(SCG->SPLLCSR & SCG_SPLLCSR_LK_MASK); /* Ensure SPLLCSR unlocked */
SCG->SPLLCSR = 0x00000001; /* LK=0: SPLLCSR can be written */
/* SPLLCMRE=0: SPLL CLK monitor IRQ if enabled */
/* SPLLCM=0: SPLL CLK monitor disabled */
/* SPLLSTEN=0: SPLL disabled in Stop modes */
/* SPLLEN=1: Enable SPLL */
while(!(SCG->SPLLCSR & SCG_SPLLCSR_SPLLVLD_MASK)); /* Wait for SPLL valid */

// *** MODE CONFIG ***
SCG->RCCR=SCG_RCCR_SCS(6) /* PLL as clock source*/
|SCG_RCCR_DIVCORE(0b01) /* DIVCORE= 2, Core/Sys clock = 80 MHz*/
|SCG_RCCR_DIVBUS(0b11) /* DIVBUS = 4, bus clock = 40 MHz*/
|SCG_RCCR_DIVSLOW(0b111); /* DIVSLOW = 8, SCG slow, flash clock= 20 MHz*/

SMC->PMCTRL = SMC_PMCTRL_RUNM(0b00); //enter RUN

}

void GPIO_Init(void)
{
PCC->PCCn[PCC_PORTD_INDEX] |= PCC_PCCn_CGC_MASK; /* CGC=1: Clock enabled */

PORTD->PCR[0] |= PORT_PCR_MUX(1); /* MUX=1: PTD0, ALT=1 as GPIO */
PORTD->PCR[15] |= PORT_PCR_MUX(1); /* MUX=1: PTD15, ALT=1 as GPIO */
PORTD->PCR[16] |= PORT_PCR_MUX(1); /* MUX=1: PTD16, ALT=1 as GPIO */

PTD->PDDR |= 1<<0 | /* Configure BLUE LED as an output */ //LED on PCOR
1<<15 | /* Configure RED LED as an output */
1<<16; /* Configure GREEN LED as an output */

PTD->PSOR |= 1<<0 | /* Turn off BLUE */
1<<15 | /* Turn off RED */
1<<16; /* Turn off GREEN */

}


void PDB_Init(void)
{
PCC->PCCn[PCC_PDB0_INDEX] |= PCC_PCCn_CGC_MASK; /* Enable bus clock in PDB0 */
// PDB0->CNT especifies de current value of the counter
PDB0->SC |= PDB_SC_TRGSEL(0xF) | /* b1111: Software trigger is selected */
PDB_SC_PRESCALER(1) | /* Prescaler: 010 = sysclck/(2*MULT) = 80 / (2*1) = 40MHz */
PDB_SC_MULT(0) | /* 00: Multiplication factor is 1. */
PDB_SC_PDBEN_MASK; /* 1: PDB enabled */
PDB0->CH[0].C1 |= PDB_C1_BB(0xe) | /* DLY[0] : pre-trigger from PDB DLY BACK-TO-BACK OPERTATION*/
/* DLY[3:1] : back-to-back enabled */
PDB_C1_TOS(0x00) | /* Pretrigger Output Select: 0=bypassed , 1=enabled */
PDB_C1_EN(0xf); /* PDB channel's [3:0] pre-trigger enabled */
// PDB0->MOD = 2200;
// PDB0->IDLY = 2200;
// PDB0->CH[0].DLY[0] = 100; /* Pretrigger 0 : 100 * 25e-9 = 2.5e-6 */
PDB0->SC |= PDB_SC_LDOK_MASK; //LOAD OK: activación, cuando PDBEN =0 ---> LDOK=0 por hardware
}


void ADC_Init(void)
{

PCC->PCCn[PCC_ADC0_INDEX] &= ~PCC_PCCn_CGC_MASK; /* Disable clock to change PCS, SINO ERROR */

PCC->PCCn[PCC_ADC0_INDEX] |= PCC_PCCn_PCS(6); /* PCS=3: Select SPLL */
PCC->PCCn[PCC_ADC0_INDEX] |= PCC_PCCn_CGC_MASK; /* Enable bus clock in ADC */

/* Configuration Register ADC0 */
ADC0->CFG1 |= ADC_CFG1_ADICLK(0) | /* Only ALTCLK1 is available */ // Selected Clock
ADC_CFG1_ADIV(2) | /* the clock rate is (input clock)/4 */ // Internal clock rate
ADC_CFG1_MODE(1); /* 0b00: 8-bit, 0b01: 12-bit, 0b10: 10-bit */
/* SC: Status and Control Register */
ADC0->SC2 |= ADC_SC2_ADTRG(1) | /* Conversion Trigger: 0b0= SW , 0b1 = HW */
ADC_SC2_DMAEN(1); /* enable DMA trigger */
// Esta leyendo en 4 registros (salidas R[0-3]) la misma entrada
ADC0->SC1[0] = ADC_SC1_ADCH(12); /* Select AD12 (ADC0_SE12) @PTC14 */
ADC0->SC1[1] = ADC_SC1_ADCH(12); /* Select AD12 (ADC0_SE12) @PTC14 */
ADC0->SC1[2] = ADC_SC1_ADCH(12); /* Select AD12 (ADC0_SE12) @PTC14 */
ADC0->SC1[3] = ADC_SC1_ADCH(12); /* Select AD12 (ADC0_SE12) @PTC14 */

}


void WDOG_Disable(void)
{
WDOG->CNT=0xD928C520; /*Unlock watchdog*/
WDOG->CS &= ~WDOG_CS_EN_MASK; /*Disable watchdog*/
}


void DMA_init(void)
{

//PCC->PCCn[PCC_DMA0_INDEX] |= PCC_PCCn_CGC_MASK; // CGC=1: Clock enabled for DMA0

DMA->TCD[0].CSR &= 0xFFFFFFFF ^ DMA_TCD_CSR_DONE_MASK; // Clear Channel Done flag
DMA->TCD[0].SADDR = DMA_TCD_SADDR_SADDR(&(ADC0->R[0])); // Source Address
DMA->TCD[0].SOFF = DMA_TCD_SOFF_SOFF(4); // Source Offset
DMA->TCD[0].ATTR = DMA_TCD_ATTR_SMOD(0) | // Source address modulo feature is disabled
DMA_TCD_ATTR_SSIZE(2) | // Source data transfer size: 1: 16-bit, 2=32-bit
DMA_TCD_ATTR_DMOD(0) | // Destination address modulo feature: 0=disabled, x= x power of 2 buffer[DMOD=4->buffer of 16bytes]
DMA_TCD_ATTR_DSIZE(2); // Destination data transfer size: 1: 16-bit, 2=32-bit
DMA->TCD[0].NBYTES.MLOFFNO = DMA_TCD_NBYTES_MLNO_NBYTES(4); // Minor Byte Transfer Count is 4-bytes
DMA->TCD[0].SLAST = DMA_TCD_SLAST_SLAST(-16); // Last Source Address Adjustment is -16
DMA->TCD[0].DADDR = DMA_TCD_DADDR_DADDR(&(result[0])); // Destination Address of Buffer to save the ADC0 data
DMA->TCD[0].DOFF = DMA_TCD_DOFF_DOFF(4); // Destination Address Signed Offset is 4
DMA->TCD[0].CITER.ELINKNO = DMA_TCD_CITER_ELINKNO_CITER(4) // Current Major Iteration Count is 4
| DMA_TCD_CITER_ELINKNO_ELINK(0); // The channel-to-channel linking is disabled
DMA->TCD[0].DLASTSGA = DMA_TCD_DLASTSGA_DLASTSGA(-16); // Destination last address adjustment is -16
DMA->TCD[0].BITER.ELINKNO = DMA_TCD_BITER_ELINKNO_BITER(4) | // Starting major iteration count is 4
DMA_TCD_BITER_ELINKNO_ELINK(0); // The minor channel-to-channel linking is disabled
DMA->TCD[0].CSR = DMA_TCD_CSR_BWC(0) | // BWC=0: No eDMA engine stalls - full bandwidth
DMA_TCD_CSR_MAJORELINK(0) | // The channel-to-channel linking is disabled
DMA_TCD_CSR_MAJORLINKCH(0) | // channel 1 will be called from ch0
DMA_TCD_CSR_ESG(0) | // The current channel�fs TCD is normal format - No scatter/gather
DMA_TCD_CSR_DREQ(0) | // The channel's ERQ bit is not affected
DMA_TCD_CSR_INTHALF(0) | // The half-point interrupt is disabled
DMA_TCD_CSR_INTMAJOR(1) | // The end-of-major loop interrupt is enabled
DMA_TCD_CSR_START(0); // The channel is not explicitly started

DMA->SERQ = 0; // enable DMA channel 0 HW trigger
}


void DMAMUX_Init (void)
{
PCC->PCCn[PCC_DMAMUX0_INDEX] |= PCC_PCCn_CGC_MASK; // CGC=1: Clock enabled for DMAMUX0

DMAMUX->CHCFG[0] &= ~ DMAMUX_CHCFG_ENBL(1); // Disabling the DMA channel
DMAMUX->CHCFG[0] |= DMAMUX_CHCFG_SOURCE(40); // ADC0 COCO is the source of the DMA0 channel
DMAMUX->CHCFG[0] |= DMAMUX_CHCFG_ENBL(1); // Enabling the DMA channel
}


void IRQs_Init (void)
{
FSL_NVIC->ICPR[0] = 1 << (0 % 32); /* IRQ0-DMA ch0: clr any pending IRQ*/
FSL_NVIC->ISER[0] = 1 << (0 % 32); /* IRQ0-DMA ch0: enable IRQ */
FSL_NVIC->IP[0] = 0x1; /* IRQ0-DMA ch0: priority 10 of 0-15*/
}


void DMA0_IRQHandler(void)
{
counter++;

salidaADC=result[0]*5000/0xFFF; // El valor máximo que puede medir es 2^12 = 0xFFF = 4095,
// para normalizar hacemos resultado[0]*5000 mV/0xFFF

PDB0->SC |= PDB_SC_SWTRIG_MASK; /* restart PDB counter */

DMA->CINT = 0; // clear DMA channel 0 interrupt flag
}

int main(void)
{


WDOG_Disable();
SCG_Init();
GPIO_Init();
ADC_Init();
PDB_Init();
DMA_init();
DMAMUX_Init();

IRQs_Init();

PDB0->SC |= PDB_SC_SWTRIG_MASK; /* restart PDB counter */

for(;;) {

/* do something with converted data, change color of the LED */
if(salidaADC < 2500 && salidaADC > 10) // El valor máximo que puede medir es 2^12 = 0xFFF = 4095,
{ // para normalizar hacemos resultado[0]*5000 mV/0xFFF

PTD->PSOR |= 1<<16; // PTD16 OFF - GREEN LED

PTD->PCOR |= 1<<15; // PTD15 ON - RED LED

}
if(salidaADC >2500)// El valor máximo que puede medir es [0 - 5000] mV
{

PTD->PSOR |= 1<<15; // PTD15 OFF - RED LED

PTD->PCOR |= 1<<16; // PTD16 ON - GREEN LED

}

}

/* to avoid the warning message for GHS and IAR: statement is unreachable*/
#if defined (__ghs__)
#pragma ghs nowarning 111
#endif
#if defined (__ICCARM__)
#pragma diag_suppress=Pe111
#endif
return 0;
}

Thanks,

Jorge

Tags (2)
1 Solution
1,219 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi,

the DMA could not be triggered due to wrong DMA trigger assignment.

That example was written and tested on MCU cut1 (mask 0N77P). It is mounted on FRMD board and on some first revision on EVB board. On latest EVB revision board the cut2.x is mounted (mask (0N47T/0N57U).

There was changes in interrupt table and DMA request mapping between MCU masks.

 

To make the code running on MCU cut2.x just change DMAMUX configuration as following

DMAMUX->CHCFG[0] |= DMAMUX_CHCFG_SOURCE(42);        // ADC0 COCO is the source of the DMA0

BR, Petr

View solution in original post

1 Reply
1,220 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi,

the DMA could not be triggered due to wrong DMA trigger assignment.

That example was written and tested on MCU cut1 (mask 0N77P). It is mounted on FRMD board and on some first revision on EVB board. On latest EVB revision board the cut2.x is mounted (mask (0N47T/0N57U).

There was changes in interrupt table and DMA request mapping between MCU masks.

 

To make the code running on MCU cut2.x just change DMAMUX configuration as following

DMAMUX->CHCFG[0] |= DMAMUX_CHCFG_SOURCE(42);        // ADC0 COCO is the source of the DMA0

BR, Petr