Skip to main content
Graduate
July 25, 2024
Question

Issue with Chip Select Pin Timing in STM32-L4P5DK SPI DMA Configuration.

  • July 25, 2024
  • 2 replies
  • 1752 views

 

I have an STM32-L4P5DK connected to an external ADC, with SPI2 configured to read ADC samples on every falling edge of the DRDY signal. The DMA1 configuration is as follows:

DMA1 CHANNEL1: DMA_GENERATOR0
DMA1 CHANNEL2: SPI2_TX
DMA1 CHANNEL3: SPI2_RX

The DRDY pin is connected to EXTI1. On each falling edge of DRDY, DMA_GENERATOR0 generates a request to set the Chip Select pin low. The SPI_TX DMA request is synchronized with the rising edge of DRDY, so SPI_TX transmits dummy bytes to read the ADC data via SPI_RX DMA request, which is also synchronized with the EXTI1 rising edge. Once the SPI transmission is complete, I set the Chip Select pin high in the `HAL_SPI_TxCpltCallback` function.

The problem is that the Chip Select pin goes high before the SPI transmission completes. However, if I add a delay using a while() loop, the Chip Select timing shifts correctly.

Why is this happening, and how can I ensure that the Chip Select pin goes high only after the SPI transmission is completely finished?

void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, 1); //callback function without delay
}

for the above function , I get the below output.

fig 1:
without_delay.jpeg

 

 

void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
uint8_t i =21;
while(--i) // added delay to shift CS pin HIGH state
{
	__NOP();
}
HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, 1);
}

for the above function , I get the below output.

fig2:

with_delay.jpeg

Scope output:

>> yellow - DRDY , green - CS , red  - SCK , blue - MOSI

 

    This topic has been closed for replies.

    2 replies

    Super User
    July 25, 2024

    > Why is this happening

    The DMA transfer completes when the last byte of data is sent to the peripheral. Since the peripheral has a FIFO, this happens before some bytes before the data is actually sent out. (Even without a FIFO, it would happen before the last byte is sent.)

    > and how can I ensure that the Chip Select pin goes high only after the SPI transmission is completely finished?

    Poll the SPI BSY bit and wait for it to be 0 before de-asserting CS.

    This is actually covered in the RM:

    TDK_0-1721922547665.png

     

    ajmw_Author
    Graduate
    July 26, 2024

    Hi TDK, 

    I tried polling the SPI BSY bit, but it did not work. The CS pin becomes high even before the SPI transmission starts.

    I have resolved the chip select issue by starting the timer in the `HAL_GPIO_EXTI_Callback` function. After 120us (since I am sampling at a rate of 8000sps, i.e., every 125 microseconds), I make the chip select pin HIGH in the `HAL_TIM_PeriodElapsedCallback` function. It works fine.

     

     

    void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
     if(htim->Instance == TIM4) {
     HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);
     HAL_TIM_Base_Stop(&htim4);
     }
    }
    
    void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
     HAL_TIM_Base_Start(&htim4);
    }

     

    Regards,
    AJ

    Super User
    July 26, 2024

    > I tried polling the SPI BSY bit, but it did not work.

    It should work. Show the code.

    Super User
    July 26, 2024

    Use HAL_SPI_TransmitReceive_DMA since you are both sending and receiving data. And you can set CS high on the receive complete callback since the transfer will be done when the last byte is received, no need to poll for BSY.