mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-28 21:33:32 +00:00
spi_flash: support working on differnt buses and frequency
This commit is contained in:

committed by
bot

parent
ce4de867d6
commit
1036a091fe
39
components/soc/include/hal/esp_flash_err.h
Normal file
39
components/soc/include/hal/esp_flash_err.h
Normal file
@@ -0,0 +1,39 @@
|
||||
// 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_err.h"
|
||||
|
||||
/*
|
||||
* Possible errors returned from esp flash internal functions, these error codes
|
||||
* should be consistent with esp_err_t codes. But in order to make the source
|
||||
* files less dependent to esp_err_t, they use the error codes defined in this
|
||||
* replacable header. This header should ensure the consistency to esp_err_t.
|
||||
*/
|
||||
|
||||
/* These should be consistent with esp_err_t errors */
|
||||
#define ESP_ERR_FLASH_SIZE_NOT_MATCH ESP_ERR_INVALID_SIZE ///< The chip doesn't have enough space for the current partition table
|
||||
#define ESP_ERR_FLASH_NO_RESPONSE ESP_ERR_INVALID_RESPONSE ///< Chip did not respond to the command, or timed out.
|
||||
|
||||
|
||||
#define ESP_ERR_FLASH_ERR_BASE 0x6000 ///< Starting number of Flash error codes */
|
||||
//The ROM code has already taken 1 and 2, to avoid possible conflicts, start from 3.
|
||||
#define ESP_ERR_FLASH_NOT_INITIALISED (ESP_ERR_FLASH_ERR_BASE+3) ///< esp_flash_chip_t structure not correctly initialised by esp_flash_init().
|
||||
#define ESP_ERR_FLASH_UNSUPPORTED_HOST (ESP_ERR_FLASH_ERR_BASE+4) ///< Requested operation isn't supported via this host SPI bus (chip->spi field).
|
||||
#define ESP_ERR_FLASH_UNSUPPORTED_CHIP (ESP_ERR_FLASH_ERR_BASE+5) ///< Requested operation isn't supported by this model of SPI flash chip.
|
||||
#define ESP_ERR_FLASH_PROTECTED (ESP_ERR_FLASH_ERR_BASE+6) ///< Write operation failed due to chip's write protection being enabled.
|
||||
|
||||
|
243
components/soc/include/hal/spi_flash_hal.h
Normal file
243
components/soc/include/hal/spi_flash_hal.h
Normal file
@@ -0,0 +1,243 @@
|
||||
// Copyright 2010-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.
|
||||
|
||||
/*******************************************************************************
|
||||
* NOTICE
|
||||
* The HAL is not public api, don't use in application code.
|
||||
* See readme.md in soc/include/hal/readme.md
|
||||
******************************************************************************/
|
||||
|
||||
// The HAL layer for SPI Flash (common part)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hal/spi_flash_ll.h"
|
||||
#include "hal/spi_flash_host_drv.h"
|
||||
#include "soc/soc_memory_layout.h"
|
||||
|
||||
#define ESP_FLASH_DEFAULT_FREQ ESP_FLASH_20MHZ
|
||||
|
||||
/* Hardware host-specific constants */
|
||||
#define SPI_FLASH_HAL_MAX_WRITE_BYTES 64
|
||||
#define SPI_FLASH_HAL_MAX_READ_BYTES 64
|
||||
|
||||
///Lowest speed supported by the driver, currently 5 MHz
|
||||
#define ESP_FLASH_SPEED_MIN ESP_FLASH_5MHZ
|
||||
|
||||
/**
|
||||
* @brief SPI flash clock speed values, always refer to them by the enum rather
|
||||
* than the actual value (more speed may be appended into the list).
|
||||
*
|
||||
* A strategy to select the maximum allowed speed is to enumerate from the
|
||||
* ``ESP_FLSH_SPEED_MAX-1`` or highest frequency supported by your flash, and
|
||||
* decrease the speed until the probing success.
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_FLASH_5MHZ = 0, ///< The flash runs under 5MHz
|
||||
ESP_FLASH_10MHZ, ///< The flash runs under 10MHz
|
||||
ESP_FLASH_20MHZ, ///< The flash runs under 20MHz
|
||||
ESP_FLASH_26MHZ, ///< The flash runs under 26MHz
|
||||
ESP_FLASH_40MHZ, ///< The flash runs under 40MHz
|
||||
ESP_FLASH_80MHZ, ///< The flash runs under 80MHz
|
||||
ESP_FLASH_SPEED_MAX, ///< The maximum frequency supported by the host is ``ESP_FLASH_SPEED_MAX-1``.
|
||||
} esp_flash_speed_t;
|
||||
|
||||
/**
|
||||
* Generic driver context structure for all chips using the SPI peripheral.
|
||||
* Include this into the HEAD of the driver data for other driver
|
||||
* implementations that also use the SPI peripheral.
|
||||
*/
|
||||
typedef struct {
|
||||
spi_dev_t *spi; ///< Pointer to SPI peripheral registers (SP1, SPI2 or SPI3). Set before initialisation.
|
||||
int cs_num; ///< Which cs pin is used, 0-2.
|
||||
int extra_dummy;
|
||||
spi_flash_ll_clock_reg_t clock_conf;
|
||||
} spi_flash_memspi_data_t;
|
||||
|
||||
/// Configuration structure for the SPI driver.
|
||||
typedef struct {
|
||||
int host_id; ///< SPI peripheral ID, 1 for SPI1, 2 for SPI2 (HSPI), 3 for SPI3 (VSPI)
|
||||
int cs_num; ///< Which cs pin is used, 0-2.
|
||||
bool iomux; ///< Whether the IOMUX is used, used for timing compensation.
|
||||
int input_delay_ns; ///< Input delay on the MISO pin after the launch clock, used for timing compensation.
|
||||
esp_flash_speed_t speed;///< SPI flash clock speed to work at.
|
||||
} spi_flash_memspi_config_t;
|
||||
|
||||
/**
|
||||
* Configure SPI flash hal settings.
|
||||
*
|
||||
* @param data Buffer to hold configured data, the buffer should be in DRAM to be available when cache disabled
|
||||
* @param cfg Configurations to set
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - ESP_ERR_INVALID_ARG: the data buffer is not in the DRAM.
|
||||
*/
|
||||
esp_err_t spi_flash_hal_init(spi_flash_memspi_data_t *data_out, const spi_flash_memspi_config_t *cfg);
|
||||
|
||||
/**
|
||||
* Configure the device-related register before transactions.
|
||||
*
|
||||
* @param driver The driver context.
|
||||
*
|
||||
* @return always return ESP_OK.
|
||||
*/
|
||||
esp_err_t spi_flash_hal_device_config(spi_flash_host_driver_t *driver);
|
||||
|
||||
/**
|
||||
* Send an user-defined spi transaction to the device.
|
||||
*
|
||||
* @note This is usually used when the memspi interface doesn't support some
|
||||
* particular commands. Since this function supports timing compensation, it is
|
||||
* also used to receive some data when the frequency is high.
|
||||
*
|
||||
* @param driver The driver context.
|
||||
* @param trans The transaction to send, also holds the received data.
|
||||
*
|
||||
* @return always return ESP_OK.
|
||||
*/
|
||||
esp_err_t spi_flash_hal_common_command(spi_flash_host_driver_t *driver, spi_flash_trans_t *trans);
|
||||
|
||||
/**
|
||||
* Erase whole flash chip.
|
||||
*
|
||||
* @param driver The driver context.
|
||||
*/
|
||||
void spi_flash_hal_erase_chip(spi_flash_host_driver_t *driver);
|
||||
|
||||
/**
|
||||
* Erase a specific sector by its start address.
|
||||
*
|
||||
* @param driver The driver context.
|
||||
* @param start_address Start address of the sector to erase.
|
||||
*/
|
||||
void spi_flash_hal_erase_sector(spi_flash_host_driver_t *driver, uint32_t start_address);
|
||||
|
||||
/**
|
||||
* Erase a specific block by its start address.
|
||||
*
|
||||
* @param driver The driver context.
|
||||
* @param start_address Start address of the block to erase.
|
||||
*/
|
||||
void spi_flash_hal_erase_block(spi_flash_host_driver_t *driver, uint32_t start_address);
|
||||
|
||||
/**
|
||||
* Program a page of the flash.
|
||||
*
|
||||
* @param driver The driver context.
|
||||
* @param address Address of the page to program
|
||||
* @param buffer Data to program
|
||||
* @param length Size of the buffer in bytes, no larger than ``SPI_FLASH_HAL_MAX_WRITE_BYTES`` (64) bytes.
|
||||
*/
|
||||
void spi_flash_hal_program_page(spi_flash_host_driver_t *driver, const void *buffer, uint32_t address, uint32_t length);
|
||||
|
||||
/**
|
||||
* Read from the flash. The read command should be set by ``spi_flash_hal_configure_host_read_mode`` before.
|
||||
*
|
||||
* @param driver The driver context.
|
||||
* @param buffer Buffer to store the read data
|
||||
* @param address Address to read
|
||||
* @param length Length to read, no larger than ``SPI_FLASH_HAL_MAX_READ_BYTES`` (64) bytes.
|
||||
*
|
||||
* @return always return ESP_OK.
|
||||
*/
|
||||
esp_err_t spi_flash_hal_read(spi_flash_host_driver_t *driver, void *buffer, uint32_t address, uint32_t read_len);
|
||||
|
||||
/**
|
||||
* Enable or disable the write protection of the flash chip.
|
||||
*
|
||||
* @param driver The driver context.
|
||||
* @param wp true to enable the write protection, otherwise false.
|
||||
*
|
||||
* @return always return ESP_OK.
|
||||
*/
|
||||
esp_err_t spi_flash_hal_set_write_protect(spi_flash_host_driver_t *chip_drv, bool wp);
|
||||
|
||||
/**
|
||||
* Check whether the SPI host is idle and can perform other operations.
|
||||
*
|
||||
* @param driver The driver context.
|
||||
*
|
||||
* @return ture if idle, otherwise false.
|
||||
*/
|
||||
bool spi_flash_hal_host_idle(spi_flash_host_driver_t *driver);
|
||||
|
||||
/**
|
||||
* Configure the SPI host hardware registers for the specified read mode.
|
||||
*
|
||||
* Note that calling this configures SPI host registers, so if running any
|
||||
* other commands as part of set_read_mode() then these must be run before
|
||||
* calling this function.
|
||||
*
|
||||
* @param driver The driver context
|
||||
* @param read_mode The HW read mode to use
|
||||
* @param addr_bitlen Length of the address phase, in bits
|
||||
* @param dummy_cyclelen_base Base cycles of the dummy phase, some extra dummy cycles may be appended to compensate the timing.
|
||||
* @param read_command Actual reading command to send to flash chip on the bus.
|
||||
*
|
||||
* @return always return ESP_OK.
|
||||
*/
|
||||
esp_err_t spi_flash_hal_configure_host_read_mode(spi_flash_host_driver_t *driver, esp_flash_read_mode_t read_mode,
|
||||
uint32_t addr_bitlen, uint32_t dummy_cyclelen_base,
|
||||
uint32_t read_command);
|
||||
|
||||
/**
|
||||
* Poll until the last operation is done.
|
||||
*
|
||||
* @param driver The driver context.
|
||||
*/
|
||||
void spi_flash_hal_poll_cmd_done(spi_flash_host_driver_t *driver);
|
||||
|
||||
/**
|
||||
* Check whether the given buffer can be used as the write buffer directly. If 'chip' is connected to the main SPI bus, we can only write directly from
|
||||
* regions that are accessible ith cache disabled. *
|
||||
*
|
||||
* @param driver The driver context
|
||||
* @param p The buffer holding data to send.
|
||||
*
|
||||
* @return True if the buffer can be used to send data, otherwise false.
|
||||
*/
|
||||
static inline bool spi_flash_hal_supports_direct_write(spi_flash_host_driver_t *driver, const void *p)
|
||||
{
|
||||
#ifdef ESP_PLATFORM
|
||||
bool direct_write = ( ((spi_flash_memspi_data_t *)driver->driver_data)->spi != &SPI1
|
||||
|| esp_ptr_in_dram(p) );
|
||||
#else
|
||||
//If it is not on real chips, there is no limitation that the data has to be in DRAM.
|
||||
bool direct_write = true;
|
||||
#endif
|
||||
return direct_write;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given buffer can be used as the read buffer directly. If 'chip' is connected to the main SPI bus, we can only read directly from
|
||||
* regions that are accessible ith cache disabled. *
|
||||
*
|
||||
* @param driver The driver context
|
||||
* @param p The buffer to hold the received data.
|
||||
*
|
||||
* @return True if the buffer can be used to receive data, otherwise false.
|
||||
*/
|
||||
static inline bool spi_flash_hal_supports_direct_read(spi_flash_host_driver_t *driver, const void *p)
|
||||
{
|
||||
#ifdef ESP_PLATFORM
|
||||
//currently the driver doesn't support to read through DMA, no word-aligned requirements
|
||||
bool direct_read = ( ((spi_flash_memspi_data_t *)driver->driver_data)->spi != &SPI1
|
||||
|| esp_ptr_in_dram(p) );
|
||||
#else
|
||||
//If it is not on real chips, there is no limitation that the data has to be in DRAM.
|
||||
bool direct_read = true;
|
||||
#endif
|
||||
return direct_read;
|
||||
}
|
112
components/soc/include/hal/spi_flash_host_drv.h
Normal file
112
components/soc/include/hal/spi_flash_host_drv.h
Normal file
@@ -0,0 +1,112 @@
|
||||
// Copyright 2010-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_ll.h"
|
||||
#include "hal/esp_flash_err.h"
|
||||
|
||||
/** Definition of a common transaction. Also holds the return value. */
|
||||
typedef struct {
|
||||
uint8_t command; ///< Command to send, always 8bits
|
||||
uint8_t mosi_len; ///< Output data length, in bits
|
||||
uint8_t miso_len; ///< Input data length, in bits
|
||||
uint32_t mosi_data; ///< Output data to slave
|
||||
uint32_t miso_data[2]; ///< [out] Input data from slave, little endian
|
||||
} spi_flash_trans_t;
|
||||
|
||||
|
||||
struct spi_flash_host_driver_t;
|
||||
typedef struct spi_flash_host_driver_t spi_flash_host_driver_t;
|
||||
|
||||
/** Host driver configuration and context structure. */
|
||||
struct spi_flash_host_driver_t {
|
||||
/**
|
||||
* Configuration and static data used by the specific host driver. The type
|
||||
* is determined by the host driver.
|
||||
*/
|
||||
void *driver_data;
|
||||
/**
|
||||
* Configure the device-related register before transactions. This saves
|
||||
* some time to re-configure those registers when we send continuously
|
||||
*/
|
||||
esp_err_t (*dev_config)(spi_flash_host_driver_t *driver);
|
||||
/**
|
||||
* Send an user-defined spi transaction to the device.
|
||||
*/
|
||||
esp_err_t (*common_command)(spi_flash_host_driver_t *driver, spi_flash_trans_t *t);
|
||||
/**
|
||||
* Read flash ID.
|
||||
*/
|
||||
esp_err_t (*read_id)(spi_flash_host_driver_t *driver, uint32_t *id);
|
||||
/**
|
||||
* Erase whole flash chip.
|
||||
*/
|
||||
void (*erase_chip)(spi_flash_host_driver_t *driver);
|
||||
/**
|
||||
* Erase a specific sector by its start address.
|
||||
*/
|
||||
void (*erase_sector)(spi_flash_host_driver_t *driver, uint32_t start_address);
|
||||
/**
|
||||
* Erase a specific block by its start address.
|
||||
*/
|
||||
void (*erase_block)(spi_flash_host_driver_t *driver, uint32_t start_address);
|
||||
/**
|
||||
* Read the status of the flash chip.
|
||||
*/
|
||||
esp_err_t (*read_status)(spi_flash_host_driver_t *driver, uint8_t *out_sr);
|
||||
/**
|
||||
* Disable write protection.
|
||||
*/
|
||||
esp_err_t (*set_write_protect)(spi_flash_host_driver_t *driver, bool wp);
|
||||
/**
|
||||
* Program a page of the flash. Check ``max_write_bytes`` for the maximum allowed writing length.
|
||||
*/
|
||||
void (*program_page)(spi_flash_host_driver_t *driver, const void *buffer, uint32_t address, uint32_t length);
|
||||
/** Check whether need to allocate new buffer to write */
|
||||
bool (*supports_direct_write)(spi_flash_host_driver_t *driver, const void *p);
|
||||
/** Check whether need to allocate new buffer to read */
|
||||
bool (*supports_direct_read)(spi_flash_host_driver_t *driver, const void *p);
|
||||
/** maximum length of program_page */
|
||||
int max_write_bytes;
|
||||
/**
|
||||
* Read data from the flash. Check ``max_read_bytes`` for the maximum allowed reading length.
|
||||
*/
|
||||
esp_err_t (*read)(spi_flash_host_driver_t *driver, void *buffer, uint32_t address, uint32_t read_len);
|
||||
/** maximum length of read */
|
||||
int max_read_bytes;
|
||||
/**
|
||||
* Check whether the host is idle to perform new operations.
|
||||
*/
|
||||
bool (*host_idle)(spi_flash_host_driver_t *driver);
|
||||
/**
|
||||
* Configure the host to work at different read mode.
|
||||
*/
|
||||
esp_err_t (*configure_host_read_mode)(spi_flash_host_driver_t *driver, esp_flash_read_mode_t read_mode, uint32_t addr_bitlen, uint32_t dummy_bitlen_base, uint32_t read_command);
|
||||
/**
|
||||
* Internal use, poll the HW until the last operation is done.
|
||||
*/
|
||||
void (*poll_cmd_done)(spi_flash_host_driver_t *driver);
|
||||
/**
|
||||
* For some host (SPI1), they are shared with a cache. When the data is
|
||||
* modified, the cache needs to be flushed. Left NULL if not supported.
|
||||
*/
|
||||
esp_err_t (*flush_cache)(spi_flash_host_driver_t* driver, uint32_t addr, uint32_t size);
|
||||
/**
|
||||
* Check if the given region is protected (e.g. is the bootloader). Left
|
||||
* NULL if current host doesn't need protection.
|
||||
*/
|
||||
bool (*region_protected)(spi_flash_host_driver_t* driver, uint32_t addr, uint32_t size);
|
||||
};
|
||||
|
Reference in New Issue
Block a user