mirror of
https://github.com/espressif/esp-idf
synced 2025-03-09 17:19:09 -04:00
Merge branch 'feature/flash_software_resume_v5.4' into 'release/v5.4'
feat(spi_flash): Add config for adding auto check status after suspend to improve performance (backport v5.4) See merge request espressif/esp-idf!36525
This commit is contained in:
commit
cf392937b6
@ -18,7 +18,7 @@
|
||||
#include <sys/param.h> // For MIN/MAX
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "hal/misc.h"
|
||||
#include "soc/spi_periph.h"
|
||||
#include "hal/spi_types.h"
|
||||
#include "hal/spi_flash_types.h"
|
||||
@ -144,7 +144,7 @@ static inline void spimem_flash_ll_auto_resume_init(spi_mem_dev_t *dev, bool aut
|
||||
*/
|
||||
static inline void spimem_flash_ll_suspend_cmd_setup(spi_mem_dev_t *dev, uint32_t sus_cmd)
|
||||
{
|
||||
dev->flash_sus_cmd.flash_pes_command = sus_cmd;
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_cmd, flash_pes_command, sus_cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -156,7 +156,7 @@ static inline void spimem_flash_ll_suspend_cmd_setup(spi_mem_dev_t *dev, uint32_
|
||||
*/
|
||||
static inline void spimem_flash_ll_resume_cmd_setup(spi_mem_dev_t *dev, uint32_t res_cmd)
|
||||
{
|
||||
dev->flash_sus_cmd.flash_per_command = res_cmd;
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_cmd, flash_per_command, res_cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -168,7 +168,7 @@ static inline void spimem_flash_ll_resume_cmd_setup(spi_mem_dev_t *dev, uint32_t
|
||||
*/
|
||||
static inline void spimem_flash_ll_rd_sus_cmd_setup(spi_mem_dev_t *dev, uint32_t pesr_cmd)
|
||||
{
|
||||
dev->flash_sus_cmd.wait_pesr_command = pesr_cmd;
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_cmd, wait_pesr_command, pesr_cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -205,7 +205,7 @@ static inline void spimem_flash_ll_res_check_sus_setup(spi_mem_dev_t *dev, bool
|
||||
static inline void spimem_flash_ll_set_read_sus_status(spi_mem_dev_t *dev, uint32_t sus_conf)
|
||||
{
|
||||
dev->flash_sus_ctrl.frd_sus_2b = 0;
|
||||
dev->flash_sus_ctrl.pesr_end_msk = sus_conf;
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_ctrl, pesr_end_msk, sus_conf);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -236,13 +236,14 @@ static inline void spimem_flash_set_cs_hold_delay(spi_mem_dev_t *dev, uint32_t c
|
||||
* Initialize auto wait idle mode
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param auto_waiti Enable/disable auto wait-idle function
|
||||
* @param per_waiti Enable wait-idle with time delay function after resume.
|
||||
* @param pes_waiti Enable wait-idle with time delay function after suspend.
|
||||
*/
|
||||
static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti)
|
||||
static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool per_waiti, bool pes_waiti)
|
||||
{
|
||||
dev->flash_waiti_ctrl.waiti_cmd = 0x05;
|
||||
dev->flash_sus_ctrl.flash_per_wait_en = auto_waiti;
|
||||
dev->flash_sus_ctrl.flash_pes_wait_en = auto_waiti;
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_waiti_ctrl, waiti_cmd, 0x05);
|
||||
dev->flash_sus_ctrl.flash_per_wait_en = per_waiti;
|
||||
dev->flash_sus_ctrl.flash_pes_wait_en = pes_waiti;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -518,11 +519,8 @@ static inline void spimem_flash_ll_set_mosi_bitlen(spi_mem_dev_t *dev, uint32_t
|
||||
static inline void spimem_flash_ll_set_command(spi_mem_dev_t *dev, uint32_t command, uint32_t bitlen)
|
||||
{
|
||||
dev->user.usr_command = 1;
|
||||
typeof(dev->user2) user2 = {
|
||||
.usr_command_value = command,
|
||||
.usr_command_bitlen = (bitlen - 1),
|
||||
};
|
||||
dev->user2.val = user2.val;
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_value, command);
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_bitlen, (bitlen - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -238,13 +238,14 @@ static inline void spimem_flash_set_cs_hold_delay(spi_mem_dev_t *dev, uint32_t c
|
||||
* Initialize auto wait idle mode
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param auto_waiti Enable/disable auto wait-idle function
|
||||
* @param per_waiti Enable wait-idle with time delay function after resume.
|
||||
* @param pes_waiti Enable wait-idle with time delay function after suspend.
|
||||
*/
|
||||
static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti)
|
||||
static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool per_waiti, bool pes_waiti)
|
||||
{
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_waiti_ctrl, waiti_cmd, 0x05);
|
||||
dev->flash_sus_ctrl.flash_per_wait_en = auto_waiti;
|
||||
dev->flash_sus_ctrl.flash_pes_wait_en = auto_waiti;
|
||||
dev->flash_sus_ctrl.flash_per_wait_en = per_waiti;
|
||||
dev->flash_sus_ctrl.flash_pes_wait_en = pes_waiti;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -520,11 +521,8 @@ static inline void spimem_flash_ll_set_mosi_bitlen(spi_mem_dev_t *dev, uint32_t
|
||||
static inline void spimem_flash_ll_set_command(spi_mem_dev_t *dev, uint32_t command, uint32_t bitlen)
|
||||
{
|
||||
dev->user.usr_command = 1;
|
||||
typeof(dev->user2) user2 = {
|
||||
.usr_command_value = command,
|
||||
.usr_command_bitlen = (bitlen - 1),
|
||||
};
|
||||
dev->user2.val = user2.val;
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_value, command);
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_bitlen, (bitlen - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -243,13 +243,14 @@ static inline void spimem_flash_set_cs_hold_delay(spi_mem_dev_t *dev, uint32_t c
|
||||
* Initialize auto wait idle mode
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param auto_waiti Enable/disable auto wait-idle function
|
||||
* @param per_waiti Enable wait-idle with time delay function after resume.
|
||||
* @param pes_waiti Enable wait-idle with time delay function after suspend.
|
||||
*/
|
||||
static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti)
|
||||
static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool per_waiti, bool pes_waiti)
|
||||
{
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_waiti_ctrl, waiti_cmd, 0x05);
|
||||
dev->flash_sus_ctrl.flash_per_wait_en = auto_waiti;
|
||||
dev->flash_sus_ctrl.flash_pes_wait_en = auto_waiti;
|
||||
dev->flash_sus_ctrl.flash_per_wait_en = per_waiti;
|
||||
dev->flash_sus_ctrl.flash_pes_wait_en = pes_waiti;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -530,11 +531,8 @@ static inline void spimem_flash_ll_set_mosi_bitlen(spi_mem_dev_t *dev, uint32_t
|
||||
static inline void spimem_flash_ll_set_command(spi_mem_dev_t *dev, uint32_t command, uint32_t bitlen)
|
||||
{
|
||||
dev->user.usr_command = 1;
|
||||
typeof(dev->user2) user2 = {
|
||||
.usr_command_value = command,
|
||||
.usr_command_bitlen = (bitlen - 1),
|
||||
};
|
||||
dev->user2.val = user2.val;
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_value, command);
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_bitlen, (bitlen - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -239,13 +239,14 @@ static inline void spimem_flash_set_cs_hold_delay(spi_mem_dev_t *dev, uint32_t c
|
||||
* Initialize auto wait idle mode
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param auto_waiti Enable/disable auto wait-idle function
|
||||
* @param per_waiti Enable wait-idle with time delay function after resume.
|
||||
* @param pes_waiti Enable wait-idle with time delay function after suspend.
|
||||
*/
|
||||
static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti)
|
||||
static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool per_waiti, bool pes_waiti)
|
||||
{
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_waiti_ctrl, waiti_cmd, 0x05);
|
||||
dev->flash_sus_ctrl.flash_per_wait_en = auto_waiti;
|
||||
dev->flash_sus_ctrl.flash_pes_wait_en = auto_waiti;
|
||||
dev->flash_sus_ctrl.flash_per_wait_en = per_waiti;
|
||||
dev->flash_sus_ctrl.flash_pes_wait_en = pes_waiti;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -521,11 +522,8 @@ static inline void spimem_flash_ll_set_mosi_bitlen(spi_mem_dev_t *dev, uint32_t
|
||||
static inline void spimem_flash_ll_set_command(spi_mem_dev_t *dev, uint32_t command, uint32_t bitlen)
|
||||
{
|
||||
dev->user.usr_command = 1;
|
||||
typeof(dev->user2) user2 = {
|
||||
.usr_command_value = command,
|
||||
.usr_command_bitlen = (bitlen - 1),
|
||||
};
|
||||
dev->user2.val = user2.val;
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_value, command);
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_bitlen, (bitlen - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -561,7 +559,7 @@ static inline void spimem_flash_ll_set_addr_bitlen(spi_mem_dev_t *dev, uint32_t
|
||||
static inline void spimem_flash_ll_set_extra_address(spi_mem_dev_t *dev, uint32_t extra_addr)
|
||||
{
|
||||
dev->cache_fctrl.usr_addr_4byte = 0;
|
||||
dev->rd_status.wb_mode = extra_addr;
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->rd_status, wb_mode, extra_addr);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -242,13 +242,14 @@ static inline void spimem_flash_set_cs_hold_delay(spi_mem_dev_t *dev, uint32_t c
|
||||
* Initialize auto wait idle mode
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param auto_waiti Enable/disable auto wait-idle function
|
||||
* @param per_waiti Enable wait-idle with time delay function after resume.
|
||||
* @param pes_waiti Enable wait-idle with time delay function after suspend.
|
||||
*/
|
||||
static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti)
|
||||
static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool per_waiti, bool pes_waiti)
|
||||
{
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_waiti_ctrl, waiti_cmd, 0x05);
|
||||
dev->flash_sus_ctrl.flash_per_wait_en = auto_waiti;
|
||||
dev->flash_sus_ctrl.flash_pes_wait_en = auto_waiti;
|
||||
dev->flash_sus_ctrl.flash_per_wait_en = per_waiti;
|
||||
dev->flash_sus_ctrl.flash_pes_wait_en = pes_waiti;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -523,11 +524,8 @@ static inline void spimem_flash_ll_set_mosi_bitlen(spi_mem_dev_t *dev, uint32_t
|
||||
static inline void spimem_flash_ll_set_command(spi_mem_dev_t *dev, uint32_t command, uint32_t bitlen)
|
||||
{
|
||||
dev->user.usr_command = 1;
|
||||
typeof(dev->user2) user2 = {
|
||||
.usr_command_value = command,
|
||||
.usr_command_bitlen = (bitlen - 1),
|
||||
};
|
||||
dev->user2.val = user2.val;
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_value, command);
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_bitlen, (bitlen - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -563,7 +561,7 @@ static inline void spimem_flash_ll_set_addr_bitlen(spi_mem_dev_t *dev, uint32_t
|
||||
static inline void spimem_flash_ll_set_extra_address(spi_mem_dev_t *dev, uint32_t extra_addr)
|
||||
{
|
||||
dev->cache_fctrl.cache_usr_addr_4byte = 0;
|
||||
dev->rd_status.wb_mode = extra_addr;
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->rd_status, wb_mode, extra_addr);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -240,13 +240,14 @@ static inline void spimem_flash_set_cs_hold_delay(spi_mem_dev_t *dev, uint32_t c
|
||||
* Initialize auto wait idle mode
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param auto_waiti Enable/disable auto wait-idle function
|
||||
* @param per_waiti Enable wait-idle with time delay function after resume.
|
||||
* @param pes_waiti Enable wait-idle with time delay function after suspend.
|
||||
*/
|
||||
static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti)
|
||||
static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool per_waiti, bool pes_waiti)
|
||||
{
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_waiti_ctrl, waiti_cmd, 0x05);
|
||||
dev->flash_sus_ctrl.flash_per_wait_en = auto_waiti;
|
||||
dev->flash_sus_ctrl.flash_pes_wait_en = auto_waiti;
|
||||
dev->flash_sus_ctrl.flash_per_wait_en = per_waiti;
|
||||
dev->flash_sus_ctrl.flash_pes_wait_en = pes_waiti;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -542,11 +543,8 @@ static inline void spimem_flash_ll_set_mosi_bitlen(spi_mem_dev_t *dev, uint32_t
|
||||
static inline void spimem_flash_ll_set_command(spi_mem_dev_t *dev, uint32_t command, uint32_t bitlen)
|
||||
{
|
||||
dev->user.usr_command = 1;
|
||||
typeof(dev->user2) user2 = {
|
||||
.usr_command_value = command,
|
||||
.usr_command_bitlen = (bitlen - 1),
|
||||
};
|
||||
dev->user2.val = user2.val;
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_value, command);
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_bitlen, (bitlen - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -582,7 +580,7 @@ static inline void spimem_flash_ll_set_addr_bitlen(spi_mem_dev_t *dev, uint32_t
|
||||
static inline void spimem_flash_ll_set_extra_address(spi_mem_dev_t *dev, uint32_t extra_addr)
|
||||
{
|
||||
dev->cache_fctrl.usr_addr_4byte = 0;
|
||||
dev->rd_status.wb_mode = extra_addr;
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->rd_status, wb_mode, extra_addr);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -245,13 +245,14 @@ static inline void spimem_flash_set_cs_hold_delay(spi_mem_dev_t *dev, uint32_t c
|
||||
* Initialize auto wait idle mode
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param auto_waiti Enable/disable auto wait-idle function
|
||||
* @param per_waiti Enable wait-idle with time delay function after resume.
|
||||
* @param pes_waiti Enable wait-idle with time delay function after suspend.
|
||||
*/
|
||||
static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti)
|
||||
static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool per_waiti, bool pes_waiti)
|
||||
{
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_waiti_ctrl, waiti_cmd, 0x05);
|
||||
dev->flash_sus_ctrl.flash_per_wait_en = auto_waiti;
|
||||
dev->flash_sus_ctrl.flash_pes_wait_en = auto_waiti;
|
||||
dev->flash_sus_ctrl.flash_per_wait_en = per_waiti;
|
||||
dev->flash_sus_ctrl.flash_pes_wait_en = pes_waiti;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -531,11 +532,8 @@ static inline void spimem_flash_ll_set_mosi_bitlen(spi_mem_dev_t *dev, uint32_t
|
||||
static inline void spimem_flash_ll_set_command(spi_mem_dev_t *dev, uint32_t command, uint32_t bitlen)
|
||||
{
|
||||
dev->user.usr_command = 1;
|
||||
typeof(dev->user2) user2 = {
|
||||
.usr_command_value = command,
|
||||
.usr_command_bitlen = (bitlen - 1),
|
||||
};
|
||||
dev->user2.val = user2.val;
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_value, command);
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_bitlen, (bitlen - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -209,12 +209,13 @@ static inline void spimem_flash_ll_res_check_sus_setup(spi_mem_dev_t *dev, bool
|
||||
* Initialize auto wait idle mode
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param auto_waiti Enable/disable auto wait-idle function
|
||||
* @param per_waiti Enable wait-idle with time delay function after resume.
|
||||
* @param pes_waiti Enable wait-idle with time delay function after suspend.
|
||||
*/
|
||||
static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti)
|
||||
static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool per_waiti, bool pes_waiti)
|
||||
{
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_waiti_ctrl, waiti_cmd, 0x05); // Set the command to send, to fetch flash status reg value.
|
||||
dev->flash_waiti_ctrl.waiti_en = auto_waiti; // enable auto wait-idle function.
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_waiti_ctrl, waiti_cmd, 0x05);
|
||||
dev->flash_waiti_ctrl.waiti_en = (per_waiti | pes_waiti); // enable auto wait-idle function.
|
||||
}
|
||||
|
||||
/**
|
||||
@ -460,11 +461,8 @@ static inline void spimem_flash_ll_set_mosi_bitlen(spi_mem_dev_t *dev, uint32_t
|
||||
static inline void spimem_flash_ll_set_command(spi_mem_dev_t *dev, uint32_t command, uint32_t bitlen)
|
||||
{
|
||||
dev->user.usr_command = 1;
|
||||
typeof(dev->user2) user2 = {
|
||||
.usr_command_value = command,
|
||||
.usr_command_bitlen = (bitlen - 1),
|
||||
};
|
||||
dev->user2.val = user2.val;
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_value, command);
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_bitlen, (bitlen - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -264,14 +264,15 @@ static inline uint32_t spimem_flash_ll_get_tsus_unit_in_cycles(spi_mem_dev_t *de
|
||||
* Initialize auto wait idle mode
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param auto_waiti Enable/disable auto wait-idle function
|
||||
* @param per_waiti Enable wait-idle with time delay function after resume.
|
||||
* @param pes_waiti Enable wait-idle with time delay function after suspend.
|
||||
*/
|
||||
static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti)
|
||||
static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool per_waiti, bool pes_waiti)
|
||||
{
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_waiti_ctrl, waiti_cmd, 0x05); // Set the command to send, to fetch flash status reg value.
|
||||
dev->flash_waiti_ctrl.waiti_en = auto_waiti; // enable auto wait-idle function.
|
||||
dev->flash_sus_cmd.flash_per_wait_en = 1;
|
||||
dev->flash_sus_cmd.flash_pes_wait_en = 1;
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_waiti_ctrl, waiti_cmd, 0x05);
|
||||
dev->flash_waiti_ctrl.waiti_en = (per_waiti | pes_waiti); // enable auto wait-idle function.
|
||||
dev->flash_sus_cmd.flash_per_wait_en = per_waiti;
|
||||
dev->flash_sus_cmd.flash_pes_wait_en = pes_waiti;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -538,11 +539,8 @@ static inline void spimem_flash_ll_set_mosi_bitlen(spi_mem_dev_t *dev, uint32_t
|
||||
static inline void spimem_flash_ll_set_command(spi_mem_dev_t *dev, uint32_t command, uint32_t bitlen)
|
||||
{
|
||||
dev->user.usr_command = 1;
|
||||
typeof(dev->user2) user2 = {
|
||||
.usr_command_value = command,
|
||||
.usr_command_bitlen = (bitlen - 1),
|
||||
};
|
||||
dev->user2.val = user2.val;
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_value, command);
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_bitlen, (bitlen - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2010-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -27,6 +27,10 @@ extern "C" {
|
||||
#define SPI_FLASH_HAL_MAX_WRITE_BYTES 64
|
||||
#define SPI_FLASH_HAL_MAX_READ_BYTES 64
|
||||
|
||||
/* spi flash state */
|
||||
#define SPI_FLASH_HAL_STATUS_BUSY BIT0
|
||||
#define SPI_FLASH_HAL_STATUS_SUSPEND BIT1
|
||||
|
||||
/**
|
||||
* Generic driver context structure for all chips using the SPI peripheral.
|
||||
* Include this into the HEAD of the driver data for other driver
|
||||
@ -53,6 +57,7 @@ typedef struct {
|
||||
#define SPI_FLASH_HOST_CONTEXT_SLICER_FLAG_DTR BIT(0) ///< Slice data according to DTR mode, the address and length must be even (A0=0).
|
||||
int freq_mhz; /// Flash clock frequency.
|
||||
uint8_t tsus_val; ///< Tsus value of suspend (us)
|
||||
bool auto_waiti_pes; ///< True for auto-wait idle after suspend command. False for using time delay.
|
||||
} spi_flash_hal_context_t;
|
||||
ESP_STATIC_ASSERT(sizeof(spi_flash_hal_context_t) == 48, "size of spi_flash_hal_context_t incorrect. Please check data compatibility with the ROM");
|
||||
|
||||
@ -82,11 +87,12 @@ typedef struct {
|
||||
int cs_num; ///< Which cs pin is used, 0-(SOC_SPI_PERIPH_CS_NUM-1).
|
||||
bool auto_sus_en; ///< Auto suspend feature enable bit 1: enable, 0: disable.
|
||||
bool octal_mode_en; ///< Octal spi flash mode enable bit 1: enable, 0: disable.
|
||||
bool using_timing_tuning; ///< System exist SPI0/1 timing tuning, using value from system directely if set to 1.
|
||||
bool using_timing_tuning; ///< System exist SPI0/1 timing tuning, using value from system directly if set to 1.
|
||||
esp_flash_io_mode_t default_io_mode; ///< Default flash io mode.
|
||||
int freq_mhz; ///< SPI flash clock speed (MHZ).
|
||||
int clock_src_freq; ///< SPI flash clock source (MHZ).
|
||||
uint8_t tsus_val; ///< Tsus value of suspend (us)
|
||||
uint8_t tsus_val; ///< Tsus value of suspend (us).
|
||||
bool auto_waiti_pes; ///< True for auto-wait idle after suspend command. False for using time delay.
|
||||
} spi_flash_hal_config_t;
|
||||
|
||||
/**
|
||||
|
@ -130,8 +130,13 @@ esp_err_t spi_flash_hal_init(spi_flash_hal_context_t *data_out, const spi_flash_
|
||||
data_out->flags |= SPI_FLASH_HOST_CONTEXT_FLAG_AUTO_SUSPEND;
|
||||
data_out->flags |= SPI_FLASH_HOST_CONTEXT_FLAG_AUTO_RESUME;
|
||||
data_out->tsus_val = cfg->tsus_val;
|
||||
data_out->auto_waiti_pes = cfg->auto_waiti_pes;
|
||||
}
|
||||
|
||||
#if CONFIG_SPI_FLASH_SOFTWARE_RESUME
|
||||
data_out->flags &= ~SPI_FLASH_HOST_CONTEXT_FLAG_AUTO_RESUME;
|
||||
#endif
|
||||
|
||||
#if SOC_SPI_MEM_SUPPORT_OPI_MODE
|
||||
if (cfg->octal_mode_en) {
|
||||
data_out->flags |= SPI_FLASH_HOST_CONTEXT_FLAG_OCTAL_MODE;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -145,7 +145,8 @@ void spi_flash_hal_setup_auto_suspend_mode(spi_flash_host_inst_t *host)
|
||||
{
|
||||
spi_mem_dev_t *dev = (spi_mem_dev_t*)spi_flash_ll_get_hw(SPI1_HOST);
|
||||
spi_flash_hal_context_t* ctx = (spi_flash_hal_context_t*)host;
|
||||
spimem_flash_ll_auto_wait_idle_init(dev, true);
|
||||
bool pes_waiti_delay = ctx->auto_waiti_pes ? false : true;
|
||||
spimem_flash_ll_auto_wait_idle_init(dev, true, pes_waiti_delay);
|
||||
if (ctx->freq_mhz == 120) {
|
||||
spimem_flash_ll_set_wait_idle_dummy_phase(dev, ctx->extra_dummy);
|
||||
}
|
||||
@ -159,6 +160,7 @@ void spi_flash_hal_setup_auto_suspend_mode(spi_flash_host_inst_t *host)
|
||||
spimem_flash_ll_sus_set_spi0_lock_trans(dev, SPIMEM_FLASH_LL_SPI0_MAX_LOCK_VAL_MSPI_TICKS);
|
||||
#if SOC_SPI_MEM_SUPPORT_CHECK_SUS
|
||||
spimem_flash_ll_sus_check_sus_setup(dev, true);
|
||||
spimem_flash_ll_res_check_sus_setup(dev, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -166,18 +168,16 @@ void spi_flash_hal_setup_auto_resume_mode(spi_flash_host_inst_t *host)
|
||||
{
|
||||
spi_mem_dev_t *dev = (spi_mem_dev_t*)spi_flash_ll_get_hw(SPI1_HOST);
|
||||
spimem_flash_ll_auto_resume_init(dev, true);
|
||||
#if SOC_SPI_MEM_SUPPORT_CHECK_SUS
|
||||
spimem_flash_ll_res_check_sus_setup(dev, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
void spi_flash_hal_disable_auto_suspend_mode(spi_flash_host_inst_t *host)
|
||||
{
|
||||
spi_mem_dev_t *dev = (spi_mem_dev_t *)spi_flash_ll_get_hw(SPI1_HOST);
|
||||
spimem_flash_ll_auto_wait_idle_init(dev, false);
|
||||
spimem_flash_ll_auto_wait_idle_init(dev, false, false);
|
||||
spimem_flash_ll_auto_suspend_init(dev, false);
|
||||
#if SOC_SPI_MEM_SUPPORT_CHECK_SUS
|
||||
spimem_flash_ll_sus_check_sus_setup(dev, false);
|
||||
spimem_flash_ll_res_check_sus_setup(dev, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -185,9 +185,6 @@ void spi_flash_hal_disable_auto_resume_mode(spi_flash_host_inst_t *host)
|
||||
{
|
||||
spi_mem_dev_t *dev = (spi_mem_dev_t*)spi_flash_ll_get_hw(SPI1_HOST);
|
||||
spimem_flash_ll_auto_resume_init(dev, false);
|
||||
#if SOC_SPI_MEM_SUPPORT_CHECK_SUS
|
||||
spimem_flash_ll_res_check_sus_setup(dev, false);
|
||||
#endif
|
||||
}
|
||||
#endif // SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND
|
||||
|
||||
@ -195,6 +192,7 @@ void spi_flash_hal_resume(spi_flash_host_inst_t *host)
|
||||
{
|
||||
#if SOC_SPI_MEM_SUPPORT_SW_SUSPEND
|
||||
spimem_flash_ll_resume((spi_mem_dev_t*)(((spi_flash_hal_context_t *)host)->spi));
|
||||
host->driver->poll_cmd_done(host);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
@ -204,6 +202,7 @@ void spi_flash_hal_suspend(spi_flash_host_inst_t *host)
|
||||
{
|
||||
#if SOC_SPI_MEM_SUPPORT_SW_SUSPEND
|
||||
spimem_flash_ll_suspend((spi_mem_dev_t *)(((spi_flash_hal_context_t *)host)->spi));
|
||||
host->driver->poll_cmd_done(host);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
|
@ -120,6 +120,40 @@ menu "Main Flash configuration"
|
||||
|
||||
For new users, DO NOT enable this config.
|
||||
|
||||
config SPI_FLASH_SOFTWARE_RESUME
|
||||
bool "Resume flash program/erase form suspend state by software control"
|
||||
default n
|
||||
depends on SPI_FLASH_AUTO_SUSPEND && FREERTOS_UNICORE && IDF_EXPERIMENTAL_FEATURES
|
||||
help
|
||||
Enable this config will disable auto-resume from hardware. Thus the software will resume the chip
|
||||
after any higher priority task/interrupt which suspend the chip. The benefit is that the suspend-resume
|
||||
will not disturb the higher priority task and interrupt.
|
||||
|
||||
This currently is only valid on single core chip.
|
||||
|
||||
config SPI_FLASH_DISABLE_SCHEDULER_IN_SUSPEND
|
||||
bool "Disable task scheduler when suspend is enabled when SPI1 operation is ongoing"
|
||||
default n
|
||||
# Only valid on single core because no protection is supported on multi core
|
||||
depends on SPI_FLASH_AUTO_SUSPEND && FREERTOS_UNICORE
|
||||
help
|
||||
Disable freertos task scheduler when CONFIG_SPI_FLASH_AUTO_SUSPEND is enabled.
|
||||
Thus only interrupt can trigger a suspend. When SPI_FLASH_AUTO_SUSPEND is enabled,
|
||||
default behavior is not disable the task scheduler, so both interrupt and high priority
|
||||
task can suspend the erase/program operation. When this option is enabled, task
|
||||
scheduler is disabled, only interrupt can suspend erase/program operation.
|
||||
|
||||
config SPI_FLASH_AUTO_CHECK_SUSPEND_STATUS
|
||||
bool "Check flash status automatically after flash suspend"
|
||||
default n
|
||||
depends on SPI_FLASH_AUTO_SUSPEND
|
||||
help
|
||||
Majority flash supports to use flash register to judge if flash suspend status is
|
||||
done or not. So enable this config, the behavior would use flash register WIP bit to judge
|
||||
whether suspend is valid instead of waiting for a specific long time, which can save a
|
||||
lot of time and benefit for performance improvement.
|
||||
|
||||
|
||||
endmenu
|
||||
endmenu
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "esp_rom_spiflash.h"
|
||||
#include "esp_private/esp_clk.h"
|
||||
#include "esp_spi_flash_counters.h"
|
||||
#include "esp_check.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp_crypto_lock.h" // for locking flash encryption peripheral
|
||||
@ -1269,7 +1270,7 @@ esp_err_t IRAM_ATTR esp_flash_write_encrypted(esp_flash_t *chip, uint32_t addres
|
||||
that share a key (as derived from flash address).
|
||||
|
||||
On ESP32-S2 and later, the temporary buffer need to be
|
||||
seperated into 16-bytes, 32-bytes, 64-bytes(if supported).
|
||||
separated into 16-bytes, 32-bytes, 64-bytes(if supported).
|
||||
|
||||
So, on ESP32-S2 and later, here has a totally different
|
||||
data prepare implementation.
|
||||
|
@ -386,6 +386,10 @@ esp_err_t esp_flash_init_default_chip(void)
|
||||
cfg.tsus_val = TSUS_VAL_SUSPEND;
|
||||
#endif // CONFIG_SPI_FLASH_AUTO_SUSPEND
|
||||
|
||||
#if CONFIG_SPI_FLASH_AUTO_CHECK_SUSPEND_STATUS
|
||||
cfg.auto_waiti_pes = true;
|
||||
#endif
|
||||
|
||||
//the host is already initialized, only do init for the data and load it to the host
|
||||
esp_err_t err = memspi_host_init_pointers(&esp_flash_default_host, &cfg);
|
||||
if (err != ESP_OK) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -204,7 +204,7 @@ esp_err_t esp_flash_erase_chip(esp_flash_t *chip);
|
||||
* @param start Address to start erasing flash. Must be sector aligned.
|
||||
* @param len Length of region to erase. Must also be sector aligned.
|
||||
*
|
||||
* Sector size is specifyed in chip->drv->sector_size field (typically 4096 bytes.) ESP_ERR_INVALID_ARG will be
|
||||
* Sector size is specified 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
|
||||
|
@ -376,6 +376,7 @@ esp_err_t spi_flash_chip_generic_wait_idle(esp_flash_t *chip, uint32_t timeout_u
|
||||
|
||||
uint8_t status = 0;
|
||||
const int interval = CHIP_WAIT_IDLE_INTERVAL_US;
|
||||
bool suspend_state = false;
|
||||
while (timeout_us > 0) {
|
||||
while (!chip->host->driver->host_status(chip->host) && timeout_us > 0) {
|
||||
|
||||
@ -388,6 +389,15 @@ esp_err_t spi_flash_chip_generic_wait_idle(esp_flash_t *chip, uint32_t timeout_u
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_SPI_FLASH_SOFTWARE_RESUME
|
||||
suspend_state = ((chip->host->driver->host_status(chip->host) & SPI_FLASH_HAL_STATUS_SUSPEND) != 0) ? true : false;
|
||||
|
||||
if (suspend_state) {
|
||||
// Oh! find you are in suspend state
|
||||
chip->host->driver->resume(chip->host);
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t read;
|
||||
esp_err_t err = chip->chip_drv->read_reg(chip, SPI_FLASH_REG_STATUS, &read);
|
||||
if (err != ESP_OK) {
|
||||
@ -395,7 +405,7 @@ esp_err_t spi_flash_chip_generic_wait_idle(esp_flash_t *chip, uint32_t timeout_u
|
||||
}
|
||||
status = read;
|
||||
|
||||
if ((status & SR_WIP) == 0) { // Verify write in progress is complete
|
||||
if ((status & SR_WIP) == 0 && (suspend_state == false)) { // Verify write in progress is complete
|
||||
if (chip->busy == 1) {
|
||||
chip->busy = 0;
|
||||
if ((status & SR_WREN) != 0) { // The previous command is not accepted, leaving the WEL still set.
|
||||
|
@ -121,6 +121,20 @@ static IRAM_ATTR esp_err_t spi1_start(void *arg)
|
||||
//directly disable the cache and interrupts when lock is not used
|
||||
cache_disable(NULL);
|
||||
#endif
|
||||
|
||||
#if CONFIG_SPI_FLASH_DISABLE_SCHEDULER_IN_SUSPEND
|
||||
// Disable scheduler
|
||||
if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) {
|
||||
#ifdef CONFIG_FREERTOS_SMP
|
||||
//Note: Scheduler suspension behavior changed in FreeRTOS SMP
|
||||
vTaskPreemptionDisable(NULL);
|
||||
#else
|
||||
// Disable scheduler on the current CPU
|
||||
vTaskSuspendAll();
|
||||
#endif // CONFIG_FREERTOS_SMP
|
||||
}
|
||||
#endif // CONFIG_SPI_FLASH_DISABLE_SCHEDULER_IN_SUSPEND
|
||||
|
||||
on_spi_acquired((app_func_arg_t*)arg);
|
||||
return ret;
|
||||
}
|
||||
@ -139,6 +153,18 @@ static IRAM_ATTR esp_err_t spi1_end(void *arg)
|
||||
#else
|
||||
cache_enable(NULL);
|
||||
#endif
|
||||
|
||||
#if CONFIG_SPI_FLASH_DISABLE_SCHEDULER_IN_SUSPEND
|
||||
if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) {
|
||||
#ifdef CONFIG_FREERTOS_SMP
|
||||
//Note: Scheduler suspension behavior changed in FreeRTOS SMP
|
||||
vTaskPreemptionEnable(NULL);
|
||||
#else
|
||||
xTaskResumeAll();
|
||||
#endif // CONFIG_FREERTOS_SMP
|
||||
}
|
||||
#endif // CONFIG_SPI_FLASH_DISABLE_SCHEDULER_IN_SUSPEND
|
||||
|
||||
on_spi_released((app_func_arg_t*)arg);
|
||||
return ret;
|
||||
}
|
||||
|
@ -10,3 +10,8 @@ set(COMPONENTS main esptool_py)
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
|
||||
project(test_esp_flash_drv)
|
||||
|
||||
message(STATUS "Checking memspi registers are not read-write by half-word")
|
||||
include($ENV{IDF_PATH}/tools/ci/check_register_rw_half_word.cmake)
|
||||
check_register_rw_half_word(SOC_MODULES "spi_mem*" "spi1_mem*"
|
||||
HAL_MODULES "spimem_flash")
|
||||
|
Loading…
x
Reference in New Issue
Block a user