Skip to main content
Visitor II
January 13, 2024
Solved

Re-enabling TX DMA of SPI cause wrong transmit unit (STM32F407ZET6)

  • January 13, 2024
  • 2 replies
  • 3124 views

I am working on STM32F407ZET6 with DMA+SPI in slave mode. Trying to reset DMA Counter when NSS is high to avoid shifted data transmit.

TX and RX DMA are working on Circular mode.

This is my tx data

 

typedef struct {
 uint8_t InputState[4];
 uint8_t reserved1[4];
 uint8_t reserved2[4];
 uint8_t reserved3[4];
} SyncDataTX;

 

 Inside init function, i did

 

*((uint32_t*)(txData.InputState)) = 0x11121314;
*((uint32_t*)(txData.reserved1)) = 0x15161718;
*((uint32_t*)(txData.reserved2)) = 0x19202122;
*((uint32_t*)(txData.reserved3)) = 0x23242526;
HAL_SPI_TransmitReceive_DMA(&hspi1, (uint8_t *)&txData, (uint8_t *)&rxData, sizeof(txData));

 

Inside interrupt function, i did

 

__HAL_DMA_DISABLE(&hdma_spi1_rx);
__HAL_DMA_DISABLE(&hdma_spi1_tx);
__HAL_DMA_SET_COUNTER(&hdma_spi1_rx,sizeof(SyncDataTX));
__HAL_DMA_SET_COUNTER(&hdma_spi1_tx,sizeof(SyncDataTX));
__HAL_DMA_ENABLE(&hdma_spi1_rx);
__HAL_DMA_ENABLE(&hdma_spi1_tx);

 

In the first transaction, I get this, which is correct data:

 

11121314
15161718
19202122
23242526

 

In the second transaction, I get this:

 

12131414
16171811
20212215
24252619

 

From the third transaction, I start to getting this:

 

12131423
16171811
20212215
24252619

 

 

This happens even only:

__HAL_DMA_DISABLE(&hdma_spi1_tx);
__HAL_DMA_ENABLE(&hdma_spi1_tx);

 

:thinking_face:I didn't encounter such problem in STM32H750

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

    > Trying to reset DMA Counter when NSS is high to avoid shifted data transmit.

    This is flawed. Data is already in the shift register. Changing NDTR register in DMA will affect bytes 1-2+ in the future, but not the next byte that is sent out.

    You can re-sync by disabling SPI entirely and restarting with HAL_SPI_TransmitReceive_DMA from the beginning.

     

    Or, better, look into why it's getting de-synced in the first place and address that.

    2 replies

    Super User
    January 13, 2024

    Hi,

    To understand, what you do - or try to do - some questions :

    - who (this F407 ? ) is sender and who is slave receiver ?

    - i see only ...  send + receive as master ?

    HAL_SPI_TransmitReceive_DMA

     - on circular setup -- why this dis-/enable dma ? (should be never needed)

    - why double same commands ?

    __HAL_DMA_DISABLE(&hdma_spi1_rx);
    __HAL_DMA_DISABLE(&hdma_spi1_tx);
    thisdpAuthor
    Visitor II
    January 13, 2024

    1.  F407 as SPI Slave.

    2.  disable/enable dma is used to clear dma counter :

    In order to make sure the last SPI communication failure won't affect the next SPI communication.

    For example, I have a 2 bytes data that need to be transfer, but the last SPI communication just send 1 byte clock and then stopped. And at this time, if i starts the next SPI communication, the whole data will be 1 byte shifted.

    3.  These are not the same commands, one is rx, and another one is tx

    __HAL_DMA_DISABLE(&hdma_spi1_rx);
    __HAL_DMA_DISABLE(&hdma_spi1_tx);
    Super User
    January 13, 2024

    >3.  These are not the same commands, one is rx, and another one is tx

    OK, my bad eyes ... :)

    But - ( i use some 3 circular dma rx +tx same time ) you control, whats tx + rx doing ? 

    So keeping to the way of circular dma is working, wouldnt it be much easier and save to send constant block/packet size (and just fill unused bytes with 00 or AA ) and never need some dis- /enable ?

    I have it this way, the cpu has nothing to do with it anyway, even when its running "idle" , with zero data.

    +

    About the SPI lines , data etc. , maybe you should switch on pullups/pulldowns on all lines, to keep the "idle" state between transfers; if you switch it off and on, it might get an extra transition , when line is "open" (tri-state).

    TDKAnswer
    Super User
    January 13, 2024

    > Trying to reset DMA Counter when NSS is high to avoid shifted data transmit.

    This is flawed. Data is already in the shift register. Changing NDTR register in DMA will affect bytes 1-2+ in the future, but not the next byte that is sent out.

    You can re-sync by disabling SPI entirely and restarting with HAL_SPI_TransmitReceive_DMA from the beginning.

     

    Or, better, look into why it's getting de-synced in the first place and address that.

    thisdpAuthor
    Visitor II
    January 14, 2024

    this makes sense. I will try your solution.

    But I'm still confused that why the problem is still there even only do this

     __HAL_DMA_DISABLE(&hdma_spi1_tx);
    __HAL_DMA_ENABLE(&hdma_spi1_tx);