-
Notifications
You must be signed in to change notification settings - Fork 2k
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
cpu/stm32/periph_spi: Fix /CS handling #20084
Conversation
I should check if hardware /CS handling still works correctly, before this get's merged 😅 And may also whether this causes regressions in regard to DMA + SPI. |
OK, hardware CS handling seems to just work, it is a pain to test with the self-testing shield as the Nucleo-64 don't have the hardware CS pin routed to Arduino pin D10. |
Adding So both hardware /CS handling and DMA still work :) |
The CR2 register was only written to if the settings differ from the reset value. This wasn't actually a bug, since it was cleared in `spi_release()` to the reset value again. Still, it looks like a bug, may cause a pipeline flush due to the branch, and increased `.text` size. So let's get rid of this.
774bdd5
to
86394c4
Compare
2fc1fdc
to
4f475e2
Compare
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.
looks good
confirmed is tested by @maribu using the selftest_shield test
https://ci.riot-os.org/details/3fbdeae7e0d249b381a652ebd5bf9a3d << some mcu does not provide the spi mode macros |
Indeed. It affects STM32 families with no SPI support yet. I prepared the |
This doesn't change the firmware, since for all STM32 MCUs with an SPI driver the register setting in the mode did match the SPI mode number by chance. But for some STM32 MCUs with no SPI driver yet the register layout is indeed different. This will help to provide an SPI driver for them as well.
Previously, the /CS signal was performed by enabling / disabling the SPI peripheral. This had the disadvantage that clock polarity settings where not applied starting with `spi_acquire()`, as assumed by e.g. the SPI SD card driver, but only just before transmitting data. Now the SPI peripheral is enabled on `spi_acquire()` and only disabled when calling `spi_release()`, and the `SPI_CR2_SSOE` bit in the `CR2` register is used for hardware /CS handling (as supposed to).
With only 8 possible prescalers, we can just loop over the values and shift the clock. In addition to being much easier to read, using shifts over divisions can be a lot faster on CPUs without hardware division. In addition an `assert()` is added that checks if the API contract regarding the SPI frequency is honored. If the requested clock is too low to be generated, we should rather have a blown assertion than hard to trace communication errors. Finally, the term prescaler is used instead of divider, as divider may imply that the frequency is divided by the given value n, but in fact is divided by 2^(n+1).
https://github.com/RIOT-OS/RIOT/compare/4f475e2ade954e007249e4bc2665542931317b4d..f4729c28ec0f9ea77bfaf4d4b1a56ad0d48fd72d is the diff combining the two force-pushes. The second one fixes a typo in a comment |
Thx :-) |
Contribution description
This PR contains two cleanup commits and one bug fix commit for the STM32 implementation of the
periph_spi
driver:/CS
settings are always applied, not when changed to from the default. (Improves readability, reduces ROM size, avoids a potential CPU pipeline flush due to one branch instruction less)spi_clk_t
is provided, since the enumeration values are used as-is to write to the hardware register. The default constant values do happen to match the new values, but now it doesn't look like an accident anymore and is more robust in regard to changing register layoutassert()
was added to ensure that the clock divider indeed manages to divide the clock down as requested. Some STM32 boards cannot reach 100 kHz (350 kHz is the lowest e.g. the Nucleo-F446RE can get). In the most common cases the caller ofspi_acquire()
will request the highest SPI frequency still supported by the hardware, so ignoring this and using a higher clock is not acceptable.Testing procedure
tests/periph/selftest_shield
now passes on STM32F3 boards (tested withnucleo-f303re
)nucleo-f303re
and a logic analyzer connected to the SPI pins and hte hardware /CS pin)nucleo-f446re
and the selftesting app)nucleo-f303re
)drivers/sdcard_spi
won't work on STM32F3 inmaster
, but should now with this PR. I haven't tested this for either branch, thoughIssues/PRs references
#20071