Driving high-resolution displays over QSPI

I'm looking to send a very long sequence of data using the QSPI peripheral (ideally many thousands of bytes long) with minimal CPU overhead. With the QSPI peripheral, it seems like after 256 bytes (or 512 bytes if PPSIZE=1), it will end the transaction, check the status register (0x05), and send a new write-enable command (0x06) before continuing to send data, with the address incremented.

  • Is there any way to either disable pagination behaviour, or increase the page size drastically (ideally to somewhere around 20,000 bytes)?
  • Can we prevent the auto-incrementing address behaviour, such that it writes to the exact same address each time without the overhead of an interrupt? 
  • Can you imagine a workaround that might plausibly work? Eg using QSPI 32-bit addressing mode, or using GPIOTE/Counter/ArrayList somehow?
  • Is there any more documentation/detail about how 32-bit addressing/ADDRCONF works? I can set NRF_QSPI_ADDRMODE_32BIT and see that 4 bytes of address are now sent, but I don't understand the ADDRCONF register - couldn't work out what any of these bits changed in practice.
  • Is it possible to entirely suppress the opcode/address, and simply send the quad data? (eg could I bit-bang the opcode/address data. then hand over control to the QSPI just for the bulk data transfer?)
  • A second candidate display requires a non-standard opcode (0xDE) instead of a normal PP4O write (0x32) when writing pixel data - is there a way to support this? I assume not as this is limited by WRITEOC options - unless there's a hidden register which can reconfigure the opcodes?

I'm interested in achieving this either on nRF52840 or nRF5340, with a preference for the nRF52840.

The context is a large (360x360 or larger) display, which accepts the command "00 3C 00" followed by display data. This is equivalent to writing pixel data to the SPI Flash address 0x003C00, however after 512 bytes, the pagination kicks in and the address is getting incremented to 0x003E00, which the display is interpreting as a different command.

This can be worked around by breaking the updates into 512-byte chunks, however this incurs a high interrupt overhead (eg with a 360x360x16bpp display that would be ~500 interrupts per frame) - this would likely have an impact on performance. The only partial workaround I've found so far is that I can switch to 32-bit addressing mode and write to address 003Cxx00 (this relies on the peripheral to discard the dummy byte `xx` which does seem to be the case. It also cuts off the first half-pixel of the display data, which is workable.

The closest post I managed to find is here:  RE: QSPI disable addressing but it seems like that wasn't resolved.

  • Hi,

     

    Using the QSPI for a non-QSPI-NOR device is not trivial, as the peripheral has been designed for NOR operation, as also described in the post that you linked to:

    The closest post I managed to find is here:  RE: QSPI disable addressing but it seems like that wasn't resolved.

    If you have to send large amount of data, I would recommend that you look at the SPIM3 peripheral (SPIM4 on nRF5340), which is a normal SPI peripheral with 32M mode available.

     

    Kind regards,

    Håkon

  • Hi Håkon,

    Single SPI would put significant limits on our maximum frame rate (360x360x16bpp at 32MHz would limit us to 15 FPS, larger resolutions would run even slower), so QSPI is highly preferable.

    We're potentially OK with complex workarounds (eg test registers/undocumented behaviour), provided that the solution is likely to persist through minor chip revisions.

    One option that could theoretically work without going outside of spec might be to use the PWM peripheral to generate the correct sequence (tightly in step with the QSPI), then mux the pin back to the QSPI pin once the opcode and address has been sent (either internal or external mux) - that's the level of complexity that we'd be OK with.

    We'd want to avoid solutions with a large BoM cost overhead (eg no FPGAs pretending to be an SPI flash chip!).

  • Hi,

     

    Charlie said:
    Single SPI would put significant limits on our maximum frame rate (360x360x16bpp at 32MHz would limit us to 15 FPS, larger resolutions would run even slower), so QSPI is highly preferable.

    What has been done in previous scenarios where a display are being used is to store display data on an external flash using QSPI, and use SPIM for the display communication.

    Is writing the full frame required by your display? Or can you update only the fields that require updating? You normally only change what needs to be changed.

     

    Charlie said:
    One option that could theoretically work without going outside of spec might be to use the PWM peripheral to generate the correct sequence (tightly in step with the QSPI), then mux the pin back to the QSPI pin once the opcode and address has been sent (either internal or external mux) - that's the level of complexity that we'd be OK with.

    As mentioned, using the QSPI for other operations than NOR-flash compatible command set is not trivial. I do not know if this will work for your use-case, but you are free to evaluate.

     

    Kind regards,

    Håkon

  • On one of our candidate displays, the display driver has no RAM of its own, requiring a full refresh every frame. Regardless of display controller, we will also have rotating elements taking up most of the screen, also requiring a full refresh. So unfortunately updating only a small area of the display isn't practical. 

    Are there any undocumented/test registers that would allow us to change opcodes and/or disable the pagination behaviour? If available, this would be a preferable solution, rather than messing around with external muxes, PPI/PWM/GPIOTE, or trying to bit-bang the right output.

  • Hi,

     

    Charlie said:
    Are there any undocumented/test registers that would allow us to change opcodes and/or disable the pagination behaviour?

    No, unfortunately not.

     

    Kind regards,

    Håkon

Related