K22 Continuous Circular DMA

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

K22 Continuous Circular DMA

1,787 Views
notthetup
Contributor I

Hello,

I'm trying to implement a continuous circular DMA on a K22 to read from the ADC.

I have the PDB and ADC side working fine, but I'm struggling with the DMA. The DMA only runs once and not continuously. The callback function only gets called twice (since I have half buffer interrupts turned on) but no more after that.

I have used EDMA_SetModulo and TCDx.DLAST_SGA as suggested by others. And also ensure that DMA_CSR_DREQ is disabled with EDMA_EnableAutoStopRequest

I looked through all the forum posts and went through all the examples (Thanks mjbcswitzerland!), but nothing seems to work for me.

What am I missing? Is there a way to automatically keep the DMA running forever without needing any software intervention (like retriggering the DMA in the callback) ?

I've attached my EDMA Initialization code below : 

static void adc_dma_callback(edma_handle_t *handle, void *userData, bool transferDone, uint32_t tcds){
  if (transferDone){
    printf("Full");
  }else{
    printf("Half");
  }
}

void edma_init(void){
  edma_config_t userConfig;
  EDMA_GetDefaultConfig(&userConfig);
  EDMA_Init(DMA0, &userConfig);
  EDMA_CreateHandle(&dma_handle, DMA0, DMA_CH);
  EDMA_InstallTCDMemory(&dma_handle, NULL, 0);
  EDMA_SetCallback(&dma_handle, adc_dma_callback, NULL);
  EDMA_SetModulo(DMA0, DMA_CH, kEDMA_ModuloDisable, kEDMA_Modulo4Kbytes);
  dma_handle.base->TCD[DMA_CH].DLAST_SGA = -2*(int32_t)sizeof(adcBuffer);
  EDMA_PrepareTransfer(&transfer_config, (void *)ADC16_RESULT_REG_ADDR, sizeof(uint32_t),
                       (void *)adcBuffer, sizeof(uint32_t), sizeof(uint32_t),
                       sizeof(adcBuffer), kEDMA_PeripheralToMemory);
  status_t ret = EDMA_SubmitTransfer(&dma_handle, &transfer_config);
  EDMA_EnableAutoStopRequest(DMA0, DMA_CH, false);
  EDMA_EnableAsyncRequest(DMA0, DMA_CH, true);
  if(ret == kStatus_Success) {
    EDMA_EnableChannelInterrupts(DMA0, DMA_CH, kEDMA_MajorInterruptEnable|kEDMA_HalfInterruptEnable);
    EDMA_StartTransfer(&dma_handle);
  }else{
    printf("ERR: DMA SUBMIT");
  }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
Labels (1)
0 Kudos
Reply
4 Replies

1,628 Views
mjbcswitzerland
Specialist V

Chinmay

For free running eDMA you need to ensure that
ptrDMA_TCD->DMA_TCD_CSR = 0
(which you say you have done).

In addition you must ensure that the
ptrDMA_TCD->DMA_TCD_DLASTSGA
and
ptrDMA_TCD->DMA_TCD_DLASTSGA
are set as required - one will be set with 0 and the other with the negative length of your DMA buffer length.

If you find it doesn't work take a look as the DMA error status since it may be that it tries to do a second scan but there is an invalid setting (eg. due to one of the last not being set and having random values - some of the DMA registers have random values after a reset and so all should be initialised). If there is a DMA error it will 'freeze' further operation until cleared.

In case of continued difficulties simply use the open source version of the uTasker project (on GitHub) since it will then allow you immediate operating solutions and full chip simulation to further avoid losing project time.

https://www.utasker.com/docs/uTasker/uTaskerADC.pdf

Regards

Mark
[uTasker project developer for Kinetis and i.MX RT]

1,628 Views
notthetup
Contributor I

Great call to look at the TDC->ES. I found Destination Bus Error was set.

0 Kudos
Reply

1,628 Views
notthetup
Contributor I

Thanks mjbcswitzerland‌. I figured out my error. The value of TCDx.DLAST_SGA was incorrect. Fixing that made the code work!

0 Kudos
Reply

1,628 Views
mjbcswitzerland
Specialist V

Hi Chinmay

Good to hear you solved it - checking the DMA error status is always the first thing to do if things don't look to be working since it is usually a 'silent' error that just freezes further DMAA operation on that channel. The error status holds almost always detailed information about why it stalled and so detecting the cause is usually quite easy. One just needs to know where to look and then no time is lost....;-)

Regards

Mark

[uTasker project developer for Kinetis and i.MX RT]

0 Kudos
Reply