Skip to main content
jogerh
Associate III
March 11, 2016
Question

STM32F37x DMA SDADC + DAC same DMA Channel

  • March 11, 2016
  • 2 replies
  • 674 views
Posted on March 11, 2016 at 17:03

Dear Community,

I am trying to use two peripherals (STM23F373) SDADC1 and DAC1_1 having the same DMA access channel: DMA2_Channel3 (STM32F37x reference page 164).

Due to a synch problem I want to use the DMA in normal mode thus I need to reset the DMA counter after each TC interrupt and unfortunately I can’t use the 12 bit ADC since it produces some strange spikes its conversion result (this topic is already addressed here but without solution). 

  

Is there a way to distinguish from which DMA memory (assigned to the SDADC or the DAC) the DMA_TC interrupt was fired ?
    This topic has been closed for replies.

    2 replies

    Amel NASRI
    ST Technical Moderator
    March 11, 2016
    Posted on March 11, 2016 at 17:25

    Hi gerh.jo,

    As stated in the reference manual: ''The hardware requests from the peripherals (TIMx, SDADCx, DAC and SPI) are simply logically ORed before entering the DMA2. This means that on one channel, only one request must be enabled at a time. ''.

    So you cannot configure DMA2_Channel3 for both SDADC and DAC at the same time.

    Why don't you use DMA1_Channel3 for DAC1_CH1?

    Then could you please share the link of the other discussion?

    -Mayla-

    To give better visibility on the answered topics, please click on "Best Answer" on the reply which solved your issue or answered your question.
    jogerh
    jogerhAuthor
    Associate III
    March 14, 2016
    Posted on March 14, 2016 at 10:17

    Dear Mayla,

    thank you very much for responding to my question. I actually tried your recommendation to use DMA1 for feeding the DAC(s) and DMA2 for reading the SDADC. However I noticed that DMA1 and DACs are not working together as expected. I was expecting to simply adapt my DAC/DMA initialization but the DMA_IRQ is not triggered but if I use the routine for initialization the DAC with DMA2_channel3 it works properly. Probably I’veoverlooked an important detail – I would be very happy, if someone could point me into the right direction (I attached my code below).

    Regarding the topic on ADC – steps and spikes please have a look for this thread:

    [DEAD LINK /public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Step%20in%20ADC%20data&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=2253]https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=%2Fpublic%2FSTe2ecommunities%2Fmcu%2FLists%2Fcortex%5Fmx%5Fstm32%2FStep%20in%20ADC%20data&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=2253

    and also here:

    /public/STe2ecommunities/mcu/Lists/STM32Discovery/Flat.aspx?RootFolder=https%3a//my.st.com/public/STe2ecommunities/mcu/Lists/STM32Discovery/SD%20card%20write%20operation%20and%20spikes%20in%20analog%20ADC%20data&FolderCTID=0x01200200770978C69A1141439FE559EB459D75800084C20D8867EAD444A5987D47BE638E0F&currentviews=1074

    void DAC12_Init() { 
    GPIO_InitTypeDef GPIO_InitStructure; 
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 
    DAC_InitTypeDef DAC_InitStructure1; 
    DAC_InitTypeDef DAC_InitStructure2; 
    DMA_InitTypeDef DMA_InitStructure1; 
    DMA_InitTypeDef DMA_InitStructure2; 
    NVIC_InitTypeDef NVIC_InitStructure1; //DMA Interupt 
    NVIC_InitTypeDef NVIC_InitStructure2; //DMA Interupt 
    // CLOCK enable************************************************************************* 
    // DMA1 clock enable (to be used with DAC) 
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); 
    // DAC clock enable 
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC1, ENABLE); 
    // Timer 2 CLOCK enable 
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); 
    // GPIOA clock enable 
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); 
    //*****************Enable GPIOA (PA4,5 & 6) as DAC output 
    // Configure PA.04 (DAC_OUT1) as analog 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; //DAC11 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; 
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; 
    GPIO_Init(GPIOA, &GPIO_InitStructure); 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //DAC12 
    GPIO_Init(GPIOA, &GPIO_InitStructure); 
    //*****************Enable Timer 3 for itterating the DAC and DMA 
    // TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); 
    // TIM_TimeBaseStructure.TIM_Period = SAMPLE_Interval;// 0x80;// 0x500; //0x80;// 0x80;// //define the periode (500 points so far 
    // TIM_TimeBaseStructure.TIM_Prescaler = 0x0; 
    // TIM_TimeBaseStructure.TIM_ClockDivision = 0x0; 
    // TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 
    // TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); 
    // TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update); 
    // TIM_Cmd(TIM3, ENABLE); //is OK 
    // TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); 
    // DAC1 channel1 and channel2 Configuration 
    DAC_InitStructure1.DAC_Trigger = DAC_Trigger_T3_TRGO;// DAC_Trigger_T2_TRGO;//DAC_Trigger_None;// DAC_Trigger_Ext_IT9; //PIN!!! 
    DAC_InitStructure1.DAC_WaveGeneration = DAC_WaveGeneration_None; 
    DAC_InitStructure1.DAC_OutputBuffer = DAC_OutputBuffer_Enable; 
    DAC_InitStructure1.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0; 
    DAC_InitStructure2.DAC_Trigger = DAC_Trigger_T3_TRGO;// DAC_Trigger_T2_TRGO;//DAC_Trigger_None;// DAC_Trigger_Ext_IT9; //PIN!!! 
    DAC_InitStructure2.DAC_WaveGeneration = DAC_WaveGeneration_None; 
    DAC_InitStructure2.DAC_OutputBuffer = DAC_OutputBuffer_Enable; 
    DAC_InitStructure2.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0; 
    //DMA 
    DMA_DeInit(DMA1_Channel4); 
    DMA_DeInit(DMA1_Channel5); 
    DMA_InitStructure1.DMA_MemoryBaseAddr = (uint32_t)&(VCOwaveOUT); //Array that contains the wave out data.. 
    DMA_InitStructure1.DMA_MemoryInc = DMA_MemoryInc_Enable; 
    DMA_InitStructure1.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//DMA_MemoryDataSize_HalfWord; // 
    DMA_InitStructure1.DMA_PeripheralBaseAddr = (uint32_t)&DAC1->DHR12R1; // DAC->DHR12R1;// //DAC->DHR8R1; //the last digit indicates for the channel 
    DMA_InitStructure1.DMA_DIR = DMA_DIR_PeripheralDST; 
    DMA_InitStructure1.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 
    DMA_InitStructure1.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;//DMA_PeripheralDataSize_HalfWord; // 
    DMA_InitStructure1.DMA_BufferSize = BLOCK_SIZE; 
    DMA_InitStructure1.DMA_Mode = DMA_Mode_Normal;// Circular;DMA_Mode_Circular; 
    DMA_InitStructure1.DMA_Priority = DMA_Priority_High; 
    DMA_InitStructure1.DMA_M2M = DMA_M2M_Disable; 
    DMA_Init(DMA1_Channel4, &DMA_InitStructure1); //accordingly to STM32F37x ref page 162 
    DMA_InitStructure2.DMA_MemoryBaseAddr = (uint32_t)&(BASEwaveOUT); //Array that contains the wave out data.. 
    DMA_InitStructure2.DMA_MemoryInc = DMA_MemoryInc_Enable; 
    DMA_InitStructure2.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//DMA_MemoryDataSize_HalfWord; // 
    DMA_InitStructure2.DMA_PeripheralBaseAddr = (uint32_t)&DAC1->DHR12R2; // DAC->DHR12R1;// //DAC->DHR8R1; //the last digit indicates for the channel 
    DMA_InitStructure2.DMA_DIR = DMA_DIR_PeripheralDST; 
    DMA_InitStructure2.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 
    DMA_InitStructure2.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;//DMA_PeripheralDataSize_HalfWord; // 
    DMA_InitStructure2.DMA_BufferSize = BLOCK_SIZE; 
    DMA_InitStructure2.DMA_Mode = DMA_Mode_Normal;// DMA_Mode_Circular; 
    DMA_InitStructure2.DMA_Priority = DMA_Priority_High; 
    DMA_InitStructure2.DMA_M2M = DMA_M2M_Disable; 
    DMA_Init(DMA1_Channel5, &DMA_InitStructure2);//accordingly to STM32F37x ref page 162 
    //Interrupts 
    //DMA_IT_TC: Transfer complete interrupt mask 
    //DMA_IT_HT: Half transfer interrupt mask 
    //DMA_IT_TE: Transfer error interrupt mask 
    // Enable DMA1 channel3 IRQ Channel 
    // Enable DMA1 channel4 IRQ Channel 
    // Enable DMA1 channel5 IRQ Channel 
    NVIC_InitStructure1.NVIC_IRQChannel = DMA1_Channel4_IRQn; 
    NVIC_InitStructure1.NVIC_IRQChannelPreemptionPriority = 0; 
    NVIC_InitStructure1.NVIC_IRQChannelSubPriority = 0; 
    NVIC_InitStructure1.NVIC_IRQChannelCmd = ENABLE; 
    NVIC_Init(&NVIC_InitStructure1); 
    NVIC_InitStructure2.NVIC_IRQChannel = DMA1_Channel5_IRQn; 
    NVIC_InitStructure2.NVIC_IRQChannelPreemptionPriority = 0; 
    NVIC_InitStructure2.NVIC_IRQChannelSubPriority = 0; 
    NVIC_InitStructure2.NVIC_IRQChannelCmd = ENABLE; 
    NVIC_Init(&NVIC_InitStructure2); 
    // NVIC_InitStructure3.NVIC_IRQChannel = DMA1_Channel5_IRQn; 
    // NVIC_InitStructure3.NVIC_IRQChannelPreemptionPriority = 0; 
    // NVIC_InitStructure3.NVIC_IRQChannelSubPriority = 0; 
    // NVIC_InitStructure3.NVIC_IRQChannelCmd = ENABLE; 
    // NVIC_Init(&NVIC_InitStructure3); 
    // DMA CONFIG 
    DMA_ITConfig(DMA1_Channel4, DMA_IT_TC , ENABLE); 
    DMA_Cmd(DMA1_Channel4, ENABLE); 
    DMA_ITConfig(DMA1_Channel5, DMA_IT_TC , ENABLE); 
    DMA_Cmd(DMA1_Channel5, ENABLE); 
    //DAC INIT 
    DAC_Init(DAC1, DAC_Channel_1, &DAC_InitStructure1); 
    DAC_Init(DAC1, DAC_Channel_2, &DAC_InitStructure2); 
    //DAC_Init(DAC2, DAC_Channel_1, &DAC_InitStructure3); 
    //DAC ENABLE 
    DAC_Cmd(DAC1,DAC_Channel_1, ENABLE); 
    DAC_Cmd(DAC1,DAC_Channel_2, ENABLE); 
    // Enable DMA for DAC Channels 
    DAC_DMACmd(DAC1, DAC_Channel_1, ENABLE); 
    DAC_DMACmd(DAC1, DAC_Channel_2, ENABLE); 
    } 
    void DMA1_Channel4_IRQHandler() { 
    if(DMA_GetFlagStatus(DMA1_IT_TC4) != RESET) { 
    DMA_ClearITPendingBit(DMA1_IT_TC4); 
    DMA_Cmd(DMA1_Channel4, DISABLE); 
    DAC1ch1_isON = false; 
    if(DAC1ch1_ON) { 
    DAC1ch1_isON = true; 
    DMA1_Channel4->CNDTR = BLOCK_SIZE; // <--- transaction length 
    DMA_Cmd(DMA1_Channel4, ENABLE); 
    } 
    } 
    DMA_ClearITPendingBit(DMA1_IT_GL4); 
    } 
    void DMA1_Channel5_IRQHandler() { 
    if(DMA_GetFlagStatus(DMA1_IT_TC5) != RESET) { 
    DMA_ClearITPendingBit(DMA1_IT_TC5); 
    DMA_Cmd(DMA1_Channel5, DISABLE); 
    DAC1ch2_isON = false; 
    if(DAC1ch2_ON) { 
    DAC1ch2_isON = true; 
    DMA1_Channel5->CNDTR = BLOCK_SIZE; // <--- transaction length 
    DMA_Cmd(DMA1_Channel5, ENABLE); 
    } 
    } 
    DMA_ClearITPendingBit(DMA1_IT_GL5); 
    } 

    *Edit I tried the DAC- DAM Channels DMA1_Channel3 -> DAC12 and DMA1_Channel4->DAC12 as well DMA1_Channel4->DAC11 and DAM1_Channel5-> DAC12 -- In all cases the IRQn routines where never called. *EditII: In the meantime I've investigatedDAC to DMA connection in the STM32F373RB device - here are my results: DMA2 Ch 1 2 3 4 5 DAC100 1 1 0 DAC20011 0 DMA1 Ch 1 2 3 4 5 6 7 DAC10 0 0 0 0 0 0 DAC20 0 0 0 0 0 0 Note: In contrast to the datasheet both the combinations DAC11 and DMA2ch4 + DAC12 and DMA2Ch3 are working well. Maybe ST want's to comment this finding