This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Slow SPI performance

I have 25Q64 SPI flash chip connected to SPI bus. Unfortunately it works too slow even with using IRQ routine via SPI0_TWI0_IRQHandler (everything done like in example spi_master-pca10028). Typical timing diagram: image description

Is this problem in SPI hardware implementation or interrupt routing via softdevice? Can you propose any ways to speed up SPI throughput? Do you have correct double-buffering example with checking if TX buffer ready for 1 or for 2 bytes? As a temporary solution I've use trick with delay:

    for (int i = 0; i<datalen; i++) {
      MEM_SPI->TXD = data[i];
      nrf_delay_us(1);
    }

It works better, but I'm not sure if this way productive and stable enough for production:

image description

If this way Ok, I'll use my own nrf_delay_us with fewer NOP's :)

Parents
  • I settled on 4MHz SPI. I get about 1.493ms per SSD1306 OLED frame (~512bytes).

    The only thing you need to deal with the double buffering is just splitting the tx/rx indexes and initially priming the tx buffer.

    In my SPI interrupt I have a tx only fast path and a rx/tx slower path (not used for the ssd1306), here is the fast path:

        /* tx only fast path */
        while (hw->EVENTS_READY && rxIdx < xfer->nbytes)
        {
            hw->EVENTS_READY = 0; // ack event 
            data = hw->RXD; // dummy receive 
            rxIdx++; // always incr 
            if (txIdx < xfer->nbytes) // more to send? 
                hw->TXD = txBuffer[txIdx++];
        }
    
Reply
  • I settled on 4MHz SPI. I get about 1.493ms per SSD1306 OLED frame (~512bytes).

    The only thing you need to deal with the double buffering is just splitting the tx/rx indexes and initially priming the tx buffer.

    In my SPI interrupt I have a tx only fast path and a rx/tx slower path (not used for the ssd1306), here is the fast path:

        /* tx only fast path */
        while (hw->EVENTS_READY && rxIdx < xfer->nbytes)
        {
            hw->EVENTS_READY = 0; // ack event 
            data = hw->RXD; // dummy receive 
            rxIdx++; // always incr 
            if (txIdx < xfer->nbytes) // more to send? 
                hw->TXD = txBuffer[txIdx++];
        }
    
Children
No Data
Related