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

44 REPLIES 44

You haven't explained yet what you mean by, "compiler may not recognize the own register-level code, such as 'SPI1->DR = (uint16_t)(tx_data << 8);'"

 

Is it giving you an error, or what?

     "You haven't explained yet what you mean by, "compiler may not recognize the own register-level code, such as 'SPI1->DR = (uint16_t)(tx_data << 8);'"

    If I add "SPI1->DR = (uint16_t)(tx_data << 8);"  which I copied from some register based STM32 SPI project C file , to my CubeMX project C file. Do you think CubeMx IDE compiler will compile it with no error on "SPI1->", ?

    "SPI1"  is not defined anywhere in my CubeMX project C/,h file; it was copied from some register based STM32 SPI project C file. Please advise.

    Thanks,

Rong

Of course it's defined - the LL and HAL code use it!

It'll be in the stmxxxxxxx.h file for the chip you're using; eg, for stm32F030x8:

AndrewNeil_0-1720459803857.png

 

Why don't you just try it?

Pretty sure putting the data in the high byte's not going to be remotely helpful.

Could you configure the SPI in 16-bit mode and send two half-words, to get your 4-bytes? Not sure what the stated inter-symbol delay is, but hard to believe it's significant.

Perhaps DMA TX via TXE ?

I don't recall if the STM32C0 has a FIFO on the SPI, RM0490 suggests it does.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

We use STM32C031C6. I will test it when I am back to work. Thank you very much! it would be a quick fix if it works.

There are a few register based SPI project C code online. I did not know how to use it in Cubemx IDE environment.

I will let you know if it can be compiled for STM32C031C6 later today.

HAL adds too much overhead (Time Delay) between two SPI API calls. LL only allows two bytes R/W while our protocol requires 4-byte package.

Thanks again,

 

Rong

 

"Not sure what the stated inter-symbol delay is, but hard to believe it's significant."

If I send "HAL_SPI_TransmitReceive(...)." twice without any delay in my code, you will see from the scope there is about 20us between the two calls inserted by HAL. Each call itself works fine; but the 20 us in between causes trouble (See below).

We need issue HAL_SPI_TransmitReceive(...) 6 times in every 128 us with the different data W/R. It becomes impossible with 20 us delay between each two calls. LL could be better, but it is not as good as the low-level register based SPI C code. Besides, our data protocol is 4-byte based while LL only handles 2-byte.

   I try to copy some code from the low-level register based SPI - I still use CubeMX SPI initialization code without using its API function calls. I will let you know if it works.

   Thanks,

Rong

 

 

 

 

 

 

So as stated, in top-post, why aren't you using the Register methods?

The FIFO is 32-bit deep, TXE would indicate you can write both 16-bit half-words back-to-back

Stop using HAL_SPI_TransmitReceive(), it's going to wait for the TX to go over the wire so it can recover the RX data symmetrically.

You should definitely be able to push 32-bits into the TX FIFO, and pull 32-bits from the RX FIFO, and there should be negligible inter-symbol delay.

Or DMA patterns on TX, RX

You should perhaps be requesting STPM34 SPI support code from your FAE / technical contact for you STMicro business. Or post as an online support ticket via OLS system.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

 I try to copy some C code from the low-level register based SPI -

 I still use CubeMX SPI initialization code without using its API function calls.

  What do you think? I will let you know if it works.

Example - SPI TX (Without calling HAL or LL anymore if it works).

 

void SPI_Transmit (uint8_t *data, int size)

{

    int i=0;

    while (i<size)

   {

        while (!((SPI1->SR)&(1<<1))) {}; //buffer empty

        SPI1->DR   data[i]; // load the data into the Data Register

        i++;

   }

}

void SPI_Receive (uint8_t *data, int size)

{

        while (size) { while (((SPI1->SR)&(1<<7))) {}; // indicate that SPI is not busy in communication

      SPI1->DR = 0; // send dummy data while (!((SPI1->SR) &(1<<0))){};  // Wait for RXNE to set Rx buf is not empty

       *data++ = (SPI1->DR); size--; } }

}

 

   Thanks,

Rong

"Is it giving you an error, or what?" - It gives no compiler error. Thank you so much!

The following code I am going to use - No more API calls for HAL or LL, which adds too much delay between two API calls - It should never happen!

 

void SPI_Transmit (uint8_t *data, int size)

{

    int i=0;

    while (i<size)

   {

        while (!((SPI1->SR)&(1<<1))) {}; //buffer empty

        SPI1->DR   data[i]; // load the data into the Data Register

        i++;

   }

}

void SPI_Receive (uint8_t *data, int size)

{

        while (size) { while (((SPI1->SR)&(1<<7))) {}; // indicate that SPI is not busy in communication

      SPI1->DR = 0; // send dummy data while (!((SPI1->SR) &(1<<0))){};  // Wait for RXNE to set Rx buf is not empty

       *data++ = (SPI1->DR); size--; } }

}