fix(driver_spi): make slave_hd isr can place in flash to save iram

This commit is contained in:
wanckl
2025-03-10 15:36:58 +08:00
parent 893a02ea51
commit 43aef06e90
10 changed files with 61 additions and 76 deletions

View File

@ -5,7 +5,6 @@ if(${target} STREQUAL "linux")
endif()
set(srcs "")
set(public_include "include")
if(CONFIG_SOC_GPSPI_SUPPORTED)
@ -13,17 +12,21 @@ if(CONFIG_SOC_GPSPI_SUPPORTED)
"src/gpspi/spi_common.c"
"src/gpspi/spi_master.c"
"src/gpspi/spi_slave.c"
"src/gpspi/spi_dma.c"
)
if(NOT CONFIG_SOC_GDMA_SUPPORTED)
list(APPEND srcs "src/gpspi/spi_dma.c")
endif()
if(CONFIG_SOC_SPI_SUPPORT_SLAVE_HD_VER2)
list(APPEND srcs "src/gpspi/spi_slave_hd.c")
endif()
endif()
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${public_include}
REQUIRES esp_pm
PRIV_REQUIRES esp_timer esp_mm esp_driver_gpio esp_ringbuf
LDFRAGMENTS "linker.lf"
)
idf_component_register(
SRCS ${srcs}
INCLUDE_DIRS ${public_include}
REQUIRES esp_pm
PRIV_REQUIRES esp_timer esp_mm esp_driver_gpio
LDFRAGMENTS "linker.lf"
)

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2010-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2010-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -274,13 +274,6 @@ void spicommon_dmaworkaround_transfer_active(int dmachan);
/*******************************************************************************
* Bus attributes
******************************************************************************/
/**
* @brief Set bus lock for the main bus, called by startup code.
*
* @param lock The lock to be used by the main SPI bus.
*/
void spi_bus_main_set_lock(spi_bus_lock_handle_t lock);
/**
* @brief Get the attributes of a specified SPI bus.
*

View File

@ -1,14 +1,3 @@
[mapping:gpspi_driver]
archive: libesp_driver_spi.a
entries:
# SOC_GDMA_SUPPORTED is undeclared if GDMA not support, so use `SOC_GDMA_SUPPORTED != y` instead
if SOC_GDMA_SUPPORTED != y && (SPI_MASTER_ISR_IN_IRAM = y || SPI_SLAVE_ISR_IN_IRAM = y):
spi_dma: spi_dma_reset (noflash)
spi_dma: spi_dma_start (noflash)
if SOC_SPI_SUPPORT_SLAVE_HD_VER2 = y:
spi_dma: spi_dma_get_eof_desc (noflash)
[mapping:gpspi_hal]
archive: libhal.a
entries:

View File

@ -29,16 +29,20 @@
#include "soc/dport_reg.h"
#endif
#if CONFIG_SPI_MASTER_ISR_IN_IRAM || CONFIG_SPI_SLAVE_ISR_IN_IRAM
#define SPI_COMMON_ISR_ATTR IRAM_ATTR
#else
#define SPI_COMMON_ISR_ATTR
#endif
static const char *SPI_TAG = "spi";
#define SPI_CHECK(a, str, ret_val) ESP_RETURN_ON_FALSE(a, ret_val, SPI_TAG, str)
#define SPI_CHECK_PIN(pin_num, pin_name, check_output) if (check_output) { \
SPI_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(pin_num), pin_name" not valid", ESP_ERR_INVALID_ARG); \
} else { \
SPI_CHECK(GPIO_IS_VALID_GPIO(pin_num), pin_name" not valid", ESP_ERR_INVALID_ARG); \
}
#define SPI_MAIN_BUS_DEFAULT() { \
.host_id = 0, \
.bus_attr = { \
@ -66,7 +70,7 @@ static spicommon_bus_context_t* bus_ctx[SOC_SPI_PERIPH_NUM] = {&s_mainbus};
static __attribute__((constructor)) void spi_bus_lock_init_main_bus(void)
{
/* Initialize bus context about the main SPI bus lock, called during chip startup. */
spi_bus_main_set_lock(g_main_spi_bus_lock);
bus_ctx[0]->bus_attr.lock = g_main_spi_bus_lock;
}
#endif
@ -303,7 +307,7 @@ esp_err_t spicommon_dma_desc_alloc(spi_dma_ctx_t *dma_ctx, int cfg_max_sz, int *
return ESP_OK;
}
void IRAM_ATTR spicommon_dma_desc_setup_link(spi_dma_desc_t *dmadesc, const void *data, int len, bool is_rx)
void SPI_COMMON_ISR_ATTR spicommon_dma_desc_setup_link(spi_dma_desc_t *dmadesc, const void *data, int len, bool is_rx)
{
dmadesc = ADDR_DMA_2_CPU(dmadesc);
int n = 0;
@ -767,11 +771,6 @@ bool spicommon_bus_using_iomux(spi_host_device_t host)
return true;
}
void spi_bus_main_set_lock(spi_bus_lock_handle_t lock)
{
bus_ctx[0]->bus_attr.lock = lock;
}
spi_bus_lock_handle_t spi_bus_lock_get_by_id(spi_host_device_t host_id)
{
return bus_ctx[host_id]->bus_attr.lock;
@ -1019,7 +1018,7 @@ static void *dmaworkaround_cb_arg;
static portMUX_TYPE dmaworkaround_mux = portMUX_INITIALIZER_UNLOCKED;
static int dmaworkaround_waiting_for_chan = 0;
bool IRAM_ATTR spicommon_dmaworkaround_req_reset(int dmachan, dmaworkaround_cb_t cb, void *arg)
bool SPI_COMMON_ISR_ATTR spicommon_dmaworkaround_req_reset(int dmachan, dmaworkaround_cb_t cb, void *arg)
{
int otherchan = (dmachan == 1) ? 2 : 1;
@ -1042,12 +1041,12 @@ bool IRAM_ATTR spicommon_dmaworkaround_req_reset(int dmachan, dmaworkaround_cb_t
return ret;
}
bool IRAM_ATTR spicommon_dmaworkaround_reset_in_progress(void)
bool SPI_COMMON_ISR_ATTR spicommon_dmaworkaround_reset_in_progress(void)
{
return (dmaworkaround_waiting_for_chan != 0);
}
void IRAM_ATTR spicommon_dmaworkaround_idle(int dmachan)
void SPI_COMMON_ISR_ATTR spicommon_dmaworkaround_idle(int dmachan)
{
portENTER_CRITICAL_ISR(&dmaworkaround_mux);
dmaworkaround_channels_busy[dmachan - 1] = 0;
@ -1064,7 +1063,7 @@ void IRAM_ATTR spicommon_dmaworkaround_idle(int dmachan)
portEXIT_CRITICAL_ISR(&dmaworkaround_mux);
}
void IRAM_ATTR spicommon_dmaworkaround_transfer_active(int dmachan)
void SPI_COMMON_ISR_ATTR spicommon_dmaworkaround_transfer_active(int dmachan)
{
portENTER_CRITICAL_ISR(&dmaworkaround_mux);
dmaworkaround_channels_busy[dmachan - 1] = 1;

View File

@ -1,13 +1,19 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_attr.h"
#include "esp_private/spi_dma.h"
#include "hal/spi_ll.h"
#if !SOC_GDMA_SUPPORTED
#if CONFIG_SPI_MASTER_ISR_IN_IRAM || CONFIG_SPI_SLAVE_ISR_IN_IRAM
#define SPI_DMA_ISR_ATTR IRAM_ATTR
#else
#define SPI_DMA_ISR_ATTR
#endif
void spi_dma_enable_burst(spi_dma_chan_handle_t chan_handle, bool data_burst, bool desc_burst)
{
spi_dma_dev_t *spi_dma = SPI_LL_GET_HW(chan_handle.host_id);
@ -35,7 +41,7 @@ void spi_dma_append(spi_dma_chan_handle_t chan_handle)
/************************************* IRAM CONTEXT **************************************/
uint32_t spi_dma_get_eof_desc(spi_dma_chan_handle_t chan_handle)
uint32_t SPI_DMA_ISR_ATTR spi_dma_get_eof_desc(spi_dma_chan_handle_t chan_handle)
{
spi_dma_dev_t *spi_dma = SPI_LL_GET_HW(chan_handle.host_id);
@ -45,7 +51,7 @@ uint32_t spi_dma_get_eof_desc(spi_dma_chan_handle_t chan_handle)
}
#endif //SOC_SPI_SUPPORT_SLAVE_HD_VER2
void spi_dma_reset(spi_dma_chan_handle_t chan_handle)
void SPI_DMA_ISR_ATTR spi_dma_reset(spi_dma_chan_handle_t chan_handle)
{
spi_dma_dev_t *spi_dma = SPI_LL_GET_HW(chan_handle.host_id);
@ -56,7 +62,7 @@ void spi_dma_reset(spi_dma_chan_handle_t chan_handle)
}
}
void spi_dma_start(spi_dma_chan_handle_t chan_handle, void *addr)
void SPI_DMA_ISR_ATTR spi_dma_start(spi_dma_chan_handle_t chan_handle, void *addr)
{
spi_dma_dev_t *spi_dma = SPI_LL_GET_HW(chan_handle.host_id);
@ -66,4 +72,3 @@ void spi_dma_start(spi_dma_chan_handle_t chan_handle, void *addr)
spi_dma_ll_rx_start(spi_dma, chan_handle.chan_id, (lldesc_t *)addr);
}
}
#endif

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2010-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2010-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -12,7 +12,6 @@
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "freertos/ringbuf.h"
#include "driver/gpio.h"
#include "esp_private/sleep_retention.h"
#include "esp_private/spi_common_internal.h"
@ -24,6 +23,12 @@
#include "esp_cache.h"
#endif
#ifdef CONFIG_SPI_SLAVE_ISR_IN_IRAM
#define SPI_SLAVE_ISR_ATTR IRAM_ATTR
#else
#define SPI_SLAVE_ISR_ATTR
#endif
#if (SOC_SPI_PERIPH_NUM == 2)
#define VALID_HOST(x) ((x) == SPI2_HOST)
#elif (SOC_SPI_PERIPH_NUM == 3)
@ -106,6 +111,9 @@ esp_err_t spi_slave_hd_init(spi_host_device_t host_id, const spi_bus_config_t *b
#elif SOC_GDMA_SUPPORTED
SPIHD_CHECK(config->dma_chan == SPI_DMA_CH_AUTO, "dma is required or invalid channel, only support SPI_DMA_CH_AUTO", ESP_ERR_INVALID_ARG);
#endif
#ifndef CONFIG_SPI_SLAVE_ISR_IN_IRAM
SPIHD_CHECK((bus_config->intr_flags & ESP_INTR_FLAG_IRAM) == 0, "ESP_INTR_FLAG_IRAM should be disabled when CONFIG_SPI_SLAVE_ISR_IN_IRAM is not set.", ESP_ERR_INVALID_ARG);
#endif
spi_chan_claimed = spicommon_periph_claim(host_id, "slave_hd");
SPIHD_CHECK(spi_chan_claimed, "host already in use", ESP_ERR_INVALID_STATE);
@ -241,12 +249,12 @@ esp_err_t spi_slave_hd_init(spi_host_device_t host_id, const spi_bus_config_t *b
//Alloc intr
if (!host->append_mode) {
ret = esp_intr_alloc(spicommon_irqsource_for_host(host_id), 0, s_spi_slave_hd_segment_isr,
ret = esp_intr_alloc(spicommon_irqsource_for_host(host_id), bus_config->intr_flags, s_spi_slave_hd_segment_isr,
(void *)host, &host->intr);
if (ret != ESP_OK) {
goto cleanup;
}
ret = esp_intr_alloc(spicommon_irqdma_source_for_host(host_id), 0, s_spi_slave_hd_segment_isr,
ret = esp_intr_alloc(spicommon_irqdma_source_for_host(host_id), bus_config->intr_flags, s_spi_slave_hd_segment_isr,
(void *)host, &host->intr_dma);
if (ret != ESP_OK) {
goto cleanup;
@ -262,7 +270,7 @@ esp_err_t spi_slave_hd_init(spi_host_device_t host_id, const spi_bus_config_t *b
gdma_register_rx_event_callbacks(host->dma_ctx->rx_dma_chan, &txrx_cbs, host);
#else
//On ESP32S2, `cmd7` and `cmd8` are designed as all `spi_dma` events, so use `dma_src` only
ret = esp_intr_alloc(spicommon_irqdma_source_for_host(host_id), 0, s_spi_slave_hd_append_legacy_isr,
ret = esp_intr_alloc(spicommon_irqdma_source_for_host(host_id), bus_config->intr_flags, s_spi_slave_hd_append_legacy_isr,
(void *)host, &host->intr_dma);
if (ret != ESP_OK) {
goto cleanup;
@ -405,7 +413,7 @@ static void rx_invoke(spi_slave_hd_slot_t *host)
portEXIT_CRITICAL(&host->int_spinlock);
}
static inline IRAM_ATTR BaseType_t intr_check_clear_callback(spi_slave_hd_slot_t *host, spi_event_t ev, slave_cb_t cb)
static inline SPI_SLAVE_ISR_ATTR BaseType_t intr_check_clear_callback(spi_slave_hd_slot_t *host, spi_event_t ev, slave_cb_t cb)
{
BaseType_t cb_awoken = pdFALSE;
if (spi_slave_hd_hal_check_clear_event(&host->hal, ev) && cb) {
@ -414,7 +422,7 @@ static inline IRAM_ATTR BaseType_t intr_check_clear_callback(spi_slave_hd_slot_t
}
return cb_awoken;
}
static IRAM_ATTR void s_spi_slave_hd_segment_isr(void *arg)
static SPI_SLAVE_ISR_ATTR void s_spi_slave_hd_segment_isr(void *arg)
{
spi_slave_hd_slot_t *host = (spi_slave_hd_slot_t *)arg;
spi_slave_hd_callback_config_t *callback = &host->callback;
@ -536,7 +544,7 @@ static IRAM_ATTR void s_spi_slave_hd_segment_isr(void *arg)
}
}
static IRAM_ATTR void spi_slave_hd_append_tx_isr(void *arg)
static SPI_SLAVE_ISR_ATTR void spi_slave_hd_append_tx_isr(void *arg)
{
spi_slave_hd_slot_t *host = (spi_slave_hd_slot_t*)arg;
spi_slave_hd_callback_config_t *callback = &host->callback;
@ -579,7 +587,7 @@ static IRAM_ATTR void spi_slave_hd_append_tx_isr(void *arg)
}
}
static IRAM_ATTR void spi_slave_hd_append_rx_isr(void *arg)
static SPI_SLAVE_ISR_ATTR void spi_slave_hd_append_rx_isr(void *arg)
{
spi_slave_hd_slot_t *host = (spi_slave_hd_slot_t*)arg;
spi_slave_hd_callback_config_t *callback = &host->callback;
@ -631,7 +639,7 @@ static IRAM_ATTR void spi_slave_hd_append_rx_isr(void *arg)
}
#if SOC_GDMA_SUPPORTED
static IRAM_ATTR bool s_spi_slave_hd_append_gdma_isr(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data)
static SPI_SLAVE_ISR_ATTR bool s_spi_slave_hd_append_gdma_isr(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data)
{
assert(event_data);
spi_slave_hd_slot_t *host = (spi_slave_hd_slot_t*)user_data;
@ -646,7 +654,7 @@ static IRAM_ATTR bool s_spi_slave_hd_append_gdma_isr(gdma_channel_handle_t dma_c
}
#else
static IRAM_ATTR void s_spi_slave_hd_append_legacy_isr(void *arg)
static SPI_SLAVE_ISR_ATTR void s_spi_slave_hd_append_legacy_isr(void *arg)
{
spi_slave_hd_slot_t *host = (spi_slave_hd_slot_t *)arg;
spi_slave_hd_hal_context_t *hal = &host->hal;

View File

@ -121,7 +121,7 @@ TEST_CASE("SPI Master clockdiv calculation routines", "[spi]")
// Test All clock source
#define TEST_CLK_BYTE_LEN 10000
#define TEST_TRANS_TIME_BIAS_RATIO (float)2.0/100 // think 2% transfer time bias as acceptable
#define TEST_TRANS_TIME_BIAS_RATIO (float)5.0/100 // think 5% transfer time bias as acceptable
TEST_CASE("SPI Master clk_source and divider accuracy", "[spi]")
{
int64_t start = 0, end = 0;
@ -1380,8 +1380,8 @@ TEST_CASE_MULTIPLE_DEVICES("SPI Master: FD, DMA, Master Single Direction Test",
/********************************************************************************
* Test SPI transaction interval
********************************************************************************/
//Disabled since the check in portENTER_CRITICAL in esp_intr_enable/disable increase the delay
#ifndef CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE
//Disabled since place code in flash increase the delay
#if CONFIG_SPI_MASTER_ISR_IN_IRAM
#define RECORD_TIME_PREPARE() uint32_t __t1, __t2
#define RECORD_TIME_START() do {__t1 = esp_cpu_get_cycle_count();}while(0)

View File

@ -10,7 +10,6 @@ from pytest_embedded_idf.utils import idf_parametrize
'config',
[
'release',
'freertos_compliance',
'freertos_flash',
],
indirect=True,
@ -47,18 +46,8 @@ def test_master_esp_flash(case_tester) -> None: # type: ignore
@pytest.mark.parametrize(
'count, config',
[
(
2,
'release',
),
(
2,
'freertos_compliance',
),
(
2,
'freertos_flash',
),
(2, 'release'),
(2, 'freertos_flash'),
(2, 'iram_safe'),
],
indirect=True,

View File

@ -1,3 +0,0 @@
CONFIG_PM_ENABLE=y
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE=y

View File

@ -1 +1,3 @@
CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y
CONFIG_SPI_MASTER_ISR_IN_IRAM=n
CONFIG_SPI_SLAVE_ISR_IN_IRAM=n