Add support for a new flash device#
This section describes supporting a new flash device using libflash or libquadflash. libflash is a library implementing support for SPI flash devices and libquadflash implements Quad SPI devices using a similar API.
To support a new flash device, a configuration file must be written that describes the device characteristics, such as page size, number of pages and commands for reading, writing and erasing data. This information can be found in the datasheet for the flash device. Many devices available in the market can be described using these configuration parameters; those that cannot are unsupported.
The resulting configuration file can be used to support an unsupported flash device within XFLASH, or used to write target software using libflash or libquadflash directly.
The configuration file for the Numonyx M25P10-A is shown below. The device is described as an initializer for a C structure, the values of which are described in the following sections.
10, /* 1. libflash device ID */
256, /* 2. Page size */
512, /* 3. Number of pages */
3, /* 4. Address size */
4, /* 5. Clock divider */
0x9f, /* 6. RDID cmd */
0, /* 7. RDID dummy bytes */
3, /* 8. RDID data size in bytes */
0x202011, /* 9. RDID manufacturer ID */
0xD8, /* 10. SE cmd */
0, /* 11. SE full sector erase */
0x06, /* 12. WREN cmd */
0x04, /* 13. WRDI cmd */
PROT_TYPE_SR, /* 14. Protection type */
{{0x0c,0x0},{0,0}}, /* 15. SR protect and unprotect cmds */
0x02, /* 16. PP cmd */
0x0b, /* 17. READ cmd */
1, /* 18. READ dummy bytes */
SECTOR_LAYOUT_REGULAR, /* 19. Sector layout */
{32768,{0,{0}}}, /* 20. Sector sizes */
0x05, /* 21. RDSR cmd */
0x01, /* 22. WRSR cmd */
0x01, /* 23. WIP bit mask */
0x000000, /* 24. RDID manufacturer ID bitmask to ignore */
0, /* 25. libquadflash: QE bit location, libflash: Reserved */
The configuration structure implements a form of parameter inheritance, allowing for up to three sources of information. In order of priority, a device configuration file can override any value obtained as a result of SFDP query (for devices where this is available), which can override the default configuration file.
The device configuration file is the most authoritative parameter set used for establishing connection with the flash device. A device ID check is performed against the configuration to match the correct file with the attached flash device as described in Read device ID.
SFDP query is the second most authoritative source of information. Any
parameter values set as -1
will be populated from the SFDP response
according to the SFDP section, if available.
The final source of parameters is the default configuration file. This contains a fallback set of parameters that are used when either a specific device configuration cannot be matched, or when the device file inherits values on a per-value basis from the default file, and the parameter was not populated by SFDP.
By setting the libflash device ID to -1
, the configuration file
describes the default set of parameters.
By setting the remaining parameters to -1
, the value is inherited from
SFDP or the default configuration file, in that order.
The default configuration should not use the value of -1
for the
remaining parameters, as there is nothing for it to inherit from. The
default configuration describes fallback parameters used when information
is missing from SFDP or the device configuration.
The values that can be currently populated from SFDP can be found in the SFDP section.
Libflash device ID#
10, /* 1. libflash device ID */
This value is returned by libflash on a call to the function fl_getFlashType
so that the application can identify the connected flash device.
If this value is set to -1
, the configuration file describes the default
set of parameters.
Page size and number of pages#
256, /* 2. Page size */
512, /* 3. Number of pages */
These values specify the size of each page in bytes and the total number of pages across all available sectors. On the M25P10-A datasheet, these can be found from the following paragraph in section 1:
The memory is organized as 4 sectors, each containing 128 pages. Each page is 256 bytes wide. Thus, the whole memory can be viewed as consisting of 512 pages, or 131,072 bytes.
Address size#
3, /* 4. Address size */
This value specifies the number of bytes used to represent an address. Table 4 of M25P10-A datasheet reproduces the part of the M25P10-A datasheet that provides this information. In the table, all instructions that require an address take three bytes.
Instruction |
Description |
One-byte instruction |
Address |
Dummy |
Data |
|
---|---|---|---|---|---|---|
code |
byte |
bytes |
bytes |
|||
WREN |
Write Enable |
0000 0110 |
06h |
0 |
0 |
0 |
WRDI |
Write Disable |
0000 0100 |
04h |
0 |
0 |
0 |
RDID |
Read Identification |
1001 1111 |
9Fh |
0 |
0 |
1 to 3 |
RDSR |
Read Status Register |
0000 0101 |
05h |
0 |
0 |
1 to infinity |
WRSR |
Write Status Register |
0000 0001 |
01h |
0 |
0 |
1 |
READ |
Read Data Bytes |
0000 0011 |
03h |
3 |
0 |
1 to infinity |
FAST_READ |
Read Data Bytes at Higher Speed |
0000 1011 |
0Bh |
3 |
1 |
1 to infinity |
PP |
Page Program |
0000 0010 |
02h |
3 |
0 |
1 to 256 |
SE |
Sector Erase |
1101 1000 |
D8h |
3 |
0 |
0 |
BE |
Bulk Erase |
1100 0111 |
C7h |
0 |
0 |
0 |
DP |
Deep Power-down |
1011 1001 |
B9h |
0 |
0 |
0 |
RES |
Release from Deep Power-down, and Read Electronic Signature |
1010 1011 |
ABh |
0 |
3 |
1 to infinity |
Release from Deep Power-down |
0 |
0 |
0 |
Clock divider#
4, /* 5. Clock divider */
This value is used to determine the clock rate for interfacing with the SPI device. For a value of n, the SPI clock rate used is 100/2*n MHz. libflash supports a maximum of 12.5MHz.
Table 18 of M25P10-A datasheet (first four entries only). reproduces the part of the M25P10-A datasheet that provides this information. The AC characteristics table shows that all instructions used in the configuration file, as discussed throughout this document, can operate at up to 25MHz. This is faster than libflash can support, so the value 4 is provided to generate a 12.5MHz clock.
Symbol |
Alt. |
Parameter |
Min |
Typ |
Max |
Unit |
---|---|---|---|---|---|---|
f C |
f C |
Clock frequency for the following instructions: FAST_READ, PP, SE, BE, DP, RES, WREN, WRDI, RDSR, WRSR |
D.C. |
25 |
MHz |
|
f R |
Clock frequency for READ instructions |
D.C. |
20 |
MHz |
||
t CH |
t CLH |
Clock High time |
18 |
ns |
||
t CL |
t CLL |
Clock Low time |
18 |
ns |
In general, if the SPI device supports different clock rates for different commands used by libflash, the lowest value must be specified.
Read device ID#
0x9f, /* 6. RDID cmd */
0, /* 7. RDID dummy bytes */
3, /* 8. RDID data size in bytes */
0x202011, /* 9. RDID manufacturer ID */
..
0x000000 /* 24. RDID manufacturer ID bitmask to ignore */
Most flash devices have a hardware identifier that can be used to identify the device. This is used by libflash when one or more flash devices are supported by the application to determine which type of device is connected. The sequence for reading a device ID is typically to issue an RDID (read ID) command, wait for zero or more dummy bytes, and then read one or more bytes of data.
Table 4 of M25P10-A datasheet reproduces the part of the
M25P10-A datasheet that provides this information. The row for the
instruction RDID shows that the command value is 0x9f
, that there
are no dummy bytes, and one to three data bytes. As shown in
Table 5 of M25P10-A datasheet and Figure 9 of M25P10-A datasheet,
the amount of data read depends on whether just the manufacturer ID
(first byte) is required, or whether both the manufacturer ID and the
device ID (second and third bytes) are required. All three bytes are
needed to uniquely identify the device, so the manufacturer ID is
specified as the three-byte value 0x202011
.
The bitmask of ID bits to ignore allows supporting a family of similar flash devices with a single configuration. libflash will attempt connection using the most specialised configurations first (those with fewest bits set).
The bitmask and device ID fields are special in that they cannot be set
to -1
to trigger inheritance - the value is considered to be set to
0xffffffff
, which in the case of the bitmask, ignores all bits of
the device ID.
Manufacturer identification |
Device identification |
|
Memory type |
Memory capacity |
|
20h |
20h |
11h |
In general, if there is a choice of RDID commands then the JEDEC compliant one should be preferred. Otherwise, the one returning the longest ID should be used.
Sector erase#
0xD8, /* 10. SE cmd */
0, /* 11. SE full sector erase */
Most flash devices provide an instruction to erase all or part of a sector.
Table 4 of M25P10-A datasheet reproduces the part of the
M25P10-A datasheet that provides this information. The row for the
instruction SE shows that the command value is 0xd8
. On the M25P10-A
datasheet, the amount of data erased can be found from the first
paragraph of section 6.9:
The Sector Erase (SE) instruction sets to ‘1’ (FFh) all bits inside the chosen sector.
In this example the SE command erases all of the sector, so the SE data value is set to 0. If the number of bytes erased is less than a full sector, this value should be set to the number of bytes erased.
Write enable/disable#
0x06, /* 12. WREN cmd */
0x04, /* 13. WRDI cmd */
Most flash devices provide instructions to enable and disable writes to
memory. Table 4 of M25P10-A datasheet reproduces the part
of the M25P10-A datasheet that provides this information. The row for
the instruction WREN shows that the command value is 0x06
, and the
row for the instruction WRDI shows that the command value is 0x04
.
Memory protection#
PROT_TYPE_SR, /* 14. Protection type */
{{0x0c,0x0},{0,0}}, /* 15. SR protect and unprotect cmds */
Some flash devices provide additional protection of sectors when writes are enabled. For devices that support this capability, libflash attempts to protect the flash image from being accidentally corrupted by the application. The supported values for protection type are:
PROT_TYPE_NONE
The device does not provide protection
PROT_TYPE_SR
The device provides protection by writing the status register
PROT_TYPE_SECS
The device provides commands to protect individual sectors
The protection details are specified as part of a construction of the form:
{{a,b},{c,d}}
If the device does not provide protection, all values should be set to 0. If the device provides SR protection, a and b should be set to the values to write to the SR to protect and unprotect the device, and c and d to 0. Otherwise, c and d should be set to the values to write to commands to protect and unprotect the device, and a and b to 0.
If using SR protection, bit 30 of a and b can be set to enable a read-modify-write method of accessing the status register. This prevents clearing unrelated status bits. In this scenario, b is reinterpreted and must otherwise contain the bitmask of bits to clear - usually the same value set in a.
Table 2 of M25P10-A datasheet and Table 6 of M25P10-A datasheet reproduce the parts of the M25P10-A datasheet that provide this information. The first table shows that BP0 and BP1 of the status register should be set to 1 to protect all sectors, and both to 0 to disable protection. The second table shows that these are bits 2 and 3 of the SR.
Status |
Memory content |
||
---|---|---|---|
Register |
|||
Content |
|||
BP1 |
BP0 |
Protected area |
Unprotected area |
bit |
bit |
||
0 |
0 |
none |
All sectors (four sectors: 0, 1, 2 and 3) |
0 |
1 |
Upper quarter (sector 3) |
Lower three-quarters (three sectors: 0 to 2) |
1 |
0 |
Upper half (two sectors: 2 and 3) |
Lower half (sectors 0 and 1) |
1 |
1 |
All sectors (four sectors: 0, 1, 2 and 3) |
none |
Programming command#
0x02, /* 16. PP cmd */
Devices are programmed either a page at a time or a small number of bytes at a time. If page programming is available it should be used, as it minimizes the amount of data transmitted over the SPI interface.
Table 4 of M25P10-A datasheet reproduces the part of the
M25P10-A datasheet that provides this information. In the table, a page
program command is provided and has the value 0x02
.
If page programming is not supported, this value is a concatenation of three separate values. Bits 0..7 must be set to 0. Bits 8..15 should contain the program command. Bits 16..23 should contain the number of bytes per command. The libflash library requires that the first program command accepts a three byte address but subsequent program command use auto address increment (AAI).
An example of a device without a PP command is the ESMT
F25L004A.
Table 7 of F25L004A datasheet. reproduces the part of the F25L004A
datasheet that provides this information. In the timing diagram, the AAI
command has a value 0xad
, followed by a three-byte address and two
bytes of data.
Symbol |
Parameter |
Minimum |
Units |
---|---|---|---|
T PU-READ |
V DD Min to Read Operation |
10 |
us |
T PU-WRITE |
V DD Min to Write Operation |
10 |
us |
The corresponding entry in the specification file is:
0x00|(0xad<<8)|(2<<16), /* No PP, have AAI for 2 bytes */
Read data#
0x0b, /* 17. READ cmd */
1, /* 18. READ dummy bytes */
The sequence for reading data from a device is typically to issue a READ command, wait for zero or more dummy bytes, and then read one or more bytes of data.
For libquadflash, command bits 0..7 denote the QUAD_READ command, typically
0xeb
. Bits 8..15 can be used to set a READ or FAST_READ command but this
defaults to 0x0b
for FAST_READ.
Table 4 of M25P10-A datasheet reproduces the part of the
M25P10-A datasheet that provides this information. There are two
commands that can be used to read data: READ and FAST_READ. The row for
the instruction FAST_READ shows that the command value is 0x0b
,
followed by one dummy byte.
Sector information#
SECTOR_LAYOUT_REGULAR, /* 19. Sector layout */
{32768,{0,{0}}}, /* 20. Sector sizes */
The first value specifies whether all sectors are the same size. The supported values are:
SECTOR_LAYOUT_REGULAR
The sectors all have the same size
SECTOR_LAYOUT_IRREGULAR
The sectors have different sizes
On the M25P10-A datasheet, this can be found from the following paragraph in section 5:
The memory is organized as:
131,072 bytes (8 bits each)
4 sectors (256 Kbits, 32768 bytes each)
512 pages (256 bytes each).
The sector sizes is specified as part of a construction:
{a, {b, {c}}}
. For regular sector sizes, the size is specified in
a. The values of b and c should be 0.
For irregular sector sizes, the size number of sectors is specified in b. The log base 2 of the number of pages in each sector is specified in c. The value of a should be 0. An example of a device with irregular sectors is the AMIC A25L80P. :ref:`add_flash_support_tab2_a25l80p reproduces the part of this datasheet that provides the sector information.
Sector |
Sector Size (Kb) |
Address Range |
|
---|---|---|---|
15 |
64 |
F0000h |
FFFFFh |
14 |
64 |
E0000h |
EFFFFh |
13 |
64 |
D0000h |
DFFFFh |
12 |
64 |
C0000h |
CFFFFh |
11 |
64 |
B0000h |
BFFFFh |
10 |
64 |
A0000h |
AFFFFh |
9 |
64 |
90000h |
9FFFFh |
8 |
64 |
80000h |
8FFFFh |
7 |
64 |
70000h |
7FFFFh |
6 |
64 |
60000h |
6FFFFh |
5 |
64 |
50000h |
5FFFFh |
4 |
64 |
40000h |
4FFFFh |
3 |
64 |
30000h |
3FFFFh |
2 |
64 |
20000h |
2FFFFh |
1 |
64 |
10000h |
1FFFFh |
0-4 |
32 |
08000h |
0FFFFh |
0-3 |
16 |
04000h |
07FFFh |
0-2 |
8 |
02000h |
03FFFh |
0-1 |
4 |
01000h |
01FFFh |
0-0 |
4 |
00000h |
00FFFh |
The corresponding entry in the specification file is:
SECTOR_LAYOUT_IRREGULAR,
{0,{20,{4,4,5,6,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8}}},
Status register bits#
0x05, /* 21. RDSR cmd */
0x01, /* 22. WRSR cmd */
0x01, /* 23. WIP bit mask */
Most flash devices provide instructions to read and write a status register, including a write-in-progress bit mask.
Table 4 of M25P10-A datasheet reproduces the part of the
M25P10-A datasheet that documents the RDSR and WRSR commands. The
diagram in Table 6 of M25P10-A datasheet shows that the WIP
bit is in bit position 0 of the SR, resulting in a bit mask of 0x01
.
Quad enable bit#
0, /* 25. libquadflash: QE bit location, libflash: Reserved */
For Quad SPI devices, an additional field is provided for encoding the location of the Quad Enable bit. This field is reserved and has no effect when using libflash for a SPI device.
Bits 0..1 of this field describe the method used to set the bit:
Value |
Method |
Description |
Read-modify-write |
---|---|---|---|
0 |
Legacy libquadflash behavior |
Set bit 6 in register 0 if manufacturer ID is ISSI or MACRONIX, otherwise set bit 1 in register 1 |
No |
1 |
Bit position override |
Set bit stored in bits 8..15 in register stored in bits 0..7, using the WRSR command |
No |
2 |
SFDP requirements |
Set bit according to JEDEC Quad Enable Requirements (QER) value stored in bits 24..26 |
Yes |
3 |
No QE bit |
Does not attempt to set a QE bit |
N/A |
It is not recommended to override this field as the default behavior
attempts SFDP query to derive a value using method 2. The value can
be left as -1
to inherit from the SFDP query. This field is provided
for devices that do not support SFDP query.
Note that XFLASH will populate this field with the QE bit position override, if any, stored in the XN file. This will couple the application XE file to a particular flash device, which may be undesirable. It is recommended to remove the QE bit location from the XN file for systems supporting SFDP.
If a method supports read-modify-write, other bits of the status register will be preserved when setting the QE bit.
SFDP#
libquadflash implements a basic level of support for JEDEC JESD216 Serial Flash Discoverable Parameters (SFDP). This automatically populates the flash configuration structure with values obtained from the attached flash device at runtime, reducing the need to manually specify some properties of the device.
The currently supported SFDP parameters and mappings include:
Quad Enable Requirements: 25 (quadEnable).
Flash Memory Density: 3 (numPages).
Page Size: 2 (pageSize).
To use this feature, the associated field in the device configuration
file (if any) must be set to -1
to inherit the value from the SFDP
query. Any other value will override the result of the query.
Select a flash device#
When selecting a flash device for use with an xCORE device, the following guidelines are recommended:
If access to the data partition is required, select a device with fine-grained erase granularity, as this will minimize the gaps between the factory and upgrade images, and will also minimize the amount of data that libflash needs to buffer when writing data.
Select a device with sector protection if possible, to ensure that the bootloader and factory image are protected from accidental corruption post-deployment.
Select a flash speed grade suitable for the application. Boot times are minimal even at low speeds.