This sketch illustrates a failure of SPI.transfer with a NUCLEO-H743ZI2. The sketch use a SCLK rate of 400kHz.
#include "SPI.h"
const uint8_t CS_PIN = 10;
void setup() {
SPI.begin();
pinMode(CS_PIN, OUTPUT);
}
void loop() {
SPI.beginTransaction(SPISettings(400000, MSBFIRST, SPI_MODE0));
digitalWrite(CS_PIN, LOW);
SPI.transfer(0x55);
digitalWrite(CS_PIN, HIGH);
SPI.endTransaction();
delay(1);
}
The problem is shown in this trace of SCLK in yellow and MOSI in green. The eighth clock pulse and data are chopped.

I looked at the SPI library code and found where the problem occurs, SPI is disabled before the last bit is complete.
The file is: STM32/hardware/stm32/1.9.0/libraries/SPI/src/utility/spi_com.c
If you add a delay here at about line 443:
#if defined(STM32H7xx) || defined(STM32MP1xx)
/* Close transfer */
/* Clear flags */
HAL_Delay(1); // <<-------------- added by WHG to delay call LL_SPI_Disable()
LL_SPI_ClearFlag_EOT(_SPI);
LL_SPI_ClearFlag_TXTF(_SPI);
/* Disable SPI peripheral */
LL_SPI_Disable(_SPI);
#endif
The SPI frame is correct.

I tried to find a SPI status check to replace the delay but was not successful when I looked at the STM32H743/753 Reference Manual.
I looked at all the SPI signals with a logic analyzer and got a message about incorrect clock polarity.
I suspect that the SPI peripheral can not be disabled at the end of transfer() since this will cause a polarity problem for some SPI modes and glitches in the signals. Seems like the peripheral must be enabled from beginTransaction() to endTransaction().
See line 306 of STM32/hardware/stm32/1.9.0/libraries/SPI/src/utility/spi_com.c
/* In order to set correctly the SPI polarity we need to enable the peripheral */
__HAL_SPI_ENABLE(handle);
Hi @greiman,
Thanks for reporting this issue.
I am able to reproduce this issue.
But I didn't yet find the right way to fix it.
... ongoing ...
I have similar problem on blackpill stm32f401cc, the NSS pin was pulled high before spi transmission ends (SCLK=656K)


my fix is simple, wait untill spi transmission ends.
modify spi_com.c
#if defined(STM32H7xx) || defined(STM32MP1xx)
while(!LL_SPI_IsActiveFlag_EOT(_SPI)); // <------ fix for stm32H7 etc.
#else
while(LL_SPI_IsActiveFlag_BSY(_SPI)); // <------ fix for stm32f1/f2/f3/f4 etc.
#endif
#if defined(STM32H7xx) || defined(STM32MP1xx)
/* Close transfer */
/* Clear flags */
LL_SPI_ClearFlag_EOT(_SPI);
LL_SPI_ClearFlag_TXTF(_SPI);
/* Disable SPI peripheral */
LL_SPI_Disable(_SPI);
#endif
return ret;
}
now it works properly

Hi @mzhboy,
Thank you for sharing your experiment.
I already tried to wait on EOT (for stm32H743) but it doesn't help on the original issue (Clock and Data truncated).
I raised this issue to our SPI experts, and I am waiting their feedback.
By the way, I also tested on STM32MP1, I reproduce this original issue, and waiting on EOT also doesn't help.
Did you try your fix on STM32H7 ?
Concerning STM32F4, I tested on NUCLEO_F429ZI (the only F4 board I have), and I could not reproduce the original issue (Clock and Data truncated). And on your screenshot, I don't see such such behavior.
So I seems you face a different issue with NSS. And your patch seems valid to me at least for other boards than MP1 and H7.
I submitted a PR for that : https://github.com/stm32duino/Arduino_Core_STM32/pull/1312
I don't have H7 board that fix for H7 is just based on reference manual.
I have tested the fix for F4. I have F0/F1/F3/F4/G4 boards but I don't have time to test it(need rewiring).
my issue was happening only when SPI setting was SPI_TRANSMITONLY, SPI_TRANSMITRECEIVE had no problem.
check out spi_com.c
if (!skipReceive) {
#if defined(STM32H7xx) || defined(STM32MP1xx)
while (!LL_SPI_IsActiveFlag_RXP(_SPI));
#else
while (!LL_SPI_IsActiveFlag_RXNE(_SPI));
#endif
*rx_buffer++ = LL_SPI_ReceiveData8(_SPI);
}
if ((Timeout != HAL_MAX_DELAY) && (HAL_GetTick() - tickstart >= Timeout)) {
ret = SPI_TIMEOUT;
break;
}
}
while (!LL_SPI_IsActiveFlag_RXNE(_SPI)); means wait until last bit shift out or shift in, that's equivalent wait until BSY=0.