How does SPI work internally?

This is moved from the I2C thread, which is not the subject.

it does 32 bit internally.
10 bytes => write 3 times (4 bytes + 4 bytes + 2 bytes)

@Dat_Tran : Interesting…

Could you please detail how this is handled under the hood, please ?
What if I send 1 byte, 2 bytes or 3 bytes ?
Are they padded to Int32 size ?
How are you splitting the data sent ?
Are you really sending Int32 on the bus ? If yes, what would be the issue with allowing the API to send shorts ?

1 byte => 1 time 1 byte
2 byte => 1 time 2 byte
3 byte => 2 time (2 bytes + 1 bytes)
4 bytes => 1 time 4 bytes
5 bytes => 2 time (4 bytes + 1 bytes)
10 bytes => 3 time (4 + 4 + 2)

Are you really sending Int32 on the bus ?

Depend on the size as above.

1 Like

I have answered this multiple times. You do not trust me do you? :grin: Yes we do and you never have to worry about updating display speed because the speed is as fast as it can be. Can we put this to rest or you will come back in a week and ask one more time? :grin:

1 Like

let change place of words of title
internally does work how spi :rofl: :rofl: :rofl:

1 Like


Speed is not the only concern, as you may remember. I was also talking about 16bit data coming from (or being sent to) a device.
For the clarity of my purpose below, I will only talk about “sending data” (and a short), but the reasoning is the same when receiving data and integers.

Many sensors or devices can accept (or even request, sometimes) data in 10/12/14/16 bit format. Padding needed for 10/12/14 bit, of course.

Sending a short or an int as a serie of consecutive bytes is not the same as really sending a short or an int. In the first case, I have to deal myself with endianness, while in the other case it’s the firmware that does it when it receives a short to send to a device.

But so far, you don’t talk about endianness so what are you assuming when I send { 0x10, 0x20 } ?

  • Am I sending two bytes ? (Perhaps a register and its value)
  • Am I sending a short because the underlying data is 10 or 12 bit long ? And in this case, am I sending 0x1020 (4128) or 0x2010 (8208) ?

The MCU has endianness registers for the SPI transfers (and frame format as well). And they are taken into account when you send something different than multiple/consecutive bytes.

Had you said you were only sending consecutive bytes, I would not have even replied because it would have meant that I had to deal myself with endianness and do not bother with data size.
But you said that you were sending bigger data at once, which is not the same.

So yes, I may come back later again on the subject, as it is not as simple as you seem to believe…
Or I may give up at some time as well.

And I will even have other questions regarding SPI, related to (real) clock frequencies. But since I’m currently testing our drivers on the dev board, it’s not time yet. You lucky :wink:

Let’s leave this at we only support bytes on SPI bus. Right now, there is no SPI device we can think of that can’t be used with TinyCLR OS. If you find such incompatible device, please bring it up so we can study the need further. After all, TinyCLR is made for you all. We are here just to make it happen.

Back to work on more serious features, like supporting external flash without compromising security… Coming this month. By the way, this one was not easy at all.


May I come back on this again ?

As you may have noticed, I’m currently wotking on the ILI9341 display. This one needs swapping endianness.
This can indeed be handled by the BitConverter.SwapEndianness() method but since this call has to be done before sending the data to the display, it implies that the whole screen has to be cleared and completely drawn again at each frame, even for a small change.
Or, as you are doing in your ST7735 driver, by creating a new array that will be swapped and sent to the device, hence doubling the amount of needed memory. It may be “safe” for the ST7735 but it would mean 300KB for the ILI9341 !

It’s even more problematic if you try to use the “ActiveWindow” feature : endianness should then be swapped only for this active window (otherwise it’s a useless feature) but it’s not possible with the current SwapEndianness() method.

To me, the endianness would better be handled at the MCU SPI level : you would not have to bother with endianness on the screen data and would only have to send the raw data. Even the windowed drawings would then be handled transparently.
This would dramatically increase the framerate in this case. No need to draw and send 150KB of data when only a small area needs to be drawn.

So, may I ask again for byte endianness in the SPI config, please ?

All makes sense but I am not seeing how would this properly be done internally. It may seem simple to you but it is not. So I will reword your request to “how do I partial refresh an spi display that needs the bytes swapped?” Please make a GitHub issues.

Let me take some time to find the details, but it’s about setting some registers in the MCU SPI config to send MSB first or LSB first. Nothing more.

We know how spi works and know the processor very well :grin: it is about how our driver is designed. Anyway, we understand what you need.

I was not sure :stuck_out_tongue:

More croissants :fr: in the game, then…

1 Like

I would even add that such “workaround” ruins the good idea/feature of automatically using unmanaged memory for graphics when available.
In this case, the new array would be allocated on the managed heap. Unless we specifically allocate it on the unmanaged memory, of course. But not all SOM/SOC have such memory.

But you got the point. That was just two more cents :wink:

1 Like