Skip to main content
Visitor II
July 8, 2024
Question

Timer Trigger DMA Tx transfer for SPI2

  • July 8, 2024
  • 7 replies
  • 2668 views

Hi there,

Iam using STM32F407ZGT6 controller, and we're interfacing DAC (MCP4902) with SPI2 and SPI2 is connected to DMA1.

 

I need to transfer data in a circular mode using DMA1 to DAC using SPI, i have gone through the reference manual only TIM1 and TIM8 are the advance timers and having PWM mode and it is connected to DMA2.

Here iam toggling cs pin and need to transfer data with this function TIM_DMACmd(TIM8, TIM_DMA_Update, ENABLE);  without enabling this  SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);

Can you please suggest me how Timer Trigger DMA for SPI 2 can be configured.



 

 

    This topic has been closed for replies.

    7 replies

    Super User
    July 8, 2024

    You don't need TIM1/TIM8 for that. DMA1 Streams (possibly triggered by timers on APB1) can write on their Peripheral port to peripherals at APB1, such as SPI2.

    The usual limitation what you may have in mind is, that DMA1 cannot write to GPIO.

    JW

     

    Visitor II
    July 8, 2024

    Could you please help me on this.

    Do you have any specific example on spi tx transfer with DMA timer request transfer for stm32f407 standard peripheral library.

    iam using SPI-2 here i dont know which timer can support timer request transfer.

    Super User
    July 8, 2024

    > Do you have any specific example

    No. It is not any different from any DMA example, if you set properly the DMA pointer registers.

    I don't use SPL. It's been deprecated by ST for around 10 years now...

    JW

    Visitor II
    July 9, 2024

    please find the code can i know where exactly going wrong ?

     

    void SigGenInitSigGen(void) {
    uint16_t tempPrescalerValue = 0;
    SigGenSpiInitData_u tempInitData;
     
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM12, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
    // RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); //
     
    IoSpiGpioInit();
     
    /*for spi2 modified by sai*/
        SPI_I2S_DeInit(SPI2);
    tempInitData.spiInitStructure.SPI_Direction = SPI_Direction_1Line_Tx;
    tempInitData.spiInitStructure.SPI_DataSize = SPI_DataSize_16b;
    tempInitData.spiInitStructure.SPI_CPOL = SPI_CPOL_Low;
    tempInitData.spiInitStructure.SPI_CPHA = SPI_CPHA_1Edge;
    tempInitData.spiInitStructure.SPI_NSS = SPI_NSS_Soft;
    tempInitData.spiInitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
    tempInitData.spiInitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    tempInitData.spiInitStructure.SPI_CRCPolynomial = 7;
    tempInitData.spiInitStructure.SPI_Mode = SPI_Mode_Master;
        SPI_Init(SPI2, &(tempInitData.spiInitStructure));
    SPI_Cmd(SPI2, ENABLE);
     
    tempPrescalerValue = (uint16_t)(SystemCoreClock / 72000000) - 1;
    // Configure Timer 3 to generate DMA requests
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_TimeBaseStructure.TIM_Period = CONF_SIGGEN_GEN_PERIOD; // Set the period according to your requirement
    TIM_TimeBaseStructure.TIM_Prescaler = tempPrescalerValue; // Set the prescaler according to your clock
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
    TIM_DMACmd(TIM3, TIM_DMA_Update, ENABLE); // Enable DMA request on timer update
    TIM_Cmd(TIM3, ENABLE); // Start the timer
    // memset(&tempInitData, 0x00, sizeof(SigGenSpiInitData_u));
     
    DMA_InitTypeDef DMA_InitStructure;
    DMA_DeInit(DMA1_Stream4); // De-initialize the DMA Stream (DMA1_Stream4 for SPI2 TX)
    DMA_InitStructure.DMA_Channel = DMA_Channel_0; // Channel selection
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI2->DR; // SPI2 data register address
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)m_SigGenGenBuffer_ch1; // Memory buffer address
    DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; // Data direction: Memory to Peripheral
    DMA_InitStructure.DMA_BufferSize = CONF_SIGGEN_GEN_BUFFER_SIZE; // Buffer size
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // Peripheral increment mode
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // Memory increment mode
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // Peripheral data size (16 bits)
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // Memory data size (16 bits)
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; // Circular mode
    DMA_InitStructure.DMA_Priority = DMA_Priority_High; // Priority level
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; // FIFO mode
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; // FIFO threshold
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; // Memory burst
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; // Peripheral burst
    DMA_Init(DMA1_Stream4, &DMA_InitStructure);
    DMA_Cmd(DMA1_Stream4, ENABLE); // Enable the DMA Stream
        DMA_ITConfig(DMA1_Stream4, DMA_IT_HT|DMA_IT_TC, ENABLE); // Enable DMA transfer complete interrupt
    NVIC_EnableIRQ(DMA1_Stream4_IRQn); // Enable DMA1 Stream4 IRQ in NVIC
     
    // Configure Timer 12 to toggle CS pin
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure2;
    TIM_OCInitTypeDef TIM_OCInitStructure;
    TIM_TimeBaseStructure2.TIM_Period =  CONF_SIGGEN_GEN_PERIOD; // Set the period according to your requirement
    TIM_TimeBaseStructure2.TIM_Prescaler = tempPrescalerValue; // Set the prescaler according to your clock
    TIM_TimeBaseStructure2.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure2.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM12, &TIM_TimeBaseStructure2);
    TIM_OCStructInit(&TIM_OCInitStructure);
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = ( CONF_SIGGEN_GEN_PERIOD * 7 / 10 ); // Adjust the pulse width as needed
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
    TIM_OC1Init(TIM12, &TIM_OCInitStructure);
    TIM_OC1PreloadConfig(TIM12, TIM_OCPreload_Disable);
    TIM_ARRPreloadConfig(TIM12, ENABLE);
    TIM_Cmd(TIM12, ENABLE); // Start Timer 12
     
     
     
     
     
    }
     
    void DMA1_Stream4_IRQHandler(void)
    {
        if (DMA_GetFlagStatus(DMA1_Stream4, DMA_FLAG_HTIF4) != RESET)
        {
            // Clear DMA transfer complete flag
            DMA_ClearFlag(DMA1_Stream4, DMA_FLAG_HTIF4);
     
          m_SigGenTempGenBufferPtr_ch1 = m_SigGenPingGenBufferPtr_ch1;
          m_SigGenData_Op1.ptrCallBackInitGenBuffer();
     
     
        }
          if(DMA_GetFlagStatus(DMA1_Stream4, DMA_FLAG_TCIF4) != RESET)
          {
           DMA_ClearFlag(DMA1_Stream4, DMA_FLAG_TCIF4);
           m_SigGenTempGenBufferPtr_ch1 = m_SigGenPongGenBufferPtr_ch1;
           m_SigGenData_Op1.ptrCallBackInitGenBuffer();
     
          }
     
     
    }

     

    Visitor II
    July 9, 2024

    i have to transfer buffer without enabling SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);

    but in my case spi is working when this function " SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);"

    is calling .

    Super User
    July 9, 2024

    > (DMA1_Stream4 for SPI2 TX)

    No.

    It's the trigger source - here, TIM3_UP - which determines the selection of DMA Stream (and Channel), so you have to use DMA1_Stream2 with Channel5.

    JW

    Visitor II
    July 9, 2024

    modified as per your comment but still not working 

    Super User
    July 9, 2024

    > still not working

    What does that mean? No output on SPI pins whatsoever?

    I don't use SPL so don't quite understand your code (nor am I willing to study it in depth).

    Read out and check/post relevant TIM, DMA and SPI registers content.

    JW

    Visitor II
    July 9, 2024

    Yes SPI is not working no signals on SPI..

    or please check who can have knowledge on SPL in your team.

     

    Thanks for the help..

    Super User
    July 9, 2024

    You may be not aware of the fact that this is a primarily user-driven forum, with casual ST presence. I am not ST.

    Also, it's unlikely anybody is willing to go through snippets of code in SPL to find any problem. You are mostly on your own.

    Read out and check/post relevant TIM, DMA and SPI registers content.

    JW

    Visitor II
    July 9, 2024

    Thanks .