[riot-notifications] [RIOT-OS/RIOT] STM32: SPI clock not returning to idle state and generating additional clock cycles (#11104)

MichelRottleuthner notifications at github.com
Tue Mar 5 11:47:15 CET 2019


<!--
====================================
IF YOUR ISSUE IS RELATED TO SECURITY
====================================
please submit it to the security mailing-list security at riot-os.org.

If your issue is a question related to the usage of RIOT, please submit it to
the user mailing-list users at riot-os.org or to the developer mailing-list
devel at riot-os.org.
-->

#### Description
<!--
Example: Cannot build gnrc_networking application for samr21-xpro board.
-->
This issue is meant to keep track of the problems discovered when testing #7354. For more details see comments there.
On some stm32 platforms the RIOT SPI driver generates faulty output on the SPI pins.
For now the problem could be reproduced on the following boards: nucleo-f446ze, nucleo-l073rz and nucleo-l476rg (no other STM32 were tested until now).

#### Steps to reproduce the issue
<!--
Try to describe as precisely as possible here the steps required to reproduce
the issue. Here you can also describe your hardware configuration, the network
setup, etc.
-->
Connect a logic analyzer to your spi pins, use tests/periph_spi and try the following cases:
1)`init 0 0 0 3 14`
clock state is NOT reset to zero properly after transmission.

2)`init 0 0 1 3 14`
clock state is NOT reset to zero properly after transmission.

3)`init 0 0 2 3 14`
clock state is NOT reset to zero properly after transmission.

4)`init 0 0 3 3 14`
clock state is reset to zero properly after transmission.

5)`init 0 0 4 3 14`
clock state is reset to zero properly after transmission.

#### Expected results
<!--
Example: The gnrc_networking application builds on samr21-xpro.
-->
No additional clock cycles before/after sending data, clock returns to idle state after transmission.

#### Actual results
<!--
Please paste or specifically describe the actual output.
-->
A) not returning to zero, using config (1) from above:
![spi_0](https://user-images.githubusercontent.com/20105554/28158232-5c8791f8-67b9-11e7-8c17-c967b90baf77.PNG)
B) returning to zero, using config (5) from above:
![spi_4](https://user-images.githubusercontent.com/20105554/28158450-0a76a52e-67ba-11e7-8bb1-51dc49fc50a0.PNG)

C) If you start another transmission after (A), you get this:
![spi_0_1](https://user-images.githubusercontent.com/20105554/28158238-61c30ac6-67b9-11e7-9570-3ce3b1415bd1.PNG)

copied from [#7354(comment)](https://github.com/RIOT-OS/RIOT/pull/7354#issuecomment-397653106):
>The root cause of this seems to be that the driver is disabling the SPI peripheral to early after the last bit was clocked out, after the transmission in [spi_transfer_bytes](https://github.com/RIOT-OS/RIOT/blob/1e3360e1bf5fd466b4076f1cd7d2512d8d6a4360/cpu/stm32_common/periph/spi.c#L273). If you insert a small timeout of ~half an SPI-clock period before the disable command, you won't see the faulty behaviour. As this hapens only with slow SPI-clock settings (clk setting <=1 in spi periph test) I assume it's some kind of race condition based on internal clock-synchronisation problems where the hardware doesn't reach the point where it switches the clock back to idle before the peripheral is disabled by the riot driver. I double checked that the driver uses the correct procedure for turning off SPI (waiting for TXE, BSY etc.) and I can't find a problem there.
Possible workarounds I identified so far: 
>1) don't disable SPI -> solves A and C, possibly bad for low power and/or shared peripheral usage 
>2) change the SPI prescalers to not support the slow clock speeds on affected MCUs -> avoids A and C but decreases functionality
>3) move setting the MSTR bit from [spi_acquire](https://github.com/RIOT-OS/RIOT/blob/1e3360e1bf5fd466b4076f1cd7d2512d8d6a4360/cpu/stm32_common/periph/spi.c#L131) to [spi_transfer_bytes](https://github.com/RIOT-OS/RIOT/blob/1e3360e1bf5fd466b4076f1cd7d2512d8d6a4360/cpu/stm32_common/periph/spi.c#L254) -> solves only C, but with no additional clock cycles it is at least ensured to not transmit borked data. Leaving the clock on the active level might not be a good thing though.
>4) poll clock gpio till returnig to idle level before [disabling SPI](https://github.com/RIOT-OS/RIOT/blob/1e3360e1bf5fd466b4076f1cd7d2512d8d6a4360/cpu/stm32_common/periph/spi.c#L254) -> solves A and C - but a bit hacky

#### Versions
<!--
Operating system: Mac OSX, Linux, Vagrant VM
Build environment: GCC, CLang versions (you can run the following command from
the RIOT base directory: ./dist/tools/ci/print_toolchain_versions.sh).
-->
The last version this was reproduced with is [3c9eb94](https://github.com/RIOT-OS/RIOT/commit/3c9eb940d52fd074d210eabdc267f89cfd16fd54) (between 2018.04 and 2018.07). Needs to be confirmed with current master again.
<!-- Thanks for contributing! -->


-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/RIOT-OS/RIOT/issues/11104
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.riot-os.org/pipermail/notifications/attachments/20190305/fca906bd/attachment.html>


More information about the notifications mailing list