Skip to content

Fix TMC6200 driver: spi->end() should be spi->endTransaction()#99

Open
94xhn wants to merge 1 commit into
simplefoc:devfrom
94xhn:fix/tmc6200-spi-endtransaction
Open

Fix TMC6200 driver: spi->end() should be spi->endTransaction()#99
94xhn wants to merge 1 commit into
simplefoc:devfrom
94xhn:fix/tmc6200-spi-endtransaction

Conversation

@94xhn

@94xhn 94xhn commented Jul 20, 2026

Copy link
Copy Markdown

Both readRegister() and writeRegister() in TMC6200.cpp pair spi->beginTransaction(settings) with spi->end() instead of spi->endTransaction(). end() fully de-initializes the SPI peripheral (on the STM32 core it calls spi_deinit()), while endTransaction() is just supposed to release the transaction lock so the bus can be shared. Every other driver in this repo (drv8316, drv832x, drv8376) gets this right and uses endTransaction().

On the STM32 Arduino core this is worse than "just needs a fresh begin() before the bus is used again": SPIClass::beginTransaction() only re-initializes the hardware when the SPISettings passed in differ from the ones cached from the previous call. TMC6200Driver reuses the same settings member for every call, so as soon as readRegister() tears the peripheral down with end(), the very next beginTransaction() (e.g. the write half of the read-modify-write in setDriverState()) sees identical settings and silently skips re-init, and the write goes out over a de-initialized peripheral with no error raised.

I confirmed this by pulling the actual SPIClass::configSpi/begin/beginTransaction/end/endTransaction implementation from Arduino_Core_STM32 and reproducing the exact call sequence (readRegister() then writeRegister(), as setDriverState() does) in a small standalone harness outside the Arduino toolchain - the peripheral ends up de-initialized after the very first register write following a read.

This was reported in #66 back in October, and the maintainer agreed with the fix ("I will fix it for the next release") but it looks like it never got applied. It's a straight two-line swap, no behavior change intended anywhere else.

readRegister() and writeRegister() both pair spi->beginTransaction()
with spi->end() instead of spi->endTransaction(). end() tears down
the whole SPI peripheral (spi_deinit on STM32), while endTransaction()
just releases the transaction lock. Every other driver in this repo
(drv8316, drv832x, drv8376) correctly uses endTransaction() here.

On the STM32 Arduino core the effect is worse than just needing a
fresh begin() before reusing the bus: SPIClass::beginTransaction()
skips re-initializing the hardware whenever the SPISettings object is
unchanged from the last call, so the very next TMC6200 register access
(e.g. the read-modify-write in setDriverState()) ends up transferring
over a peripheral that was just de-initialized by the previous call's
end(), with no error raised. Confirmed this by tracing the actual
Arduino_Core_STM32 SPI.cpp logic and reproducing the sequence in a
small standalone harness.

Reported in simplefoc#66, maintainer agreed with the fix but it was never
applied.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant