So i did write a simple code to check if it works reliably and it does but only if i use abs when calculating difference othwise i got correct reading every 2 interrupts as attached on the picture below.
volatile uint32_t timestamp_buffer[4];
volatile uint8_t init_state;
volatile float period_ns;
volatile float dutycycle_ns;
volatile float dutycycle_percent;
volatile float difference;
void DMA0_IRQHandler(void)
{
if(DMA0->INT && (1<<0))
{
DMA0 -> INT |= (1<<0);//clear flag
difference=abs(timestamp_buffer[0]-timestamp_buffer[2]);
period_ns=difference * (100/6.0f);
if(init_state == 0)
{
difference=timestamp_buffer[0]-timestamp_buffer[1];
dutycycle_ns=difference * (100/6.0f);
dutycycle_percent=(dutycycle_ns*100)/period_ns;
}
else
{
difference=timestamp_buffer[0]-timestamp_buffer[1];
dutycycle_ns=difference * (100/6.0f);
dutycycle_percent=100-((dutycycle_ns*100)/period_ns);
}
}
}
void dma_init(void)
{
DMA0->TCD[0].DADDR = (uint32_t) timestamp_buffer;
DMA0->TCD[0].DOFF = 4;
DMA0->TCD[0].DLAST_SGA = -16;
DMA0->TCD[0].SADDR = (uint32_t) & PIT->CHANNEL[0].CVAL;
DMA0->TCD[0].SOFF = 0;//offset per transfer
DMA0->TCD[0].SLAST = 0;
DMA0->TCD[0].ATTR = DMA_ATTR_SSIZE(2) | DMA_ATTR_DSIZE(2);
DMA0->TCD[0].NBYTES_MLNO = 4;
DMA0->TCD[0].CSR &= ~DMA_CSR_DREQ_MASK;
DMA0->TCD[0].CSR |= DMA_CSR_INTMAJOR_MASK;
DMA0->TCD[0].CITER_ELINKNO = DMA_CITER_ELINKNO_CITER(4);
DMA0->TCD[0].BITER_ELINKNO = DMA_BITER_ELINKNO_BITER(4);
DMAMUX->CHCFG[0] = (DMAMUX_CHCFG_ENBL_MASK | DMAMUX_CHCFG_SOURCE(52));
}
int main(void)
{
BOARD_InitBootClocks();
BOARD_InitDebugConsole();
SIM -> SCGC6 |= SIM_SCGC6_DMAMUX_MASK;
SIM -> SCGC7 |= SIM_SCGC7_DMA_MASK;
PORTD-> PCR[4] = (PORT_PCR_MUX(0x01) | PORT_PCR_IRQC(3) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK);
SIM->SCGC6 |= SIM_SCGC6_PIT_MASK;
PIT ->MCR =0;
PIT ->CHANNEL[0].LDVAL = 0xFFFFFFFF;
PIT ->CHANNEL[0].TCTRL |= PIT_TCTRL_TEN_MASK;
init_state = ((GPIOD->PDIR >> 4) & 0x01);
dma_init();
__NVIC_EnableIRQ(DMA0_IRQn);
DMA0->ERQ |= 1<<0;
while(1)
{
}
return 0 ;
}
I checked some things and it seems like every second dma interrupt data is corrupted or somehow not in the correct order? Sometimes position 2 in my array is highter than position 0 which shouldn't be possible. I know there is one scenario i should take care of which is timer overflow but it's not the problem here because it happens even before first timer overflow.
ABS function solves all the problems but how is it even possible? So it means that the data is just in the wrong order? Maybe i setup my dma wrong? I did setup my DMA for 4 transfers so the buffer always starts on the same edge.