Page 1 of 1

QSPI flash access management

Posted: Wed Apr 23, 2025 1:24 pm
by steved
Not 100% sure whether this is a bug, or just me using things in an unintended way. Anyway, its the same in at least Chibi 20 and 21.

I have a QSPI flash device as the only component connected to the QSPI bus on a 32F767. To avoid access collisions, I set:

Code: Select all

#define SNOR_SHARED_BUS             TRUE

This should effectively regulate access to the flash as well as the QSPI bus.

However, in snor_read() [hal_serial_nor.c] we have:

Code: Select all

static flash_error_t snor_read(void *instance, flash_offset_t offset,
                               size_t n, uint8_t *rp) {
  SNORDriver *devp = (SNORDriver *)instance;
  flash_error_t err;

  osalDbgCheck((instance != NULL) && (rp != NULL) && (n > 0U));
  osalDbgCheck((size_t)offset + n <= (size_t)snor_descriptor.sectors_count *
                                     (size_t)snor_descriptor.sectors_size);
  osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE)
                "invalid state");      // ********** Triggers here ************

  if (devp->state == FLASH_ERASE) {
    return FLASH_BUSY_ERASING;
  }

  /* Bus acquired.*/
  bus_acquire(devp->config->busp, devp->config->buscfg);

  /* FLASH_READY state while the operation is performed.*/
  devp->state = FLASH_READ;

Parallel accesses of snor_read() trigger an assert as labelled, where in fact they should be handled by the later bus_acquire() code.

I've changed the osalDbgAssert() to:

Code: Select all

  osalDbgAssert((devp->state == FLASH_READY) || (devp->state == FLASH_ERASE) || (devp->state == FLASH_READ),
                "invalid state");

and on a quick test all is fine.

Probably the assert should also let through (devp->state == FLASH_PGM)

Re: QSPI flash access management

Posted: Wed Apr 23, 2025 3:06 pm
by Giovanni
Hi,

Thanks, will review this as soon as possible.

Giovanni

Re: QSPI flash access management

Posted: Thu May 15, 2025 9:40 am
by Giovanni
Hi,

I was discussing this with Bob recently.

I think there is a misunderstanding at base, the option SNOR_SHARED_BUS is about mutual exclusion at bus level (SPI, WSPI), it is useful when you have multiple devices on the same SPI with different chip selects.

It is not meant to offer some intrinsic mutual exclusion on SNOR accesses, that is done using the flashAcquireExclusive() and flashReleaseExclusive() functions that need to be called from the upper layer.

The access protocol when multiple threads access a shared flash device is:

Code: Select all

flashAcquireExclusive();

/* Do here multiple flash operations atomically: read/program/erase.*/

flashReleaseExclusive();


This regardless of SNOR_SHARED_BUS setting. Like for other HAL drivers, it is the caller responsible for mutual exclusion.

Giovanni