Skip to content
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

Merged
merged 4 commits into from
Nov 24, 2023
Merged

Conversation

maribu
Copy link
Member

@maribu maribu commented Nov 14, 2023

Contribution description

This PR contains two cleanup commits and one bug fix commit for the STM32 implementation of the periph_spi driver:

  • The /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)
  • A custom 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 layout
  • The hardware /CS handling has been fixed. Before, disabling the /CS signal has been done by disabling the hole SPI peripheral rather than just the /CS signal, resulting in e.g. the STM32F3 SPI peripheral to no longer honer the SPI clock polarity.
  • The code to find the SPI clock divided has been made less magic and much shorter
  • An assert() 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 of spi_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

  • The test in tests/periph/selftest_shield now passes on STM32F3 boards (tested with nucleo-f303re)
  • SPI still works with hardware /CS instead of GPIO /CS handling (tested with nucleo-f303re and a logic analyzer connected to the SPI pins and hte hardware /CS pin)
  • SPI with DMA still works (tested with the nucleo-f446re and the selftesting app)
  • A logic analyzer connected to the SPI bus should confirm that clock polarity between two transactions (tested with the nucleo-f303re)
  • I think that drivers/sdcard_spi won't work on STM32F3 in master, but should now with this PR. I haven't tested this for either branch, though

Issues/PRs references

#20071

@maribu maribu added the State: WIP State: The PR is still work-in-progress and its code is not in its final presentable form yet label Nov 14, 2023
@github-actions github-actions bot added Platform: ARM Platform: This PR/issue effects ARM-based platforms Area: cpu Area: CPU/MCU ports labels Nov 14, 2023
@maribu
Copy link
Member Author

maribu commented Nov 14, 2023

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.

@maribu
Copy link
Member Author

maribu commented Nov 14, 2023

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.

@github-actions github-actions bot added the Area: tests Area: tests and testing framework label Nov 15, 2023
@github-actions github-actions bot removed the Area: tests Area: tests and testing framework label Nov 15, 2023
@maribu
Copy link
Member Author

maribu commented Nov 16, 2023

Adding FEATURES_OPTION += periph_dma to the peripheral selftesting app resulted in DMA being used on the Nucleo-F446RE and the test still succeeded.

So both hardware /CS handling and DMA still work :)

@maribu maribu added Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors) Type: cleanup The issue proposes a clean-up / The PR cleans-up parts of the codebase / documentation CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR and removed State: WIP State: The PR is still work-in-progress and its code is not in its final presentable form yet labels Nov 16, 2023
@riot-ci
Copy link

riot-ci commented Nov 16, 2023

Murdock results

✔️ PASSED

f4729c2 cpu/stm32/periph_spi: improve prescaler calculation

Success Failures Total Runtime
7957 0 7957 10m:02s

Artifacts

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.
cpu/stm32/periph/spi.c Outdated Show resolved Hide resolved
@maribu maribu force-pushed the stm32_spi branch 2 times, most recently from 774bdd5 to 86394c4 Compare November 23, 2023 12:14
@maribu maribu force-pushed the stm32_spi branch 2 times, most recently from 2fc1fdc to 4f475e2 Compare November 23, 2023 12:55
Copy link
Contributor

@kfessel kfessel left a 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

@maribu maribu added this pull request to the merge queue Nov 23, 2023
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Nov 23, 2023
@kfessel
Copy link
Contributor

kfessel commented Nov 23, 2023

https://ci.riot-os.org/details/3fbdeae7e0d249b381a652ebd5bf9a3d << some mcu does not provide the spi mode macros

@maribu
Copy link
Member Author

maribu commented Nov 24, 2023

Indeed. It affects STM32 families with no SPI support yet. I prepared the spi_mode_t now to also be useful for them, but adding the SPI driver will be something that needs its own PR.

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).
@maribu
Copy link
Member Author

maribu commented Nov 24, 2023

https:/RIOT-OS/RIOT/compare/4f475e2ade954e007249e4bc2665542931317b4d..f4729c28ec0f9ea77bfaf4d4b1a56ad0d48fd72d is the diff combining the two force-pushes. The second one fixes a typo in a comment

@maribu maribu added this pull request to the merge queue Nov 24, 2023
Merged via the queue into RIOT-OS:master with commit 6ae0b4d Nov 24, 2023
25 checks passed
@maribu maribu deleted the stm32_spi branch November 24, 2023 10:55
@maribu
Copy link
Member Author

maribu commented Nov 24, 2023

Thx :-)

@MrKevinWeiss MrKevinWeiss added this to the Release 2024.01 milestone Feb 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: cpu Area: CPU/MCU ports CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Platform: ARM Platform: This PR/issue effects ARM-based platforms Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors) Type: cleanup The issue proposes a clean-up / The PR cleans-up parts of the codebase / documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants