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)
| Aspect | SST26 | SFDP |
|---|---|---|
| Device Discovery | Hard-coded for specific devices | Runtime discovery via SFDP (JESD216) |
| Sector Size | Fixed (typically 4 KB) | Determined from SFDP (typically 4 KB) |
| Block Size | Fixed (8, 32, or 64 KB) | Determined from SFDP (typically 64 KB) |
| Page Size | Fixed (256 bytes) | Determined from SFDP (typically 256 bytes) |
| Open Failure | Only if hardware not initialized | Also if SFDP discovery fails |
| QUAD Mode | Always enabled if available | Conditionally enabled if device supports |
| PageWrite Signature | PageWrite(handle, data, length,
address) | PageWrite(handle, data,
address) |
| Device Support | Single device model | Any JEDEC-compliant SFDP-enabled device |
Important Notes for SFDP Driver Usage
- SFDP Discovery: Performed during
DRV_SFDP_Open()- this function may take several milliseconds to complete. - Geometry Retrieval: Always call
DRV_SFDP_GeometryGet()after opening to get actual device parameters. - Dynamic Sizing: Use geometry returned
by
GeometryGet()instead of hard-coded values. - Error Handling: Handle SFDP discovery failures explicitly (device may not support SFDP).
- Page Alignment: Write addresses must be aligned to page size (from geometry).
- Read Instructions: Read mode (SPI/QUAD) is determined from SFDP and configured automatically.
