cancel
Showing results for 
Search instead for 
Did you mean: 

Why LL SPI Receive DMA request generate clocks?

senge
Associate II

I use a ADS7056 temperature sensor. I want to read the temperature via SPI and DMA.

To do this, I have to set the CS low, generate 18 clocks, set the CS high again.

Unfortunately I haven't found a configuration that works with the LL drivers yet.

To generate the 18 clock, I execute a "dummy" LL_SPI_EnableDMAReq_TX(SPI2);

So far so good.

To read the data from the sensor i perform a LL_SPI_EnableDMAReq_RX(SPI2)

But this request generate another 18 clock.

On the other hand, wenn i execute only LL_SPI_EnableDMAReq_RX(SPI) no clocks are generated.

SPI Settings:

SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
  SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
  SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_9BIT;
  SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW;
  SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE;
  SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
  SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV8;
  SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
  SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
  SPI_InitStruct.CRCPoly = 7;
  LL_SPI_Init(SPI2, &SPI_InitStruct);
  LL_SPI_SetStandard(SPI2, LL_SPI_PROTOCOL_MOTOROLA);
  LL_SPI_DisableNSSPulseMgt(SPI2);
/** Dummy variable to send data over SPI */
uint8_t spi_TxDummy[4] = { 0 };
/** Receive data over SPI */
uint8_t spi_RxBuffer[4] = { 0 };
 
...
 
/* Set RXNE Bit when Receive 16bit (9bit from ADS7056) */
    LL_SPI_SetRxFIFOThreshold(spi_hw_settings.SPI_Interface, LL_SPI_RX_FIFO_TH_HALF);
 
 
    /* Configure DMA TX settings */
    LL_DMA_ConfigTransfer(DMA1, LL_DMA_CHANNEL_5, LL_DMA_DIRECTION_MEMORY_TO_PERIPH |
				LL_DMA_PRIORITY_HIGH | LL_DMA_MODE_NORMAL |
				LL_DMA_PERIPH_NOINCREMENT | LL_DMA_MEMORY_INCREMENT |
				LL_DMA_PDATAALIGN_BYTE | LL_DMA_PDATAALIGN_BYTE);
 
    LL_DMA_ConfigAddresses(DMA1, LL_DMA_CHANNEL_5, (uint32_t)spi_TxDummy, LL_SPI_DMA_GetRegAddr(SPI2),
				 LL_DMA_GetDataTransferDirection(DMA1, LL_DMA_CHANNEL_5));
 
    LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_5, sizeof(spi_TxDummy)/sizeof(spi_TxDummy[0]));
 
    /* Equal to "LL_DMA_SetPeriphRequest(...)" but there is a bug in the LL library */
    DMA1_CSELR->CSELR |= 1 << DMA_CSELR_C5S_Pos;
 
 
 
    /* Configure DMA RX settings */
    LL_DMA_ConfigTransfer(DMA1, LL_DMA_CHANNEL_4, LL_DMA_DIRECTION_PERIPH_TO_MEMORY |
    				LL_DMA_PRIORITY_LOW | LL_DMA_MODE_NORMAL|
    				LL_DMA_PERIPH_NOINCREMENT | LL_DMA_MEMORY_INCREMENT |
    				LL_DMA_PDATAALIGN_BYTE | LL_DMA_PDATAALIGN_BYTE);
 
    LL_DMA_ConfigAddresses(DMA1, LL_DMA_CHANNEL_4, (uint32_t)spi_RxBuffer, LL_SPI_DMA_GetRegAddr(SPI2),
       			         LL_DMA_GetDataTransferDirection(DMA1, LL_DMA_CHANNEL_4));
 
    LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_4, sizeof(spi_RxBuffer)/sizeof(spi_RxBuffer[0]));
 
    /* Equal to "LL_DMA_SetPeriphRequest(...)" but there is a bug in the LL library */
    DMA1_CSELR->CSELR |= 1 << DMA_CSELR_C4S_Pos;
 
    /* Enable DMA RX request */
    LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_5);
    LL_SPI_EnableDMAReq_RX(spi_hw_settings.SPI_Interface);
 
    /* Enable DMA TX request */
    LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_4);
    LL_SPI_EnableDMAReq_TX(spi_hw_settings.SPI_Interface);
 
    /* Set CS low */
    LL_GPIO_ResetOutputPin(spi_hw_settings.GPIO_Port, spi_hw_settings.GPIO_Pin);
 
    LL_SPI_Enable(spi_hw_settings.SPI_Interface);
 
    /* Wait until DMA dummy transfer complete */
    while (!LL_DMA_IsActiveFlag_TC5(DMA1)) {}
 
    /* Wait until clock generation complete */
    while (LL_SPI_IsActiveFlag_BSY(spi_hw_settings.SPI_Interface)) {}
    LL_SPI_Disable(spi_hw_settings.SPI_Interface);
 
    /* Set CS high again */
    LL_GPIO_SetOutputPin(spi_hw_settings.GPIO_Port, spi_hw_settings.GPIO_Pin);

So what can i do to generate 18 clock and do an DMA SPI read?

4 REPLIES 4

Clocks are generated by the SPI module, only when data are written to the SPI data register, that's in your case when the Tx DMA runs.

JW

S.Ma
Principal

Which SPI IP version is used? What is the STM32 part number?

If the SPI has FIFO, you probably won't need DMA for less than 32 bit of data transfer as the FIFOs are 32 bit.

DMA would be for 200+ bytes transfer.

Okey thx.

Here 18 clocks are generated. As it should be:

/* Enable DMA RX request */
//    LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_4);
//    LL_SPI_EnableDMAReq_RX(spi_hw_settings.SPI_Interface);
 
    /* Enable DMA TX request */
    LL_SPI_EnableDMAReq_TX(spi_hw_settings.SPI_Interface);
    LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_5);
    while (!LL_DMA_IsActiveFlag_TC5(DMA1)) {}
 
    /* Set CS low */
    LL_GPIO_ResetOutputPin(spi_hw_settings.GPIO_Port, spi_hw_settings.GPIO_Pin);
 
    /* Enable SPI interface */
    LL_SPI_Enable(spi_hw_settings.SPI_Interface);
 
    /* Wait until clock generation complete */
    while (LL_SPI_IsActiveFlag_BSY(spi_hw_settings.SPI_Interface)) {}
    LL_SPI_Disable(spi_hw_settings.SPI_Interface);
 
    /* Set CS high again */
    LL_GPIO_SetOutputPin(spi_hw_settings.GPIO_Port, spi_hw_settings.GPIO_Pin);

But why 36 clocks are generated when i enable RX request?

/* Enable DMA RX request */
    LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_4);
    LL_SPI_EnableDMAReq_RX(spi_hw_settings.SPI_Interface);
 
    /* Enable DMA TX request */
    LL_SPI_EnableDMAReq_TX(spi_hw_settings.SPI_Interface);
    LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_5);
    while (!LL_DMA_IsActiveFlag_TC5(DMA1)) {}
 
    /* Set CS low */
    LL_GPIO_ResetOutputPin(spi_hw_settings.GPIO_Port, spi_hw_settings.GPIO_Pin);
 
    /* Enable SPI interface */
    LL_SPI_Enable(spi_hw_settings.SPI_Interface);
 
    /* Wait until clock generation complete */
    while (LL_SPI_IsActiveFlag_BSY(spi_hw_settings.SPI_Interface)) {}
    LL_SPI_Disable(spi_hw_settings.SPI_Interface);
 
    /* Set CS high again */
    LL_GPIO_SetOutputPin(spi_hw_settings.GPIO_Port, spi_hw_settings.GPIO_Pin);

I'm use the library STM32Cube FW_L4 V1.14.0 with a STM32L475RETx.

I don't know.

Read out and check/post the SPI and DMA registers' content.

JW