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.

Table 4 of M25P10-A datasheet#

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 Rate#

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.

Table 18 of M25P10-A datasheet (first four entries only).#

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.

Table 5 of M25P10-A datasheet#

Manufacturer identification

Device identification

Memory type

Memory capacity

20h

20h

11h

../../../_images/fl-m25p10a-fig9.png

Figure 9 of M25P10-A datasheet#

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.

Table 2 of M25P10-A datasheet#

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

../../../_images/fl-m25p10a-tab6.png

Table 6 of M25P10-A datasheet#

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.

Table 7 of F25L004A datasheet.#

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. Table 2 of A25L80P datasheet reproduces the part of this datasheet that provides the sector information.

Table 2 of A25L80P datasheet#

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:

Quad Enable method#

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.