SPI Speed from E402 to B402

I’ve been using an ILI9341 SPI display with the E402 and I’m able to get a screen refresh (drawing the entire screen 1 color) within 256mS.

I used the same library and setup on the B402 and did the same test but on this setup up the screen refresh time is 2,210mS just about 10x slower than the E402.

I realized the system clock speed is about 1/2 of the E402 but I wouldn’t expect the screen refresh time to be off by that much.

I have set the SPI clock speeds to their maximum for each device E402 @ 60 MHz and B402 @ 32MHz. Both devices use the primary SPI interface also.

I read on this QnA from Nordic that SPI instance 3 only supports SPI speeds of 16 and 32 MHz.

Does anyone know what instance the SPI interface is on the B402?

Low level write commands are below:

void SPIhw::writeCmd(uint8_t cmd) {
    // SPI.beginTransaction(__SPISettings(120*MHZ, MSBFIRST, SPI_MODE3)); //Slows down screen refresh time
	pinResetFast(pinWR); //low
    // SPI.endTransaction();

void SPIhw::writeData(uint8_t data) {
    // SPI.beginTransaction(__SPISettings(120*MHZ, MSBFIRST, SPI_MODE3)); //Slows down screen refresh time
	pinSetFast(pinWR); //high
	// SPI.transfer(data);
    HAL_SPI_Send_Receive_Data(HAL_SPI_INTERFACE1, data); //particle low level write
    // SPI.endTransaction();

Does anyone have any insight why the refresh time is so different or make it faster on the B402?

@wesner0019, the DeviceOS running on the B402, which has an nrF52840, creates a lot of overhead, especially if you are using BLE, for example. The SPI bitrate is deceiving. The low-level code for SPI is different, the Nordic Softdevice stack is not present on the E402, DeviceOS overhead and and interrupt latency are different. In other words, the overhead on the B402 is affecting the speed at which your display code is running and writing to SPI (aka the display).

On a Boron LTE, writing to an ST7789 240x240 display, I modified a open-source library to exploit SPI DMA, taking advantage of certain ST7789 windowing features. That coupled with an FSM to do round-robin updates of display field elements ONLY when they changed. Also, I ran the TFT on the secondary SPI with a 16MHz bitrate. All this to say that you likely have to optimize your display library and your display code to get the performance you expect on the B402.

1 Like

@peekay123 Thanks for the insight into this. Our display code is fairly opimized for updating the screen to only update areas as they change. It looks like I’ll need to look into how to optimize the 240x320 ILI9341 library we’re using.

Would you be able to share any examples of how the SPI DMA works?

@wesner0019, I optimized an ST7789 library called “Arduino_ST7789_Fast” for use on Particle devices and exploiting windowed writes with SPI DMA. I balanced RAM use with speed.

I also exploited the Adafruit_GFX library’s Canvas feature that creates a virtual RAM buffer of a screen area or the entire screen. In my case, I had a portion of the screen that displayed a “rolling” graph which updated once per minute and autoscaled. Drawing to RAM and then updating using SPI DMA (once per minute) reduced the time taken by an order of magnitude!

If you want to chat about your specific code, feel free to PM me.


After some offline work, the solution turned was to optimize a rectangle fill function in @wesner0019’s graphic library to use “bulk” SPI DMA transfers of pixel data to the ILI9341 display instead of one-byte-at-a-time transfer using the writeCmd() and writeData() functions in the OP.

Based on these changes, @wesner0019 measured a 22x speed improvement in display updates, from 2200ms to 100ms!

1 Like

@peekay123 thanks for the help on this. This improvement makes a huge impact on the refresh rate.

I update my code for the E402 and the speed went from 265mS to 78mS, almost 3.5x faster.

@peekay123 would the data rate then be 240x320x2 bytes / .100 sec = 1,536,000 B/s?

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.