Working with the SPI peripheral on the STM32F411VET6, we need to connect to a device that sadly requires the CS line to toggle with every byte sent. Just about every example code runs along the logic of "write to the SPI data register and wait for TXE or BSY to change status". Here's one such from hackaday dot com :
In order to send bytes to a slave we thus follow this sequence after pulling the target’s SS line low:
Wait for SPI_SR_TXE (status register: transmit register empty) to become true.
Write data (8-16 bits) into SPI_DR. Repeat from (1) if more data has to be written.
Wait for SPI_SR_TXE to become true again.
Wait for SPI_SR_BSY (status register: bus busy) to become false.
So the problem we're having is that after a write to the data register is done and a looping check made on either TXE or BSY, the chip select line is getting toggled before the 8th clock pulse happens (in the case of checking TXE, it toggles status on the 4th clock pulse, for BSY, it toggles on the 3rd clock pulse). I will note that the RM0383 manual for this processor says "Do not use the BSY flag to handle each data transmission or reception. It is better to use the TXE and RXNE flags instead", so I suppose it's expected that bit doesn't operate as we thought it would, but why does the TXE bit toggle status before the data register's byte has even finished clocking out? We had to work around this issue by doing a countdown for-loop but it seems like this shouldn't be necessary.
> why does the TXE bit toggle status before the data register's byte has even finished clocking out?
When you write a byte, it's immediately moved to the shift register. Once that happens, TXE is asserted again. This is covered in the reference manual.
For SPI, in 4 wire mode, you can wait for RXNE to get asserted to indicate the end of the transaction, as that is populated when the byte coming in is complete. You can also use BSY. The reference manual gives instructions for this.