-
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
STM32F4 SPI 3-wire mode doesn't work correctly #14774
Comments
@ARMmbed/team-st-mcd Please review |
Hi, sorry for slow answer. The 3 wires support has been added and tested with ST sensor below: Discussing with the team who wrote this sensor driver, it seems you're using SPI3W to interface the Bosch Sensortec sensor which, maybe, differs from our ST sensors on SPI3W behavior. Maybe the SPI3W protocol can be slightly different from vendor to vendor. In our case, if sensor team remembers well, the component, before returning the data, sends back the register address. Could that make a difference ? Also a quick look at the datasheet mentions: For single byte read as well as write operations, 16-bit protocols are used. Not sure if that would solve the issue but my point is that I wonder if this may be due to protocol difference ? |
Hi
3-Wire SPI must be same across all vendors like 4-Wire SPI, although high-level device protocols
No, 16-bit protocol means that you send byte with register address and then read or write register value. For write operations it includes sending of 2 bytes. extra issue investigationI got an oscilloscope and captured SPI frames with sigrock to get extra clarification about this issue. Test programs:
UART output:
Logical analyzer data: Summary table:
ResultsAfter investigation of:
I got the following results: According documentation in "Bidirectional receive procedure" SPI starts generating clock signal continuously after SPI enabling
(see Whereas the code of So correct implementation of the
SummaryCurrent STM 3-Wire SPI hardware implementation doesn't provide reliable way to read bytes without dummy reads (or at least I don't find such approaches). So I think that it's better to drop support 3-Wire SPI from MbedOS as it has buggy implementation, or at least add some warning and cautions to documentation/code that STM 3-Wire SPI isn't able to read data reliable. @LMESTM What do you think about it? |
@vznncv thanks a lot for this detailed analysis and explanation. |
One more point: does that mean that your issue may be "solved" (worked-around) by requesting a slow SPI frequency ? |
@vznncv your analysis has been confirmed. The use case is actually document in the driver code here: It means that if we want to work-around this issue in the mbed-os code, we need to add calls to probably here: https://github.com/ARMmbed/mbed-os/blob/master/targets/TARGET_STM/stm_spi_api.c#L786 Would you mind giving it a try ? |
I have modified example to demonstrate burst read, as I noted that it's less stable:
Yes, it helps. Demo uart output: demo_200KHz_uart_output.txt But this solution has the following problems:
I checked it. It doesn't help. Demo uart output: hal_reinit_uart_output.txt Extra investigation and workaroundAfter some experiments I found that timing between last byte receiving and SPI disabling is crucial. According
and it should be too high (otherwise next byte receiving is started). So the following data receiving approach should work:
The code that implements such approach (I have added it to
Such modification works correctly. Demo uart output: fix_1Mhz_uart_output.txt It even works with higher SPI frequency (12.5 Mhz): fix_12_5Mhz_uart_output.txt (My oscilloscope cannot capture data at this frequency with sigrok, but according program output, data is received correctly)
What do you think about such approach? |
Hi @vznncv Thanks for sharing a proposed solution. Have you tested your proposed approach with a various number of read length ? Of course one major concern is how we will be able to test this proposal, as we don't have 3 WIRES SPI devices in our automated regression test setup :-( |
Hi @LMESTM
Yes I have tested it with 3 bytes reading (timestamp value from BMX160) and with 1 bytes reading (ordinary configuration registers).
I'll prepare a pull request in 1-2 weeks (currently I'm busy). I'll try to implement generic STM family approach.
How do you test ordinary (4 WIRES) SPI interface? (Do you use some sensor or something else?) |
In ST, we have 2 setup: |
@vznncv thanks for your efforts, that really makes sense to allow everyone to benefit from the good work you've done. |
|
Description of defect
Method
int SPI::write(const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length)
doesn't work correctly with SPI 3-wire mode.Actual behavior:
First byte of the
rx_buffer
afterint SPI::write(const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length)
method invocation contains last byte of the previous transaction, when SPI is configured in the 3-wire mode. Actual bytes are shifted to next positions. The last byte are "moved" to the next read transaction.Expected behavior:
rx_buffer
contains bytes only from current transaction.Target(s) affected by this defect ?
STM32F411CEU6 (custom board https://github.com/vznncv/TARGET_BLACKPILL_F411CE)
(probably all STM32F4 boards)
Toolchain(s) (name and version) displaying this defect ?
arm-none-eabi-gcc (GNU Arm Embedded Toolchain 9-2020-q2-update) 9.3.1 20200408 (release)
What version of Mbed-os are you using (tag or sha) ?
mbed-os-6.11.0
What version(s) of tools are you using. List all that apply (E.g. mbed-cli)
mbed-cli v1.10.5
How is this defect reproduced ?
Example of BMX160 sensor usage in 3-wire mode with STM32F411CEU6:
Output (first read register attempt returns incorrect value):
Example of BMX160 sensor usage in 3-wire mode with STM32F411CEU6 with explicit RX buffer cleanup of SPI2 that fixes problem:
Output (all register values are corrected):
The text was updated successfully, but these errors were encountered: