SFUD is an open source serial SPI Flash universal driver library. Since there are many types of serial Flash on the market, the specifications and commands of each Flash are different. SFUD is designed to solve the current differences in these Flashes, allowing our products to support Flash of different brands and specifications, improve the reusability and scalability of software involving Flash functions, and at the same time, it can also avoid the risks brought to the product by out-of-stock or discontinuation of Flash.
/sfud/inc/sfud_flash_def.h ). If it is not supported, you can add the parameter information of this Flash in the configuration file (see Flash that is currently not supported in the 2.5 Adding library for details). After obtaining the specifications of Flash, all operations on Flash can be achieved. The following table shows all Flashes that have been tested in real-machine on the Demo platform. Flash that does not support the SFDP standard has been defined in the Flash parameter information table. More Flash that does not support the SFDP standard needs to be improved and maintained in the future (Github|OSChina|Coding) .
If you think this open source project is great, you can click Star in the upper right corner of the project homepage and recommend it to more friends in need.
| model | Manufacturer | capacity | Maximum speed | SFDP Standard | QSPI mode | Remark |
|---|---|---|---|---|---|---|
| W25Q40BV | Winbond | 4Mb | 50Mhz | Not supported | Double line | Production has been discontinued |
| W25Q80DV | Winbond | 8Mb | 104Mhz | support | Double line | |
| W25Q16BV | Winbond | 16Mb | 104Mhz | Not supported | Double line | by slipperstree |
| W25Q16CV | Winbond | 16Mb | 104Mhz | support | Not tested | |
| W25Q16DV | Winbond | 16Mb | 104Mhz | support | Not tested | by slipperstree |
| W25Q32BV | Winbond | 32Mb | 104Mhz | support | Double line | |
| W25Q64CV | Winbond | 64Mb | 80Mhz | support | Four-line | |
| W25Q128BV | Winbond | 128Mb | 104Mhz | support | Four-line | |
| W25Q256FV | Winbond | 256Mb | 104Mhz | support | Four-line | |
| MX25L3206E | Macronix | 32Mb | 86MHz | support | Double line | |
| MX25L3233F | Macronix | 32Mb | 133MHz | support | Not tested | by JiapengLi |
| KH25L4006E | Macronix | 4Mb | 86Mhz | support | Not tested | by JiapengLi |
| KH25L3206E | Macronix | 32Mb | 86Mhz | support | Double line | |
| SST25VF016B | Microchip | 16Mb | 50MHz | Not supported | Not supported | SST has been acquired by Microchip |
| M25P40 | Micron | 4Mb | 75Mhz | Not supported | Not tested | by redocCheng |
| M25P80 | Micron | 8Mb | 75Mhz | Not supported | Not tested | by redocCheng |
| M25P32 | Micron | 32Mb | 75Mhz | Not supported | Not supported | |
| EN25Q32B | EON | 32Mb | 104MHz | Not supported | Not tested | |
| GD25Q16B | GigaDevice | 16Mb | 120Mhz | Not supported | Not tested | by TanekLiang |
| GD25Q32C | GigaDevice | 32Mb | 120Mhz | Not supported | Not tested | by gaupen1186 |
| GD25Q64B | GigaDevice | 64Mb | 120Mhz | Not supported | Double line | |
| S25FL216K | Cypress | 16Mb | 65Mhz | Not supported | Double line | |
| S25FL032P | Cypress | 32Mb | 104Mhz | Not supported | Not tested | by yc_911 |
| S25FL164K | Cypress | 64Mb | 108Mhz | support | Not tested | |
| A25L080 | AMIC | 8Mb | 100Mhz | Not supported | Double line | |
| A25LQ64 | AMIC | 64Mb | 104Mhz | support | support | |
| F25L004 | ESMT | 4Mb | 100Mhz | Not supported | Not supported | |
| PCT25VF016B | PCT | 16Mb | 80Mhz | Not supported | Not supported | SST license will be identified as SST25VF016B |
| AT45DB161E | ADESTO | 16Mb | 85MHz | Not supported | Not supported | ADESTO acquires Atmel Serial Flash Product Line |
| NM25Q128EV | Nor_Mem | 128Mb | Not tested | Not supported | Not tested | SFDP may read the information and identify it as more than 32Gb. |
| P25D40H | PUYA | 4Mb | Not tested | support | Not tested | by Shan |
| P25Q80H | PUYA | 8Mb | Not tested | support | Not tested | by Shan |
Note: In QSPI mode, double-wire means support double-wire fast reading, and four-wire means support four-wire fast reading.
Generally speaking, FLASH, which supports four-line fast reading, also supports two-line fast reading.
Let’s first explain a structure mainly used in this library sfud_flash . Its definition is located in /sfud/inc/sfud_def.h . Each SPI Flash will correspond to a structure, and the structure pointer is collectively referred to as the Flash device object. After the initialization is successful, common SPI Flash parameters will be stored in sfud_flash->chip structure. If SPI Flash also supports SFDP, you can also see more comprehensive parameter information through sfud_flash->sfdp . Many of the following functions will use the Flash device object as the first entry parameter to implement operations on the specified SPI Flash.
sfud_device_init will be called to initialize all devices in the Flash device table. If there is only one Flash, you can use sfud_device_init for single initialization only.
Note : The initialized SPI Flash has been unwrite-protected by default. If you need to enable write-protect, please use the sfud_write_status function to modify the SPI Flash status.
sfud_err sfud_init ( void ) sfud_err sfud_device_init ( sfud_flash * flash )| parameter | describe |
|---|---|
| flash | Flash device to be initialized |
When SFUD turns on QSPI mode, the Flash driver in SFUD supports communication using the QSPI bus. Compared with the traditional SPI mode, using QSPI can accelerate the reading of Flash data. However, when data needs to be written, the data writing speed of Flash itself is slower than the SPI transmission speed, so the data writing speed in QSPI mode is not significantly improved.
Therefore, SFUD's support for QSPI mode is limited to fast read commands. This function allows you to configure the actual supported maximum data line width of the QSPI bus used by Flash, such as: 1 line (default, that is, traditional SPI mode), 2 line, and 4 line.
After setting, SFUD will combine the currently set QSPI bus data line width to match the most suitable and fastest quick read command in the QSPI Flash extension information table. After that, when the user calls sfud_read(), he will use the QSPI mode transmission function to send the command.
sfud_err sfud_qspi_fast_read_enable ( sfud_flash * flash , uint8_t data_line_width )| parameter | describe |
|---|---|
| flash | Flash devices |
| data_line_width | The maximum data line width supported by the QSPI bus, such as: 1, 2, 4 |
The Flash device table is defined in the SFUD configuration file, which is responsible for storing all Flash device objects to be used, so SFUD supports multiple Flash devices to be driven simultaneously. The configuration of the device table is defined in the SFUD_FLASH_DEVICE_TABLE macro in /sfud/inc/sfud_cfg.h . For detailed configuration methods, refer to 2.3 Configuration method Flash). This method returns the Flash device object by indexing the Flash device in the device table, and returns NULL beyond the device table range.
sfud_flash * sfud_get_device ( size_t index )| parameter | describe |
|---|---|
| index | The index value of the Flash device located in the FLash device table |
sfud_err sfud_read ( const sfud_flash * flash , uint32_t addr , size_t size , uint8_t * data )| parameter | describe |
|---|---|
| flash | Flash device object |
| addr | Starting address |
| size | The total size of data read from the start address |
| data | Read data |
Note: The erase operation will be aligned according to the erase granularity of the Flash chip (see the Flash data sheet for details, generally the block size. After initialization is completed, you can view it through
sfud_flash->chip.erase_gran). Please be careful to ensure that the starting address and erase data size are aligned according to the erase granularity of the Flash chip. Otherwise, after performing the erase operation, other data will be lost.
sfud_err sfud_erase ( const sfud_flash * flash , uint32_t addr , size_t size )| parameter | describe |
|---|---|
| flash | Flash device object |
| addr | Starting address |
| size | The total size of erasing data from the start address |
sfud_err sfud_chip_erase ( const sfud_flash * flash )| parameter | describe |
|---|---|
| flash | Flash device object |
sfud_err sfud_write ( const sfud_flash * flash , uint32_t addr , size_t size , const uint8_t * data )| parameter | describe |
|---|---|
| flash | Flash device object |
| addr | Starting address |
| size | Total size of data written from the start address |
| data | Data to be written |
Note: The erase operation will be aligned according to the erase granularity of the Flash chip (see the Flash data sheet for details, generally the block size. After initialization is completed, you can view it through
sfud_flash->chip.erase_gran). Please be careful to ensure that the starting address and erase data size are aligned according to the erase granularity of the Flash chip. Otherwise, after performing the erase operation, other data will be lost.
sfud_err sfud_erase_write ( const sfud_flash * flash , uint32_t addr , size_t size , const uint8_t * data )| parameter | describe |
|---|---|
| flash | Flash device object |
| addr | Starting address |
| size | Total size of data written from the start address |
| data | Data to be written |
sfud_err sfud_read_status ( const sfud_flash * flash , uint8_t * status )| parameter | describe |
|---|---|
| flash | Flash device object |
| status | Current status register value |
sfud_err sfud_write_status ( const sfud_flash * flash , bool is_volatile , uint8_t status )| parameter | describe |
|---|---|
| flash | Flash device object |
| is_volatile | Is it easy to miss? true: easy to miss, and will be lost after power outage |
| status | Current status register value |
All configurations are located in /sfud/inc/sfud_cfg.h . Please refer to the configuration introduction below to select the configuration that suits your project.
Turn on/off SFUD_DEBUG_MODE macro definition
Turn on/off SFUD_USING_SFDP macro definition
Note: After closing, only the Flash information table provided by the library in
/sfud/inc/sfud_flash_def.hwill be queried. Although this will reduce the adaptability of the software, it will reduce the amount of code.
Turn on/off SFUD_USING_FAST_READ macro definition. Many Flash read modes may not meet the higher SPI frequency (for details, please refer to the data sheet exchange characteristics of each Flash), and the fast read mode needs to be enabled.
Note: Because the fast read mode inserts a default null byte when reading, it may be slower than the read mode when the SPI rate is slower.
Turn on/off SFUD_USING_FLASH_INFO_TABLE macro definition
Note: After closing, this library will only drive Flash that supports SFDP specifications, which will also appropriately reduce the amount of code. In addition, the two macro definitions of 2.3.2 and 2.3.3 define at least one of them, and they can also be selected in both ways.
In order to further reduce the amount of code, SFUD_USING_SFDP and SFUD_USING_FLASH_INFO_TABLE may also be neither defined .
At this time, just specify the Flash parameters when defining the Flash device, and then call sfud_device_init to initialize the device. Refer to the following code:
sfud_flash sfud_norflash0 = {
. name = "norflash0" ,
. spi . name = "SPI1" ,
. chip = { "W25Q64FV" , SFUD_MF_ID_WINBOND , 0x40 , 0x17 , 8L * 1024L * 1024L , SFUD_WM_PAGE_256B , 4096 , 0x20 } };
......
sfud_device_init ( & sfud_norflash0 );
...... If there are multiple Flashes in the product, you can add the Flash device table. Modify the macro definition of SFUD_FLASH_DEVICE_TABLE , the example is as follows:
enum {
SFUD_W25Q64CV_DEVICE_INDEX = 0 ,
SFUD_GD25Q64B_DEVICE_INDEX = 1 ,
};
#define SFUD_FLASH_DEVICE_TABLE
{
[SFUD_W25Q64CV_DEVICE_INDEX] = {.name = "W25Q64CV", .spi.name = "SPI1"},
[SFUD_GD25Q64B_DEVICE_INDEX] = {.name = "GD25Q64B", .spi.name = "SPI3"},
} The above defines two Flash devices (one of most products is sufficient). The names of the two devices are "W25Q64CV" and "GD25Q64B" , corresponding to the two SPI device names "SPI1" and "SPI3" respectively (it will be used when migrating the SPI interface, located in /sfud/port/sfud_port.c ). The two enumerations of SFUD_W25Q16CV_DEVICE_INDEX and SFUD_GD25Q64B_DEVICE_INDEX define the index of the two devices in the device table. You can obtain the device table through sfud_get_device_table() method, and then access the specified device with this index value.
Turn on/off SFUD_USING_QSPI macro definition
When enabled, SFUD will also support Flash connected using the QSPI bus.
The port file is located in /sfud/port/sfud_port.c . sfud_err sfud_spi_port_init(sfud_flash *flash) method in the file is a port method provided by the library. It completes the configuration of SPI read and write drivers (required), retry times (required), retry interface (optional) and SPI locks (optional). For more detailed porting content, you can refer to the porting files of each platform in the demo.
Here you need to modify /sfud/inc/sfdu_flash_def.h . See the SFUD_FLASH_CHIP_TABLE macro definition for all supported Flashes. The Flash parameters that need to be prepared in advance are: | Name | Manufacturer ID | Type ID | Capacity ID | Capacity | Write mode | Erase granularity (the minimum unit of erasing) | Erase granularity corresponding command | . Here we take GD25Q64B Flash with GigaDevice as an example.
This Flash is an early-produced model of Gioyi Innovation, so it does not support the SFDP standard. First, you need to download its data sheet and find the three IDs returned by the 0x9F command. Here you need the last two byte ID, namely type id and capacity id . GD25Q64B corresponds to these two IDs: 0x40 and 0x17 respectively. The other Flash parameters required above can be found in the data sheet. Here we will focus on the writing mode . This parameter is provided by the library itself. There are 4 types of write modes. For details, please refer to the sfud_write_mode enumeration type at the top of the file. The same Flash can support multiple write modes at the same time, depending on the situation. For GD25Q64B , the supported write mode should be SFUD_WM_PAGE_256B , that is, write 1-256 bytes per page. Combined with the above GD25Q64B Flash parameters should be as follows:
{"GD25Q64B", SFUD_MF_ID_GIGADEVICE, 0x40, 0x17, 8*1024*1024, SFUD_WM_PAGE_256B, 4096, 0x20},
Add it to the end of the SFUD_FLASH_CHIP_TABLE macro definition to complete the library's support for GD25Q64B .
Currently, it has supported demos under the following platforms
| path | Platform Description |
|---|---|
| /demo/stm32f10x_non_os | STM32F10X bare metal platform |
| /demo/stm32f2xx_rtt | STM32F2XX + RT-Thread operating system platform |
| /demo/stm32l475_non_os_qspi | STM32L475 + QSPI mode bare metal platform |
| /demo/esp32_ext_spi_flash | ESP32C3 + SPI external Flash ESP-IDF framework |
Use the MIT open source protocol. Please read the contents of the LICENSE file in the project for details.