cancel
Showing results for 
Search instead for 
Did you mean: 

Why am i not able to switch on and off DMA randomly in STM32F051R6T6TR?

Amal Babu
Associate III

i'm trying to sample 40 adc values by using dma which means i have configure adc with dma(interrupt).Time period is also a constrain which means that a value is read after every 500us.After obtaining 40 readings

,i disabled both timer and dma then send the adc values via uart.I repeated this procedure several times and happen to notice that the program doesnt enter DMA ISR after random number of cycles therefater unable to read ADC values.

I have atatched my DMA code configurations below:

void DMA_config()

{   

   RCC->AHBENR |= RCC_AHBENR_DMA1EN;

   ADC1->CFGR1 |= ADC_CFGR1_DMAEN | ADC_CFGR1_DMACFG;

   DMA1_Channel1->CPAR = (uint32_t) (&(ADC1->DR));

   DMA1_Channel1->CMAR = (uint32_t)(ADC_array);

   DMA1_Channel1->CNDTR = 1 ;

   DMA1_Channel1->CCR |= DMA_CCR_MINC | DMA_CCR_MSIZE_0 | DMA_CCR_PSIZE_0 | DMA_CCR_CIRC | DMA_CCR_PL_0;   

   DMA1_Channel1->CCR |= DMA_CCR_EN|DMA_CCR_TCIE;

   NVIC_EnableIRQ(DMA1_Ch1_IRQn);

}

void timer_DMA_off()

{

   TIM3->DIER &= ~TIM_DIER_UIE;   

   DMA1_Channel1->CCR &= ~(DMA_CCR_EN|DMA_CCR_TCIE);

}

void timer_DMA_on()

{   

      //TIMER

   RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;      

   TIM3->DIER = TIM_DIER_UIE;   

   TIM3->CR1 |= TIM_CR1_CEN;        

   NVIC_EnableIRQ(TIM3_IRQn);

      //ADC   

   ADC1->CR |= ADC_CR_ADEN;

   while(!(ADC1->ISR & ADC_ISR_ADRDY));

   ADC1->CR |= ADC_CR_ADSTART;

       //DMA

   ADC1->CFGR1 |= ADC_CFGR1_DMAEN | ADC_CFGR1_DMACFG;

   DMA1_Channel1->CCR |= DMA_CCR_EN|DMA_CCR_TCIE;   

}

void adc_configuration()

{

   PORTA_CLK_EN ;

   GPIOA->MODER |= BIT(11) | BIT(10);

   RCC->APB2ENR |= RCC_APB2ENR_ADCEN;  

       RCC->CR2 |= RCC_CR2_HSI14ON;

   while(!(RCC->CR2 & RCC_CR2_HSI14RDY));

   ADC1->CFGR2 &=~ ADC_CFGR2_CKMODE;                    // Asynchronous clock mode

       ADC1->CFGR1 |= ADC_CFGR1_CONT | ADC_CFGR1_DMACFG | ADC_CFGR1_DMAEN | ADC_CFGR1_RES_0;

       //ADC1->CFGR1 |= ADC_CFGR1_RES_0;                      // 10 bit resolution

   ADC1->CFGR1 &=~ ADC_CFGR1_ALIGN | ADC_CFGR1_SCANDIR; // Right alignment, Upward scan

       ADC1->SMPR &=~ ADC_SMPR_SMP; 

       ADC1->CHSELR |= ADC_CHSELR_CHSEL5 ;   

   ADC1->CR |= 0;

   ADC1->CR |= ADC_CR_ADEN;

   while(!(ADC1->ISR & ADC_ISR_ADRDY));

   ADC1->CR |= ADC_CR_ADSTART;

}

void timer_config()

{

   RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;      

   TIM3->ARR = 23400;   

   TIM3->CR1 |= TIM_CR1_ARPE | TIM_CR1_CKD_0 | TIM_CR1_CEN;                                

   TIM3->DIER &= ~TIM_DIER_UIE;   

   TIM3->EGR |= TIM_EGR_UG;    

   NVIC_EnableIRQ(TIM3_IRQn);   

}

2 REPLIES 2

There may be several reasons why DMA stops working, but one of them is ADC overrun, see ADC chapter in RM.

JW

Amal Babu
Associate III

Hai,

Actually please note that we are just turning the DMA and the timer on and off but the ADC isn't turned off at any instant.When i checked the code i found that, the error which you specified could be due to overrun is not happening if i continuously read adc.It happens only when turning on and off DMA.