Microchip® Advanced Software Framework

 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
AT25DFx SerialFlash Driver

This driver provides an interface for basic usage of SerialFlash devices, i.e., read/write, global and local protect/unprotect of sectors, and sleep/wake.

It supports multiple instances, and the instances can be connected to either common or individual SPI interfaces. For a list of the supported SerialFlash types, see at25dfx_type.

The following peripherals are used by this module:

The outline of this documentation is as follows:

Prerequisites

This driver requires that the SPI drivers are instantiated, initialized and enabled by the user, and that the SPI instances are persistent for as long as the associated instances of this driver exist or are used. To ensure persistence of the SPI instances, the convention is to define them in the same scope as the instances of this driver, which is usually a global one.

The hardware abstraction layer (HAL) of this driver supports several SPI driver implementations, but not at the same time. So for a given project, one must select which implementation to support, and use it for all instances. The reader is assumed to be familiar with how to configure and initialize the SPI drivers, but the basic configuration to use is supplied by this driver's HAL:

To ensure correct operation, the user should not change anything in the base configuration except the baud rate, the SERCOM MUX and the pin MUX settings.

Module Overview

This driver enables the user to do basic operations on SerialFlash devices in the AT25DFx series, such as checking their presence, reading from and writing to them, putting them to sleep and waking them back up when needed. Basic security is implemented, i.e., sector protection to prevent accidental erase and write. Functionality for permanently locking and securing AT25DFx devices is not implemented in this driver.

Each instance of this driver corresponds to a single AT25DFx device, and must be associated with an instance of the SPI driver supported by the selected HAL implementation, as well as a PORT pin for chip select (CS).

All functions of this driver are blocking, which means that they do not return until the initiated operation completes. Further, since the selected HAL might use an interrupt-driven driver, this driver should not be used within interrupts.

SPI Bus Sharing

SerialFlash devices can share a SPI bus, due to the use of CS lines. SPI bus sharing is supported by this driver without any special configuration. To share a SPI bus, simply associate the same SPI driver instance to multiple instances of this driver.

The figure below illustrates an example where two out of three instances of this driver are associated with the same SPI driver instance.

at25dfx.png
AT25DFx and SPI instance sharing.

Use in Threaded Environments

The functions of this driver rely on the locking mechanism in the SPI drivers to ensure exclusive access to a SPI driver instance for the entire duration of an operation, such as writing data to the AT25DFx device. They will not wait for an already locked instance to be unlocked. Instead, they will simply return a status code indicating that it was busy.

This behavior means that the functions are thread safe in the sense that no two operations may interfere with each other. It also means that there is no queueing of operations. Assuming the illustration above was a multi-threaded application, it would have to wait for an operation on AT25DFx instance #2 to end before one could be initiated on instance #3, and vice versa. If queueing of operations is needed, it must be implemented as a layer on top of this driver.

Be aware that the protocol implementation in this driver is not interrupt- driven, and the HAL may use a polled driver. Hence, an on-going operation may be temporarily paused if the MCU switches threads.

Special Considerations

Device Specifics

The available erase block sizes, and the availability and granularity of protection sectors may differ between devices.

For example, with AT25F512B (AT25DFX_512B), issuing a 64 kB block erase command will cause a 32 kB erase, and it does not support setting protection on individual sectors, only globally.

Refer to the SerialFlash device's datasheet for details about which operations are supported and what limitations apply to them.

Flash Memory Behavior

The reader should be aware of some details of how flash memory generally functions:

  1. Erasing a flash memory block means that all bits in the block are reset to a high level (logical "1"), i.e., all bytes will read as 0xFF.
  2. Writing to a flash memory location will only set relevant bits to a low level (logical "0"), never to a high level.
  3. It is possible to write several times to a flash memory block without erasing, but there may be limitations on the number of times it can be done.

Extra Information

For extra information, see Extra Information for AT25DFx SerialFlash Driver. This includes:

Examples

For a list of examples related to this driver, see Examples for AT25DFx SerialFlash Driver.

API Overview

Modules

 Quick Start Guide(s)
 In this section you can find a list of all Quick Start guides related to the AT25DFx SerialFlash Driver.
 

Data Structures

struct  at25dfx_chip_config
 SerialFlash chip configuration. More...
 
struct  at25dfx_chip_module
 SerialFlash chip driver instance. More...
 

Typedefs

typedef uint32_t at25dfx_address_t
 SerialFlash internal address. More...
 
typedef uint16_t at25dfx_datalen_t
 Length of data package to read/write. More...
 

Enumerations

enum  at25dfx_block_size {
  AT25DFX_BLOCK_SIZE_4KB,
  AT25DFX_BLOCK_SIZE_32KB,
  AT25DFX_BLOCK_SIZE_64KB
}
 Size of block to erase. More...
 
enum  at25dfx_type {
  AT25DFX_512B,
  AT25DFX_021,
  AT25DFX_041A,
  AT25DFX_081,
  AT25DFX_081A,
  AT25DFX_161,
  AT25DFX_L161,
  AT25DFX_Q161,
  AT25DFX_321A,
  AT25DFX_641,
  AT25DFX_041B
}
 SerialFlash type. More...
 
typedef struct
spi_master_vec_module 
at25dfx_spi_module_t
 Typedef for SPI HAL. More...
 
static void at25dfx_spi_master_vec_get_config_defaults (struct spi_master_vec_config *const config)
 Initialize SPI configuration. More...
 
typedef struct spi_module at25dfx_spi_module_t
 Typedef for SPI HAL. More...
 
static void at25dfx_spi_get_config_defaults (struct spi_config *const config)
 Initialize SPI configuration. More...
 

Initialization

static enum status_code at25dfx_chip_init (struct at25dfx_chip_module *const module, at25dfx_spi_module_t *const spi_module, const struct at25dfx_chip_config *const config)
 Initialize chip driver instance. More...
 

Presence

enum status_code at25dfx_chip_check_presence (struct at25dfx_chip_module *chip)
 Check presence of chip. More...
 

Read/Write

enum status_code at25dfx_chip_read_buffer (struct at25dfx_chip_module *chip, at25dfx_address_t address, void *data, at25dfx_datalen_t length)
 Read data from chip. More...
 
enum status_code at25dfx_chip_write_buffer (struct at25dfx_chip_module *chip, at25dfx_address_t address, const void *data, at25dfx_datalen_t length)
 Write data to chip. More...
 

Erase

enum status_code at25dfx_chip_erase (struct at25dfx_chip_module *chip)
 Erase chip. More...
 
enum status_code at25dfx_chip_erase_block (struct at25dfx_chip_module *chip, at25dfx_address_t address, enum at25dfx_block_size block_size)
 Erase block. More...
 

Sector Protect

enum status_code at25dfx_chip_set_global_sector_protect (struct at25dfx_chip_module *chip, bool protect)
 Set sector protection globally. More...
 
enum status_code at25dfx_chip_set_sector_protect (struct at25dfx_chip_module *chip, at25dfx_address_t address, bool protect)
 Set protection setting of a single sector. More...
 
enum status_code at25dfx_chip_get_sector_protect (struct at25dfx_chip_module *chip, at25dfx_address_t address, bool *protect)
 Get protection setting of a single sector. More...
 

Sleep/Wake

enum status_code at25dfx_chip_sleep (struct at25dfx_chip_module *chip)
 Put device to sleep. More...
 
enum status_code at25dfx_chip_wake (struct at25dfx_chip_module *chip)
 Wake device from sleep. More...
 

typedef uint32_t at25dfx_address_t

SerialFlash internal address.

typedef uint16_t at25dfx_datalen_t

Length of data package to read/write.

Typedef for SPI HAL.

Typedef for SPI HAL.

Size of block to erase.

Enumerator
AT25DFX_BLOCK_SIZE_4KB 

4 kiloByte block size.

AT25DFX_BLOCK_SIZE_32KB 

32 kiloByte block size.

AT25DFX_BLOCK_SIZE_64KB 

64 kiloByte block size.

SerialFlash type.

Enumerator
AT25DFX_512B 

AT25F512B, compatible with AT25BCM512B.

AT25DFX_021 

AT25DF021.

AT25DFX_041A 

AT25DF041A.

AT25DFX_081 

AT25DF081, compatible with AT25DL081.

AT25DFX_081A 

AT25DF081A, compatible with AT26DF081A.

AT25DFX_161 

AT25DF161.

AT25DFX_L161 

AT25DL161.

AT25DFX_Q161 

AT25DQ161.

AT25DFX_321A 

AT25DF321A.

AT25DFX_641 

AT25DF641, compatible with AT25DF641A.

AT25DFX_041B 

AT25DF041B.

enum status_code at25dfx_chip_check_presence ( struct at25dfx_chip_module chip)

Check presence of chip.

This function checks whether or not the SerialFlash device is present by attempting to read out its device ID, and comparing it with the one that its type should have.

Parameters
[in]chipAddress of SerialFlash chip instance to operate on.
Returns
Status of operation.
Return values
STATUS_OKif chip responded with ID matching its type.
STATUS_BUSYif SPI is busy with some other operation.
STATUS_ERR_NOT_FOUNDif chip did not respond, or with wrong ID.

References _at25dfx_chip_issue_read_command_wait(), _at25dfx_get_device_id(), _at25dfx_spi_lock, _at25dfx_spi_unlock, at25dfx_command::address, Assert, AT25DFX_COMMAND_READ_DEVICE_ID, at25dfx_command::command_size, at25dfx_command::data, at25dfx_command::length, NULL, at25dfx_command::opcode, at25dfx_command::rx, status, STATUS_BUSY, STATUS_ERR_NOT_FOUND, and STATUS_OK.

Referenced by main(), and run_check_presence_test().

enum status_code at25dfx_chip_erase ( struct at25dfx_chip_module chip)

Erase chip.

This function erases all content of the SerialFlash device.

Precondition
All sectors must be unprotected prior to a chip erase, or it will not be performed.
See Also
at25dfx_chip_set_global_sector_protect()
Parameters
[in]chipAddress of SerialFlash chip instance to operate on.
Returns
Status of operation.
Return values
STATUS_OKif operation succeeded.
STATUS_ERR_IOif operation failed.
STATUS_BUSYif SPI is busy with some other operation.

References _at25dfx_chip_enable_write(), _at25dfx_chip_get_nonbusy_status(), _at25dfx_chip_issue_write_command_wait(), _at25dfx_spi_lock, _at25dfx_spi_unlock, at25dfx_command::address, Assert, AT25DFX_COMMAND_ERASE_CHIP, at25dfx_command::command_size, at25dfx_command::data, at25dfx_command::length, NULL, at25dfx_command::opcode, status, STATUS_BUSY, and at25dfx_command::tx.

Referenced by run_erase_test(), run_global_sector_protect_test(), and run_read_write_buffer_test().

enum status_code at25dfx_chip_erase_block ( struct at25dfx_chip_module chip,
at25dfx_address_t  address,
enum at25dfx_block_size  block_size 
)

Erase block.

This function erases all content within a block of the SerialFlash device.

Precondition
The sector(s) which the block resides in must be unprotected prior to a block erase, or it will not be performed.
See Also
at25dfx_chip_set_sector_protect()
Note
The alignment of the erase blocks is given by the erase block size. The SerialFlash device will simply ignore address bits which index within the block. For example, doing a 4 kB block erase with the start address set to the 2 kB boundary will cause the first 4 kB to get erased, not 4 kB starting at the 2 kB boundary.
Parameters
[in]chipAddress of SerialFlash chip instance to operate on.
[in]addressAddress within the block to erase.
[in]block_sizeSize of block to erase.
Returns
Status of operation.
Return values
STATUS_OKif operation succeeded.
STATUS_ERR_IOif operation failed.
STATUS_BUSYif SPI is busy with some other operation.
STATUS_ERR_INVALID_ARGif address is out of bounds.

References _at25dfx_chip_enable_write(), _at25dfx_chip_get_nonbusy_status(), _at25dfx_chip_issue_write_command_wait(), _at25dfx_get_device_size(), _at25dfx_spi_lock, _at25dfx_spi_unlock, at25dfx_command::address, Assert, AT25DFX_BLOCK_SIZE_32KB, AT25DFX_BLOCK_SIZE_4KB, AT25DFX_BLOCK_SIZE_64KB, AT25DFX_COMMAND_ERASE_BLOCK_32KB, AT25DFX_COMMAND_ERASE_BLOCK_4KB, AT25DFX_COMMAND_ERASE_BLOCK_64KB, at25dfx_command::command_size, at25dfx_command::data, at25dfx_command::length, NULL, at25dfx_command::opcode, status, STATUS_BUSY, STATUS_ERR_INVALID_ARG, and at25dfx_command::tx.

Referenced by main(), run_erase_block_test(), and run_sleep_wake_test().

enum status_code at25dfx_chip_get_sector_protect ( struct at25dfx_chip_module chip,
at25dfx_address_t  address,
bool protect 
)

Get protection setting of a single sector.

This function gets the protect setting of a single sector.

See Also
at25dfx_chip_set_sector_protect()
Parameters
[in]chipAddress of SerialFlash chip instance to operate on.
[in]addressAddress within sector to get setting of.
[out]boolAddress of variable to store the setting to.
Returns
Status of operation.
Return values
STATUS_OKif operation succeeded.
STATUS_BUSYif SPI is busy with some other operation.
STATUS_ERR_INVALID_ARGif address is out of bounds.

References _at25dfx_chip_issue_read_command_wait(), _at25dfx_get_device_size(), _at25dfx_spi_lock, _at25dfx_spi_unlock, at25dfx_command::address, Assert, AT25DFX_COMMAND_READ_PROTECT_SECTOR, at25dfx_command::command_size, at25dfx_command::data, at25dfx_command::length, at25dfx_command::opcode, at25dfx_command::rx, status, STATUS_BUSY, STATUS_ERR_INVALID_ARG, and STATUS_OK.

Referenced by run_set_get_sector_protect_test().

static enum status_code at25dfx_chip_init ( struct at25dfx_chip_module *const  module,
at25dfx_spi_module_t *const  spi_module,
const struct at25dfx_chip_config *const  config 
)
inlinestatic

Initialize chip driver instance.

This function initializes a chip instance and associates it with a specified SPI instance.

Parameters
[out]modulePointer to the chip instance to initialize.
[in]spi_modulePointer to the SPI instance to associate with.
[in]configPointer to the configuration for the chip.

References at25dfx_chip_config::cs_pin, port_config::direction, port_get_config_defaults(), PORT_PIN_DIR_OUTPUT, port_pin_set_config(), port_pin_set_output_level(), STATUS_OK, and at25dfx_chip_config::type.

Referenced by at25dfx_init(), and test_at25dfx_init().

enum status_code at25dfx_chip_read_buffer ( struct at25dfx_chip_module chip,
at25dfx_address_t  address,
void *  data,
at25dfx_datalen_t  length 
)

Read data from chip.

This function reads data from the SerialFlash device, into a buffer.

Parameters
[in]chipAddress of SerialFlash chip instance to operate on.
[in]addressSerialFlash internal address to start reading from.
[out]dataBuffer to write data into.
[in]lengthNumber of bytes to read.
Returns
Status of operation.
Return values
STATUS_OKif operation succeeded.
STATUS_BUSYif SPI is busy with some other operation.
STATUS_ERR_INVALID_ARGif address and/or length is out of bounds.

References _at25dfx_chip_issue_read_command_wait(), _at25dfx_get_device_size(), _at25dfx_spi_lock, _at25dfx_spi_unlock, at25dfx_command::address, Assert, AT25DFX_COMMAND_READ_ARRAY, at25dfx_command::command_size, at25dfx_command::data, at25dfx_command::length, length, at25dfx_command::opcode, at25dfx_command::rx, status, STATUS_BUSY, STATUS_ERR_INVALID_ARG, and STATUS_OK.

Referenced by main(), run_erase_block_test(), run_erase_test(), run_global_sector_protect_test(), run_read_write_buffer_test(), and run_sleep_wake_test().

enum status_code at25dfx_chip_set_global_sector_protect ( struct at25dfx_chip_module chip,
bool  protect 
)

Set sector protection globally.

This function applies a protect setting to all sectors.

Note
Global setting of sector protection is done by writing to the status register of the device.
Parameters
[in]chipAddress of SerialFlash chip instance to operate on.
[in]boolProtection setting to apply.
  • true if the sectors should be protected.
  • false if the sectors should be unprotected.
Returns
Status of operation.
Return values
STATUS_OKif write operation succeeded.
STATUS_BUSYif SPI is busy with some other operation.

References _at25dfx_chip_enable_write(), _at25dfx_chip_issue_write_command_wait(), _at25dfx_spi_lock, _at25dfx_spi_unlock, at25dfx_command::address, Assert, AT25DFX_COMMAND_WRITE_STATUS, AT25DFX_STATUS_GLOBAL_PROTECT, at25dfx_command::command_size, at25dfx_command::data, at25dfx_command::length, NULL, at25dfx_command::opcode, status, STATUS_BUSY, STATUS_OK, and at25dfx_command::tx.

Referenced by main(), run_erase_block_test(), run_erase_test(), run_global_sector_protect_test(), run_read_write_buffer_test(), run_set_get_sector_protect_test(), and run_sleep_wake_test().

enum status_code at25dfx_chip_set_sector_protect ( struct at25dfx_chip_module chip,
at25dfx_address_t  address,
bool  protect 
)

Set protection setting of a single sector.

This function applies a protect setting to a single sector.

Note
The granularity of the sectors for protection can vary between SerialFlash devices and is not necessarily uniform. Please refer to the datasheet for details.
Parameters
[in]chipAddress of SerialFlash chip instance to operate on.
[in]addressAddress within sector to protect.
[in]boolProtection setting to apply.
  • true if the sector should be protected.
  • false if the sector should be unprotected.
Returns
Status of operation.
Return values
STATUS_OKif write operation succeeded.
STATUS_BUSYif SPI is busy with some other operation.
STATUS_ERR_INVALID_ARGif address is out of bounds.

References _at25dfx_chip_enable_write(), _at25dfx_chip_issue_write_command_wait(), _at25dfx_get_device_size(), _at25dfx_spi_lock, _at25dfx_spi_unlock, at25dfx_command::address, Assert, AT25DFX_COMMAND_PROTECT_SECTOR, AT25DFX_COMMAND_UNPROTECT_SECTOR, at25dfx_command::command_size, at25dfx_command::data, at25dfx_command::length, NULL, at25dfx_command::opcode, status, STATUS_BUSY, STATUS_ERR_INVALID_ARG, STATUS_OK, and at25dfx_command::tx.

Referenced by main(), and run_set_get_sector_protect_test().

enum status_code at25dfx_chip_sleep ( struct at25dfx_chip_module chip)

Put device to sleep.

This function puts the SerialFlash device to sleep for the purpose of reducing power consumption while the device is not needed.

See Also
at25dfx_chip_wake()
Note
The device will not respond to any commands until it is woken up.
Parameters
[in]chipAddress of SerialFlash chip instance to operate on.
Returns
Status of operation.
Return values
STATUS_OKif write operation succeeded.
STATUS_BUSYif SPI is busy with some other operation.

References _at25dfx_chip_issue_write_command_wait(), _at25dfx_spi_lock, _at25dfx_spi_unlock, at25dfx_command::address, Assert, AT25DFX_COMMAND_SLEEP, at25dfx_command::command_size, at25dfx_command::data, at25dfx_command::length, NULL, at25dfx_command::opcode, status, STATUS_BUSY, STATUS_OK, and at25dfx_command::tx.

Referenced by main(), and run_sleep_wake_test().

enum status_code at25dfx_chip_wake ( struct at25dfx_chip_module chip)

Wake device from sleep.

This function wakes the SerialFlash device from sleep.

See Also
at25dfx_chip_sleep()
Parameters
[in]chipAddress of SerialFlash chip instance to operate on.
Returns
Status of operation.
Return values
STATUS_OKif write operation succeeded.
STATUS_BUSYif SPI is busy with some other operation.

References _at25dfx_chip_issue_write_command_wait(), _at25dfx_spi_lock, _at25dfx_spi_unlock, at25dfx_command::address, Assert, AT25DFX_COMMAND_WAKE, at25dfx_command::command_size, at25dfx_command::data, at25dfx_command::length, NULL, at25dfx_command::opcode, status, STATUS_BUSY, STATUS_OK, and at25dfx_command::tx.

Referenced by main(), and run_sleep_wake_test().

enum status_code at25dfx_chip_write_buffer ( struct at25dfx_chip_module chip,
at25dfx_address_t  address,
const void *  data,
at25dfx_datalen_t  length 
)

Write data to chip.

This function writes data to the SerialFlash device, from a buffer.

Parameters
[in]chipAddress of SerialFlash chip instance to operate on.
[in]addressSerialFlash internal address to start writing to.
[in]dataBuffer to read data from.
[in]lengthNumber of bytes to write.
Returns
Status of operation.
Return values
STATUS_OKif operation succeeded.
STATUS_ERR_IOif operation failed.
STATUS_BUSYif SPI is busy with some other operation.
STATUS_ERR_INVALID_ARGif address and/or length is out of bounds.

References _at25dfx_chip_enable_write(), _at25dfx_chip_get_nonbusy_status(), _at25dfx_chip_issue_write_command_wait(), _at25dfx_get_device_size(), _at25dfx_spi_lock, _at25dfx_spi_unlock, at25dfx_command::address, Assert, AT25DFX_COMMAND_PROGRAM_PAGE, AT25DFX_PAGE_SIZE, at25dfx_command::command_size, at25dfx_command::data, at25dfx_command::length, min, at25dfx_command::opcode, status, STATUS_BUSY, STATUS_ERR_INVALID_ARG, STATUS_OK, and at25dfx_command::tx.

Referenced by main(), run_erase_block_test(), run_erase_test(), run_global_sector_protect_test(), run_read_write_buffer_test(), and run_sleep_wake_test().

static void at25dfx_spi_get_config_defaults ( struct spi_config *const  config)
inlinestatic

Initialize SPI configuration.

This function initializes the SPI configuration struct with default settings that should work with SerialFlash devices.

The user can change the baud rate and the MUX settings for SERCOM and GPIO pads, but should leave all other settings intact.

Parameters
[out]configAddress of config struct to initialize.

References spi_get_config_defaults().

Referenced by at25dfx_init(), and test_at25dfx_init().

static void at25dfx_spi_master_vec_get_config_defaults ( struct spi_master_vec_config *const  config)
inlinestatic

Initialize SPI configuration.

This function initializes the SPI configuration struct with default settings that should work with SerialFlash devices.

The user can change the baud rate and the MUX settings for SERCOM and GPIO pads, but should leave all other settings intact.

Parameters
[out]configAddress of config struct to initialize.

References spi_master_vec_get_config_defaults().

Referenced by test_at25dfx_init().