2024-07-08 07:14 AM
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
Solved! Go to Solution.
2024-07-08 10:12 AM
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?
2024-07-08 10:22 AM
"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
2024-07-08 10:30 AM
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:
Why don't you just try it?
2024-07-08 10:34 AM - edited 2024-07-08 10:38 AM
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.
2024-07-08 10:41 AM
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
2024-07-08 10:55 AM
"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
2024-07-08 11:08 AM
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.
2024-07-08 11:39 AM
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).
{
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
2024-07-08 12:11 PM
"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!
{
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--; } }
}
2024-07-08 03:28 PM
Please see how to properly post source code: