Tool/software: TI-RTOS
Hi,
What I see when I debug my code is that sometimes (seems to be random) EDMA transfer is doubled.
What I do is "EDMA multi-dimensional shift register" triggered with CPU. I use "self-chain" for partial transfer (for huge data size is advice to split transfer into several smaller chunks) and "self-prepare / link mode" to reload PaRAM without CPU intervention.
Can you please check my setup:
ch_chain_link1 = EDMA3_DRV_LINK_CHANNEL; ch_chain_link2 = EDMA3_DRV_LINK_CHANNEL; for(ch_chain = 31; ch_chain < 64; ch_chain++){ tcc_chain = ch_chain; edmaResult = EDMA3_DRV_requestChannel(hEdma, &ch_chain, &tcc_chain,(EDMA3_RM_EventQueue)2,NULL, NULL); if(edmaResult == EDMA3_DRV_SOK){ break; } } if(edmaResult != EDMA3_DRV_SOK){ ERROR_H; } edmaResult = EDMA3_DRV_requestChannel(hEdma, &ch_chain_link1, NULL,(EDMA3_RM_EventQueue)2,NULL, NULL); if(edmaResult != EDMA3_DRV_SOK){ ERROR_H; } edmaResult = EDMA3_DRV_requestChannel(hEdma, &ch_chain_link2, NULL,(EDMA3_RM_EventQueue)2,NULL, NULL); if(edmaResult != EDMA3_DRV_SOK){ ERROR_H; } /* Transfer complete chaining enable. */ chain.tcchEn = EDMA3_DRV_TCCHEN_DIS; /* Intermediate transfer complete chaining enable. */ chain.itcchEn = EDMA3_DRV_ITCCHEN_EN; /* Transfer complete interrupt is enabled. */ chain.tcintEn = EDMA3_DRV_TCINTEN_EN; /* Intermediate transfer complete interrupt is disabled. */ chain.itcintEn = EDMA3_DRV_ITCINTEN_DIS; memset(&opt, 0, sizeof(opt)); opt.reg = 0; /* Src & Dest are in INCR modes */ opt.reg_bit.sam = 0; opt.reg_bit.dam = 0; /* Program the TCC */ opt.reg |= ((tcc_chain << (0x0000000Cu)) & (0x0003F000u)); /* Final transfer completion interrupt */ opt.reg_bit.itcinten = 0; opt.reg_bit.tcinten= 1; opt.reg_bit.syncdim = 1; PaRAM.opt = opt.reg; PaRAM.srcAddr = (uint32_t)&context->FIRdata.FIR_shiftReg[0][FIR_LEN-2]; PaRAM.destAddr = (uint32_t)&context->FIRdata.FIR_shiftReg[0][FIR_LEN-1]; PaRAM.aCnt = sizeof(context->FIRdata.FIR_shiftReg[0][0]); PaRAM.bCnt = FIR_LEN-1; PaRAM.cCnt = NUMBER_OF_FIR_CH; PaRAM.bCntReload = FIR_LEN-1; PaRAM.srcBIdx = (int16_t)( (int32_t)&context->FIRdata.FIR_shiftReg[0][FIR_LEN-3] - (int32_t)&context->FIRdata.FIR_shiftReg[0][FIR_LEN-2]); PaRAM.srcCIdx = (int16_t)((int32_t)&context->FIRdata.FIR_shiftReg[1][0] - (int32_t)&context->FIRdata.FIR_shiftReg[0][0]); PaRAM.destBIdx = (int16_t)((int32_t)&context->FIRdata.FIR_shiftReg[0][FIR_LEN-2] - (int32_t)&context->FIRdata.FIR_shiftReg[0][FIR_LEN-1]); PaRAM.destCIdx = (int16_t)((int32_t)&context->FIRdata.FIR_shiftReg[1][0] - (int32_t)&context->FIRdata.FIR_shiftReg[0][0]); PaRAM.linkAddr = 0xFFFF; edmaResult |= EDMA3_DRV_setPaRAM (context->hEdma, ch_chain, &PaRAM); edmaResult |= EDMA3_DRV_chainChannel(context->hEdma, ch_chain, ch_chain, (EDMA3_DRV_ChainOptions *)&chain); edmaResult |= EDMA3_DRV_registerTccCb(context->hEdma, ch_chain, FIRshift_DmaIRQ, context); edmaResult |= EDMA3_DRV_getPaRAM(context->hEdma, ch_chain, &PaRAM); edmaResult |= EDMA3_DRV_setPaRAM (context->hEdma, ch_chain_link1, &PaRAM); edmaResult |= EDMA3_DRV_setPaRAM (context->hEdma, ch_chain_link2, &PaRAM); edmaResult |= EDMA3_DRV_linkChannel (context->hEdma, ch_chain, ch_chain_link1); edmaResult |= EDMA3_DRV_linkChannel (context->hEdma, ch_chain_link1, ch_chain_link2); edmaResult |= EDMA3_DRV_linkChannel (context->hEdma, ch_chain_link2, ch_chain_link1); if(edmaResult != EDMA3_DRV_SOK){ ERROR_H; }
This is how I triger:
if(EDMA3_DRV_SOK != EDMA3_DRV_enableTransfer(context->hEdma,context->CH, EDMA3_DRV_TRIG_MODE_MANUAL)){ ERROR_H; }
This is isr callback function:
static void FIRshift_DmaIRQ(uint32_t tcc,EDMA3_RM_TccStatus status,void *appData){ FIR_shiftContext *context = (FIR_shiftContext *)appData; int x; if(EDMA3_RM_XFER_COMPLETE == status){ Custom_cache_invalidate((uint32_t)context->FIRdata.FIR_shiftReg, sizeof(context->FIRdata.FIR_shiftReg)); // for(x = 0; x < NUMBER_OF_FIR_CH; x++){ // context->FIRdata.FIR_shiftReg[x][0] = context->FIRdata.inputBuff.inputFIR[x]; // Custom_cache_writeBack((uint32_t)&context->FIRdata.FIR_shiftReg[x][0], sizeof(context->FIRdata.FIR_shiftReg[x][0])); // } context->FIRdata.FIR_shiftReg[0][0].int_shiftReg = context->FIRdata.inputBuff.filds.index; Custom_cache_writeBack((uint32_t)&context->FIRdata.FIR_shiftReg[0][0], sizeof(context->FIRdata.FIR_shiftReg[0][0].int_shiftReg)); context->FIRdata.FIR_shiftReg[1][0].int_shiftReg = context->FIRdata.inputBuff.filds.UTC; Custom_cache_writeBack((uint32_t)&context->FIRdata.FIR_shiftReg[1][0], sizeof(context->FIRdata.FIR_shiftReg[0][0].int_shiftReg)); context->FIRdata.FIR_shiftReg[2][0].float_shiftReg = context->FIRdata.inputBuff.filds.freq; Custom_cache_writeBack((uint32_t)&context->FIRdata.FIR_shiftReg[2][0], sizeof(context->FIRdata.FIR_shiftReg[0][0].int_shiftReg)); for(x = 0; x < FIR_PHASOR_LEN; x++){ context->FIRdata.FIR_shiftReg[3+x*2][0].float_shiftReg = context->FIRdata.inputBuff.filds.phasor[x].Re_;//re Custom_cache_writeBack((uint32_t)&context->FIRdata.FIR_shiftReg[x*2][0], sizeof(context->FIRdata.FIR_shiftReg[0][0].float_shiftReg)); context->FIRdata.FIR_shiftReg[4+x*2][0].float_shiftReg = context->FIRdata.inputBuff.filds.phasor[x].Im_;//im Custom_cache_writeBack((uint32_t)&context->FIRdata.FIR_shiftReg[1+x*2][0], sizeof(context->FIRdata.FIR_shiftReg[0][0].float_shiftReg)); } //postEvent if(context->DownSamplingCounters.lastREGISTER != context->FIRdata.inputBuff.filds.index){ context->DownSamplingCounters.lastREGISTER = context->FIRdata.inputBuff.filds.index; Event_post(context->FIRactionEvent, EVENT_FIR_SHIFT_END); } else{ __asm__("BKPT"); } } else{ __asm__("BKPT"); } }
After some random time, I get duplicated index.. also I can see duplicated value in output data....
Is this issue/behavioural known? Or more likely I do something stupid (but can't see for a week of investigating)..
Best regards , Mare