1.1.8.2 Using the SFDP Driver Library

The SFDP driver provides non-blocking APIs to read, write and erase JEDEC-compliant NOR Flash memory with automatic parameter discovery.

The SFDP driver can be used in following ways:

  • To perform page write to SFDP Flash. Here, the memory start address must be aligned to the page boundary (page size discovered from device).
  • To perform Sector/Bulk/Chip Erase operations (sizes discovered from device via SFDP).
  • To unlock Flash before performing Erase/Write operations. Done as part of DRV_SFDP_Open().
  • To read Flash JEDEC-ID.
  • To interface with the Memory driver to perform block operations on the SFDP Flash.
  • To discover and adapt to different Flash device capabilities at runtime using SFDP.
Note: The client should poll for the status of the data transfer when in QSPI/SPI mode. SFDP discovery is performed during DRV_SFDP_Open() and may fail if the device is not SFDP-compliant.

Example Application to Erase, Write and Read SFDP Flash Memory

/* Erase-Write-Read 2 Sectors of Data (size determined from SFDP discovery) */
  #define BUFFER_SIZE     8192
  #define MEM_ADDRESS     0x0

  APP_DATA CACHE_ALIGN appData;

  static uint32_t erase_index = 0;
  static uint32_t write_index = 0;

  /* Transfer event handler - signals when an operation completes */
  void APP_FLASH_EventHandler(DRV_SFDP_TRANSFER_STATUS event, uintptr_t context)
  {
      switch(event)
      {
          case DRV_SFDP_TRANSFER_COMPLETED:
          case DRV_SFDP_TRANSFER_ERROR_UNKNOWN:
          {
              appData.isTransferDone = true;
              break;
          }
          default:
          {
              break;
          }
      }
  }

  void APP_Initialize ( void )
  {
      uint32_t i = 0;

      /* Place the App state machine in its initial state. */
      appData.state = APP_STATE_INIT;

      for (i = 0; i < BUFFER_SIZE; i++)
      {
          appData.writeBuffer[i] = i;
      }
  }

  void APP_Tasks ( void )
  {
      DRV_SFDP_TRANSFER_STATUS transferStatus = DRV_SFDP_TRANSFER_ERROR_UNKNOWN;

      /* Check the application's current state. */
      switch ( appData.state )
      {
          /* Application's initial state. */
          case APP_STATE_INIT:
          {
              if (DRV_SFDP_Status(DRV_SFDP_INDEX) == SYS_STATUS_READY)
              {
                  appData.state = APP_STATE_OPEN_DRIVER;
              }
              break;
          }

          case APP_STATE_OPEN_DRIVER:
          {
              appData.handle = DRV_SFDP_Open(DRV_SFDP_INDEX, DRV_IO_INTENT_READWRITE);

              if (appData.handle != DRV_HANDLE_INVALID)
              {
                  /* Register the transfer event handler */
                  DRV_SFDP_EventHandlerSet(appData.handle, APP_FLASH_EventHandler, (uintptr_t)NULL);

                  appData.state = APP_STATE_GEOMETRY_GET;
              }
              else
              {
                  /* SFDP discovery failed - device may not be SFDP-compliant */
                  appData.state = APP_STATE_ERROR;
              }

              break;
          }

          case APP_STATE_GEOMETRY_GET:
          {
              /* Get device geometry discovered from SFDP parameters */
              if (DRV_SFDP_GeometryGet(appData.handle, &appData.geometry) != true)
              {
                  appData.state = APP_STATE_ERROR;
                  break;
              }

              erase_index = 0;
              write_index = 0;
              appData.state = APP_STATE_ERASE_FLASH;

              break;
          }

          case APP_STATE_ERASE_FLASH:
          {
              appData.isTransferDone = false;

              /* Erase sector (size from SFDP discovery, typically 4 KByte) */
              if (DRV_SFDP_SectorErase(appData.handle, (MEM_ADDRESS + erase_index)) != true)
              {
                  appData.state = APP_STATE_ERROR;
              }

              appData.state = APP_STATE_ERASE_WAIT;

              break;
          }

          case APP_STATE_ERASE_WAIT:
          {
              if (appData.isTransferDone == true)
              {
                  transferStatus = DRV_SFDP_TransferStatusGet(appData.handle);

                  if(transferStatus == DRV_SFDP_TRANSFER_COMPLETED)
                  {
                      erase_index += appData.geometry.erase_blockSize;

                      if (erase_index < BUFFER_SIZE)
                      {
                          appData.state = APP_STATE_ERASE_FLASH;
                      }
                      else
                      {
                          appData.state = APP_STATE_WRITE_MEMORY;
                      }
                  }
                  else if (transferStatus == DRV_SFDP_TRANSFER_ERROR_UNKNOWN)
                  {
                      appData.state = APP_STATE_ERROR;
                  }
              }
              break;
          }

          case APP_STATE_WRITE_MEMORY:
          {
              appData.isTransferDone = false;

              /* Write page (size from SFDP discovery, typically 256 bytes) */
              if (DRV_SFDP_PageWrite(appData.handle, (uint32_t *)&appData.writeBuffer[write_index], (MEM_ADDRESS +
  write_index)) != true)
              {
                  appData.state = APP_STATE_ERROR;
                  break;
              }

              appData.state = APP_STATE_WRITE_WAIT;

              break;
          }

          case APP_STATE_WRITE_WAIT:
          {
              if (appData.isTransferDone == true)
              {
                  transferStatus = DRV_SFDP_TransferStatusGet(appData.handle);

                  if(transferStatus == DRV_SFDP_TRANSFER_COMPLETED)
                  {
                      write_index += appData.geometry.write_blockSize;

                      if (write_index < BUFFER_SIZE)
                      {
                          appData.state = APP_STATE_WRITE_MEMORY;
                      }
                      else
                      {
                          appData.state = APP_STATE_READ_MEMORY;
                      }
                  }
                  else if (transferStatus == DRV_SFDP_TRANSFER_ERROR_UNKNOWN)
                  {
                      appData.state = APP_STATE_ERROR;
                  }
              }

              break;
          }

          case APP_STATE_READ_MEMORY:
          {
              appData.isTransferDone = false;

              /* Read data from flash (read instruction from SFDP discovery) */
              if (DRV_SFDP_Read(appData.handle, (uint32_t *)&appData.readBuffer, BUFFER_SIZE, MEM_ADDRESS) != true)
              {
                  appData.state = APP_STATE_ERROR;
              }
              else
              {
                  appData.state = APP_STATE_READ_WAIT;
              }

              break;
          }

          case APP_STATE_READ_WAIT:
          {
              if (appData.isTransferDone == true)
              {
                  transferStatus = DRV_SFDP_TransferStatusGet(appData.handle);

                  if(transferStatus == DRV_SFDP_TRANSFER_COMPLETED)
                  {
                      appData.state = APP_STATE_VERIFY_DATA;
                  }
                  else if (transferStatus == DRV_SFDP_TRANSFER_ERROR_UNKNOWN)
                  {
                      appData.state = APP_STATE_ERROR;
                  }
              }

              break;
          }

          case APP_STATE_VERIFY_DATA:
          {
              if (!memcmp(appData.writeBuffer, appData.readBuffer, BUFFER_SIZE))
              {
                  appData.state = APP_STATE_SUCCESS;
              }
              else
              {
                  appData.state = APP_STATE_ERROR;
              }

              break;
          }

          case APP_STATE_SUCCESS:
          {
              DRV_SFDP_Close(appData.handle);

              break;
          }

          case APP_STATE_ERROR:
          default:
          {
              DRV_SFDP_Close(appData.handle);
              break;
          }
      }
  }

Key Differences From Fixed-Device Drivers (SST26)

AspectSST26SFDP
Device DiscoveryHard-coded for specific devicesRuntime discovery via SFDP (JESD216)
Sector SizeFixed (typically 4 KB)Determined from SFDP (typically 4 KB)
Block SizeFixed (8, 32, or 64 KB)Determined from SFDP (typically 64 KB)
Page SizeFixed (256 bytes)Determined from SFDP (typically 256 bytes)
Open FailureOnly if hardware not initializedAlso if SFDP discovery fails
QUAD ModeAlways enabled if availableConditionally enabled if device supports
PageWrite SignaturePageWrite(handle, data, length, address)PageWrite(handle, data, address)
Device SupportSingle device modelAny JEDEC-compliant SFDP-enabled device

Important Notes for SFDP Driver Usage

  1. SFDP Discovery: Performed during DRV_SFDP_Open() - this function may take several milliseconds to complete.
  2. Geometry Retrieval: Always call DRV_SFDP_GeometryGet() after opening to get actual device parameters.
  3. Dynamic Sizing: Use geometry returned by GeometryGet() instead of hard-coded values.
  4. Error Handling: Handle SFDP discovery failures explicitly (device may not support SFDP).
  5. Page Alignment: Write addresses must be aligned to page size (from geometry).
  6. Read Instructions: Read mode (SPI/QUAD) is determined from SFDP and configured automatically.