cancel
Showing results for 
Search instead for 
Did you mean: 

We need the register-based low level SPI R/W drive for STM32C031C6

RongShengWang
Associate III

1. CubeMX only allows HAL or LL for SPI and other peripherals. STM32C031C6 itself provides the good SPI clock rate. 

   SPI LL API function only allows two-byte R/W.. The slave STPM34 Meter IC requires 4-Byte SPI R/W. So we have to choose HAL SPI API calls, such as HAL_SPI_TransmitReceive().   

    However HAL introduces a big delay (15 us or more) between two consecutive HAL SPI-API calls. We need 6 SPI-API calls within 128us for our application,  This big delay inserted by HAL makes it impossible. .

2. The only solution is to write the register low level SPI R/W functions. Is it possible to write it under the current CubeMx IDE compiler for STM32C031C6? Could you provide us the solutions?

 

Thanks,

 

Rong

1 ACCEPTED SOLUTION

Accepted Solutions

Hello @RongShengWang 

 

I updated my code. Could you check with this please.

void SPI_Transmit_Receive(const uint8_t *data_tx, uint8_t *data_rx, uint8_t size)
{
	uint8_t rx_size= size;
	uint8_t tx_size = size;


    /* Set the Rx Fifo threshold */
    if (size > 1U)
    {
      /* Set fiforxthreshold according the reception data length: 16bit */
      CLEAR_BIT(SPI1->CR2, SPI_RXFIFO_THRESHOLD);
    }
    else
    {
      /* Set fiforxthreshold according the reception data length: 8bit */
      SET_BIT(SPI1->CR2, SPI_RXFIFO_THRESHOLD);
    }

    /* Enable SPI */
    SPI1->CR1 |= SPI_CR1_SPE;


    while (size > 0)
    {
        /* Wait until TXE (Transmit buffer empty) flag is set */
        while (!__HAL_SPI_GET_FLAG(&hspi1, SPI_FLAG_TXE));

        /* Transmit data */
      if (tx_size > 1U)
      {
        SPI1->DR = *((uint16_t *)data_tx);
        data_tx += sizeof(uint16_t);
        tx_size -= 2U;
      }
      else
      {
        *(__IO uint8_t *)&SPI1->DR = (*data_tx);
        data_tx ++;
        tx_size --;
      }

        /* Wait until RXNE (Receive buffer not empty) flag is set */
        while (!__HAL_SPI_GET_FLAG(&hspi1, SPI_FLAG_RXNE));


		if (rx_size > 1U)
        {
          *((uint16_t *)data_rx) = (uint16_t)SPI1->DR;
          data_rx += sizeof(uint16_t);
          rx_size -= 2U;
          if (rx_size <= 1U)
          {
            /* Set RX Fifo threshold before to switch on 8 bit data size */
            SET_BIT(SPI1->CR2, SPI_RXFIFO_THRESHOLD);
          }
        }
        else
        {
          (*(uint8_t *)data_rx) = *(__IO uint8_t *)&SPI1->DR;
          data_rx++;
          rx_size --;
        }
    }

    /* Wait until the SPI is not busy */
    while (__HAL_SPI_GET_FLAG(&hspi1, SPI_FLAG_BSY));

    /* Disable SPI */
    SPI1->CR1 &= ~SPI_CR1_SPE;
}
If your question is answered, please close this topic by clicking "Accept as Solution".

Thanks
Omar

View solution in original post

44 REPLIES 44
Andrew Neil
Evangelist III

The auto-generated code just does the initialisation stuff - you can write your own register-level code to do the runtime sending thereafter.

Amel NASRI
ST Employee

Hi @RongShengWang ,

Here 2 examples with SPI LL APIs using STM32C031: https://github.com/STMicroelectronics/STM32CubeC0/tree/main/Projects/NUCLEO-C031C6/Examples_LL/SPI.

You can start from the IOC file of each example and adapt it to yours needs. 

-Amel

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

 

Hi, Almel,

   SPI LL API function only allows two-byte R/W each time. The slave side requires 4-Byte SPI R/W each time. We can't use LL for the Master SPI.

   HAL introduces a big delay (15 us -20 us) between two consecutive HAL SPI-API calls (such as two calls to HAL_SPI_TransmitReceive()).  We need 6 SPI-API calls within 128us for our application,  This big delay inserted by HAL between any two consecutive HAL SPI-API calls makes  it impossible. .

Could you explain how your LL example can overcome the problem in the above?

 

Thanks

 

Rong

Hi, Andrew Neil,

    "you can write your own register-level code to do the runtime" - Could you provide me with a reference code?

     Thanks,

 

Rong

    

 

Sorry, no.

I suggest you look at the LL code, and adapt that...

Hi,

    "you can write your own register-level code to do the runtime sending thereafter." - The CubeMX compiler may not recognize the own register-level code, such as "SPI1->DR = (uint16_t)(tx_data << 8);", which I copied from some

reference projects using STM32 SPI registers to handle SPI.

    How to make CubeMX compiler to recognize it?

   Thanks,

 

Rong

 

    


@RongShengWang wrote:

The CubeMX compiler ...    


You mean the CubeIDE compiler - ie, GCC ?

 


@RongShengWang wrote:

... may not recognize the own register-level code, such as "SPI1->DR = (uint16_t)(tx_data << 8);"


What makes you say that?

I am using CubeIDE compiler for everything now.

Hi, Almel,

   SPI LL API function only allows two-byte R/W each time. The slave side requires 4-Byte SPI R/W each time. We can't use LL for the Master SPI because the protocol is 4-byte based.

    Besides We need 6 SPI-API calls within 128us for our application.

    Could you explain why LL can satisfy the above requirement?

 

Thanks,

 

Rong