cancel
Showing results for 
Search instead for 
Did you mean: 

SPI MOSI idle state quirk - sometimes high, sometimes low

gregstm
Senior III

I'm DMAing a buffer to the SPI transmitter, and require the idle state of the MOSI line to be low while the next buffer is waiting for its queue to be sent.

After some limited testing (STM32L433) I have found that the idle state of the line depends on the LSBit of the second to last word sent in the buffer. If that bit is low, the idle state is low, etc.

I'm assuming there is no way to ensure that the line stays low without sending two 0's at the end of the buffer (but if there is, please let me know)

7 REPLIES 7

IMO it's the last bit transmitted.

>I'm assuming there is no way to ensure that the line stays low

Why would that be so? It's your software which determines how does the hardware behave. Just switch the pin to GPIO output between transmissions.

JW

berendi
Principal

You can switch the pin to output in GPIO->MODER at the end of the transmission. The tricky part is to time it properly.

When exactly does it have to go low? Do you have a timing diagram? Who is controlling NSS?

If the timing requirements are tight, it would require a couple of DMA channels and maybe some external connections.

gregstm
Senior III

Thanks for the replies/suggestions -

"IMO it's the last bit transmitted" - if that was the case I would be happy. I zeroed the buffer and stepped a single "1" through the bit positions. The high idle state only occurred 32 bits in from the end (16 bit SPI word size). When I tried an 8 bit word size the high state occurred 16 bits from the end.

"The tricky part is to time it properly" - yes, this is a very time critical piece of code, there are very few clock cycles between the end of the DMA and the start of the new DMA (triggered by a timer edge).

However, I think I have found a solution to this problem and will try it out (I will move to Timer 2 so that I can use an extra channel to trigger the DMA a bit later to give me enough time to send a couple of zero words at the end of the buffer).

Anyway, I thought I would mention this issue just in case others are familiar with it - if not, others (and perhaps even ST) might find it interesting/relevant.

ADunc.1
Senior

I can confirm that the behavior the OP mentioned is indeed what happens in practice. In my case the idle state of MOSI is determined by the MSB of the second to last byte transmitted. It may depend if you are running in MSB or LSB first as to whether the the MSB or LSB of the second to last byte controls the MOSI idle state.

I would have argued that the idle state should have been that of the last bit sent. Or that it should be the level of the first bit of the last byte (as that is technically the next bit to be transmitted if the clock was to start again without writing to the data register).

Tested on STM32H753, SPI1, 8 bit data, MSB mode. Tested all clock phase and polarity settings. This is just an odd hardware quirk. Annoying that you need to send an extra byte but not the end of the world. It is rare that the idle state of MODI actually matters anyway.

Yes an interesting oddity revealing the internals of the SPI, but with no practical consequence except some rare exotic nonstandard cases.

JW

gregstm
Senior III

"...with no practical consequence except some rare exotic nonstandard cases." - in case anyone is curious, I was trying to produce a VGA signal using the SPI so I could display it on largish TV (using a VGA to HDMI converter) - more info via the link below: https://community.st.com/s/question/0D53W00000DI2uXSAT/full-screen-vga-display-on-hd-tv-using-stm32l4-it-is-possible-sort-of

ADunc.1
Senior

"...with no practical consequence except some rare exotic nonstandard cases." - I was using SPI to drive a string of digital LEDs. Not a standard use for SPI, but a legitimate use of a peripheral designed to clock out 1's and 0's none the less.