The spiflash-class1.c driver is a generic SPI driver for external flash chips that use a similar command set.  It supports a large number of flash chips as it is provided to customers with our EmberZNet and Silicon Labs Thread stacks.  However, because of the wide variety of chips and sizes and the like, it cannot support every chip that uses that interface.  Fortunately the driver is very generic and can easily be extended to include chips that are not supported by it.  This KBA will help you understand and easily modify the driver to support any compatible chips that are not supported by default.

 

The first thing that needs to be understood are what chips the device support by default.  These chips are:

 

Macronix

  • MX25L2006E (2Mbit)
  • MX25L4006E (4Mbit)
  • MX25L8006E (8Mbit)
  • MX25R8035F (8Mbit low power)
  • MX25L1606E (16Mbit)
  • MX25U1635E (16Mbit 2Volt)
  • MX25R6435F (64Mbit low power)

ISSI

  • IS25LQ025B (256Kbit)
  • IS25LQ512B (512Kbit)
  • IS25LQ010B (1Mbit)
  • IS25LQ020B (2Mbit)
  • IS25LQ040B (4Mbit)


Numonyx/Micron

  • M25P20 (2Mbit)
  • M25P40 (4Mbit)
  • M25P80 (8Mbit)
  • M25P16 (16Mbit)

 Atmel/Adesto

  • AT25DF041A (4Mbit)
  • AT25SF041 (4Mbit)
  • AT25DF081A (8Mbit)

Winbond

  • W25X20BV (2Mbit)
  • W25Q80BV (8Mbit)

Spansion

  • S25FL208K (8Mbit)

 

With some editing, the spiflash driver can support any chip from these companies that support the same SPI instruction set.

 

Next you have to understand the sections of the spiflash driver.

 

Section 1 - Lines 43-155, defines various parameters of the chip such as size, speed, page definitions and timing.

Section 2 - Lines 157-247 are name definitions that match individual parts by name

Section 3 - Lines 249-533 are the chip definitions contained in a HalEepromInformationType struct.  These are built from the parameters in lines 43-155

Section 4 - Lines 535-561 are an enumeration of the parts supported

Section 5 - Lines 563-EOF function definitions

 

 

1. The primary thing you will need to make sure you build is the HalEepromInformationType struct for your chip.  You will want the data sheet for your part handy to look up specs on your part.  Here is the definition from the file bootloader-eeprom.h:

 

typedef struct {
uint16_t version; /** The version of this data structure */
uint16_t capabilitiesMask; /** A bitmask describing the capabilites of this particular external EEPROM */
uint16_t pageEraseMs; /** Maximum time it takes to erase a page. (in 1025Hz Milliseconds) */
uint16_t partEraseMs; /** Maximum time it takes to erase the entire part. (in 1024Hz Milliseconds) */
uint32_t pageSize; /** The size of a single erasable page in bytes */
uint32_t partSize; /** The total size of the external EEPROM in bytes */
const char * const partDescription; /** Pointer to a string describing the attached external EEPROM */
uint8_t wordSizeBytes; /** The number of bytes in a word for the external EEPROM **/
} HalEepromInformationType;

You might want to look at one of the included structs for a reference:

 

#if defined(SPIFLASH_SPANSION_S25FL208K)
static const HalEepromInformationType spansion8MInfo = {
EEPROM_INFO_VERSION,
EEPROM_CAPABILITIES_ERASE_SUPPORTED | EEPROM_CAPABILITIES_PAGE_ERASE_REQD,
TIMING_ERASE_4K_MAX_MS,
TIMING_ERASE_SPANSION_8M_MAX_MS,
DEVICE_SECTOR_SIZE,
DEVICE_SIZE_8M,
"S25FL208K",
DEVICE_WORD_SIZE // word size in bytes
};
#endif

 

When building your definition:

versioncapabilitiesMask - wordSizeBytes - these values should probably be copied from their defaults.


pageEraseMspartEraseMspageSizepartSize - These will come from the data sheet.  It should be noted that page refers to the smallest unit that can be erased on a part, it might also be called Sector or Block.  In terms of the erase times, you probably want to give some extra time just to make sure you erase takes place.
If section 1 does not have some of these values, such as the right page size, you can create your own.

 

partDescription - This can be just a raw string describing your part

 

2. Once you have built your struct, surround it by #if defined statements and include a unique identifier for your part.  Add this to the list in section 3.

 

Once this is set for your chip, once you build your project, it should be able to address your part correctly.  If one of the settings is not right, it will usually cause your program to assert when initializing the serial flash.

 

Additional references:

UG266: Silicon Labs Gecko Bootloader User’s Guide

AN1084: Using the Gecko Bootloader with EmberZNet and Silicon Labs Thread

AN772: Using the Ember Application Bootloader

  • ZigBee and Thread
  • Knowledge Base Articles