cancel
Showing results for 
Search instead for 
Did you mean: 

I am trying to setup DMA with ADC on stm32h747 even thoug conversion end DMA transfer never completes. The ADC's conversions are triggered by a timer (this part of the code works fine) and the DMA is supposed to write the data to memory.

HTess.1
Associate III

Here is how I setup my DMA ;

  1. Enable Clock for DMA1
  2. Periph to memory
  3. set memory and periph size to half word
  4. set memory address increment and clear periph address increment
  5. set circular mode
  6. give the flow control to the ADC
  7. Set DMAMUX
  8. Set DMA periph address
  9. Enable Transfer complete interrupt
  10. Enable DMA

How I setup the DMAMUX :

I configured the DMAREQ_ID bits to 10 (adc2_dma). Is there no clock I need to enable for the DMAMUX ?? This setup feels a bit too light!

How I setup ADC :

Classic way just set the Data management to DMA circular.

Just to be sure thanks to the DMAMUX there is no longer a peripheral linked to only one DMA? Wether I use DMA1 or DMA2 for my ADC does not matter?

Code for DMA :

void DMA_Config(void) {
  /************DMA CLock Enable******************/
  SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_DMA1EN_Msk);
  delay(1000);
  /***************P2M****************************/
  CLEAR_BIT(DMA1_Stream1->CR, DMA_SxCR_DIR_0 | DMA_SxCR_DIR_1);
  /******************Disable FIFO*************************/
  //LL_DMA_DisableFifoMode(DMA1, LL_DMA_STREAM_1);
  //LL_DMA_SetMemoryBurstxfer(DMA1, LL_DMA_STREAM_1, LL_DMA_MBURST_SINGLE);
  /******************Memory size**************************/
  SET_BIT(DMA1_Stream1->CR, DMA_SxCR_MSIZE_0);
  CLEAR_BIT(DMA1_Stream1->CR, DMA_SxCR_MSIZE_1);
  /******************MEM Increment**********************/
  SET_BIT(DMA1_Stream1->CR, DMA_SxCR_MINC_Msk);
  /******************MEM Address to buffer**************/
  DMA1_Stream1->M0AR = 0x30000000;
  /******************Circular Mode**********************/
  SET_BIT(DMA1_Stream1->CR, DMA_SxCR_CIRC_Msk);
  /*******************Flow controller*******************/
  SET_BIT(DMA1_Stream1->CR, DMA_SxCR_PFCTRL_Msk);//ADC in control
  /******************Periph size************************/
  SET_BIT(DMA1_Stream1->CR, DMA_SxCR_PSIZE_0);
  CLEAR_BIT(DMA1_Stream1->CR, DMA_SxCR_PSIZE_1);
  /******************Peripheral no Increment*************/
  CLEAR_BIT(DMA1_Stream1->CR, DMA_SxCR_PINCOS_Msk);
  /******************Periph request**********************/
  SET_BIT(DMAMUX1_Channel1->CCR, DMAMUX_CxCR_DMAREQ_ID_1 | DMAMUX_CxCR_DMAREQ_ID_3);//adc2_dma
  //  SET_BIT(DMAMUX1_Channel1->CCR, DMAMUX_CxCR_SYNC_ID_0 | DMAMUX_CxCR_SYNC_ID_1 | DMAMUX_CxCR_SYNC_ID_2);//TIM12_TRGO
  //  SET_BIT(DMAMUX1_Channel1->CCR, DMAMUX_CxCR_SPOL_0);//rising edge
  //  DMAMUX1_Channel1->CCR = 0; //Number of requests after synchro (add 1 to the reg value)
  //  SET_BIT(DMAMUX1_Channel1->CCR, DMAMUX_CxCR_EGE_Msk);//Event Generation end of synchro req
  //  SET_BIT(DMAMUX1_Channel1->CCR, DMAMUX_CxCR_SE_Msk);//Synchro Enable
  /******************Periph address***********************/
  DMA1_Stream1->PAR = (uint32_t)&ADC2->DR;
  /******************TC IT********************************/
  SET_BIT(DMA1_Stream1->CR, DMA_SxCR_TCIE_Msk | DMA_SxCR_TEIE_Msk); //TC IT
  DMA1->LIFCR = DMA_LIFCR_CTCIF1;//Clear IT in LISR Register
  NVIC_SetVector(DMA1_Stream1_IRQn, (uint32_t)&DMA1_Stream1_IRQHandler);
  NVIC_EnableIRQ(DMA1_Stream1_IRQn);
  /*******************Enable DMA****************************/
  SET_BIT(DMA1_Stream1->CR, DMA_SxCR_EN_Msk);
}
void DMA1_Stream1_IRQHandler(void) {
  if (DMA1->LISR & DMA_LISR_TCIF1 ) {
    DMABuffered = DMABuffered + 1;
    DMA1->LIFCR = DMA_LIFCR_CTCIF1;
  }
  if(DMA1->LISR & DMA_LISR_TEIF1 ){
    DMAError = DMAError +1;
    DMA1->LIFCR = DMA_LIFCR_CTEIF1;
  }
}

Code for ADC :

void ADC_Init(void) {
  /*******************Horloges**************************/
  SET_BIT(RCC->APB4ENR, RCC_APB4ENR_SYSCFGEN_Msk); //SYSCFG clock
  delay(1000);
  SET_BIT(RCC->APB4ENR, RCC_APB4ENR_RTCAPBEN_Msk); //RTCAPB clock
  delay(1000);
  SET_BIT(RCC->AHB1ENR, RCC_AHB1ENR_ADC12EN_Msk); //ADC12 clocks
  delay(1000);
  SET_BIT(RCC->AHB4ENR, RCC_AHB4ENR_GPIOAEN_Msk); //GPIOA clock
  delay(1000);
  /********************Port config************************/
  SET_BIT(GPIOA->MODER, GPIO_MODER_MODE1_0);
  SET_BIT(GPIOA->MODER, GPIO_MODER_MODE1_1);
  CLEAR_BIT(GPIOA->PUPDR, GPIO_PUPDR_PUPD1_0);
  CLEAR_BIT(GPIOA->PUPDR, GPIO_PUPDR_PUPD1_1);
  SET_BIT(SYSCFG->PMCR, SYSCFG_PMCR_PA0SO_Msk);
  delay(1000);//PA0_C in analog mode
  /********************ADC voltage regulator***************/
  CLEAR_BIT(ADC2->CR, ADC_CR_DEEPPWD_Msk); //END DEEPPWD
  SET_BIT(ADC2->CR, ADC_CR_ADVREGEN_Msk); //ENABLE ADC VOLTAGE REG
  delay(1000);//WAIT VOLTAGE REG
  /********************ADC calibration*********************/
  CLEAR_BIT(ADC2->CR, ADC_CR_ADCALDIF_Msk);
  SET_BIT(ADC2->CR, ADC_CR_ADCALLIN_Msk);
  SET_BIT(ADC2->CR, ADC_CR_ADCAL_Msk);
  while (ADC_CR_ADCAL & ADC_CR_ADCAL_Msk != 0) {}
  /******************ADC clock*****************************/
  SET_BIT(ADC12_COMMON->CCR, ADC_CCR_CKMODE_0 | ADC_CCR_CKMODE_1);
  /*******************ADC Prescaler************************/
  SET_BIT(ADC12_COMMON->CCR, ADC_CCR_PRESC_0 | ADC_CCR_PRESC_1 );
  /*******************Input Mode***************************/
  CLEAR_BIT(ADC2->DIFSEL, ADC_DIFSEL_DIFSEL_0); //Single Ended
  /*******************ADC Enable***************************/
  SET_BIT(ADC2->ISR, ADC_ISR_ADRDY_Msk);
  SET_BIT(ADC2->CR, ADC_CR_ADEN_Msk);
  while (ADC_ISR_ADRDY & ADC_ISR_ADRDY_Msk != 1) {}
  SET_BIT(ADC2->ISR, ADC_ISR_ADRDY_Msk);
  /********************ADC RES*****************************/
  SET_BIT(ADC2->CFGR, ADC_CFGR_RES_2 | ADC_CFGR_RES_1);
  CLEAR_BIT(ADC2->CFGR, ADC_CFGR_RES_0);
  /********************ADC Data Management*****************/
  SET_BIT(ADC2->CFGR, ADC_CFGR_DMNGT_0 | ADC_CFGR_DMNGT_1);//DMA Circular mode
  /********************OVRMODE*****************************/
  SET_BIT(ADC2->CFGR, ADC_CFGR_OVRMOD_Msk); //Erase old data
  /********************CONT/Single/Discont*****************/
  SET_BIT(ADC2->CFGR, ADC_CFGR_DISCEN_Msk); // discontinuous mode
  CLEAR_BIT(ADC2->CFGR, ADC_CFGR_CONT_Msk); // | ADC_CFGR_DISCEN_Msk
  /********************Trigger Detection*******************/
  SET_BIT(ADC2->CFGR, ADC_CFGR_EXTEN_0 | ADC_CFGR_EXTSEL_1 | ADC_CFGR_EXTSEL_3);//Trig rising edge TRGO2
  CLEAR_BIT(ADC2->CFGR, ADC_CFGR_EXTEN_1 | ADC_CFGR_EXTSEL_0 | ADC_CFGR_EXTSEL_2 | ADC_CFGR_EXTSEL_4);
  /********************INput Preselection******************/
  SET_BIT(ADC2->PCSEL, ADC_PCSEL_PCSEL_0);//Chan 0
  /********************Sample Time reg*********************/
  SET_BIT(ADC2->SMPR1, ADC_SMPR1_SMP0_0); //2.5 CLCK Cycles
  /********************ADC IT******************************/
  SET_BIT(ADC2->IER, ADC_IER_EOCIE_Msk | ADC_IER_EOSMPIE_Msk  );//| ADC_IER_EOSIE_Msk | ADC_IER_OVRIE_Msk
  NVIC_EnableIRQ(ADC_IRQn);
  NVIC_SetVector(ADC_IRQn, (uint32_t)&ADC_IRQHandler);
}

Code for timer

void AC_TIMER1_Init(void) {
  //------------------------------Horloge Timer1----------------------------------------//
  SET_BIT(RCC->APB2ENR, RCC_APB2ENR_TIM1EN_Msk);
  //------------------------------Select TRGO source-----------------------------------//
  TIM1->PSC = 8399; //PSC=1
  //----------------------------------------------------------TIM2 autoreload register--------------------------------------------//
  TIM1->ARR = 10000;
  //---------selectupdatevent-----------------//
  SET_BIT(TIM1->CR2, TIM_CR2_MMS2_1);
  //-----------IT-----------------------//
  //  SET_BIT(TIM1->DIER,TIM_DIER_UIE_Msk);
  //  NVIC_SetPriority(TIM1_UP_IRQn,0);
  //  NVIC_SetVector(TIM1_UP_IRQn, (uint32_t)&TIM1_UP_IRQHandler);
  //  NVIC_EnableIRQ(TIM1_UP_IRQn);
  SET_BIT(TIM1->CR1, TIM_CR1_CEN_Msk);//CEN=1
}

Main :

void setup() {
  // put your setup code here, to run once:
  VREFBUF_Init();
  DMA_Config();
  AC_TIMER1_Init();
  ADC_Init();
  ADC_Start();
}

1 REPLY 1
HTess.1
Associate III

Nevermind I am a lost cause 🙂 missed :

/*******************Number of data transfer***********/
  SET_BIT(DMA1_Stream1->NDTR, DMA_SxNDT_0);

There is still something I do not understand : why is it that it only works when the one in control is the DMA (PFCTRL=0) isn't the ADC the one who can tell the DMA to move the DATA after each EOC?