Async(ish) SPI.write?

Working libraries, libraries being ported and related hardware
heisan
Posts: 111
Joined: Thu May 31, 2018 5:39 pm

Re: Async(ish) SPI.write?

Post by heisan » Thu Aug 09, 2018 8:11 am

Thanks "-O3" gets it to DMA speed for all cases - at the cost of 10% of the flash.

Strangely, any attempts at local optimisations, eg:

Code: Select all

void __attribute__((optimize("O3"))) drawFB(int x, int y, Adafruit_FB& fb, uint16_t pal[]) {
make it slower!

Another option is bit banding:

Code: Select all

  volatile uint32_t * bp = (volatile uint32_t *)((((uint32_t)fb.buffer) - 0x20000000UL) * 32 + 0x22000000UL);
  int bc = 0;
  for(iy = 0; iy < fb.fbheight(); iy++) {
   for(ix = 0; ix < fb.fbwidth(); ix++) {
    while(!(regs->SR & SPI_SR_TXE));
    regs->DR = pal[bp[0]];
    bp += 8;
   }
   if(bc == 7) {
    bc = 0;
    bp -= 7;
   } else {
    bp -= (fb.fbwidth() * 8) - 1;
    bc++;
   }
  }
This gets me down to DMA speed with -Os, but only for 1bpp - for more bits, the mask and shift method is quicker than doing a second derefference.

heisan
Posts: 111
Joined: Thu May 31, 2018 5:39 pm

Re: Async(ish) SPI.write?

Post by heisan » Fri Aug 17, 2018 7:24 pm

I have been playing around with this some more, and I am still wondering...

A lot of work has been done to add the DMA layer, and port libraries over to using DMA. But as far as I can see, in every case the result is actually bigger, slower code.

The only way to get a real advantage out of DMA is to use dmaSendAsync, but the current API is not workable from libraries - especially if the bus is shared.

At the very least, state needs to be polled in beginTransaction and endTransaction to ensure that it has gone back to SPI_STATE_READY (async transfer complete) before releasing/grabbing the SPI device. Or it could be made more transparent to application developers by checking state on all the API entry points.

Opinions?

Post Reply