Skip to main content
Visitor II
December 9, 2023
Solved

STM32L476 SPI3 Using DMA2 Chan 2. No Transmit.

  • December 9, 2023
  • 11 replies
  • 3967 views

Hello Everyone. My how the forum has changed. Just dropping a recent odd experience here to see if anyone might have any comments. No. I don't use CubeMx and no this isn't another 3 year anniversary item regarding initializing the DMA before any peripherals that use it. We do that by default. However - working on a colleagues project, I have some code written to do some work that IS HAL library style stuff.

Getting a DMA controlled transmission from SPI 3 from the micro.

I have a DMA transmission from SPI 1 working. So I am familiar…….

Second Saturday in a row working on this for SPI3…..    Nothing I try works when using the DMA approach.

I can get all the SPI 3 hardware to work and send data if I call the BLOCKING SPI routine. NOT using the DMA.

Dumped out tons of register settings – All looks as it should.

Finally I give in to what I figure is a LOOOOOOOOOOONNNGGGGGG shot . --------              Try a different board.

It appears to work.  (???????????????)

Mind you --- the first board works with everything EXCEPT a DMA transfer for SPI3. Leads me to believe that – the micro has a BURRIED PERIPHERAL BAD ? One that has NO OUTSIDE WORLD HOOKUPS ?

*THAT*   will definitely be a FIRST for me.  I don’t know if I believe what I see until I try this on several boards.       I have 4. Of course -  I'm spooked about some sort of configuration weirdo that allows some race to occur that will maybe work on some chips and not on others.  My only question would be ---  Suggestions as to Where? I have this set up to test as a 1 pass event then trap it after the call to HAL_SPI_Transmit_DMA(&Spi_3_Handle, source, 33840). So not getting a loop around recall. And yes I always  wait after enabling clocks .

How rare is the bad burried peripheral idea?

Any feedback appreciated!

Thanks.

R

    This topic has been closed for replies.
    Best answer by shingadaddy

    Arg,,,,   Probably 4-5-6 years since I was bit by that one. 

    Okay - Say you need to use 2 SPI devices. And you want to use DMA on BOTH!

    You KNOW you need to init the DMA before any of the other peripheral stuff that uses it gets initialized.

    So "I" did EXACTLY this, one right after the other.:

    /***********************************************************************************************************************/
    /********************** SPI3 using DMA 2 *********************/
    __HAL_RCC_DMA2_CLK_ENABLE(); /*  DMA peripheral clock   */
    HAL_Delay(100);
     
        /*##-3- Configure the DMA ##################################################*/
        /* Configure the DMA handler for Transmission process */
        hdma_tx.Instance                    = DMA2_Channel2;
        hdma_tx.Init.Request              = DMA_REQUEST_3;
        hdma_tx.Init.Direction             = DMA_MEMORY_TO_PERIPH;
        hdma_tx.Init.PeriphInc            = DMA_PINC_DISABLE;
        hdma_tx.Init.MemInc               = DMA_MINC_ENABLE;
        hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        hdma_tx.Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;
        hdma_tx.Init.Mode                = DMA_NORMAL;
        hdma_tx.Init.Priority            = DMA_PRIORITY_LOW;
     
        HAL_DMA_Init(&hdma_tx);
     
        /* Associate the initialized DMA handle to the the SPI handle */
        __HAL_LINKDMA(&Spi_3_Handle, hdmatx, hdma_tx);
    /********************************************************************/
     
    //#if 0
    /********************** SPI2 using DMA 1 *********************/
    __HAL_RCC_DMA1_CLK_ENABLE(); /* DMA peripheral clock */
    HAL_Delay(100);
     
        /*##-3- Configure the DMA ##################################################*/
        /* Configure the DMA handler for Transmission process */
        hdma_tx.Instance                 = DMA1_Channel5;
        hdma_tx.Init.Request             = DMA_REQUEST_1;
        hdma_tx.Init.Direction           = DMA_MEMORY_TO_PERIPH;
        hdma_tx.Init.PeriphInc           = DMA_PINC_DISABLE;
        hdma_tx.Init.MemInc              = DMA_MINC_ENABLE;
        hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        hdma_tx.Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;
        hdma_tx.Init.Mode                = DMA_NORMAL;
        hdma_tx.Init.Priority            = DMA_PRIORITY_LOW;
     
        HAL_DMA_Init(&hdma_tx);
     
        /* Associate the initialized DMA handle to the the SPI handle */
        __HAL_LINKDMA(&Spi_2_Handle, hdmatx, hdma_tx);
    //#endif
    /***************************************************************************************************************/
     
    Then proceeded onward to init the SPI and GPIO stuff. 
    Problem - 
    Here - That hdma_tx struct isn't used as a generic "fill it out and fling it into a peripheral register" use. 
    Having both of these DMA inits in code caused to the top one , SPI3-DMA2 to fly off in the weeds. when the DMA TX was called. (NOT DURING INIT TIME ...) 
    POUND IFING (Commenting)  the bottom one out - let the top one operate as it should. Creating separate  hdma1_tx and hdma2_tx structs seems to have done the trick. At least with both using those individual structs - the top one works. I'll get to testing both DMA transmits simultaneously in the near future.  
     
    There was no 1 board works and the other doesn't. THAT was *my* mistake where I commented out the second DMA setup after thinking - "Lets deal with one DMA at a time". SO I commented it out.. THEN tried it on - THE BOARD THAT WORKED.    Little did I now that THAT was where the issue was...And around the circle I went.
    Bottom line ------------    DON'T DO THAT.    :\  
     
    AND! - I found a while(1)  (Didn't have any ill effects on the SPI DMA TX however)       
    AND it looked exactly like that. No brackets! 
    And the compiler (complainer) never barked at me for it.   I'm somewhat surprised by that. Thank you all for your feedback / encouragement. 
     

    11 replies

    Super User
    December 25, 2023

    Wait wait. The problem was caused by the code generation. "HAL" is the library, it is independent from the code generation. With all criticism thrown at it, mostly it is "good enough" for a quick prototype. 

     Remember HAL is FREE. And - you get what you pay for. 

    Kudo to you again :)

     

     

    Visitor II
    December 26, 2023

    Yes.   Prototypes which many times turn into solutions for quick turn one off projects. 

    And in THIS case - the "code generation" is done by ...............   ME! ... :) 

    Not CubeMX. 

    "I" don't use CubeMX. 

    Now of course - I'm tempted to try CubeMX with 2 SPI busses set up with both using interrupts and DMA to see what it spits out. But unfortunately - that would be pointless in the existing SCHEDULED activities here.