-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
STM32: fix SPI 16 bit mode #15206
STM32: fix SPI 16 bit mode #15206
Conversation
Update SPI logic to process 16 bit words in the same way by sync/async, 3/4 wires modes: - fix 3-wire synchronous transmission to move 2 or more bytes between buffer and SPI register per word tarnsmission - fix 4-wire synchronous transmission to move 2 or more bytes between buffer and SPI register per word tarnsmission
By default, HAL functions (HAL_SPI_TransmitReceive_IT/HAL_SPI_Transmit_IT/HAL_SPI_Receive_IT) assume that SPI is disabled between function invocation. It's needed to set transfer size (CR2 register), that can be modified only if SPI disabled. But `stm32_spi_api.c` keeps SPI enabled after initialization. This commit adds helper code for STM32H7 (SPI_IP_VERSION_V2) that disables SPI before HAL_SPI_TransmitReceive_IT/HAL_SPI_Transmit_IT/HAL_SPI_Receive_IT and after end of transaction for HAL API compatibility.
@vznncv, thank you for your changes. |
Is this known issue or should be reported? |
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Impressive work!
Thx
Tested impressively 💯 |
Jenkins CI Test : ✔️ SUCCESSBuild Number: 1 | 🔒 Jenkins CI Job | 🌐 Logs & ArtifactsCLICK for Detailed Summary
|
Not exactly. With 4-wire or 3-wire (write only) mode you can use high frequency SPI clock signal, but due interrupt routine overhead there will be delays between frames. It significantly reduces average SPI speed and increases CPU usage, but it is still correct SPI communication and you don't lose any data. But the mentioned issue is related only with 3-wire mode and data reading: in this case STM SPI IP v1 generates SPI clock signal and receives frames continuously until SPI is disabled programmatically. It means that after receiving of last SPI frame, SPI device should be disabled immediately before next SPI clock cycle. Unfortunately HAL library IRQ implementation isn't fast enough (even with "release" build), so SPI starts receiving next frame (in rare cases I got up to several dozens of extra frames). Usually it doesn't hinder many SPI sensors/modules, but if you read data from sensor/module buffer, you will lose some data. It may occurs even with low SPI speed (400 kHz).
I don't see any github issue about it. If it's needed I can create a new one.
I'd prefer to wait @JojoS62. This PR contains only fixes without SPI state logic changes, whereas @JojoS62 wanted to implement some SPI enabling/disabling optimizations. |
thanks, I had no time to work on this further. I think the fix is ok, for optimization the transfer function should be used. |
Summary of changes
The current low-level STM32 SPI API implementation (file
stm_spi_api.c
) doesn't processes SPI frames in 16 bit modecorrectly. If we need to sent 2 bytes
0x11 0x22
in 16 bit mode, SPI device sends 4 bytes (extra0x00
byte is addedbefore each one)
0x00 0x11 0x00 0x22
. This pull request fixes this behaviour to send correct data:0x22 0x11
issue: #15113
related pull request: #15115
Impact of changes
Fix data frame format of SPI in 16 bit mode for all STM32 devices.
Migration actions required
Documentation
Pull request type
Test results
SPI monitoring with logic analyzer
This demo program simply writes bytes to SPI device with loopback (MISO is connected to MOSI). It allows checking SPI
frames with logic analyzer.
Results of
const uint16_t tx_data_16[2] = {0x1122, 0x3344};
data transmission without fixes:3-wire mode, synchronous transmission
3-wire mode, asynchronous transmission:
4-wire mode, synchronous transmission:
4-wire mode, asynchronous transmission:
full results. Console logs: no_fix_serial_logs.txt, logical analyzer data (sigrok format): no_fix_data.zip
Although we transmit the same data, synchronous and asynchronous SPI API give different results (asynchronous API
transmits data correctly).
Results of
const uint16_t tx_data_16[2] = {0x1122, 0x3344};
data transmission after fixes:3-wire mode, synchronous transmission:
3-wire mode, asynchronous transmission:
4-wire mode, synchronous transmission:
4-wire mode, asynchronous transmission:
full results. Console logs: with_fix_serial_logs.txt, logical analyzer data (sigrok
format): with_fix_data.zip
All SPI APIs give the same result after fix.
SPI test with sensor BMX160 (3 wire SPI mode)
This demo writes data to BMX160 sensor, reads them back and compares sent and received bytes. Additionally, it controls
number of SPI clock cycles with STM32 timer ETR feature.
After data sending/receiving with different SPI modes (8/16 bit) and frequencies it prints summary table with test
results.
Results:
full logs: main_3wire_stm32f103c8_logs.txt
full logs: main_3wire_stm32f411ce_logs.txt
full logs: main_3wire_stm32h743vi_logs.txt
Result notes:
<single|burst>_w<8|16>_r<8|16>
that means:single
- test sends single SPI data frame to BMX160 and then receives single SPI data frameburst
- test sends multiple SPI data frames to BMX160 and then receives multiple SPI data framesw<8|16>
- test sends SPI data frames in 8/16 bit moder<8|16>
- test receives SPI data frames in 8/16 bit modedoesn't implement correct data reading with interrupts (it doesn't disable SPI in time, that causes dummy reads).
SPI loopback test (4 wire SPI mode)
This demo sends and receives data with SPI loopback. After data transmission it checks that sent and received data is
the same. Additionally, it controls number of SPI clock cycles with STM32 timer ETR feature.
After data sending/receiving with different SPI modes (8/16 bit) and frequencies it prints summary table with test
results.
Results:
full logs: main_4wire_stm32f103c8_logs.txt
full logs: main_4wire_stm32f411ce_logs.txt
full logs: main_4wire_stm32h743vi_logs.txt
Reviewers