AnsweredAssumed Answered

K22 Continuous Circular DMA

Question asked by Chinmay Pendharkar on Apr 9, 2020
Latest reply on Apr 10, 2020 by Mark Butcher

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 Mark Butcher!), 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");
  }
}

Outcomes