v2.0.0 Add support for ESP32S2 and update ESP-IDF to 4.4 (#4996)

This is very much still work in progress and much more will change before the final 2.0.0

Some APIs have changed. New libraries have been added. LittleFS included.

Co-authored-by: Seon Rozenblum <seonr@3sprockets.com>
Co-authored-by: Me No Dev <me-no-dev@users.noreply.github.com>
Co-authored-by: geeksville <kevinh@geeksville.com>
Co-authored-by: Mike Dunston <m_dunston@comcast.net>
Co-authored-by: Unexpected Maker <seon@unexpectedmaker.com>
Co-authored-by: Seon Rozenblum <seonr@3sprockets.com>
Co-authored-by: microDev <70126934+microDev1@users.noreply.github.com>
Co-authored-by: tobozo <tobozo@users.noreply.github.com>
Co-authored-by: bobobo1618 <bobobo1618@users.noreply.github.com>
Co-authored-by: lorol <lorolouis@gmail.com>
Co-authored-by: geeksville <kevinh@geeksville.com>
Co-authored-by: Limor "Ladyada" Fried <limor@ladyada.net>
Co-authored-by: Sweety <switi.mhaiske@espressif.com>
Co-authored-by: Loick MAHIEUX <loick111@gmail.com>
Co-authored-by: Larry Bernstone <lbernstone@gmail.com>
Co-authored-by: Valerii Koval <valeros@users.noreply.github.com>
Co-authored-by: 快乐的我531 <2302004040@qq.com>
Co-authored-by: chegewara <imperiaonline4@gmail.com>
Co-authored-by: Clemens Kirchgatterer <clemens@1541.org>
Co-authored-by: Aron Rubin <aronrubin@gmail.com>
Co-authored-by: Pete Lewis <601236+lewispg228@users.noreply.github.com>
This commit is contained in:
Me No Dev
2021-04-05 14:23:58 +03:00
committed by GitHub
parent 46d5afb17f
commit 5502879a5b
5209 changed files with 826360 additions and 322816 deletions

View File

@ -0,0 +1,367 @@
// 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 "hal/spi_flash_types.h"
#ifdef __cplusplus
extern "C" {
#endif
struct spi_flash_chip_t;
typedef struct spi_flash_chip_t spi_flash_chip_t;
typedef struct esp_flash_t esp_flash_t;
/** @brief Structure for describing a region of flash */
typedef struct {
uint32_t offset; ///< Start address of this region
uint32_t size; ///< Size of the region
} esp_flash_region_t;
/** @brief OS-level integration hooks for accessing flash chips inside a running OS
*
* It's in the public header because some instances should be allocated statically in the startup
* code. May be updated according to hardware version and new flash chip feature requirements,
* shouldn't be treated as public API.
*
* For advanced developers, you may replace some of them with your implementations at your own
* risk.
*/
typedef struct {
/**
* 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);
/** Called before any erase/write operations to check whether the region is limited by the OS */
esp_err_t (*region_protected)(void* arg, size_t start_addr, size_t size);
/** Delay for at least 'us' microseconds. Called in between 'start' and 'end'. */
esp_err_t (*delay_us)(void *arg, uint32_t us);
/** Called for get temp buffer when buffer from application cannot be directly read into/write from. */
void *(*get_temp_buffer)(void* arg, size_t reqest_size, size_t* out_size);
/** Called for release temp buffer. */
void (*release_temp_buffer)(void* arg, void *temp_buf);
#define SPI_FLASH_YIELD_REQ_YIELD BIT(0)
#define SPI_FLASH_YIELD_REQ_SUSPEND BIT(1)
/** Yield to other tasks. Called during erase operations.
* @return ESP_OK means yield needs to be called (got an event to handle), while ESP_ERR_TIMEOUT means skip yield.*/
esp_err_t (*check_yield)(void *arg, uint32_t chip_status, uint32_t* out_request);
#define SPI_FLASH_YIELD_STA_RESUME BIT(2)
/** Yield to other tasks. Called during erase operations. */
esp_err_t (*yield)(void *arg, uint32_t* out_status);
/** Called for get system time. */
int64_t (*get_system_time)(void *arg);
} esp_flash_os_functions_t;
/** @brief Structure to describe a SPI flash chip connected to the system.
Structure must be initialized before use (passed to esp_flash_init()). It's in the public
header because some instances should be allocated statically in the startup code. May be
updated according to hardware version and new flash chip feature requirements, shouldn't be
treated as public API.
For advanced developers, you may replace some of them with your implementations at your own
risk.
*/
struct esp_flash_t {
spi_flash_host_inst_t* host; ///< Pointer to hardware-specific "host_driver" structure. Must be initialized before used.
const spi_flash_chip_t *chip_drv; ///< Pointer to chip-model-specific "adapter" structure. If NULL, will be detected during initialisation.
const esp_flash_os_functions_t *os_func; ///< Pointer to os-specific hook structure. Call ``esp_flash_init_os_functions()`` to setup this field, after the host is properly initialized.
void *os_func_data; ///< Pointer to argument for os-specific hooks. Left NULL and will be initialized with ``os_func``.
esp_flash_io_mode_t read_mode; ///< Configured SPI flash read mode. Set before ``esp_flash_init`` is called.
uint32_t size; ///< Size of SPI flash in bytes. If 0, size will be detected during initialisation.
uint32_t chip_id; ///< Detected chip id.
uint32_t busy :1; ///< This flag is used to verify chip's status.
uint32_t reserved_flags :31; ///< reserved.
};
/** @brief Initialise SPI flash chip interface.
*
* This function must be called before any other API functions are called for this chip.
*
* @note Only the ``host`` and ``read_mode`` fields of the chip structure must
* be initialised before this function is called. Other fields may be
* auto-detected if left set to zero or NULL.
*
* @note If the chip->drv pointer is NULL, chip chip_drv will be auto-detected
* 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 ESP_OK on success, or a flash error code if initialisation fails.
*/
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.
*
* @param chip Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()
* @param[out] out_id Pointer to receive ID value.
*
* ID is a 24-bit value. Lower 16 bits of 'id' are the chip ID, upper 8 bits are the manufacturer ID.
*
* @return ESP_OK on success, or a flash error code if operation failed.
*/
esp_err_t esp_flash_read_id(esp_flash_t *chip, uint32_t *out_id);
/** @brief Detect flash size based on flash ID.
*
* @param chip Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()
* @param[out] out_size Detected size in bytes.
*
* @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 ESP_OK on success, or a flash error code if operation failed.
*/
esp_err_t esp_flash_get_size(esp_flash_t *chip, uint32_t *out_size);
/** @brief Read flash unique ID via the common "RDUID" SPI flash command.
*
* @param chip Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init().
* @param[out] out_id Pointer to receive unique ID value.
*
* ID is a 64-bit value.
*
* @return
* - ESP_OK on success, or a flash error code if operation failed.
* - ESP_ERR_NOT_SUPPORTED if the chip doesn't support read id.
*/
esp_err_t esp_flash_read_unique_chip_id(esp_flash_t *chip, uint64_t *out_id);
/** @brief Erase flash chip contents
*
* @param chip Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()
*
*
* @return
* - ESP_OK on success,
* - ESP_ERR_NOT_SUPPORTED if the chip is not able to perform the operation. This is indicated by WREN = 1 after the command is sent.
* - Other flash error code if operation failed.
*/
esp_err_t esp_flash_erase_chip(esp_flash_t *chip);
/** @brief Erase a region of the flash chip
*
* @param chip Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()
* @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.) 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
* - ESP_OK on success,
* - ESP_ERR_NOT_SUPPORTED if the chip is not able to perform the operation. This is indicated by WREN = 1 after the command is sent.
* - Other flash error code if operation failed.
*/
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 chip_drv in use (via the 'chip->drv'
* field).
*
* @return ESP_OK on success, or a flash error code if operation failed.
*/
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_protect Boolean value for the write protect flag
*
* @note Correct behaviour of this function depends on the SPI flash chip model and chip_drv in use (via the 'chip->drv'
* field).
*
* 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 ESP_OK on success, or a flash error code if operation failed.
*/
esp_err_t esp_flash_set_chip_write_protect(esp_flash_t *chip, bool write_protect);
/** @brief Read the list of individually protectable regions of this SPI flash chip.
*
* @param chip Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()
* @param[out] out_regions Pointer to receive a pointer to the array of protectable regions of the chip.
* @param[out] out_num_regions 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 chip_drv in use (via the 'chip->drv'
* field).
*
* @return ESP_OK on success, or a flash error code if operation failed.
*/
esp_err_t esp_flash_get_protectable_regions(const esp_flash_t *chip, const esp_flash_region_t **out_regions, uint32_t *out_num_regions);
/** @brief Detect if a region of the SPI flash chip is protected
*
* @param chip Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()
* @param region Pointer to a struct describing a protected region. This must match one of the regions returned from esp_flash_get_protectable_regions(...).
* @param[out] out_protected Pointer to a flag which is set based on the protected status for this region.
*
* @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 chip_drv in use (via the 'chip->drv'
* field).
*
* @return ESP_OK on success, or a flash error code if operation failed.
*/
esp_err_t esp_flash_get_protected_region(esp_flash_t *chip, const esp_flash_region_t *region, bool *out_protected);
/** @brief Update the protected status for a region of the SPI flash chip
*
* @param chip Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()
* @param region Pointer to a struct describing a protected region. This must match one of the regions returned from esp_flash_get_protectable_regions(...).
* @param protect Write protection flag to set.
*
* @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 chip_drv in use (via the 'chip->drv'
* field).
*
* @return ESP_OK on success, or a flash error code if operation failed.
*/
esp_err_t esp_flash_set_protected_region(esp_flash_t *chip, const esp_flash_region_t *region, bool protect);
/** @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. 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.
*
* There are no alignment constraints on buffer, address or length.
*
* @note If on-chip flash encryption is used, this function returns raw (ie encrypted) data. Use the flash cache
* to transparently decrypt data.
*
* @return
* - ESP_OK: success
* - ESP_ERR_NO_MEM: Buffer is in external PSRAM which cannot be concurrently accessed, and a temporary internal buffer could not be allocated.
* - or a flash error code if operation failed.
*/
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. 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
* - ESP_OK on success,
* - ESP_ERR_NOT_SUPPORTED if the chip is not able to perform the operation. This is indicated by WREN = 1 after the command is sent.
* - Other flash error code if operation failed.
*/
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
*
* @param chip Pointer to identify flash chip. Must be NULL (the main flash chip). For other chips, encrypted write is not supported.
* @param address Address on flash to write to. 16 byte aligned. 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 length Length (in bytes) of data to write. 16 byte aligned.
*
* @note Both address & length must be 16 byte aligned, as this is the encryption block size
*
* @return
* - ESP_OK: on success
* - ESP_ERR_NOT_SUPPORTED: encrypted write not supported for this chip.
* - ESP_ERR_INVALID_ARG: Either the address, buffer or length is invalid.
* - or other flash error code from spi_flash_write_encrypted().
*/
esp_err_t esp_flash_write_encrypted(esp_flash_t *chip, uint32_t address, const void *buffer, uint32_t length);
/** @brief Read and decrypt data from the SPI flash chip using on-chip hardware flash encryption
*
* @param chip Pointer to identify flash chip. Must be NULL (the main flash chip). For other chips, encrypted read is not supported.
* @param address Address on flash to read from.
* @param out_buffer Pointer to a buffer for the data to read to.
* @param length Length (in bytes) of data to read.
*
* @return
* - ESP_OK: on success
* - ESP_ERR_NOT_SUPPORTED: encrypted read not supported for this chip.
* - or other flash error code from spi_flash_read_encrypted().
*/
esp_err_t esp_flash_read_encrypted(esp_flash_t *chip, uint32_t address, void *out_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 esp_flash_t *esp_flash_default_chip;
/*******************************************************************************
* Utility Functions
******************************************************************************/
/**
* @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 esp_flash_is_quad_mode(const esp_flash_t *chip)
{
return (chip->read_mode == SPI_FLASH_QIO) || (chip->read_mode == SPI_FLASH_QOUT);
}
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,120 @@
// 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 <driver/spi_common_internal.h>
#include "sdkconfig.h"
#include "esp_flash.h"
/** Internal API, don't use in the applications */
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Initialise the default SPI flash chip
*
* Called by OS startup code. You do not need to call this in your own applications.
*/
#ifdef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
#define esp_flash_init_default_chip(...) ({ESP_OK;})
#else
esp_err_t esp_flash_init_default_chip(void);
#endif
/**
* Enable OS-level SPI flash protections in IDF
*
* Called by OS startup code. You do not need to call this in your own applications.
*
* @return ESP_OK if success, otherwise failed. See return value of ``esp_flash_init_os_functions``.
*/
#ifdef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
#define esp_flash_app_init(...) ({ESP_OK;})
#else
esp_err_t esp_flash_app_init(void);
#endif
/**
* Disable (or enable) OS-level SPI flash protections in IDF
*
* Called by the IDF internal code (e.g. coredump). You do not need to call this in your own applications.
*
* @return always ESP_OK.
*/
#ifdef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
#define esp_flash_app_disable_protect(...) ({ESP_OK;})
#else
esp_err_t esp_flash_app_disable_protect(bool disable);
#endif
/**
* Initialize OS-level functions for a specific chip.
*
* @param chip The chip to init os functions.
* @param host_id Which SPI host to use, 1 for SPI1, 2 for SPI2 (HSPI), 3 for SPI3 (VSPI)
* @param out_dev_id Output of occupied device slot
*
* @return
* - ESP_OK if success
* - ESP_ERR_INVALID_ARG if host_id is invalid
*/
esp_err_t esp_flash_init_os_functions(esp_flash_t *chip, int host_id, int *out_dev_id);
/**
* @brief Deinitialize OS-level functions
*
* @param chip The chip to deinit os functions
* @return always ESP_OK.
*/
esp_err_t esp_flash_deinit_os_functions(esp_flash_t* chip);
/**
* @brief Initialize the bus lock on the SPI1 bus. Should be called if drivers (including esp_flash)
* wants to use SPI1 bus.
*
* @note When using legacy spi flash API, the bus lock will not be available on SPI1 bus.
*
* @return esp_err_t always ESP_OK.
*/
esp_err_t esp_flash_init_main_bus_lock(void);
/**
* Initialize OS-level functions for the main flash chip.
*
* @param chip The chip to init os functions. Only pointer to the default chip is supported now.
*
* @return always ESP_OK
*/
esp_err_t esp_flash_app_enable_os_functions(esp_flash_t* chip);
/**
* Disable OS-level functions for the main flash chip during special phases (e.g. coredump)
*
* @param chip The chip to init os functions. Only "esp_flash_default_chip" is supported now.
*
* @return always ESP_OK
*/
esp_err_t esp_flash_app_disable_os_functions(esp_flash_t* chip);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,67 @@
// 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_types.h"
#include "esp_flash.h"
#ifdef __cplusplus
extern "C" {
#endif
/// Configurations for the SPI Flash to init
typedef struct {
spi_host_device_t host_id; ///< Bus to use
int cs_io_num; ///< GPIO pin to output the CS signal
esp_flash_io_mode_t io_mode; ///< IO mode to read from the Flash
esp_flash_speed_t speed; ///< Speed of the Flash clock
int input_delay_ns; ///< Input delay of the data pins, in ns. Set to 0 if unknown.
/**
* CS line ID, ignored when not `host_id` is not SPI1_HOST, or
* `CONFIG_SPI_FLASH_SHARE_SPI1_BUS` is enabled. In this case, the CS line used is
* automatically assigned by the SPI bus lock.
*/
int cs_id;
} esp_flash_spi_device_config_t;
/**
* Add a SPI Flash device onto the SPI bus.
*
* The bus should be already initialized by ``spi_bus_initialization``.
*
* @param out_chip Pointer to hold the initialized chip.
* @param config Configuration of the chips to initialize.
*
* @return
* - ESP_ERR_INVALID_ARG: out_chip is NULL, or some field in the config is invalid.
* - ESP_ERR_NO_MEM: failed to allocate memory for the chip structures.
* - ESP_OK: success.
*/
esp_err_t spi_bus_add_flash_device(esp_flash_t **out_chip, const esp_flash_spi_device_config_t *config);
/**
* Remove a SPI Flash device from the SPI bus.
*
* @param chip The flash device to remove.
*
* @return
* - ESP_ERR_INVALID_ARG: The chip is invalid.
* - ESP_OK: success.
*/
esp_err_t spi_bus_remove_flash_device(esp_flash_t *chip);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,432 @@
// Copyright 2015-2016 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.
#ifndef __ESP_PARTITION_H__
#define __ESP_PARTITION_H__
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "esp_err.h"
#include "esp_flash.h"
#include "esp_spi_flash.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file esp_partition.h
* @brief Partition APIs
*/
/**
* @brief Partition type
*
* @note Partition types with integer value 0x00-0x3F are reserved for partition types defined by ESP-IDF.
* Any other integer value 0x40-0xFE can be used by individual applications, without restriction.
*
* @internal Keep this enum in sync with PartitionDefinition class gen_esp32part.py @endinternal
*
*/
typedef enum {
ESP_PARTITION_TYPE_APP = 0x00, //!< Application partition type
ESP_PARTITION_TYPE_DATA = 0x01, //!< Data partition type
} esp_partition_type_t;
/**
* @brief Partition subtype
*
* @note These ESP-IDF-defined partition subtypes apply to partitions of type ESP_PARTITION_TYPE_APP
* and ESP_PARTITION_TYPE_DATA.
*
* Application-defined partition types (0x40-0xFE) can set any numeric subtype value.
*
* @internal Keep this enum in sync with PartitionDefinition class gen_esp32part.py @endinternal
*/
typedef enum {
ESP_PARTITION_SUBTYPE_APP_FACTORY = 0x00, //!< Factory application partition
ESP_PARTITION_SUBTYPE_APP_OTA_MIN = 0x10, //!< Base for OTA partition subtypes
ESP_PARTITION_SUBTYPE_APP_OTA_0 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 0, //!< OTA partition 0
ESP_PARTITION_SUBTYPE_APP_OTA_1 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 1, //!< OTA partition 1
ESP_PARTITION_SUBTYPE_APP_OTA_2 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 2, //!< OTA partition 2
ESP_PARTITION_SUBTYPE_APP_OTA_3 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 3, //!< OTA partition 3
ESP_PARTITION_SUBTYPE_APP_OTA_4 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 4, //!< OTA partition 4
ESP_PARTITION_SUBTYPE_APP_OTA_5 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 5, //!< OTA partition 5
ESP_PARTITION_SUBTYPE_APP_OTA_6 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 6, //!< OTA partition 6
ESP_PARTITION_SUBTYPE_APP_OTA_7 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 7, //!< OTA partition 7
ESP_PARTITION_SUBTYPE_APP_OTA_8 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 8, //!< OTA partition 8
ESP_PARTITION_SUBTYPE_APP_OTA_9 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 9, //!< OTA partition 9
ESP_PARTITION_SUBTYPE_APP_OTA_10 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 10,//!< OTA partition 10
ESP_PARTITION_SUBTYPE_APP_OTA_11 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 11,//!< OTA partition 11
ESP_PARTITION_SUBTYPE_APP_OTA_12 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 12,//!< OTA partition 12
ESP_PARTITION_SUBTYPE_APP_OTA_13 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 13,//!< OTA partition 13
ESP_PARTITION_SUBTYPE_APP_OTA_14 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 14,//!< OTA partition 14
ESP_PARTITION_SUBTYPE_APP_OTA_15 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 15,//!< OTA partition 15
ESP_PARTITION_SUBTYPE_APP_OTA_MAX = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 16,//!< Max subtype of OTA partition
ESP_PARTITION_SUBTYPE_APP_TEST = 0x20, //!< Test application partition
ESP_PARTITION_SUBTYPE_DATA_OTA = 0x00, //!< OTA selection partition
ESP_PARTITION_SUBTYPE_DATA_PHY = 0x01, //!< PHY init data partition
ESP_PARTITION_SUBTYPE_DATA_NVS = 0x02, //!< NVS partition
ESP_PARTITION_SUBTYPE_DATA_COREDUMP = 0x03, //!< COREDUMP partition
ESP_PARTITION_SUBTYPE_DATA_NVS_KEYS = 0x04, //!< Partition for NVS keys
ESP_PARTITION_SUBTYPE_DATA_EFUSE_EM = 0x05, //!< Partition for emulate eFuse bits
ESP_PARTITION_SUBTYPE_DATA_ESPHTTPD = 0x80, //!< ESPHTTPD partition
ESP_PARTITION_SUBTYPE_DATA_FAT = 0x81, //!< FAT partition
ESP_PARTITION_SUBTYPE_DATA_SPIFFS = 0x82, //!< SPIFFS partition
ESP_PARTITION_SUBTYPE_ANY = 0xff, //!< Used to search for partitions with any subtype
} esp_partition_subtype_t;
/**
* @brief Convenience macro to get esp_partition_subtype_t value for the i-th OTA partition
*/
#define ESP_PARTITION_SUBTYPE_OTA(i) ((esp_partition_subtype_t)(ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ((i) & 0xf)))
/**
* @brief Opaque partition iterator type
*/
typedef struct esp_partition_iterator_opaque_* esp_partition_iterator_t;
/**
* @brief partition information structure
*
* This is not the format in flash, that format is esp_partition_info_t.
*
* However, this is the format used by this API.
*/
typedef struct {
esp_flash_t* flash_chip; /*!< SPI flash chip on which the partition resides */
esp_partition_type_t type; /*!< partition type (app/data) */
esp_partition_subtype_t subtype; /*!< partition subtype */
uint32_t address; /*!< starting address of the partition in flash */
uint32_t size; /*!< size of the partition, in bytes */
char label[17]; /*!< partition label, zero-terminated ASCII string */
bool encrypted; /*!< flag is set to true if partition is encrypted */
} esp_partition_t;
/**
* @brief Find partition based on one or more parameters
*
* @param type Partition type, one of esp_partition_type_t values or an 8-bit unsigned integer
* @param subtype Partition subtype, one of esp_partition_subtype_t values or an 8-bit unsigned integer.
* To find all partitions of given type, use ESP_PARTITION_SUBTYPE_ANY.
* @param label (optional) Partition label. Set this value if looking
* for partition with a specific name. Pass NULL otherwise.
*
* @return iterator which can be used to enumerate all the partitions found,
* or NULL if no partitions were found.
* Iterator obtained through this function has to be released
* using esp_partition_iterator_release when not used any more.
*/
esp_partition_iterator_t esp_partition_find(esp_partition_type_t type, esp_partition_subtype_t subtype, const char* label);
/**
* @brief Find first partition based on one or more parameters
*
* @param type Partition type, one of esp_partition_type_t values or an 8-bit unsigned integer
* @param subtype Partition subtype, one of esp_partition_subtype_t values or an 8-bit unsigned integer
* To find all partitions of given type, use ESP_PARTITION_SUBTYPE_ANY.
* @param label (optional) Partition label. Set this value if looking
* for partition with a specific name. Pass NULL otherwise.
*
* @return pointer to esp_partition_t structure, or NULL if no partition is found.
* This pointer is valid for the lifetime of the application.
*/
const esp_partition_t* esp_partition_find_first(esp_partition_type_t type, esp_partition_subtype_t subtype, const char* label);
/**
* @brief Get esp_partition_t structure for given partition
*
* @param iterator Iterator obtained using esp_partition_find. Must be non-NULL.
*
* @return pointer to esp_partition_t structure. This pointer is valid for the lifetime
* of the application.
*/
const esp_partition_t* esp_partition_get(esp_partition_iterator_t iterator);
/**
* @brief Move partition iterator to the next partition found
*
* Any copies of the iterator will be invalid after this call.
*
* @param iterator Iterator obtained using esp_partition_find. Must be non-NULL.
*
* @return NULL if no partition was found, valid esp_partition_iterator_t otherwise.
*/
esp_partition_iterator_t esp_partition_next(esp_partition_iterator_t iterator);
/**
* @brief Release partition iterator
*
* @param iterator Iterator obtained using esp_partition_find. Must be non-NULL.
*
*/
void esp_partition_iterator_release(esp_partition_iterator_t iterator);
/**
* @brief Verify partition data
*
* Given a pointer to partition data, verify this partition exists in the partition table (all fields match.)
*
* This function is also useful to take partition data which may be in a RAM buffer and convert it to a pointer to the
* permanent partition data stored in flash.
*
* Pointers returned from this function can be compared directly to the address of any pointer returned from
* esp_partition_get(), as a test for equality.
*
* @param partition Pointer to partition data to verify. Must be non-NULL. All fields of this structure must match the
* partition table entry in flash for this function to return a successful match.
*
* @return
* - If partition not found, returns NULL.
* - If found, returns a pointer to the esp_partition_t structure in flash. This pointer is always valid for the lifetime of the application.
*/
const esp_partition_t *esp_partition_verify(const esp_partition_t *partition);
/**
* @brief Read data from the partition
*
* Partitions marked with an encryption flag will automatically be
* be read and decrypted via a cache mapping.
*
* @param partition Pointer to partition structure obtained using
* esp_partition_find_first or esp_partition_get.
* Must be non-NULL.
* @param dst Pointer to the buffer where data should be stored.
* Pointer must be non-NULL and buffer must be at least 'size' bytes long.
* @param src_offset Address of the data to be read, relative to the
* beginning of the partition.
* @param size Size of data to be read, in bytes.
*
* @return ESP_OK, if data was read successfully;
* ESP_ERR_INVALID_ARG, if src_offset exceeds partition size;
* ESP_ERR_INVALID_SIZE, if read would go out of bounds of the partition;
* or one of error codes from lower-level flash driver.
*/
esp_err_t esp_partition_read(const esp_partition_t* partition,
size_t src_offset, void* dst, size_t size);
/**
* @brief Write data to the partition
*
* Before writing data to flash, corresponding region of flash needs to be erased.
* This can be done using esp_partition_erase_range function.
*
* Partitions marked with an encryption flag will automatically be
* written via the spi_flash_write_encrypted() function. If writing to
* an encrypted partition, all write offsets and lengths must be
* multiples of 16 bytes. See the spi_flash_write_encrypted() function
* for more details. Unencrypted partitions do not have this
* restriction.
*
* @param partition Pointer to partition structure obtained using
* esp_partition_find_first or esp_partition_get.
* Must be non-NULL.
* @param dst_offset Address where the data should be written, relative to the
* beginning of the partition.
* @param src Pointer to the source buffer. Pointer must be non-NULL and
* buffer must be at least 'size' bytes long.
* @param size Size of data to be written, in bytes.
*
* @note Prior to writing to flash memory, make sure it has been erased with
* esp_partition_erase_range call.
*
* @return ESP_OK, if data was written successfully;
* ESP_ERR_INVALID_ARG, if dst_offset exceeds partition size;
* ESP_ERR_INVALID_SIZE, if write would go out of bounds of the partition;
* or one of error codes from lower-level flash driver.
*/
esp_err_t esp_partition_write(const esp_partition_t* partition,
size_t dst_offset, const void* src, size_t size);
/**
* @brief Read data from the partition without any transformation/decryption.
*
* @note This function is essentially the same as \c esp_partition_read() above.
* It just never decrypts data but returns it as is.
*
* @param partition Pointer to partition structure obtained using
* esp_partition_find_first or esp_partition_get.
* Must be non-NULL.
* @param dst Pointer to the buffer where data should be stored.
* Pointer must be non-NULL and buffer must be at least 'size' bytes long.
* @param src_offset Address of the data to be read, relative to the
* beginning of the partition.
* @param size Size of data to be read, in bytes.
*
* @return ESP_OK, if data was read successfully;
* ESP_ERR_INVALID_ARG, if src_offset exceeds partition size;
* ESP_ERR_INVALID_SIZE, if read would go out of bounds of the partition;
* or one of error codes from lower-level flash driver.
*/
esp_err_t esp_partition_read_raw(const esp_partition_t* partition,
size_t src_offset, void* dst, size_t size);
/**
* @brief Write data to the partition without any transformation/encryption.
*
* @note This function is essentially the same as \c esp_partition_write() above.
* It just never encrypts data but writes it as is.
*
* Before writing data to flash, corresponding region of flash needs to be erased.
* This can be done using esp_partition_erase_range function.
*
* @param partition Pointer to partition structure obtained using
* esp_partition_find_first or esp_partition_get.
* Must be non-NULL.
* @param dst_offset Address where the data should be written, relative to the
* beginning of the partition.
* @param src Pointer to the source buffer. Pointer must be non-NULL and
* buffer must be at least 'size' bytes long.
* @param size Size of data to be written, in bytes.
*
* @note Prior to writing to flash memory, make sure it has been erased with
* esp_partition_erase_range call.
*
* @return ESP_OK, if data was written successfully;
* ESP_ERR_INVALID_ARG, if dst_offset exceeds partition size;
* ESP_ERR_INVALID_SIZE, if write would go out of bounds of the partition;
* or one of the error codes from lower-level flash driver.
*/
esp_err_t esp_partition_write_raw(const esp_partition_t* partition,
size_t dst_offset, const void* src, size_t size);
/**
* @brief Erase part of the partition
*
* @param partition Pointer to partition structure obtained using
* esp_partition_find_first or esp_partition_get.
* Must be non-NULL.
* @param offset Offset from the beginning of partition where erase operation
* should start. Must be aligned to 4 kilobytes.
* @param size Size of the range which should be erased, in bytes.
* Must be divisible by 4 kilobytes.
*
* @return ESP_OK, if the range was erased successfully;
* ESP_ERR_INVALID_ARG, if iterator or dst are NULL;
* ESP_ERR_INVALID_SIZE, if erase would go out of bounds of the partition;
* or one of error codes from lower-level flash driver.
*/
esp_err_t esp_partition_erase_range(const esp_partition_t* partition,
size_t offset, size_t size);
/**
* @brief Configure MMU to map partition into data memory
*
* Unlike spi_flash_mmap function, which requires a 64kB aligned base address,
* this function doesn't impose such a requirement.
* If offset results in a flash address which is not aligned to 64kB boundary,
* address will be rounded to the lower 64kB boundary, so that mapped region
* includes requested range.
* Pointer returned via out_ptr argument will be adjusted to point to the
* requested offset (not necessarily to the beginning of mmap-ed region).
*
* To release mapped memory, pass handle returned via out_handle argument to
* spi_flash_munmap function.
*
* @param partition Pointer to partition structure obtained using
* esp_partition_find_first or esp_partition_get.
* Must be non-NULL.
* @param offset Offset from the beginning of partition where mapping should start.
* @param size Size of the area to be mapped.
* @param memory Memory space where the region should be mapped
* @param out_ptr Output, pointer to the mapped memory region
* @param out_handle Output, handle which should be used for spi_flash_munmap call
*
* @return ESP_OK, if successful
*/
esp_err_t esp_partition_mmap(const esp_partition_t* partition, size_t offset, size_t size,
spi_flash_mmap_memory_t memory,
const void** out_ptr, spi_flash_mmap_handle_t* out_handle);
/**
* @brief Get SHA-256 digest for required partition.
*
* For apps with SHA-256 appended to the app image, the result is the appended SHA-256 value for the app image content.
* The hash is verified before returning, if app content is invalid then the function returns ESP_ERR_IMAGE_INVALID.
* For apps without SHA-256 appended to the image, the result is the SHA-256 of all bytes in the app image.
* For other partition types, the result is the SHA-256 of the entire partition.
*
* @param[in] partition Pointer to info for partition containing app or data. (fields: address, size and type, are required to be filled).
* @param[out] sha_256 Returned SHA-256 digest for a given partition.
*
* @return
* - ESP_OK: In case of successful operation.
* - ESP_ERR_INVALID_ARG: The size was 0 or the sha_256 was NULL.
* - ESP_ERR_NO_MEM: Cannot allocate memory for sha256 operation.
* - ESP_ERR_IMAGE_INVALID: App partition doesn't contain a valid app image.
* - ESP_FAIL: An allocation error occurred.
*/
esp_err_t esp_partition_get_sha256(const esp_partition_t *partition, uint8_t *sha_256);
/**
* @brief Check for the identity of two partitions by SHA-256 digest.
*
* @param[in] partition_1 Pointer to info for partition 1 containing app or data. (fields: address, size and type, are required to be filled).
* @param[in] partition_2 Pointer to info for partition 2 containing app or data. (fields: address, size and type, are required to be filled).
*
* @return
* - True: In case of the two firmware is equal.
* - False: Otherwise
*/
bool esp_partition_check_identity(const esp_partition_t *partition_1, const esp_partition_t *partition_2);
/**
* @brief Register a partition on an external flash chip
*
* This API allows designating certain areas of external flash chips (identified by the esp_flash_t structure)
* as partitions. This allows using them with components which access SPI flash through the esp_partition API.
*
* @param flash_chip Pointer to the structure identifying the flash chip
* @param offset Address in bytes, where the partition starts
* @param size Size of the partition in bytes
* @param label Partition name
* @param type One of the partition types (ESP_PARTITION_TYPE_*), or an integer. Note that applications can not be booted from external flash
* chips, so using ESP_PARTITION_TYPE_APP is not supported.
* @param subtype One of the partition subtypes (ESP_PARTITION_SUBTYPE_*), or an integer.
* @param[out] out_partition Output, if non-NULL, receives the pointer to the resulting esp_partition_t structure
* @return
* - ESP_OK on success
* - ESP_ERR_NOT_SUPPORTED if CONFIG_CONFIG_SPI_FLASH_USE_LEGACY_IMPL is enabled
* - ESP_ERR_NO_MEM if memory allocation has failed
* - ESP_ERR_INVALID_ARG if the new partition overlaps another partition on the same flash chip
* - ESP_ERR_INVALID_SIZE if the partition doesn't fit into the flash chip size
*/
esp_err_t esp_partition_register_external(esp_flash_t* flash_chip, size_t offset, size_t size,
const char* label, esp_partition_type_t type, esp_partition_subtype_t subtype,
const esp_partition_t** out_partition);
/**
* @brief Deregister the partition previously registered using esp_partition_register_external
* @param partition pointer to the partition structure obtained from esp_partition_register_external,
* @return
* - ESP_OK on success
* - ESP_ERR_NOT_FOUND if the partition pointer is not found
* - ESP_ERR_INVALID_ARG if the partition comes from the partition table
* - ESP_ERR_INVALID_ARG if the partition was not registered using
* esp_partition_register_external function.
*/
esp_err_t esp_partition_deregister_external(const esp_partition_t* partition);
#ifdef __cplusplus
}
#endif
#endif /* __ESP_PARTITION_H__ */

View File

@ -0,0 +1,428 @@
// Copyright 2015-2016 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.
#ifndef ESP_SPI_FLASH_H
#define ESP_SPI_FLASH_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "esp_err.h"
#include "sdkconfig.h"
#include "esp_spi_flash_counters.h"
#ifdef __cplusplus
extern "C" {
#endif
#define ESP_ERR_FLASH_OP_FAIL (ESP_ERR_FLASH_BASE + 1)
#define ESP_ERR_FLASH_OP_TIMEOUT (ESP_ERR_FLASH_BASE + 2)
#define SPI_FLASH_SEC_SIZE 4096 /**< SPI Flash sector size */
#define SPI_FLASH_MMU_PAGE_SIZE 0x10000 /**< Flash cache MMU mapping page size */
typedef enum {
FLASH_WRAP_MODE_8B = 0,
FLASH_WRAP_MODE_16B = 2,
FLASH_WRAP_MODE_32B = 4,
FLASH_WRAP_MODE_64B = 6,
FLASH_WRAP_MODE_DISABLE = 1
} spi_flash_wrap_mode_t;
/**
* @brief set wrap mode of flash
*
* @param mode: wrap mode support disable, 16 32, 64 byte
*
* @return esp_err_t : ESP_OK for successful.
*
*/
esp_err_t spi_flash_wrap_set(spi_flash_wrap_mode_t mode);
/**
* @brief Initialize SPI flash access driver
*
* 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.
*
*/
void spi_flash_init(void);
/**
* @brief Get flash chip size, as set in binary image header
*
* @note This value does not necessarily match real flash size.
*
* @return size of flash chip, in bytes
*/
size_t spi_flash_get_chip_size(void);
/**
* @brief Erase the Flash sector.
*
* @param sector: Sector number, the count starts at sector 0, 4KB per sector.
*
* @return esp_err_t
*/
esp_err_t spi_flash_erase_sector(size_t sector);
/**
* @brief Erase a range of flash sectors
*
* @param start_address Address where erase operation has to start.
* Must be 4kB-aligned
* @param size Size of erased range, in bytes. Must be divisible by 4kB.
*
* @return esp_err_t
*/
esp_err_t spi_flash_erase_range(size_t start_address, size_t size);
/**
* @brief Write data to Flash.
*
* @note For fastest write performance, write a 4 byte aligned size at a
* 4 byte aligned offset in flash from a source buffer in DRAM. Varying any of
* these parameters will still work, but will be slower due to buffering.
*
* @note Writing more than 8KB at a time will be split into multiple
* write operations to avoid disrupting other tasks in the system.
*
* @param dest_addr Destination address in Flash.
* @param src Pointer to the source buffer.
* @param size Length of data, in bytes.
*
* @return esp_err_t
*/
esp_err_t spi_flash_write(size_t dest_addr, const void *src, size_t size);
/**
* @brief Write data encrypted to Flash.
*
* @note Flash encryption must be enabled for this function to work.
*
* @note Flash encryption must be enabled when calling this function.
* If flash encryption is disabled, the function returns
* ESP_ERR_INVALID_STATE. Use esp_flash_encryption_enabled()
* function to determine if flash encryption is enabled.
*
* @note Both dest_addr and size must be multiples of 16 bytes. For
* absolute best performance, both dest_addr and size arguments should
* be multiples of 32 bytes.
*
* @param dest_addr Destination address in Flash. Must be a multiple of 16 bytes.
* @param src Pointer to the source buffer.
* @param size Length of data, in bytes. Must be a multiple of 16 bytes.
*
* @return esp_err_t
*/
esp_err_t spi_flash_write_encrypted(size_t dest_addr, const void *src, size_t size);
/**
* @brief Read data from Flash.
*
* @note For fastest read performance, all parameters should be
* 4 byte aligned. If source address and read size are not 4 byte
* aligned, read may be split into multiple flash operations. If
* destination buffer is not 4 byte aligned, a temporary buffer will
* be allocated on the stack.
*
* @note Reading more than 16KB of data at a time will be split
* into multiple reads to avoid disruption to other tasks in the
* system. Consider using spi_flash_mmap() to read large amounts
* of data.
*
* @param src_addr source address of the data in Flash.
* @param dest pointer to the destination buffer
* @param size length of data
*
*
* @return esp_err_t
*/
esp_err_t spi_flash_read(size_t src_addr, void *dest, size_t size);
/**
* @brief Read data from Encrypted Flash.
*
* If flash encryption is enabled, this function will transparently decrypt data as it is read.
* If flash encryption is not enabled, this function behaves the same as spi_flash_read().
*
* See esp_flash_encryption_enabled() for a function to check if flash encryption is enabled.
*
* @param src source address of the data in Flash.
* @param dest pointer to the destination buffer
* @param size length of data
*
* @return esp_err_t
*/
esp_err_t spi_flash_read_encrypted(size_t src, void *dest, size_t size);
/**
* @brief Enumeration which specifies memory space requested in an mmap call
*/
typedef enum {
SPI_FLASH_MMAP_DATA, /**< map to data memory (Vaddr0), allows byte-aligned access, 4 MB total */
SPI_FLASH_MMAP_INST, /**< map to instruction memory (Vaddr1-3), allows only 4-byte-aligned access, 11 MB total */
} spi_flash_mmap_memory_t;
/**
* @brief Opaque handle for memory region obtained from spi_flash_mmap.
*/
typedef uint32_t spi_flash_mmap_handle_t;
/**
* @brief Map region of flash memory into data or instruction address space
*
* This function allocates sufficient number of 64kB MMU pages and configures
* them to map the requested region of flash memory into the address space.
* It may reuse MMU pages which already provide the required mapping.
*
* As with any allocator, if mmap/munmap are heavily used then the address space
* may become fragmented. To troubleshoot issues with page allocation, use
* spi_flash_mmap_dump() function.
*
* @param src_addr Physical address in flash where requested region starts.
* This address *must* be aligned to 64kB boundary
* (SPI_FLASH_MMU_PAGE_SIZE)
* @param size Size of region to be mapped. This size will be rounded
* up to a 64kB boundary
* @param memory Address space where the region should be mapped (data or instruction)
* @param[out] out_ptr Output, pointer to the mapped memory region
* @param[out] out_handle Output, handle which should be used for spi_flash_munmap call
*
* @return ESP_OK on success, ESP_ERR_NO_MEM if pages can not be allocated
*/
esp_err_t spi_flash_mmap(size_t src_addr, size_t size, spi_flash_mmap_memory_t memory,
const void** out_ptr, spi_flash_mmap_handle_t* out_handle);
/**
* @brief Map sequences of pages of flash memory into data or instruction address space
*
* This function allocates sufficient number of 64kB MMU pages and configures
* them to map the indicated pages of flash memory contiguously into address space.
* In this respect, it works in a similar way as spi_flash_mmap() but it allows mapping
* a (maybe non-contiguous) set of pages into a contiguous region of memory.
*
* @param pages An array of numbers indicating the 64kB pages in flash to be mapped
* contiguously into memory. These indicate the indexes of the 64kB pages,
* not the byte-size addresses as used in other functions.
* Array must be located in internal memory.
* @param page_count Number of entries in the pages array
* @param memory Address space where the region should be mapped (instruction or data)
* @param[out] out_ptr Output, pointer to the mapped memory region
* @param[out] out_handle Output, handle which should be used for spi_flash_munmap call
*
* @return
* - ESP_OK on success
* - ESP_ERR_NO_MEM if pages can not be allocated
* - ESP_ERR_INVALID_ARG if pagecount is zero or pages array is not in
* internal memory
*/
esp_err_t spi_flash_mmap_pages(const int *pages, size_t page_count, spi_flash_mmap_memory_t memory,
const void** out_ptr, spi_flash_mmap_handle_t* out_handle);
/**
* @brief Release region previously obtained using spi_flash_mmap
*
* @note Calling this function will not necessarily unmap memory region.
* Region will only be unmapped when there are no other handles which
* reference this region. In case of partially overlapping regions
* it is possible that memory will be unmapped partially.
*
* @param handle Handle obtained from spi_flash_mmap
*/
void spi_flash_munmap(spi_flash_mmap_handle_t handle);
/**
* @brief Display information about mapped regions
*
* This function lists handles obtained using spi_flash_mmap, along with range
* of pages allocated to each handle. It also lists all non-zero entries of
* MMU table and corresponding reference counts.
*/
void spi_flash_mmap_dump(void);
/**
* @brief get free pages number which can be mmap
*
* This function will return number of free pages available in mmu table. This could be useful
* before calling actual spi_flash_mmap (maps flash range to DCache or ICache memory) to check
* if there is sufficient space available for mapping.
*
* @param memory memory type of MMU table free page
*
* @return number of free pages which can be mmaped
*/
uint32_t spi_flash_mmap_get_free_pages(spi_flash_mmap_memory_t memory);
#define SPI_FLASH_CACHE2PHYS_FAIL UINT32_MAX /*<! Result from spi_flash_cache2phys() if flash cache address is invalid */
/**
* @brief Given a memory address where flash is mapped, return the corresponding physical flash offset.
*
* Cache address does not have have been assigned via spi_flash_mmap(), any address in memory mapped flash space can be looked up.
*
* @param cached Pointer to flashed cached memory.
*
* @return
* - SPI_FLASH_CACHE2PHYS_FAIL If cache address is outside flash cache region, or the address is not mapped.
* - Otherwise, returns physical offset in flash
*/
size_t spi_flash_cache2phys(const void *cached);
/** @brief Given a physical offset in flash, return the address where it is mapped in the memory space.
*
* Physical address does not have to have been assigned via spi_flash_mmap(), any address in flash can be looked up.
*
* @note Only the first matching cache address is returned. If MMU flash cache table is configured so multiple entries
* point to the same physical address, there may be more than one cache address corresponding to that physical
* address. It is also possible for a single physical address to be mapped to both the IROM and DROM regions.
*
* @note This function doesn't impose any alignment constraints, but if memory argument is SPI_FLASH_MMAP_INST and
* phys_offs is not 4-byte aligned, then reading from the returned pointer will result in a crash.
*
* @param phys_offs Physical offset in flash memory to look up.
* @param memory Address space type to look up a flash cache address mapping for (instruction or data)
*
* @return
* - NULL if the physical address is invalid or not mapped to flash cache of the specified memory type.
* - Cached memory address (in IROM or DROM space) corresponding to phys_offs.
*/
const void *spi_flash_phys2cache(size_t phys_offs, spi_flash_mmap_memory_t memory);
/** @brief Check at runtime if flash cache is enabled on both CPUs
*
* @return true if both CPUs have flash cache enabled, false otherwise.
*/
bool spi_flash_cache_enabled(void);
/**
* @brief Re-enable cache for the core defined as cpuid parameter.
*
* @param cpuid the core number to enable instruction cache for
*/
void spi_flash_enable_cache(uint32_t cpuid);
/**
* @brief SPI flash critical section enter function.
*
*/
typedef void (*spi_flash_guard_start_func_t)(void);
/**
* @brief SPI flash critical section exit function.
*/
typedef void (*spi_flash_guard_end_func_t)(void);
/**
* @brief SPI flash operation lock function.
*/
typedef void (*spi_flash_op_lock_func_t)(void);
/**
* @brief SPI flash operation unlock function.
*/
typedef void (*spi_flash_op_unlock_func_t)(void);
/**
* @brief Function to protect SPI flash critical regions corruption.
*/
typedef bool (*spi_flash_is_safe_write_address_t)(size_t addr, size_t size);
/**
* @brief Function to yield to the OS during erase operation.
*/
typedef void (*spi_flash_os_yield_t)(void);
/**
* Structure holding SPI flash access critical sections management functions.
*
* Flash API uses two types of flash access management functions:
* 1) Functions which prepare/restore flash cache and interrupts before calling
* appropriate ROM functions (SPIWrite, SPIRead and SPIEraseBlock):
* - 'start' function should disables flash cache and non-IRAM interrupts and
* is invoked before the call to one of ROM function above.
* - 'end' function should restore state of flash cache and non-IRAM interrupts and
* is invoked after the call to one of ROM function above.
* These two functions are not recursive.
* 2) Functions which synchronizes access to internal data used by flash API.
* This functions are mostly intended to synchronize access to flash API internal data
* in multithreaded environment and use OS primitives:
* - 'op_lock' locks access to flash API internal data.
* - 'op_unlock' unlocks access to flash API internal data.
* These two functions are recursive and can be used around the outside of multiple calls to
* 'start' & 'end', in order to create atomic multi-part flash operations.
* 3) When CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is disabled, flash writing/erasing
* API checks for addresses provided by user to avoid corruption of critical flash regions
* (bootloader, partition table, running application etc.).
*
* Different versions of the guarding functions should be used depending on the context of
* execution (with or without functional OS). In normal conditions when flash API is called
* from task the functions use OS primitives. When there is no OS at all or when
* it is not guaranteed that OS is functional (accessing flash from exception handler) these
* functions cannot use OS primitives or even does not need them (multithreaded access is not possible).
*
* @note Structure and corresponding guard functions should not reside in flash.
* For example structure can be placed in DRAM and functions in IRAM sections.
*/
typedef struct {
spi_flash_guard_start_func_t start; /**< critical section start function. */
spi_flash_guard_end_func_t end; /**< critical section end function. */
spi_flash_op_lock_func_t op_lock; /**< flash access API lock function.*/
spi_flash_op_unlock_func_t op_unlock; /**< flash access API unlock function.*/
#if !CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED
spi_flash_is_safe_write_address_t is_safe_write_address; /**< checks flash write addresses.*/
#endif
spi_flash_os_yield_t yield; /**< yield to the OS during flash erase */
} spi_flash_guard_funcs_t;
/**
* @brief Sets guard functions to access flash.
*
* @note Pointed structure and corresponding guard functions should not reside in flash.
* For example structure can be placed in DRAM and functions in IRAM sections.
*
* @param funcs pointer to structure holding flash access guard functions.
*/
void spi_flash_guard_set(const spi_flash_guard_funcs_t* funcs);
/**
* @brief Get the guard functions used for flash access
*
* @return The guard functions that were set via spi_flash_guard_set(). These functions
* can be called if implementing custom low-level SPI flash operations.
*/
const spi_flash_guard_funcs_t *spi_flash_guard_get(void);
/**
* @brief Default OS-aware flash access guard functions
*/
extern const spi_flash_guard_funcs_t g_flash_guard_default_ops;
/**
* @brief Non-OS flash access guard functions
*
* @note This version of flash guard functions is to be used when no OS is present or from panic handler.
* It does not use any OS primitives and IPC and implies that only calling CPU is active.
*/
extern const spi_flash_guard_funcs_t g_flash_guard_no_os_ops;
#ifdef __cplusplus
}
#endif
#endif /* ESP_SPI_FLASH_H */

View File

@ -0,0 +1,65 @@
// Copyright 2015-2016 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 <stdbool.h>
#include "esp_err.h"
#include "sdkconfig.h"
#if CONFIG_SPI_FLASH_ENABLE_COUNTERS
#ifdef __cplusplus
extern "C" {
#endif
/**
* Structure holding statistics for one type of operation
*/
typedef struct {
uint32_t count; // number of times operation was executed
uint32_t time; // total time taken, in microseconds
uint32_t bytes; // total number of bytes
} spi_flash_counter_t;
typedef struct {
spi_flash_counter_t read;
spi_flash_counter_t write;
spi_flash_counter_t erase;
} spi_flash_counters_t;
/**
* @brief Reset SPI flash operation counters
*/
void spi_flash_reset_counters(void);
/**
* @brief Print SPI flash operation counters
*/
void spi_flash_dump_counters(void);
/**
* @brief Return current SPI flash operation counters
*
* @return pointer to the spi_flash_counters_t structure holding values
* of the operation counters
*/
const spi_flash_counters_t* spi_flash_get_counters(void);
#ifdef __cplusplus
}
#endif
#endif //CONFIG_SPI_FLASH_ENABLE_COUNTERS

View File

@ -0,0 +1,182 @@
// 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, \
.write_data_slicer = memspi_host_write_data_slicer, \
.read = spi_flash_hal_read, \
.read_data_slicer = memspi_host_read_data_slicer, \
.host_status = spi_flash_hal_check_status, \
.configure_host_io_mode = spi_flash_hal_configure_host_io_mode, \
.poll_cmd_done = spi_flash_hal_poll_cmd_done, \
.flush_cache = memspi_host_flush_cache, \
.check_suspend = NULL, \
.resume = spi_flash_hal_resume, \
.suspend = spi_flash_hal_suspend,\
.sus_setup = spi_flash_hal_setup_read_suspend,\
}
/// configuration for the memspi host
typedef spi_flash_hal_config_t memspi_host_config_t;
/// context for the memspi host
typedef spi_flash_hal_context_t memspi_host_inst_t;
/**
* Initialize the memory SPI host.
*
* @param host Pointer to the host structure.
* @param cfg Pointer to configuration structure
*
* @return always return ESP_OK
*/
esp_err_t memspi_host_init_pointers(memspi_host_inst_t *host, 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 hal/include/hal/readme.md
******************************************************************************/
/**
* @brief Read the Status Register read from RDSR (05h).
*
* High speed implementation of RDID through memspi interface relying on the
* ``common_command``.
*
* @param host 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_inst_t *host, uint32_t *id);
/**
* High speed implementation of RDSR through memspi interface relying on the
* ``common_command``.
*
* @param host 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_inst_t *host, uint8_t *out_sr);
/**
* Flush the cache (if needed) after the contents are modified.
*
* @param host 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_inst_t *host, uint32_t addr, uint32_t size);
/**
* Erase contents of entire chip.
*
* @param host The driver context.
*/
void memspi_host_erase_chip(spi_flash_host_inst_t *host);
/**
* Erase a sector starting from a given address. For 24bit address only.
*
* @param host The driver context.
* @param start_address Starting address of the sector.
*/
void memspi_host_erase_sector(spi_flash_host_inst_t *host, uint32_t start_address);
/**
* Erase a block starting from a given address. For 24bit address only.
*
* @param host The driver context.
* @param start_address Starting address of the block.
*/
void memspi_host_erase_block(spi_flash_host_inst_t *host, uint32_t start_address);
/**
* Program a page with contents of a buffer. For 24bit address only.
*
* @param host The driver context.
* @param buffer Buffer which contains the data to be flashed.
* @param address Starting address of where to flash the data.
* @param length The number of bytes to flash.
*/
void memspi_host_program_page(spi_flash_host_inst_t *host, const void *buffer, uint32_t address, uint32_t length);
/**
* Set ability to write to chip.
*
* @param host The driver context.
* @param wp Enable or disable write protect (true - enable, false - disable).
*/
esp_err_t memspi_host_set_write_protect(spi_flash_host_inst_t *host, bool wp);
/**
* Read data to buffer.
*
* @param host The driver context.
* @param buffer Buffer which contains the data to be read.
* @param address Starting address of where to read the data.
* @param length The number of bytes to read.
*/
esp_err_t memspi_host_read(spi_flash_host_inst_t *host, void *buffer, uint32_t address, uint32_t read_len);
/**
* @brief Slicer for read data used in non-encrypted regions. This slicer does nothing but
* limit the length to the maximum size the host supports.
*
* @param address Flash address to read
* @param len Length to read
* @param align_address Output of the address to read, should be equal to the input `address`
* @param page_size Physical SPI flash page size
*
* @return Length that can actually be read in one `read` call in `spi_flash_host_driver_t`.
*/
int memspi_host_read_data_slicer(spi_flash_host_inst_t *host, uint32_t address, uint32_t len, uint32_t *align_address, uint32_t page_size);
/**
* @brief Slicer for write data used in non-encrypted regions. This slicer limit the length to the
* maximum size the host supports, and truncate if the write data lie accross the page boundary
* (256 bytes)
*
* @param address Flash address to write
* @param len Length to write
* @param align_address Output of the address to write, should be equal to the input `address`
* @param page_size Physical SPI flash page size
*
* @return Length that can actually be written in one `program_page` call in `spi_flash_host_driver_t`.
*/
int memspi_host_write_data_slicer(spi_flash_host_inst_t *host, uint32_t address, uint32_t len, uint32_t *align_address, uint32_t page_size);

View File

@ -0,0 +1,21 @@
// Copyright 2015-2021 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"
extern const spi_flash_chip_t esp_flash_chip_boya;

View File

@ -0,0 +1,205 @@
// 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_flash.h"
struct esp_flash_t;
typedef struct esp_flash_t esp_flash_t;
typedef struct spi_flash_chip_t spi_flash_chip_t;
/** Timeout configurations for flash operations, all in us */
typedef struct {
uint32_t idle_timeout; ///< Default timeout for other commands to be sent by host and get done by flash
uint32_t chip_erase_timeout; ///< Timeout for chip erase operation
uint32_t block_erase_timeout; ///< Timeout for block erase operation
uint32_t sector_erase_timeout; ///< Timeout for sector erase operation
uint32_t page_program_timeout; ///< Timeout for page program operation
} flash_chip_op_timeout_t;
typedef enum {
SPI_FLASH_REG_STATUS = 1,
} spi_flash_register_t;
/** @brief SPI flash chip driver definition structure.
*
* 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. 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 chip driver functions directly in other contexts.
*
* 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.
*/
struct spi_flash_chip_t {
const char *name; ///< Name of the chip driver
const flash_chip_op_timeout_t *timeout; ///< Timeout configuration for this chip
/* 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.
*
* Auto-detection of a SPI flash chip calls this function in turn on each registered driver (see esp_flash_registered_flash_drivers).
*
* ID - as read by spi_flash_generic_read_id() - is supplied so each probe
* function doesn't need to unnecessarily read ID, but probe is permitted
* to interrogate flash in any non-destructive way.
*
* 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 ESP_OK if probing was successful, an error otherwise. Driver may
* assume that returning ESP_OK means it has claimed this chip.
*/
esp_err_t (*probe)(esp_flash_t *chip, uint32_t flash_id);
esp_err_t (*reset)(esp_flash_t *chip);
/* Detect SPI flash size
*
* Interrogate the chip to detect its 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_err_t (*erase_chip)(esp_flash_t *chip);
/* Erase a sector of the chip. Sector size is specified in the 'sector_size' field.
sector_address is an offset in bytes.
Caller has verified that this sector should be non-write-protected.
*/
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_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_err_t (*get_chip_write_protect)(esp_flash_t *chip, bool *out_write_protected);
/* Set the write protect status of the entire chip. */
esp_err_t (*set_chip_write_protect)(esp_flash_t *chip, bool chip_write_protect);
/* Number of individually write protectable regions on this chip. Range 0-63. */
uint8_t num_protectable_regions;
/* Pointer to an array describing each protectable region. Should have num_protectable_regions elements. */
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_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_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_err_t (*read)(esp_flash_t *chip, void *buffer, uint32_t address, uint32_t length);
/* Write any amount of data to the chip.
*/
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.
*
* This function is expected to be called by chip->drv->write (if the
* chip->drv->write implementation doesn't call it then it can be left as NULL.)
*
* - The length argument supplied to this function is at most 'page_size' bytes.
*
* - 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_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_err_t (*write_encrypted)(esp_flash_t *chip, const void *buffer, uint32_t address, uint32_t length);
/* 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 ESP_ERR_TIMEOUT. This is useful to avoid hanging
if the chip is otherwise unresponsive (ie returns all 0xFF or similar.)
*/
esp_err_t (*wait_idle)(esp_flash_t *chip, uint32_t timeout_us);
/* 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 ESP_ERR_FLASH_UNSUPPORTED_HOST or ESP_ERR_FLASH_UNSUPPORTED_CHIP if the specified mode is unsupported.
*/
esp_err_t (*set_io_mode)(esp_flash_t *chip);
/*
* Get whether the Quad Enable (QE) is set. (*out_io_mode)=SPI_FLASH_QOUT if
* enabled, otherwise disabled
*/
esp_err_t (*get_io_mode)(esp_flash_t *chip, esp_flash_io_mode_t* out_io_mode);
/*
* Read the chip ID. Called when chip driver is set, but we want to know the exact chip id (to
* get the size, etc.).
*/
esp_err_t (*read_id)(esp_flash_t *chip, uint32_t* out_chip_id);
/*
* Read the requested register (status, etc.).
*/
esp_err_t (*read_reg)(esp_flash_t *chip, spi_flash_register_t reg_id, uint32_t* out_reg);
/** Yield to other tasks. Called during erase operations. */
esp_err_t (*yield)(esp_flash_t *chip, uint32_t wip);
/** Setup flash suspend configuration. */
esp_err_t (*sus_setup)(esp_flash_t *chip);
/**
* Read the chip unique ID.
*/
esp_err_t (*read_unique_id)(esp_flash_t *chip, uint64_t* flash_unique_id);
};
/* 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.
Array is terminated with a NULL pointer.
This pointer can be overwritten with a pointer to a new array, to update the list of known flash chips.
*/
extern const spi_flash_chip_t **esp_flash_registered_chips;

View File

@ -0,0 +1,36 @@
// 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"
/**
* GD (GigaDevice) 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.
*
* Note that this is for GD chips with product ID 40H (GD25Q) and 60H (GD25LQ). The chip diver uses
* different commands to write the SR2 register according to the chip ID. For GD25Q40 - GD25Q16
* chips, and GD25LQ chips, WRSR (01H) command is used; while WRSR2 (31H) is used for GD25Q32 -
* GD25Q127 chips.
*/
esp_err_t spi_flash_chip_gd_probe(esp_flash_t *chip, uint32_t flash_id);
esp_err_t spi_flash_chip_gd_set_io_mode(esp_flash_t *chip);
esp_err_t spi_flash_chip_gd_get_io_mode(esp_flash_t *chip, esp_flash_io_mode_t* out_io_mode);
extern const spi_flash_chip_t esp_flash_chip_gd;

View File

@ -0,0 +1,400 @@
// 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 command.
*
* @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.
*
* @return
* - ESP_OK if success
* - ESP_ERR_NOT_SUPPORTED if the chip is not able to perform the operation. This is indicated by WREN = 1 after the command is sent.
* - 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 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
* - ESP_ERR_NOT_SUPPORTED if the chip is not able to perform the operation. This is indicated by WREN = 1 after the command is sent.
* - 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 the generic 64KB block erase 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
* - ESP_ERR_NOT_SUPPORTED if the chip is not able to perform the operation. This is indicated by WREN = 1 after the command is sent.
* - 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 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
* - ESP_ERR_NOT_SUPPORTED if the chip is not able to perform the operation. This is indicated by WREN = 1 after the command is sent.
* - 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 or write disable 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_set_write_protect(esp_flash_t *chip, bool write_protect);
/**
* @brief Check whether WEL (write enable latch) bit is set in the Status Register read from RDSR.
*
* @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.
* @param out_write_protect Output of whether the write protect is set.
*
* @return
* - ESP_OK if success
* - or other error passed from the ``read_status`` function of host driver
*/
esp_err_t spi_flash_chip_generic_get_write_protect(esp_flash_t *chip, bool *out_write_protect);
#define ESP_FLASH_CHIP_GENERIC_NO_TIMEOUT -1
/**
* @brief Send commands to read one of the reg of the chip
*
* @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.
* @param reg_id Type of the register to read
* @param out_reg Output of the register value
* @return esp_err_t Error code passed from the ``read_status`` function of host driver.
*/
esp_err_t spi_flash_chip_generic_read_reg(esp_flash_t* chip, spi_flash_register_t reg_id, uint32_t* out_reg);
/**
* @brief Read flash status via the RDSR command 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_us Time to wait before timeout, in us.
*
* @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_us);
/**
* @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_io_mode(esp_flash_t *chip);
/**
* Get whether the Quad Enable (QE) is set.
*
* @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.
* @param out_quad_mode Pointer to store the output mode.
* - SPI_FLASH_QOUT: QE is enabled
* - otherwise: QE is disabled
*
* @return
* - ESP_OK if success
* - or other error passed from the ``common_command`` function of host driver
*/
esp_err_t spi_flash_chip_generic_get_io_mode(esp_flash_t *chip, esp_flash_io_mode_t* out_quad_mode);
/**
* @brief Read the chip unique ID.
*
* @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.
* @param flash_unique_id Pointer to store output unique id.
*
* @return
* - ESP_OK if success
* - ESP_ERR_NOT_SUPPORTED if the chip doesn't support read id.
*/
esp_err_t spi_flash_chip_generic_read_unique_id(esp_flash_t *chip, uint64_t* flash_unique_id);
/**
* 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
*******************************************************************************/
/// Function pointer type for reading status register with QE bit.
typedef esp_err_t (*esp_flash_rdsr_func_t)(esp_flash_t* chip, uint32_t* out_sr);
/**
* Use RDSR2 (35H) to read bit 15-8 of the SR, and RDSR (05H) to read bit 7-0.
*
* @param chip Pointer to SPI flash chip to use.
* @param out_sr Pointer to buffer to hold the status register, 16 bits.
*
* @return ESP_OK if success, otherwise error code passed from the
* `common_command` function of the host driver.
*/
esp_err_t spi_flash_common_read_status_16b_rdsr_rdsr2(esp_flash_t* chip, uint32_t* out_sr);
/**
* Use RDSR2 (35H) to read bit 15-8 of the SR.
*
* @param chip Pointer to SPI flash chip to use.
* @param out_sr Pointer to buffer to hold the status register, 8 bits.
*
* @return ESP_OK if success, otherwise error code passed from the
* `common_command` function of the host driver.
*/
esp_err_t spi_flash_common_read_status_8b_rdsr2(esp_flash_t* chip, uint32_t* out_sr);
/**
* Use RDSR (05H) to read bit 7-0 of the SR.
*
* @param chip Pointer to SPI flash chip to use.
* @param out_sr Pointer to buffer to hold the status register, 8 bits.
*
* @return ESP_OK if success, otherwise error code passed from the
* `common_command` function of the host driver.
*/
esp_err_t spi_flash_common_read_status_8b_rdsr(esp_flash_t* chip, uint32_t* out_sr);
/// Function pointer type for writing status register with QE bit.
typedef esp_err_t (*esp_flash_wrsr_func_t)(esp_flash_t* chip, uint32_t sr);
/**
* Use WRSR (01H) to write bit 7-0 of the SR.
*
* @param chip Pointer to SPI flash chip to use.
* @param sr Value of the status register to write, 8 bits.
*
* @return ESP_OK if success, otherwise error code passed from the
* `common_command` function of the host driver.
*/
esp_err_t spi_flash_common_write_status_8b_wrsr(esp_flash_t* chip, uint32_t sr);
/**
* Use WRSR (01H) to write bit 15-0 of the SR.
*
* @param chip Pointer to SPI flash chip to use.
* @param sr Value of the status register to write, 16 bits.
*
* @return ESP_OK if success, otherwise error code passed from the
* `common_command` function of the host driver.
*/
esp_err_t spi_flash_common_write_status_16b_wrsr(esp_flash_t* chip, uint32_t sr);
/**
* Use WRSR2 (31H) to write bit 15-8 of the SR.
*
* @param chip Pointer to SPI flash chip to use.
* @param sr Value of the status register to write, 8 bits.
*
* @return ESP_OK if success, otherwise error code passed from the
* `common_command` function of the host driver.
*/
esp_err_t spi_flash_common_write_status_8b_wrsr2(esp_flash_t* chip, uint32_t sr);
/**
* @brief Utility function for set_read_mode chip_drv function. If required,
* set and check the QE bit in the flash chip to enable the QIO/QOUT mode.
*
* Most chip QE enable follows a common pattern, though commands to read/write
* the status register may be different, as well as the position of QE bit.
*
* Registers to actually do Quad transtions and command to be sent in reading
* should also be configured via
* spi_flash_chip_generic_config_host_io_mode().
*
* Note that the bit length and qe position of wrsr_func, rdsr_func and
* qe_sr_bit should be consistent.
*
* @param chip Pointer to SPI flash chip to use.
* @param wrsr_func Function pointer for writing the status register
* @param rdsr_func Function pointer for reading the status register
* @param qe_sr_bit status with the qe bit only.
*
* @return always ESP_OK (currently).
*/
esp_err_t spi_flash_common_set_io_mode(esp_flash_t *chip, esp_flash_wrsr_func_t wrsr_func, esp_flash_rdsr_func_t rdsr_func, uint32_t qe_sr_bit);
/**
* @brief Configure the host registers to use the specified read mode set in
* the ``chip->read_mode``.
*
* Usually called in chip_drv read() functions before actual reading
* transactions. Also prepare the command to be sent in read functions.
*
* @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.
* @param addr_32bit Whether 32 bit commands will be used (Currently only W25Q256 is supported)
*
* @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_io_mode(esp_flash_t *chip, bool addr_32bit);
/**
* @brief Handle explicit yield requests
*
* @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.
* @param wip Write (erase) in progress, `true` if this function is called during waiting idle of a erase/write command; else `false`.
* @return ESP_OK if success, otherwise failed.
*/
esp_err_t spi_flash_chip_generic_yield(esp_flash_t* chip, uint32_t wip);
/**
* @brief Setup for flash suspend command configuration.
*
* @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.
* @return ESP_OK
*/
esp_err_t spi_flash_chip_generic_suspend_cmd_conf(esp_flash_t *chip);
/// Default timeout configuration used by most chips
const flash_chip_op_timeout_t spi_flash_chip_generic_timeout;

View File

@ -0,0 +1,31 @@
// 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.
*/
esp_err_t spi_flash_chip_issi_probe(esp_flash_t *chip, uint32_t flash_id);
esp_err_t spi_flash_chip_issi_set_io_mode(esp_flash_t *chip);
esp_err_t spi_flash_chip_issi_get_io_mode(esp_flash_t *chip, esp_flash_io_mode_t* out_io_mode);
extern const spi_flash_chip_t esp_flash_chip_issi;

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"
/**
* MXIC 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_mxic;

View File

@ -0,0 +1,27 @@
// Copyright 2015-2020 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"
/**
* Winbond 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_winbond;