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 would love DMA too - oddly enough I went through this today. I'm also writing OLED driving code (SSD1306) and mine runs at 8MHz and even with a loop which checks EVENT_READY, clears it, reads the RXD byte (required to get another event), writes the next byte to TXD, increments and checks the data pointer, that ends up being a loop of about 60 instructions or 4µs. Release mode optimised it's about 3µs and I don't think the optimiser has done a great job, but even if I hand-coded it I could do only a little better. So the max effective SPI rate is about 3MHz. At that speed the double-buffering doesn't even help, it costs more machine cycles to track whether you have 1 or 2 TXD slots remaining than it does to pretend there's only one. My code is hybrid and does drop into interrupt mode when it loops and finds EVENT_READY isn't set, I find I have to drop to 1MHz SPI before that happens.

Reply
  • I would love DMA too - oddly enough I went through this today. I'm also writing OLED driving code (SSD1306) and mine runs at 8MHz and even with a loop which checks EVENT_READY, clears it, reads the RXD byte (required to get another event), writes the next byte to TXD, increments and checks the data pointer, that ends up being a loop of about 60 instructions or 4µs. Release mode optimised it's about 3µs and I don't think the optimiser has done a great job, but even if I hand-coded it I could do only a little better. So the max effective SPI rate is about 3MHz. At that speed the double-buffering doesn't even help, it costs more machine cycles to track whether you have 1 or 2 TXD slots remaining than it does to pretend there's only one. My code is hybrid and does drop into interrupt mode when it loops and finds EVENT_READY isn't set, I find I have to drop to 1MHz SPI before that happens.

Children
No Data
Related