(F4) Hardware SPI not driving SSEL pin correctly since v2.7.0 (affects STM32F4xx and others) #2834
Unanswered
danieltr3s
asked this question in
Q&A
Replies: 1 comment
-
|
Hi @danieltr3s
And well described also here: About pre-2.7.0, in fact as the SPI always init, then the SPI was disabled, init then enabled producinf change on the SSEL pin. I've modified the Arduino SD library to be able to use the hardware NSS and tested with card info example and it works, using Hardware SS or not. I saw the signal is kept LOW but is is not an issue.
|
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment



Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Since release 2.7.0, the SPI library no longer properly drives the SSEL (NSS) pin when using hardware SPI. This affects at least the STM32F4xx variants, and possibly others.
When defining a new SPIClass instance with AF MOSI/MISO/SCLK/SSEL pins, or when calling SPI.setSSEL(AF_PIN), the SPI peripheral does not drive the SSEL pin as expected. This forces users to manually control the SSEL pin in software, which breaks compatibility with many libraries that rely on hardware-controlled chip select.
(see MPU9250_WE by Wolfgang Ewald as an example, but nearly all libs, that use SPI, resort to software driven SSEL pin).
This issue persists up to v2.11.0.
My setup consists on using SPI2 with alternate function pins:
1- Use SPI2 (or other SPI peripheral) with alternate function pin mapping such as:
2- Instantiate SPI with these pins:
SPIClass SPI_2(PB_15, PB_14, PB_13, PB_12); SPI_2.begin();Attempt to communicate with a peripheral (e.g. MPU6500) using hardware-controlled SSEL.
SPI_2.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE3)); SPI_2.transfer(data); SPI_2.endTransaction();Observe that the SSEL pin is not driven by hardware, causing SPI communication to fail unless SSEL is handled manually via GPIO.
Root Cause Analysis
The issue was introduced in 2.7.0, where SPIClass::beginTransaction() stopped calling spi_init() unconditionally.
The intention was to avoid reinitializing the SPI peripheral if settings hadn’t changed. However, at the end of each transaction the SPI peripheral is internally reset to default values (including NSS configuration), which the _spiSettings struct does not reflect.
As a result, subsequent transactions run with an uninitialized peripheral.
Proposed Fix
Always call spi_init() on beginTransaction().
In SPI.cpp, move the spi_init() call outside the if scope:
void SPIClass::beginTransaction(SPISettings settings) { if (_spiSettings != settings) { _spiSettings = settings; +++ } spi_init(&_spi, _spiSettings.clockFreq, _spiSettings.dataMode, _spiSettings.bitOrder); --- } }This restores pre-2.7.0 behavior and fixes SSEL handling for all transactions.
Beta Was this translation helpful? Give feedback.
All reactions