spi_flash: support working on differnt buses and frequency

This commit is contained in:
Michael (XIAO Xufeng)
2019-01-08 18:29:25 +08:00
committed by bot
parent ce4de867d6
commit 1036a091fe
52 changed files with 3974 additions and 1727 deletions

View File

@@ -1,31 +1,28 @@
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include "esp_err.h"
#include <stdint.h>
#include <stdbool.h>
#include "soc/spi_struct.h"
#include "hal/spi_flash_host_drv.h"
struct esp_flash_driver;
struct spi_flash_chip_t;
typedef struct spi_flash_chip_t spi_flash_chip_t;
/** @brief Mode used for reading from SPI flash */
typedef enum {
ESP_FLASH_QIO, ///< Both address & data transferred using quad I/O
ESP_FLASH_QOUT, ///< Data read using quad I/O
ESP_FLASH_DIO, ///< Both address & data transferred using dual I/O
ESP_FLASH_DOUT, ///< Data read using dual I/O
ESP_FLASH_FASTRD, ///< Data read using single I/O, no limit on speed
ESP_FLASH_SLOWRD, ///< Data read using single I/O, some limits on speed
ESP_FLASH_READ_MODE_MAX,
} esp_flash_read_mode_t;
/** @brief Configured SPI flash clock speed */
typedef enum {
ESP_FLASH_80MHZ,
ESP_FLASH_40MHZ,
ESP_FLASH_26MHZ,
ESP_FLASH_20MHZ,
ESP_FLASH_SPEED_MAX,
} esp_flash_speed_t;
typedef struct esp_flash_t esp_flash_t;
/** @brief Structure for describing a region of flash */
typedef struct {
@@ -33,56 +30,60 @@ typedef struct {
uint32_t size;
} esp_flash_region_t;
// TODO this is copied from SPI driver, should be unified somehow
/* OS-level integration hooks for accessing flash chips inside a running OS */
typedef struct {
int mosi_io_num; ///< GPIO pin for Master Out Slave In (=spi_d) signal
int miso_io_num; ///< GPIO pin for Master In Slave Out (=spi_q) signal
int sclk_io_num; ///< GPIO pin for Spi CLocK signal
int quadwp_io_num; ///< GPIO pin for WP (Write Protect) signal which is used as D2 in 4-bit communication modes, or -1 if not used.
int quadhd_io_num; ///< GPIO pin for HD (HolD) signal which is used as D3 in 4-bit communication modes, or -1 if not used.
} esp_flash_pin_cfg_t;
/**
* Called before commencing any flash operation. Does not need to be
* recursive (ie is called at most once for each call to 'end').
*/
esp_err_t (*start)(void *arg);
/** Called after completing any flash operation. */
esp_err_t (*end)(void *arg);
/** Delay for at least 'ms' milliseconds. Called in between 'start' and 'end'. */
esp_err_t (*delay_ms)(void *arg, unsigned ms);
} esp_flash_os_functions_t;
/** @brief Structure to describe a SPI flash chip connected to the system.
Structure must be passed to esp_flash_init() before use.
*/
typedef struct {
spi_dev_t *spi; ///< Pointer to hardware SPI bus registers used for connection (SP1, SPI2 or SPI3). Set before initialisation.
esp_flash_speed_t speed; ///< Configured SPI flash clock speed. Set before initialisation.
struct esp_flash_t {
const spi_flash_chip_t *chip_drv; ///< Pointer to chip-model-specific "adpater" structure. If NULL, will be detected during initialisatiopn.
spi_flash_host_driver_t *host; ///< Pointer to hardware-specific "host_driver" structure.
const esp_flash_os_functions_t *os_func; ///< Pointer to os-specific hooker strcuture.
void *os_func_data; ///< Pointer to argument for os-specific hooker.
esp_flash_read_mode_t read_mode; ///< Configured SPI flash read mode. Set before initialisation.
uint32_t size; ///< Size of SPI flash in bytes. If 0, size will be detected during initialisation.
const struct esp_flash_driver *drv; ///< Pointer to chip-model-specific "driver" structure. If NULL, will be detected during initialisatiopn.
const esp_flash_pin_cfg_t *pins; ///< Pin configuration for the chip
};
void *driver_data; ///< Currently unused, allows drivers to store driver-implementation-specific data on initialisation
} esp_flash_chip_t;
/** @brief Possible errors returned from SPI flash low-level API */
typedef enum {
FLASH_OK = 0, ///< Success
FLASH_ERR_NOT_INITIALISED, ///< esp_flash_chip_t structure not correctly initialised by esp_flash_init().
FLASH_ERR_INVALID_ARG, ///< A supplied argument was invalid.
FLASH_ERR_NOT_FOUND, ///< A requested value is not found.
FLASH_ERR_NO_RESPONSE, ///< Chip did not respond to the command, or timed out.
FLASH_ERR_UNSUPPORTED_HOST, ///< Requested operation isn't supported via this host SPI bus (chip->spi field).
FLASH_ERR_UNSUPPORTED_CHIP, ///< Requested operation isn't supported by this model of SPI flash chip.
FLASH_ERR_PROTECTED, ///< Write operation failed due to chip's write protection being enabled.
} esp_flash_err_t;
/** @brief Initialise SPI flash chip interface.
*
*
* This function must be called before any other API functions are called for this chip.
*
* @note Only the spi, speed & read_mode fields of the chip structure need to be initialised. Other fields will be auto-detected
* if left set to zero or NULL.
*
* @note If the chip->drv pointer is NULL, chip driver will be autodetected based on its manufacturer & product IDs. See
* @note If the chip->drv pointer is NULL, chip chip_drv will be autodetected based on its manufacturer & product IDs. See
* esp_flash_registered_flash_drivers pointer for details of this process.
*
* @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.
* @return FLASH_OK on success, or a flash error code if initialisation fails.
* @return ESP_OK on success, or a flash error code if initialisation fails.
*/
esp_flash_err_t esp_flash_init(esp_flash_chip_t *chip);
esp_err_t esp_flash_init(esp_flash_t *chip);
/**
* Check if appropriate chip driver is set.
*
* @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.
*
* @return true if set, otherwise false.
*/
bool esp_flash_chip_driver_initialized(const esp_flash_t *chip);
/** @brief Read flash ID via the common "RDID" SPI flash command.
*
@@ -91,9 +92,9 @@ esp_flash_err_t esp_flash_init(esp_flash_chip_t *chip);
*
* ID is a 24-bit value. Lower 16 bits of 'id' are the chip ID, upper 8 bits are the manufacturer ID.
*
* @return FLASH_OK on success, or a flash error code if operation failed.
* @return ESP_OK on success, or a flash error code if operation failed.
*/
esp_flash_err_t esp_flash_read_id(const esp_flash_chip_t *chip, uint32_t *id);
esp_err_t esp_flash_read_id(esp_flash_t *chip, uint32_t *id);
/** @brief Detect flash size based on flash ID.
*
@@ -103,18 +104,18 @@ esp_flash_err_t esp_flash_read_id(const esp_flash_chip_t *chip, uint32_t *id);
* @note Most flash chips use a common format for flash ID, where the lower 4 bits specify the size as a power of 2. If
* the manufacturer doesn't follow this convention, the size may be incorrectly detected.
*
* @return FLASH_OK on success, or a flash error code if operation failed.
* @return ESP_OK on success, or a flash error code if operation failed.
*/
esp_flash_err_t esp_flash_detect_size(const esp_flash_chip_t *chip, uint32_t *size);
esp_err_t esp_flash_get_size(esp_flash_t *chip, uint32_t *size);
/** @brief Erase flash chip contents
*
* @param chip Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()
*
*
* @return FLASH_OK on success, or a flash error code if operation failed.
* @return ESP_OK on success, or a flash error code if operation failed.
*/
esp_flash_err_t esp_flash_erase_chip(const esp_flash_chip_t *chip);
esp_err_t esp_flash_erase_chip(esp_flash_t *chip);
/** @brief Erase a region of the flash chip
*
@@ -122,45 +123,45 @@ esp_flash_err_t esp_flash_erase_chip(const esp_flash_chip_t *chip);
* @param start Address to start erasing flash. Must be sector aligned.
* @param len Length of region to erase. Must also be sector aligned.
*
* Sector size is specifyed in chip->drv->sector_size field (typically 4096 bytes.) FLASH_ERR_INVALID_ARG will be
* Sector size is specifyed in chip->drv->sector_size field (typically 4096 bytes.) ESP_ERR_INVALID_ARG will be
* returned if the start & length are not a multiple of this size.
*
* Erase is performed using block (multi-sector) erases where possible (block size is specified in
* chip->drv->block_erase_size field, typically 65536 bytes). Remaining sectors are erased using individual sector erase
* commands.
*
* @return FLASH_OK on success, or a flash error code if operation failed.
* @return ESP_OK on success, or a flash error code if operation failed.
*/
esp_flash_err_t esp_flash_erase_region(const esp_flash_chip_t *chip, uint32_t start, uint32_t len);
esp_err_t esp_flash_erase_region(esp_flash_t *chip, uint32_t start, uint32_t len);
/** @brief Read if the entire chip is write protected
*
* @param chip Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()
* @param[out] write_protected Pointer to boolean, set to the value of the write protect flag.
*
* @note A correct result for this flag depends on the SPI flash chip model and driver in use (via the 'chip->drv'
* @note A correct result for this flag depends on the SPI flash chip model and chip_drv in use (via the 'chip->drv'
* field).
*
* @return FLASH_OK on success, or a flash error code if operation failed.
* @return ESP_OK on success, or a flash error code if operation failed.
*/
esp_flash_err_t esp_flash_get_chip_write_protect(const esp_flash_chip_t *chip, bool *write_protected);
esp_err_t esp_flash_get_chip_write_protect(esp_flash_t *chip, bool *write_protected);
/** @brief Set write protection for the SPI flash chip
*
* @param chip Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()
* @param write_protected Boolean value for the write protect flag
*
* @note Correct behaviour of this function depends on the SPI flash chip model and driver in use (via the 'chip->drv'
* @note Correct behaviour of this function depends on the SPI flash chip model and chip_drv in use (via the 'chip->drv'
* field).
*
* If write protection is enabled, destructive operations will fail with FLASH_ERR_PROTECTED.
* If write protection is enabled, destructive operations will fail with ESP_ERR_FLASH_PROTECTED.
*
* Some SPI flash chips may require a power cycle before write protect status can be cleared. Otherwise,
* write protection can be removed via a follow-up call to this function.
*
* @return FLASH_OK on success, or a flash error code if operation failed.
* @return ESP_OK on success, or a flash error code if operation failed.
*/
esp_flash_err_t esp_flash_set_chip_write_protect(const esp_flash_chip_t *chip, bool write_protect_chip);
esp_err_t esp_flash_set_chip_write_protect(esp_flash_t *chip, bool write_protect_chip);
/** @brief Read the list of individually protectable regions of this SPI flash chip.
@@ -169,12 +170,13 @@ esp_flash_err_t esp_flash_set_chip_write_protect(const esp_flash_chip_t *chip, b
* @param regions[out] Pointer to receive a pointer to the array of protectable regions of the chip.
* @param[out] Pointer to an integer receiving the count of protectable regions in the array returned in 'regions'.
*
* @note Correct behaviour of this function depends on the SPI flash chip model and driver in use (via the 'chip->drv'
* @note Correct behaviour of this function depends on the SPI flash chip model and chip_drv in use (via the 'chip->drv'
* field).
*
* @return FLASH_OK on success, or a flash error code if operation failed.
* @return ESP_OK on success, or a flash error code if operation failed.
*/
esp_flash_err_t esp_flash_get_protectable_regions(const esp_flash_chip_t *chip, const esp_flash_region_t **regions, uint32_t *num_regions);
esp_err_t
esp_flash_get_protectable_regions(const esp_flash_t *chip, const esp_flash_region_t **regions, uint32_t *num_regions);
/** @brief Detect if a region of the SPI flash chip is protected
@@ -185,12 +187,12 @@ esp_flash_err_t esp_flash_get_protectable_regions(const esp_flash_chip_t *chip,
*
* @note It is possible for this result to be false and write operations to still fail, if protection is enabled for the entire chip.
*
* @note Correct behaviour of this function depends on the SPI flash chip model and driver in use (via the 'chip->drv'
* @note Correct behaviour of this function depends on the SPI flash chip model and chip_drv in use (via the 'chip->drv'
* field).
*
* @return FLASH_OK on success, or a flash error code if operation failed.
* @return ESP_OK on success, or a flash error code if operation failed.
*/
esp_flash_err_t esp_flash_get_protected_region(const esp_flash_chip_t *chip, const esp_flash_region_t *region, bool *protected);
esp_err_t esp_flash_get_protected_region(esp_flash_t *chip, const esp_flash_region_t *region, bool *protected);
/** @brief Update the protected status for a region of the SPI flash chip
*
@@ -200,17 +202,17 @@ esp_flash_err_t esp_flash_get_protected_region(const esp_flash_chip_t *chip, con
*
* @note It is possible for the region protection flag to be cleared and write operations to still fail, if protection is enabled for the entire chip.
*
* @note Correct behaviour of this function depends on the SPI flash chip model and driver in use (via the 'chip->drv'
* @note Correct behaviour of this function depends on the SPI flash chip model and chip_drv in use (via the 'chip->drv'
* field).
*
* @return FLASH_OK on success, or a flash error code if operation failed.
* @return ESP_OK on success, or a flash error code if operation failed.
*/
esp_flash_err_t esp_flash_set_protected_region(const esp_flash_chip_t *chip, const esp_flash_region_t *region, bool protected);
esp_err_t esp_flash_set_protected_region(esp_flash_t *chip, const esp_flash_region_t *region, bool protected);
/** @brief Read data from the SPI flash chip
*
* @param chip Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()
* @param buffer Pointer to a buffer where the data will be read.
* @param buffer Pointer to a buffer where the data will be read. To get better performance, this should be in the DRAM and word aligned.
* @param address Address on flash to read from. Must be less than chip->size field.
* @param length Length (in bytes) of data to read.
*
@@ -219,22 +221,26 @@ esp_flash_err_t esp_flash_set_protected_region(const esp_flash_chip_t *chip, con
* @note If on-chip flash encryption is used, this function returns raw (ie encrypted) data. Use the flash cache
* to transparently decrypt data.
*
* @return FLASH_OK on success, or a flash error code if operation failed.
* @return
* - ESP_OK: success
* - ESP_ERR_NO_MEM: the buffer is not valid, however failed to malloc on
* the heap.
* - or a flash error code if operation failed.
*/
esp_flash_err_t esp_flash_read(const esp_flash_chip_t *chip, void *buffer, uint32_t address, uint32_t length);
esp_err_t esp_flash_read(esp_flash_t *chip, void *buffer, uint32_t address, uint32_t length);
/** @brief Write data to the SPI flash chip
*
* @param chip Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()
* @param address Address on flash to write to. Must be previously erased (SPI NOR flash can only write bits 1->0).
* @param buffer Pointer to a buffer with the data to write.
* @param buffer Pointer to a buffer with the data to write. To get better performance, this should be in the DRAM and word aligned.
* @param length Length (in bytes) of data to write.
*
* There are no alignment constraints on buffer, address or length.
*
* @return FLASH_OK on success, or a flash error code if operation failed.
* @return ESP_OK on success, or a flash error code if operation failed.
*/
esp_flash_err_t esp_flash_write(const esp_flash_chip_t *chip, uint32_t address, const void *buffer, uint32_t length);
esp_err_t esp_flash_write(esp_flash_t *chip, const void *buffer, uint32_t address, uint32_t length);
/** @brief Encrypted and write data to the SPI flash chip using on-chip hardware flash encryption
*
@@ -245,21 +251,44 @@ esp_flash_err_t esp_flash_write(const esp_flash_chip_t *chip, uint32_t address,
*
* @note Both address & length must be 16 byte aligned, as this is the encryption block size
*
* @return FLASH_OK on success, or a flash error code if operation failed.
* @return ESP_OK on success, or a flash error code if operation failed.
*/
esp_flash_err_t esp_flash_write_encrypted(const esp_flash_chip_t *chip, uint32_t address, const void *buffer, uint32_t length);
esp_err_t esp_flash_write_encrypted(esp_flash_t *chip, uint32_t address, const void *buffer, uint32_t length);
/** @brief Pointer to the "default" SPI flash chip, ie the main chip attached to the MCU.
This chip is used if the 'chip' argument pass to esp_flash_xxx API functions is ever NULL.
*/
extern const esp_flash_chip_t *esp_flash_default_chip;
extern esp_flash_t *esp_flash_default_chip;
/** @brief Initialise the default SPI flash chip
*
* Called by OS startup code. You do not need to call this in your own applications.
*/
esp_flash_err_t esp_flash_init_default_chip();
esp_err_t esp_flash_init_default_chip();
/** Enable OS-level SPI flash protections in IDF */
void esp_flash_low_level_app_init(); /* ROM TODO move this to IDF */
/**
* Enable OS-level SPI flash protections in IDF
*
* @return ESP_OK if success, otherwise failed. See return value of ``esp_flash_init_os_functions``.
*/
esp_err_t esp_flash_app_init(); /* ROM TODO move this to IDF */
/**
* Enable OS-level SPI flash for a specific chip.
*
* @param chip The chip to init os functions.
* @param host_id Which SPI host to use, 0 for SPI1, 1 for HSPI2 and 2 for VSPI.
*
* @return ESP_OK if success, otherwise failed. See return value of ``esp_flash_init_os_functions``.
*/
esp_err_t esp_flash_init_os_functions(esp_flash_t *chip, int host_id);
/* The default (ie initial boot) no-OS ROM esp_flash_os_functions_t */
extern const esp_flash_os_functions_t spi1_default_os_functions; //todo: put into non-ROM headers
/* Pointer to the current esp_flash_os_functions_t structure in use.
Can be changed at runtime to reflect different running conditions.
*/
//extern const esp_flash_os_functions_t *os_func;

View File

@@ -25,7 +25,6 @@
extern "C" {
#endif
#define ESP_ERR_FLASH_BASE 0x10010
#define ESP_ERR_FLASH_OP_FAIL (ESP_ERR_FLASH_BASE + 1)
#define ESP_ERR_FLASH_OP_TIMEOUT (ESP_ERR_FLASH_BASE + 2)
@@ -36,7 +35,7 @@ extern "C" {
/**
* @brief Initialize SPI flash access driver
*
* This function must be called exactly once, before any other
* This function must be called exactly once, before any other
* spi_flash_* functions are called.
* Currently this function is called from startup code. There is
* no need to call it from application code.

View File

@@ -0,0 +1,111 @@
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include "hal/spi_flash_hal.h"
/** Default configuration for the memspi (high speed version) */
#define ESP_FLASH_DEFAULT_HOST_DRIVER() (spi_flash_host_driver_t) { \
.dev_config = spi_flash_hal_device_config, \
.common_command = spi_flash_hal_common_command, \
.read_id = memspi_host_read_id_hs, \
.erase_chip = spi_flash_hal_erase_chip, \
.erase_sector = spi_flash_hal_erase_sector, \
.erase_block = spi_flash_hal_erase_block, \
.read_status = memspi_host_read_status_hs, \
.set_write_protect = spi_flash_hal_set_write_protect, \
.supports_direct_write = spi_flash_hal_supports_direct_write, \
.supports_direct_read = spi_flash_hal_supports_direct_read, \
.program_page = spi_flash_hal_program_page, \
.max_write_bytes = SPI_FLASH_HAL_MAX_WRITE_BYTES, \
.read = spi_flash_hal_read, \
.max_read_bytes = SPI_FLASH_HAL_MAX_READ_BYTES, \
.host_idle = spi_flash_hal_host_idle, \
.configure_host_read_mode = spi_flash_hal_configure_host_read_mode, \
.poll_cmd_done = spi_flash_hal_poll_cmd_done, \
.flush_cache = memspi_host_flush_cache, \
.region_protected = memspi_region_protected, \
}
/// configuration for the memspi host
typedef spi_flash_memspi_config_t memspi_host_config_t;
/// context for the memspi host
typedef spi_flash_memspi_data_t memspi_host_data_t;
/**
* Initialize the memory SPI host.
*
* @param host Pointer to the host structure.
* @param data Pointer to allocated space to hold the context of host driver.
* @param cfg Pointer to configuration structure
*
* @return always return ESP_OK
*/
esp_err_t memspi_host_init_pointers(spi_flash_host_driver_t *host, memspi_host_data_t *data, const memspi_host_config_t *cfg);
/*******************************************************************************
* NOTICE
* Rest part of this file are part of the HAL layer
* The HAL is not public api, don't use in application code.
* See readme.md in soc/include/hal/readme.md
******************************************************************************/
/**
* High speed implementation of RDID through memspi interface relying on the
* ``common_command``.
*
* @param driver The driver context.
* @param id Output of the read ID from the slave.
*
* @return
* - ESP_OK: if success
* - ESP_ERR_FLASH_NO_RESPONSE: if no response from chip
* - or other cases from ``spi_hal_common_command``
*/
esp_err_t memspi_host_read_id_hs(spi_flash_host_driver_t *driver, uint32_t *id);
/**
* High speed implementation of RDSR through memspi interface relying on the
* ``common_command``.
*
* @param driver The driver context.
* @param id Output of the read ID from the slave.
*
* @return
* - ESP_OK: if success
* - or other cases from ``spi_hal_common_command``
*/
esp_err_t memspi_host_read_status_hs(spi_flash_host_driver_t *driver, uint8_t *out_sr);
/**
* Flush the cache (if needed) after the contents are modified.
*
* @param driver The driver context.
* @param addr Start address of the modified region
* @param size Size of the region modified.
*
* @return always ESP_OK.
*/
esp_err_t memspi_host_flush_cache(spi_flash_host_driver_t* driver, uint32_t addr, uint32_t size);
/**
* Check if the given region is protected.
*
* @param driver The driver context.
* @param addr Start address of the region.
* @param size Size of the region to check.
*
* @return true if protected, otherwise false.
*/
bool memspi_region_protected(spi_flash_host_driver_t* driver, uint32_t addr, uint32_t size);

View File

@@ -1,23 +1,43 @@
#pragma once
#include "spi_flash_lowlevel.h"
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/** @brief SPI flash driver definition structure.
#pragma once
#include "esp_flash.h"
struct esp_flash_t;
typedef struct esp_flash_t esp_flash_t;
typedef struct spi_flash_chip_t spi_flash_chip_t;
/** @brief SPI flash chip driver definition structure.
*
* The driver structure contains chip-specific pointers to functions to perform SPI flash operations, and some
* The chip driver structure contains chip-specific pointers to functions to perform SPI flash operations, and some
* chip-specific numeric values.
*
* @note This is not a public API. Driver-specific functions are called from the public API (declared in
* spi_flash_lowlevel.h). They assume the caller has already validated arguments and enabled relevant protections
* @note This is not a public API. These functions are called from the public API (declared in
* esp_flash.h). They assume the caller has already validated arguments and enabled relevant protections
* (disabling flash cache, prevent concurrent SPI access, etc.)
*
* Do not call driver functions directly in other contexts.
* Do not call chip driver functions directly in other contexts.
*
* A generic driver and it's related operations are defined in spi_flash_lowlevel_generic.h which can be used as
* building blocks for written new/specific SPI flash chip drivers.
* A generic driver for generic chips and its related operations are defined in
* spi_flash_chip_generic.h which can be used as building blocks for written
* new/specific SPI flash chip drivers.
*
* @note All of these functions may be called with SPI flash cache disabled, so must only ever access IRAM/DRAM/ROM.
*/
typedef struct esp_flash_driver {
struct spi_flash_chip_t {
const char *name; ///< Name of the chip driver
/* Probe to detect if a supported SPI flash chip is found.
*
* Attempts to configure 'chip' with these operations and probes for a matching SPI flash chip.
@@ -31,28 +51,25 @@ typedef struct esp_flash_driver {
* It is permissible for the driver to modify the 'chip' structure if probing succeeds (specifically, to assign something to the
* driver_data pointer if that is useful for the driver.)
*
* @return FLASH_OK if probing was successful, an error otherwise. Driver may
* assume that returning FLASH_OK means it has claimed this chip.
* @return ESP_OK if probing was successful, an error otherwise. Driver may
* assume that returning ESP_OK means it has claimed this chip.
*/
esp_flash_err_t (*probe)(esp_flash_chip_t *chip, uint32_t flash_id);
esp_err_t (*probe)(esp_flash_t *chip, uint32_t flash_id);
esp_err_t (*reset)(esp_flash_t *chip);
/* Read SPI flash ID
*
* Sends RDID (or an equivalent command) to the device.
*/
esp_flash_err_t (*read_id)(const esp_flash_chip_t *chip, uint32_t *id);
/* Detect SPI flash size
*
* Interrogate the chip to detect it's size.
* Interrogate the chip to detect its size.
*/
esp_flash_err_t (*detect_size)(const esp_flash_chip_t *chip, uint32_t *size);
esp_err_t (*detect_size)(esp_flash_t *chip, uint32_t *size);
/* Erase the entire chip
Caller has verified the chip is not write protected.
*/
esp_flash_err_t (*erase_chip)(const esp_flash_chip_t *chip);
esp_err_t (*erase_chip)(esp_flash_t *chip);
/* Erase a sector of the chip. Sector size is specified in the 'sector_size' field.
@@ -60,23 +77,23 @@ typedef struct esp_flash_driver {
Caller has verified that this sector should be non-write-protected.
*/
esp_flash_err_t (*erase_sector)(const esp_flash_chip_t *chip, uint32_t sector_address);
esp_err_t (*erase_sector)(esp_flash_t *chip, uint32_t sector_address);
/* Erase a multi-sector block of the chip. Block size is specified in the 'block_erase_size' field.
sector_address is an offset in bytes.
Caller has verified that this block should be non-write-protected.
*/
esp_flash_err_t (*erase_block)(const esp_flash_chip_t *chip, uint32_t block_address);
esp_err_t (*erase_block)(esp_flash_t *chip, uint32_t block_address);
uint32_t sector_size; /* Sector is minimum erase size */
uint32_t block_erase_size; /* Optimal (fastest) block size for multi-sector erases on this chip */
/* Read the write protect status of the entire chip. */
esp_flash_err_t (*get_chip_write_protect)(const esp_flash_chip_t *chip, bool *write_protected);
esp_err_t (*get_chip_write_protect)(esp_flash_t *chip, bool *write_protected);
/* Set the write protect status of the entire chip. */
esp_flash_err_t (*set_chip_write_protect)(const esp_flash_chip_t *chip, bool write_protect_chip);
esp_err_t (*set_chip_write_protect)(esp_flash_t *chip, bool write_protect_chip);
/* Number of individually write protectable regions on this chip. Range 0-63. */
uint8_t num_protectable_regions;
@@ -84,20 +101,20 @@ typedef struct esp_flash_driver {
const esp_flash_region_t *protectable_regions;
/* Get a bitmask describing all protectable regions on the chip. Each bit represents one entry in the
protectable_regions array, ie bit (1<<N) is set then the region at array entry N is write protected. */
esp_flash_err_t (*get_protected_regions)(const esp_flash_chip_t *chip, uint64_t *regions);
esp_err_t (*get_protected_regions)(esp_flash_t *chip, uint64_t *regions);
/* Set protectable regions on the chip. Each bit represents on entry in the protectable regions array. */
esp_flash_err_t (*set_protected_regions)(const esp_flash_chip_t *chip, uint64_t regions);
esp_err_t (*set_protected_regions)(esp_flash_t *chip, uint64_t regions);
/* Read data from the chip.
*
* Before calling this function, the caller will have called chip->drv->set_read_mode(chip) in order to configure the chip's read mode correctly.
*/
esp_flash_err_t (*read)(const esp_flash_chip_t *chip, void *buffer, uint32_t address, uint32_t length);
esp_err_t (*read)(esp_flash_t *chip, void *buffer, uint32_t address, uint32_t length);
/* Write any amount of data to the chip.
*/
esp_flash_err_t (*write)(const esp_flash_chip_t *chip, uint32_t address, const void *buffer, uint32_t length);
esp_err_t (*write)(esp_flash_t *chip, const void *buffer, uint32_t address, uint32_t length);
/* Use the page program command to write data to the chip.
@@ -110,33 +127,33 @@ typedef struct esp_flash_driver {
* - The region between 'address' and 'address + length' will not cross a page_size aligned boundary (the write
* implementation is expected to split such a write into two before calling page_program.)
*/
esp_flash_err_t (*page_program)(const esp_flash_chip_t *chip, uint32_t address, const void *buffer, uint32_t length);
esp_err_t (*program_page)(esp_flash_t *chip, const void *buffer, uint32_t address, uint32_t length);
/* Page size as written by the page_program function. Usually 256 bytes. */
uint32_t page_size;
/* Perform an encrypted write to the chip, using internal flash encryption hardware. */
esp_flash_err_t (*write_encrypted)(const esp_flash_chip_t *chip, uint32_t address, const void *buffer, uint32_t length);
esp_err_t (*write_encrypted)(esp_flash_t *chip, const void *buffer, uint32_t address, uint32_t length);
/* Set the write enable flag. This function is called internally by other functions in this structure, before a destructive
operation takes place. */
esp_flash_err_t (*write_enable)(const esp_flash_chip_t *chip);
esp_err_t (*set_write_protect)(esp_flash_t *chip, bool write_protect);
/* Wait for the SPI flash chip to be idle (any write operation to be complete.) This function is both called from the higher-level API functions, and from other functions in this structure.
timeout_ms should be a timeout (in milliseconds) before the function returns FLASH_ERR_NO_RESPONSE. This is useful to avoid hanging
timeout_ms should be a timeout (in milliseconds) before the function returns ESP_ERR_TIMEOUT. This is useful to avoid hanging
if the chip is otherwise unresponsive (ie returns all 0xFF or similar.)
*/
esp_flash_err_t (*wait_idle)(const esp_flash_chip_t *chip, unsigned timeout_ms);
esp_err_t (*wait_idle)(esp_flash_t *chip, unsigned timeout_ms);
/* Configure both the SPI host and the chip for the read mode specified in chip->read_mode.
*
* This function is called by the higher-level API before the 'read' function is called.
*
* Can return FLASH_ERR_UNSUPPORTED_HOST or FLASH_ERR_UNSUPPORTED_CHIP if the specified mode is unsupported.
* Can return ESP_ERR_FLASH_UNSUPPORTED_HOST or ESP_ERR_FLASH_UNSUPPORTED_CHIP if the specified mode is unsupported.
*/
esp_flash_err_t (*set_read_mode)(const esp_flash_chip_t *chip);
} esp_flash_driver_t;
esp_err_t (*set_read_mode)(esp_flash_t *chip);
};
/* Pointer to an array of pointers to all known drivers for flash chips. This array is used
by esp_flash_init() to detect the flash chip driver, if none is supplied by the caller.
@@ -145,32 +162,4 @@ typedef struct esp_flash_driver {
This pointer can be overwritten with a pointer to a new array, to update the list of known flash chips.
*/
extern const esp_flash_driver_t **esp_flash_registered_flash_drivers;
/* Provide OS-level integration hooks for accessing flash chips
inside a running OS */
typedef struct
{
/* Call this function before commencing any flash operation.
Does not need to be recursive (ie is called at most once for each call to 'end'.
*/
esp_flash_err_t (*start)(const esp_flash_chip_t *chip);
/* Call this function after completing any flash operation. */
esp_flash_err_t (*end)(const esp_flash_chip_t *chip);
/* Delay for at least 'ms' milliseconds.
This function will be called in between 'start' and 'end'.
*/
esp_flash_err_t (*delay_ms)(unsigned ms);
} esp_flash_os_functions_t;
/* The default (ie initial boot) no-OS ROM esp_flash_os_functions_t */
const esp_flash_os_functions_t esp_flash_noos_functions;
/* Pointer to the current esp_flash_os_functions_t structure in use.
Can be changed at runtime to reflect different running conditions.
*/
extern const esp_flash_os_functions_t *esp_flash_os_functions;
extern const spi_flash_chip_t **esp_flash_registered_chips;

View File

@@ -0,0 +1,275 @@
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <stdint.h>
#include "esp_flash.h"
#include "spi_flash_chip_driver.h"
/*
* The 'chip_generic' SPI flash operations are a lowest common subset of SPI
* flash commands, that work across most chips.
*
* These can be used as-is via the esp_flash_common_chip_driver chip_drv, or
* they can be used as "base chip_drv" functions when creating a new
* spi_flash_host_driver_t chip_drv structure.
*
* All of the functions in this header are internal functions, not part of a
* public API. See esp_flash.h for the public API.
*/
/**
* @brief Generic probe function
*
* @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.
* @param flash_id expected manufacture id.
*
* @return ESP_OK if the id read from chip->drv_read_id matches (always).
*/
esp_err_t spi_flash_chip_generic_probe(esp_flash_t *chip, uint32_t flash_id);
/**
* @brief Generic reset function
*
* @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.
*
* @return ESP_OK if sending success, or error code passed from ``common_command`` or ``wait_idle`` functions of host driver.
*/
esp_err_t spi_flash_chip_generic_reset(esp_flash_t *chip);
/**
* @brief Generic size detection function
*
* Tries to detect the size of chip by using the lower 4 bits of the chip->drv->read_id result = N, and assuming size is 2 ^ N.
*
* @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.
* @param size Output of the detected size
*
* @return
* - ESP_OK if success
* - ESP_ERR_FLASH_UNSUPPORTED_CHIP if the manufacturer id is not correct, which may means an error in the reading
* - or other error passed from the ``read_id`` function of host driver
*/
esp_err_t spi_flash_chip_generic_detect_size(esp_flash_t *chip, uint32_t *size);
/**
* @brief Erase chip by using the generic erase chip (C7h) command.
*
* @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.
*
* @return
* - ESP_OK if success
* - or other error passed from the ``set_write_protect``, ``wait_idle`` or ``erase_chip`` function of host driver
*/
esp_err_t spi_flash_chip_generic_erase_chip(esp_flash_t *chip);
/**
* @brief Erase sector by using the generic sector erase (20h) command.
*
* @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.
* @param start_address Start address of the sector to erase
*
* @return
* - ESP_OK if success
* - or other error passed from the ``set_write_protect``, ``wait_idle`` or ``erase_sector`` function of host driver
*/
esp_err_t spi_flash_chip_generic_erase_sector(esp_flash_t *chip, uint32_t start_address);
/**
* @brief Erase block by using the generic 64KB block erase (D8h) command
*
* @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.
* @param start_address Start address of the block to erase
*
* @return
* - ESP_OK if success
* - or other error passed from the ``set_write_protect``, ``wait_idle`` or ``erase_block`` function of host driver
*/
esp_err_t spi_flash_chip_generic_erase_block(esp_flash_t *chip, uint32_t start_address);
/**
* @brief Read from flash by using a read command that matches the programmed
* read mode.
*
* @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.
* @param buffer Buffer to hold the data read from flash
* @param address Start address of the data on the flash
* @param length Length to read
*
* @return always ESP_OK currently
*/
esp_err_t spi_flash_chip_generic_read(esp_flash_t *chip, void *buffer, uint32_t address, uint32_t length);
/**
* @brief Perform a page program using the page program (02h) command.
*
* @note Length of each call should not excced the limitation in
* ``chip->host->max_write_bytes``. This function is called in
* ``spi_flash_chip_generic_write`` recursively until the whole page is
* programmed. Strongly suggest to call ``spi_flash_chip_generic_write``
* instead.
*
* @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.
* @param buffer Buffer holding the data to program
* @param address Start address to write to flash
* @param length Length to write, no longer than ``chip->host->max_write_bytes``.
*
* @return
* - ESP_OK if success
* - or other error passed from the ``wait_idle`` or ``program_page`` function of host driver
*/
esp_err_t
spi_flash_chip_generic_page_program(esp_flash_t *chip, const void *buffer, uint32_t address, uint32_t length);
/**
* @brief Perform a generic write. Split the write buffer into page program
* operations, and call chip->chip_drv->page-program() for each.
*
* @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.
* @param buffer Buffer holding the data to program
* @param address Start address to write to flash
* @param length Length to write
*
* @return
* - ESP_OK if success
* - or other error passed from the ``wait_idle`` or ``program_page`` function of host driver
*/
esp_err_t spi_flash_chip_generic_write(esp_flash_t *chip, const void *buffer, uint32_t address, uint32_t length);
/**
* @brief Perform a write using on-chip flash encryption. Not implemented yet.
*
* @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.
* @param buffer Buffer holding the data to program
* @param address Start address to write to flash
* @param length Length to write
*
* @return always ESP_ERR_FLASH_UNSUPPORTED_HOST.
*/
esp_err_t
spi_flash_chip_generic_write_encrypted(esp_flash_t *chip, const void *buffer, uint32_t address, uint32_t length);
/**
* @brief Send the write enable (06h) command and verify the expected bit (1) in
* the status register is set.
*
* @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.
* @param write_protect true to enable write protection, false to send write enable.
*
* @return
* - ESP_OK if success
* - or other error passed from the ``wait_idle``, ``read_status`` or ``set_write_protect`` function of host driver
*/
esp_err_t spi_flash_chip_generic_write_enable(esp_flash_t *chip, bool write_protect);
/**
* @brief Read flash status via the RDSR command (05h) and wait for bit 0 (write
* in progress bit) to be cleared.
*
* @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.
* @param timeout_ms Time to wait before timeout, in ms.
*
* @return
* - ESP_OK if success
* - ESP_ERR_TIMEOUT if not idle before timeout
* - or other error passed from the ``wait_idle`` or ``read_status`` function of host driver
*/
esp_err_t spi_flash_chip_generic_wait_idle(esp_flash_t *chip, uint32_t timeout_ms);
/**
* @brief Set the specified SPI read mode according to the data in the chip
* context. Set quad enable status register bit if needed.
*
* @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.
*
* @return
* - ESP_OK if success
* - ESP_ERR_TIMEOUT if not idle before timeout
* - or other error passed from the ``set_write_protect`` or ``common_command`` function of host driver
*/
esp_err_t spi_flash_chip_generic_set_read_mode(esp_flash_t *chip);
/**
* Generic SPI flash chip_drv, uses all the above functions for its operations.
* In default autodetection, this is used as a catchall if a more specific
* chip_drv is not found.
*/
extern const spi_flash_chip_t esp_flash_chip_generic;
/*******************************************************************************
* Utilities
*******************************************************************************/
/**
* @brief Wait for the SPI host hardware state machine to be idle.
*
* This isn't a flash chip_drv operation, but it's called by
* spi_flash_chip_generic_wait_idle() and may be useful when implementing
* alternative drivers.
*
* timeout_ms will be decremented if the function needs to wait until the host hardware is idle.
*
* @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.
*
* @return
* - ESP_OK if success
* - ESP_ERR_TIMEOUT if not idle before timeout
* - or other error passed from the ``set_write_protect`` or ``common_command`` function of host driver
*/
esp_err_t spi_flash_generic_wait_host_idle(esp_flash_t *chip, uint32_t *timeout_ms);
/**
* @brief Utility function for set_read_mode chip_drv function
*
* Most setting of read mode follows a common pattern, except for how to enable Quad I/O modes (QIO/QOUT).
* These use different commands to read/write the status register, and a different bit is set/cleared.
*
* This is a generic utility function to implement set_read_mode() for this pattern. Also configures host
* registers via spi_flash_common_configure_host_read_mode().
*
* @param qe_rdsr_command SPI flash command to read status register
* @param qe_wrsr_command SPI flash command to write status register
* @param qe_sr_bitwidth Width of the status register these commands operate on, in bits.
* @param qe_sr_bit Bit mask for enabling Quad Enable functions on this chip.
*
* @return always ESP_OK (currently).
*/
esp_err_t spi_flash_common_set_read_mode(esp_flash_t *chip, uint8_t qe_rdsr_command, uint8_t qe_wrsr_command, uint8_t qe_sr_bitwidth, unsigned qe_sr_bit);
/**
* @brief Configure the host to use the specified read mode set in the ``chip->read_mode``.
*
* @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.
*
* @return
* - ESP_OK if success
* - ESP_ERR_FLASH_NOT_INITIALISED if chip not initialized properly
* - or other error passed from the ``configure_host_mode`` function of host driver
*/
esp_err_t spi_flash_chip_generic_config_host_read_mode(esp_flash_t *chip);
/**
* @brief Returns true if chip is configured for Quad I/O or Quad Fast Read.
*
* @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.
*
* @return true if flash works in quad mode, otherwise false
*/
static inline bool spi_flash_is_quad_mode(const esp_flash_t *chip)
{
return (chip->read_mode == SPI_FLASH_QIO) || (chip->read_mode == SPI_FLASH_QOUT);
}

View File

@@ -0,0 +1,27 @@
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <stdint.h>
#include "esp_flash.h"
#include "spi_flash_chip_driver.h"
/**
* ISSI SPI flash chip_drv, uses all the above functions for its operations. In
* default autodetection, this is used as a catchall if a more specific chip_drv
* is not found.
*/
extern const spi_flash_chip_t esp_flash_chip_issi;

View File

@@ -1,151 +0,0 @@
#pragma once
#include "spi_flash_lowlevel_driver.h"
/* The 'generic' SPI flash operations are a lowest common subset of SPI flash commands, that work across most chips.
*
* These can be used as-is vai the esp_flash_common_chip_driver driver, or they can be used as "base driver" functions when
* creating a new esp_flash_driver_t driver structure.
*
*
* All of the functions in this header are internal functions, not part of a public API. See spi_flash_lowlevel.h for
* the public API.
*/
/* SPI commands (actual on-wire commands not SPI controller bitmasks)
Suitable for use with spi_flash_common_command static function.
*/
#define CMD_RDID 0x9F
#define CMD_WRSR 0x01
#define CMD_WRSR2 0x31 /* Not all SPI flash uses this command */
#define CMD_WREN 0x06
#define CMD_WRDI 0x04
#define CMD_RDSR 0x05
#define CMD_RDSR2 0x35 /* Not all SPI flash uses this command */
#define CMD_FASTRD_QIO 0xEB
#define CMD_FASTRD_QUAD 0x6B
#define CMD_FASTRD_DIO 0xBB
#define CMD_FASTRD_DUAL 0x3B
#define CMD_FASTRD 0x0B
#define CMD_READ 0x03 /* Speed limited */
#define CMD_CHIP_ERASE 0xC7
#define CMD_SECTOR_ERASE 0x20
#define CMD_LARGE_BLOCK_ERASE 0xD8 /* 64KB block erase command */
#define SR_WIP (1<<0) /* Status register write-in-progress bit */
#define SR_WREN (1<<1) /* Status register write enable bit */
/** @brief Execute a simple SPI flash command against the chip.
*
* @param chip Pointer to the chip to use.
* @param command Command to execute (an on-wire hex command.)
* @param mosi_data Up to 32 bits of MOSI data to write after the command.
* @param mosi_len Length of MOSI data (in bits.)
* @param miso_len Length of MISO data (in bits.)
* @return MISO value read back, if any (depending on miso_len value.)
*/
uint32_t spi_flash_common_command(const esp_flash_chip_t *chip, uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len);
/** @brief Returns true if the pin configuration for this chip uses the GPIO matrix for any signals. */
bool spi_flash_uses_gpio_matrix(const esp_flash_chip_t *chip);
/** @brief Generic probe function
*
* If chip->drv_read_id succeeds, the probe succeeds.
*/
esp_flash_err_t spi_flash_generic_probe(esp_flash_chip_t *chip, uint32_t flash_id);
/** @brief Generic implementation of esp_flash_driver_t->read_id
*
* Uses the RDID command (9Fh) supported by most SPI flash chips.
*
* Results of all-zeroes or all-ones are considered failures (probably no chip attached.)
*/
esp_flash_err_t spi_flash_generic_read_id(const esp_flash_chip_t *chip, uint32_t *id);
/** @brief Generic size detection function
*
* Tries to detect the size of chip by using the lower 4 bits of the chip->drv->read_id result = N, and assuming size is 2 ^ N.
*/
esp_flash_err_t spi_flash_generic_detect_size(const esp_flash_chip_t *chip, uint32_t *size);
/** @brief Erase chip by using the generic erase chip (C7h) command. */
esp_flash_err_t spi_flash_generic_erase_chip(const esp_flash_chip_t *chip);
/** @brief Erase sector by using the generic sector erase (20h) command. */
esp_flash_err_t spi_flash_generic_erase_sector(const esp_flash_chip_t *chip, uint32_t start_address);
/** @brief Erase block by using the generic 64KB block erase (D8h) command */
esp_flash_err_t spi_flash_generic_erase_block(const esp_flash_chip_t *chip, uint32_t start_address);
/** @brief Read from flash by using a read command that matches the programmed read mode. */
esp_flash_err_t spi_flash_generic_read(const esp_flash_chip_t *chip, void *buffer, uint32_t address, uint32_t length);
/** @brief Perform a page program using the page program (02h) command. */
esp_flash_err_t spi_flash_generic_page_program(const esp_flash_chip_t *chip, uint32_t address, const void *buffer, uint32_t length);
/** @brief Perform a generic write. Split the write buffer into
one page operations, and call chip->drv->page-program() for each.
*/
esp_flash_err_t spi_flash_generic_write(const esp_flash_chip_t *chip, uint32_t address, const void *buffer, uint32_t length);
/** @brief Perform a write using on-chip flash encryption */
esp_flash_err_t spi_flash_generic_write_encrypted(const esp_flash_chip_t *chip, uint32_t address, const void *buffer, uint32_t length);
/** @brief Send the write enable (06h) command and verify the expected bit (1) in the status register is set. */
esp_flash_err_t spi_flash_generic_write_enable(const esp_flash_chip_t *chip);
/** @brief Wait for the SPI host hardware state machine to be idle.
This isn't a flash driver operation, but it's called by spi_flash_generic_wait_idle() and may be useful when implementing alternative drivers.
timeout_ms will be decremented if the function needs to wait until the host hardware is idle.
*/
esp_flash_err_t spi_flash_generic_wait_host_idle(const esp_flash_chip_t *chip, uint32_t *timeout_ms);
/** @brief Read flash status via the RDSR command (05h) and wait for bit 0 (write in progress bit) to be cleared. */
esp_flash_err_t spi_flash_generic_wait_idle(const esp_flash_chip_t *chip, uint32_t timeout_ms);
/** @brief Utility function to configure the SPI host hardware registers for the specified read mode.
Called by spi_flash_generic_set_read_mode() but may also be useful
when implementing other SPI flash drivers.
Note that calling this configures SPI host registers, so if running any other commands as part of set_read_mode() then these must be run before calling this function.
*/
esp_flash_err_t spi_flash_common_configure_host_read_mode(const esp_flash_chip_t *chip);
/** @brief Utility function for set_read_mode driver function
*
* Most setting of read mode follows a common pattern, except for how to enable Quad I/O modes (QIO/QOUT).
* These use different commands to read/write the status register, and a different bit is set/cleared.
*
* This is a generic utility function to implement set_read_mode() for this pattern. Also configures host
* registers via spi_flash_common_configure_host_read_mode().
*
* @param qe_rdsr_command SPI flash command to read status register
* @param qe_wrsr_command SPI flash command to write status register
* @param qe_sr_bitwidth Width of the status register these commands operate on, in bits.
* @param qe_sr_bit Bit mask for enabling Quad Enable functions on this chio.
*/
esp_flash_err_t spi_flash_common_set_read_mode(const esp_flash_chip_t *chip, uint8_t qe_rdsr_command, uint8_t qe_wrsr_command, uint8_t qe_sr_bitwidth, unsigned qe_sr_bit);
/** @brief Set the specified SPI read mode.
*
* Includes setting SPI host hardware registers, but also setting quad enable status register bit if needed.
*/
esp_flash_err_t spi_flash_generic_set_read_mode(const esp_flash_chip_t *chip);
/** @brief Returns true if chip is configured for Quad I/O or
Quad Fast Read */
inline static bool spi_flash_is_quad_mode(const esp_flash_chip_t *chip)
{
return chip->read_mode == ESP_FLASH_QIO || chip->read_mode == ESP_FLASH_QOUT;
}
/* Generic SPI flash driver, uses all the above functions for its operations. In default autodetection, this is used as
a catchall if a more specific driver is not found.
*/
extern const esp_flash_driver_t esp_flash_generic_chip_driver;