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:
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.
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.
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.
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.
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.
The reader should be aware of some details of how flash memory generally functions:
0xFF
.For extra information, see Extra Information for AT25DFx SerialFlash Driver. This includes:
For a list of examples related to this driver, see Examples for AT25DFx SerialFlash Driver.
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 struct spi_module at25dfx_spi_module_t |
Typedef for SPI HAL.
typedef struct spi_master_vec_module at25dfx_spi_module_t |
Typedef for SPI HAL.
enum at25dfx_block_size |
enum at25dfx_type |
SerialFlash type.
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.
[in] | chip | Address of SerialFlash chip instance to operate on. |
STATUS_OK | if chip responded with ID matching its type. |
STATUS_BUSY | if SPI is busy with some other operation. |
STATUS_ERR_NOT_FOUND | if 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.
[in] | chip | Address of SerialFlash chip instance to operate on. |
STATUS_OK | if operation succeeded. |
STATUS_ERR_IO | if operation failed. |
STATUS_BUSY | if 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.
[in] | chip | Address of SerialFlash chip instance to operate on. |
[in] | address | Address within the block to erase. |
[in] | block_size | Size of block to erase. |
STATUS_OK | if operation succeeded. |
STATUS_ERR_IO | if operation failed. |
STATUS_BUSY | if SPI is busy with some other operation. |
STATUS_ERR_INVALID_ARG | if 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.
[in] | chip | Address of SerialFlash chip instance to operate on. |
[in] | address | Address within sector to get setting of. |
[out] | bool | Address of variable to store the setting to. |
STATUS_OK | if operation succeeded. |
STATUS_BUSY | if SPI is busy with some other operation. |
STATUS_ERR_INVALID_ARG | if 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().
|
inlinestatic |
Initialize chip driver instance.
This function initializes a chip instance and associates it with a specified SPI instance.
[out] | module | Pointer to the chip instance to initialize. |
[in] | spi_module | Pointer to the SPI instance to associate with. |
[in] | config | Pointer 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.
[in] | chip | Address of SerialFlash chip instance to operate on. |
[in] | address | SerialFlash internal address to start reading from. |
[out] | data | Buffer to write data into. |
[in] | length | Number of bytes to read. |
STATUS_OK | if operation succeeded. |
STATUS_BUSY | if SPI is busy with some other operation. |
STATUS_ERR_INVALID_ARG | if 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.
[in] | chip | Address of SerialFlash chip instance to operate on. |
[in] | bool | Protection setting to apply.
|
STATUS_OK | if write operation succeeded. |
STATUS_BUSY | if 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.
[in] | chip | Address of SerialFlash chip instance to operate on. |
[in] | address | Address within sector to protect. |
[in] | bool | Protection setting to apply.
|
STATUS_OK | if write operation succeeded. |
STATUS_BUSY | if SPI is busy with some other operation. |
STATUS_ERR_INVALID_ARG | if 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.
[in] | chip | Address of SerialFlash chip instance to operate on. |
STATUS_OK | if write operation succeeded. |
STATUS_BUSY | if 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.
[in] | chip | Address of SerialFlash chip instance to operate on. |
STATUS_OK | if write operation succeeded. |
STATUS_BUSY | if 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.
[in] | chip | Address of SerialFlash chip instance to operate on. |
[in] | address | SerialFlash internal address to start writing to. |
[in] | data | Buffer to read data from. |
[in] | length | Number of bytes to write. |
STATUS_OK | if operation succeeded. |
STATUS_ERR_IO | if operation failed. |
STATUS_BUSY | if SPI is busy with some other operation. |
STATUS_ERR_INVALID_ARG | if 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().
|
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.
[out] | config | Address of config struct to initialize. |
References spi_get_config_defaults().
Referenced by at25dfx_init(), and test_at25dfx_init().
|
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.
[out] | config | Address of config struct to initialize. |
References spi_master_vec_get_config_defaults().
Referenced by test_at25dfx_init().