Merge branch 'refactor/esp_driver_spi' into 'master'

refactor(spi): make spi driver as component

Closes IDF-8371

See merge request espressif/esp-idf!26549
This commit is contained in:
Armando (Dou Yiwen) 2023-11-09 21:41:29 +08:00
commit 2b173ce727
82 changed files with 823 additions and 712 deletions

View File

@ -5,8 +5,7 @@ if(${target} STREQUAL "linux")
endif()
# Always compiled source files
set(srcs
"spi/spi_bus_lock.c")
set(srcs)
# Always included headers
set(includes "include"
@ -21,8 +20,8 @@ set(includes "include"
"rmt/include"
"sdio_slave/include"
"sdmmc/include"
"sdspi/include"
"sigma_delta/include"
"spi/include"
"temperature_sensor/include"
"touch_sensor/include"
"twai/include"
@ -153,19 +152,13 @@ if(CONFIG_SOC_SDM_SUPPORTED)
"deprecated/sigma_delta_legacy.c")
endif()
# SPI related source files
# SDSPI related source files
if(CONFIG_SOC_GPSPI_SUPPORTED)
list(APPEND srcs "spi/gpspi/spi_common.c"
"spi/gpspi/spi_master.c"
"spi/gpspi/spi_slave.c"
"spi/sdspi/sdspi_crc.c"
"spi/sdspi/sdspi_host.c"
"spi/sdspi/sdspi_transaction.c")
list(APPEND srcs "sdspi/sdspi_crc.c"
"sdspi/sdspi_host.c"
"sdspi/sdspi_transaction.c")
endif()
if(CONFIG_SOC_SPI_SUPPORT_SLAVE_HD_VER2)
list(APPEND srcs "spi/gpspi/spi_slave_hd.c")
endif()
# Temperature Sensor related source files
if(CONFIG_SOC_TEMP_SENSOR_SUPPORTED)
@ -218,7 +211,7 @@ else()
REQUIRES esp_pm esp_ringbuf freertos soc hal esp_hw_support
# for backward compatibility, the driver component needs to
# have a public dependency on other "esp_driver_foo" components
esp_driver_gpio esp_driver_pcnt esp_driver_gptimer
esp_driver_gpio esp_driver_pcnt esp_driver_gptimer esp_driver_spi
LDFRAGMENTS ${ldfragments}
)
endif()

View File

@ -62,68 +62,6 @@ menu "Driver Configurations"
endmenu # ADC Configuration
menu "SPI Configuration"
config SPI_MASTER_IN_IRAM
bool "Place transmitting functions of SPI master into IRAM"
default n
depends on !FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
select SPI_MASTER_ISR_IN_IRAM
help
Normally only the ISR of SPI master is placed in the IRAM, so that it
can work without the flash when interrupt is triggered.
For other functions, there's some possibility that the flash cache
miss when running inside and out of SPI functions, which may increase
the interval of SPI transactions.
Enable this to put ``queue_trans``, ``get_trans_result`` and
``transmit`` functions into the IRAM to avoid possible cache miss.
This configuration won't be available if `CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH` is enabled.
During unit test, this is enabled to measure the ideal case of api.
config SPI_MASTER_ISR_IN_IRAM
bool "Place SPI master ISR function into IRAM"
default y
depends on !HEAP_PLACE_FUNCTION_INTO_FLASH
select PERIPH_CTRL_FUNC_IN_IRAM
select HAL_SPI_MASTER_FUNC_IN_IRAM
help
Place the SPI master ISR in to IRAM to avoid possible cache miss.
Enabling this configuration is possible only when HEAP_PLACE_FUNCTION_INTO_FLASH
is disabled since the spi master uses can allocate transactions buffers into DMA
memory section using the heap component API that ipso facto has to be placed in IRAM.
Also you can forbid the ISR being disabled during flash writing
access, by add ESP_INTR_FLAG_IRAM when initializing the driver.
config SPI_SLAVE_IN_IRAM
bool "Place transmitting functions of SPI slave into IRAM"
default n
select SPI_SLAVE_ISR_IN_IRAM
help
Normally only the ISR of SPI slave is placed in the IRAM, so that it
can work without the flash when interrupt is triggered.
For other functions, there's some possibility that the flash cache
miss when running inside and out of SPI functions, which may increase
the interval of SPI transactions.
Enable this to put ``queue_trans``, ``get_trans_result`` and
``transmit`` functions into the IRAM to avoid possible cache miss.
config SPI_SLAVE_ISR_IN_IRAM
bool "Place SPI slave ISR function into IRAM"
default y
select PERIPH_CTRL_FUNC_IN_IRAM
select HAL_SPI_SLAVE_FUNC_IN_IRAM
help
Place the SPI slave ISR in to IRAM to avoid possible cache miss.
Also you can forbid the ISR being disabled during flash writing
access, by add ESP_INTR_FLAG_IRAM when initializing the driver.
endmenu # SPI Configuration
orsource "./twai/Kconfig.twai"
menu "Temperature sensor Configuration"

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -65,9 +65,9 @@ typedef struct {
gpio_num_t gpio_cd; ///< GPIO number of card detect signal
gpio_num_t gpio_wp; ///< GPIO number of write protect signal
gpio_num_t gpio_int; ///< GPIO number of interrupt line (input) for SDIO card.
bool gpio_wp_polarity; ///< GPIO write protect polarity
/// 0 means "active low", i.e. card is protected when the GPIO is low;
/// 1 means "active high", i.e. card is protected when GPIO is high.
bool gpio_wp_polarity; /*!< GPIO write protect polarity
0 means "active low", i.e. card is protected when the GPIO is low;
1 means "active high", i.e. card is protected when GPIO is high. */
} sdspi_device_config_t;
#define SDSPI_SLOT_NO_CS GPIO_NUM_NC ///< indicates that card select line is not used

View File

@ -0,0 +1,45 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include "sdspi_crc.h"
#include "sdkconfig.h"
#include "esp_rom_crc.h"
static const uint8_t crc7_table[256] = {
0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
0x19, 0x10, 0x0b, 0x02, 0x3d, 0x34, 0x2f, 0x26, 0x51, 0x58, 0x43, 0x4a, 0x75, 0x7c, 0x67, 0x6e,
0x32, 0x3b, 0x20, 0x29, 0x16, 0x1f, 0x04, 0x0d, 0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45,
0x2b, 0x22, 0x39, 0x30, 0x0f, 0x06, 0x1d, 0x14, 0x63, 0x6a, 0x71, 0x78, 0x47, 0x4e, 0x55, 0x5c,
0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b, 0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13,
0x7d, 0x74, 0x6f, 0x66, 0x59, 0x50, 0x4b, 0x42, 0x35, 0x3c, 0x27, 0x2e, 0x11, 0x18, 0x03, 0x0a,
0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69, 0x1e, 0x17, 0x0c, 0x05, 0x3a, 0x33, 0x28, 0x21,
0x4f, 0x46, 0x5d, 0x54, 0x6b, 0x62, 0x79, 0x70, 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31, 0x38,
0x41, 0x48, 0x53, 0x5a, 0x65, 0x6c, 0x77, 0x7e, 0x09, 0x00, 0x1b, 0x12, 0x2d, 0x24, 0x3f, 0x36,
0x58, 0x51, 0x4a, 0x43, 0x7c, 0x75, 0x6e, 0x67, 0x10, 0x19, 0x02, 0x0b, 0x34, 0x3d, 0x26, 0x2f,
0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04,
0x6a, 0x63, 0x78, 0x71, 0x4e, 0x47, 0x5c, 0x55, 0x22, 0x2b, 0x30, 0x39, 0x06, 0x0f, 0x14, 0x1d,
0x25, 0x2c, 0x37, 0x3e, 0x01, 0x08, 0x13, 0x1a, 0x6d, 0x64, 0x7f, 0x76, 0x49, 0x40, 0x5b, 0x52,
0x3c, 0x35, 0x2e, 0x27, 0x18, 0x11, 0x0a, 0x03, 0x74, 0x7d, 0x66, 0x6f, 0x50, 0x59, 0x42, 0x4b,
0x17, 0x1e, 0x05, 0x0c, 0x33, 0x3a, 0x21, 0x28, 0x5f, 0x56, 0x4d, 0x44, 0x7b, 0x72, 0x69, 0x60,
0x0e, 0x07, 0x1c, 0x15, 0x2a, 0x23, 0x38, 0x31, 0x46, 0x4f, 0x54, 0x5d, 0x62, 0x6b, 0x70, 0x79,
};
// returns the CRC-7 for a message of "length" bytes
uint8_t sdspi_crc7(const uint8_t *data, size_t size)
{
uint8_t result = 0;
for (size_t i = 0; i < size; ++i) {
result = crc7_table[(result << 1) ^ data[i]];
}
return result;
}
/// Return CRC16 of data, in the on-the-wire format used by SD protocol
uint16_t sdspi_crc16(const uint8_t* data, size_t size)
{
return __builtin_bswap16(esp_rom_crc16_be(UINT16_MAX, data, size) ^ UINT16_MAX);
}

View File

@ -12,7 +12,6 @@ extern "C"
{
#endif
/**
* @brief Return CRC7 of data, in the format used by SD protocol
* @param data array of data used to compute CRC
@ -29,7 +28,6 @@ uint8_t sdspi_crc7(const uint8_t *data, size_t size);
*/
uint16_t sdspi_crc16(const uint8_t* data, size_t size);
#ifdef __cplusplus
}
#endif

View File

@ -22,7 +22,6 @@
#include "freertos/semphr.h"
#include "soc/soc_memory_layout.h"
/// Max number of transactions in flight (used in start_command_write_blocks)
#define SDSPI_TRANSACTION_COUNT 4
#define SDSPI_MOSI_IDLE_VAL 0xff //!< Data value which causes MOSI to stay high
@ -67,7 +66,6 @@ static const char *TAG = "sdspi_host";
static const bool use_polling = true;
static const bool no_use_polling = true;
/// Functions to send out different kinds of commands
static esp_err_t start_command_read_blocks(slot_info_t *slot, sdspi_hw_cmd_t *cmd,
uint8_t *data, uint32_t rx_length, bool need_stop_command);
@ -286,7 +284,9 @@ esp_err_t sdspi_host_deinit(void)
for (size_t i = 0; i < sizeof(s_slots) / sizeof(s_slots[0]); ++i) {
slot_info_t* slot = remove_slot_info(i);
//slot isn't used, skip
if (slot == NULL) continue;
if (slot == NULL) {
continue;
}
deinit_slot(slot);
}
@ -553,7 +553,9 @@ static esp_err_t start_command_default(slot_info_t *slot, int flags, sdspi_hw_cm
// we have sent and received bytes with enough length.
// now shift the response to match the offset of sdspi_hw_cmd_t
ret = shift_cmd_response(cmd, cmd_size);
if (ret != ESP_OK) return ESP_ERR_TIMEOUT;
if (ret != ESP_OK) {
return ESP_ERR_TIMEOUT;
}
if (flags & SDSPI_CMD_FLAG_RSP_R1B) {
ret = poll_busy(slot, cmd->timeout_ms, no_use_polling);
@ -649,9 +651,13 @@ static esp_err_t shift_cmd_response(sdspi_hw_cmd_t* cmd, int sent_bytes)
uint8_t* pr1 = &cmd->r1;
int ncr_cnt = 1;
while (true) {
if ((*pr1 & SD_SPI_R1_NO_RESPONSE) == 0) break;
if ((*pr1 & SD_SPI_R1_NO_RESPONSE) == 0) {
break;
}
pr1++;
if (++ncr_cnt > 8) return ESP_ERR_NOT_FOUND;
if (++ncr_cnt > 8) {
return ESP_ERR_NOT_FOUND;
}
}
int copy_bytes = sent_bytes - SDSPI_CMD_SIZE - ncr_cnt;
@ -662,7 +668,6 @@ static esp_err_t shift_cmd_response(sdspi_hw_cmd_t* cmd, int sent_bytes)
return ESP_OK;
}
/**
* Receiving one or more blocks of data happens as follows:
* 1. send command + receive r1 response (SDSPI_CMD_R1_SIZE bytes total)
@ -920,7 +925,9 @@ static esp_err_t start_command_write_blocks(slot_info_t *slot, sdspi_hw_cmd_t *c
}
uint8_t data_rsp = t_crc_rsp.rx_data[2];
if (!SD_SPI_DATA_RSP_VALID(data_rsp)) return ESP_ERR_INVALID_RESPONSE;
if (!SD_SPI_DATA_RSP_VALID(data_rsp)) {
return ESP_ERR_INVALID_RESPONSE;
}
switch (SD_SPI_DATA_RSP(data_rsp)) {
case SD_SPI_DATA_ACCEPTED:
break;
@ -976,7 +983,9 @@ esp_err_t sdspi_host_io_int_wait(sdspi_dev_handle_t handle, TickType_t timeout_t
{
slot_info_t* slot = get_slot_info(handle);
//skip the interrupt and semaphore if the gpio is already low.
if (gpio_get_level(slot->gpio_int)==0) return ESP_OK;
if (gpio_get_level(slot->gpio_int) == 0) {
return ESP_OK;
}
//clear the semaphore before wait
xSemaphoreTake(slot->semphr_int, 0);

View File

@ -34,7 +34,6 @@
/// Data rejected due to write error
#define TOKEN_RSP_WRITE_ERR 0b01101
/// Data error tokens have format 0b0000xyzw where xyzw are signle bit flags.
/// MASK and VAL are used to check if a token is an error token
#define TOKEN_ERR_MASK 0b11110000
@ -49,7 +48,6 @@
/// Card is locked
#define TOKEN_ERR_LOCKED BIT(0)
/// Transfer format in SPI mode. See section 7.3.1.1 of SD simplified spec.
typedef struct {
// These fields form the command sent from host to the card (6 bytes)

View File

@ -137,9 +137,13 @@ esp_err_t sdspi_host_do_transaction(int slot, sdmmc_command_t *cmdinfo)
flags |= SDSPI_CMD_FLAG_RSP_R5;
} else if (!s_app_cmd && cmdinfo->opcode == SD_IO_RW_EXTENDED) {
flags |= SDSPI_CMD_FLAG_RSP_R5 | SDSPI_CMD_FLAG_DATA;
if (cmdinfo->arg & SD_ARG_CMD53_WRITE) flags |= SDSPI_CMD_FLAG_WRITE;
if (cmdinfo->arg & SD_ARG_CMD53_WRITE) {
flags |= SDSPI_CMD_FLAG_WRITE;
}
// The CMD53 can assign block mode in the arg when the length is exactly 512 bytes
if (cmdinfo->arg & SD_ARG_CMD53_BLOCK_MODE) flags |= SDSPI_CMD_FLAG_MULTI_BLK;
if (cmdinfo->arg & SD_ARG_CMD53_BLOCK_MODE) {
flags |= SDSPI_CMD_FLAG_MULTI_BLK;
}
} else if (!s_app_cmd && (cmdinfo->opcode == MMC_ERASE || cmdinfo->opcode == MMC_STOP_TRANSMISSION)) {
flags |= SDSPI_CMD_FLAG_RSP_R1B;
} else {

View File

@ -1,46 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include "sdspi_crc.h"
#include "sdkconfig.h"
#include "esp_rom_crc.h"
static const uint8_t crc7_table[256] =
{
0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
0x19, 0x10, 0x0b, 0x02, 0x3d, 0x34, 0x2f, 0x26, 0x51, 0x58, 0x43, 0x4a, 0x75, 0x7c, 0x67, 0x6e,
0x32, 0x3b, 0x20, 0x29, 0x16, 0x1f, 0x04, 0x0d, 0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45,
0x2b, 0x22, 0x39, 0x30, 0x0f, 0x06, 0x1d, 0x14, 0x63, 0x6a, 0x71, 0x78, 0x47, 0x4e, 0x55, 0x5c,
0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b, 0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13,
0x7d, 0x74, 0x6f, 0x66, 0x59, 0x50, 0x4b, 0x42, 0x35, 0x3c, 0x27, 0x2e, 0x11, 0x18, 0x03, 0x0a,
0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69, 0x1e, 0x17, 0x0c, 0x05, 0x3a, 0x33, 0x28, 0x21,
0x4f, 0x46, 0x5d, 0x54, 0x6b, 0x62, 0x79, 0x70, 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31, 0x38,
0x41, 0x48, 0x53, 0x5a, 0x65, 0x6c, 0x77, 0x7e, 0x09, 0x00, 0x1b, 0x12, 0x2d, 0x24, 0x3f, 0x36,
0x58, 0x51, 0x4a, 0x43, 0x7c, 0x75, 0x6e, 0x67, 0x10, 0x19, 0x02, 0x0b, 0x34, 0x3d, 0x26, 0x2f,
0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04,
0x6a, 0x63, 0x78, 0x71, 0x4e, 0x47, 0x5c, 0x55, 0x22, 0x2b, 0x30, 0x39, 0x06, 0x0f, 0x14, 0x1d,
0x25, 0x2c, 0x37, 0x3e, 0x01, 0x08, 0x13, 0x1a, 0x6d, 0x64, 0x7f, 0x76, 0x49, 0x40, 0x5b, 0x52,
0x3c, 0x35, 0x2e, 0x27, 0x18, 0x11, 0x0a, 0x03, 0x74, 0x7d, 0x66, 0x6f, 0x50, 0x59, 0x42, 0x4b,
0x17, 0x1e, 0x05, 0x0c, 0x33, 0x3a, 0x21, 0x28, 0x5f, 0x56, 0x4d, 0x44, 0x7b, 0x72, 0x69, 0x60,
0x0e, 0x07, 0x1c, 0x15, 0x2a, 0x23, 0x38, 0x31, 0x46, 0x4f, 0x54, 0x5d, 0x62, 0x6b, 0x70, 0x79,
};
// returns the CRC-7 for a message of "length" bytes
uint8_t sdspi_crc7(const uint8_t *data, size_t size)
{
uint8_t result = 0;
for (size_t i = 0; i < size; ++i) {
result = crc7_table[(result << 1) ^ data[i]];
}
return result;
}
/// Return CRC16 of data, in the on-the-wire format used by SD protocol
uint16_t sdspi_crc16(const uint8_t* data, size_t size)
{
return __builtin_bswap16(esp_rom_crc16_be(UINT16_MAX, data, size) ^ UINT16_MAX);
}

View File

@ -139,23 +139,6 @@ components/driver/test_apps/sigma_delta:
depends_components:
- esp_driver_gpio
components/driver/test_apps/spi/master:
disable:
- if: SOC_GPSPI_SUPPORTED != 1
components/driver/test_apps/spi/param:
disable:
- if: SOC_GPSPI_SUPPORTED != 1
components/driver/test_apps/spi/slave:
disable:
- if: SOC_GPSPI_SUPPORTED != 1
components/driver/test_apps/spi/slave_hd:
disable:
- if: SOC_GPSPI_SUPPORTED != 1
- if: SOC_SPI_SUPPORT_SLAVE_HD_VER2 != 1
components/driver/test_apps/temperature_sensor:
disable:
- if: SOC_TEMP_SENSOR_SUPPORTED != 1

View File

@ -8,6 +8,6 @@ components/esp_adc/test_apps/adc:
- esp_adc
- esp_driver_gpio
- efuse
- esp_driver_spi # ADC continuous driver relies on SPI on ESP32S2
depends_filepatterns:
- components/driver/spi/**/* # ADC continuous driver relies on SPI on ESP32S2
- components/driver/i2s/**/* # ADC continuous driver relies on I2S on ESP32

View File

@ -0,0 +1,26 @@
idf_build_get_property(target IDF_TARGET)
if(${target} STREQUAL "linux")
return() # This component is not supported by the POSIX/Linux simulator
endif()
set(srcs "spi_bus_lock.c")
set(public_include "include")
if(CONFIG_SOC_GPSPI_SUPPORTED)
list(APPEND srcs "src/gpspi/spi_common.c"
"src/gpspi/spi_master.c"
"src/gpspi/spi_slave.c")
endif()
if(CONFIG_SOC_SPI_SUPPORT_SLAVE_HD_VER2)
list(APPEND srcs "src/gpspi/spi_slave_hd.c")
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"
)

View File

@ -0,0 +1,61 @@
menu "ESP-Driver:SPI Configurations"
depends on SOC_GPSPI_SUPPORTED
config SPI_MASTER_IN_IRAM
bool "Place transmitting functions of SPI master into IRAM"
default n
depends on !FREERTOS_PLACE_FUNCTIONS_INTO_FLASH
select SPI_MASTER_ISR_IN_IRAM
help
Normally only the ISR of SPI master is placed in the IRAM, so that it
can work without the flash when interrupt is triggered.
For other functions, there's some possibility that the flash cache
miss when running inside and out of SPI functions, which may increase
the interval of SPI transactions.
Enable this to put ``queue_trans``, ``get_trans_result`` and
``transmit`` functions into the IRAM to avoid possible cache miss.
This configuration won't be available if `CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH` is enabled.
During unit test, this is enabled to measure the ideal case of api.
config SPI_MASTER_ISR_IN_IRAM
bool "Place SPI master ISR function into IRAM"
default y
depends on !HEAP_PLACE_FUNCTION_INTO_FLASH
select PERIPH_CTRL_FUNC_IN_IRAM
select HAL_SPI_MASTER_FUNC_IN_IRAM
help
Place the SPI master ISR in to IRAM to avoid possible cache miss.
Enabling this configuration is possible only when HEAP_PLACE_FUNCTION_INTO_FLASH
is disabled since the spi master uses can allocate transactions buffers into DMA
memory section using the heap component API that ipso facto has to be placed in IRAM.
Also you can forbid the ISR being disabled during flash writing
access, by add ESP_INTR_FLAG_IRAM when initializing the driver.
config SPI_SLAVE_IN_IRAM
bool "Place transmitting functions of SPI slave into IRAM"
default n
select SPI_SLAVE_ISR_IN_IRAM
help
Normally only the ISR of SPI slave is placed in the IRAM, so that it
can work without the flash when interrupt is triggered.
For other functions, there's some possibility that the flash cache
miss when running inside and out of SPI functions, which may increase
the interval of SPI transactions.
Enable this to put ``queue_trans``, ``get_trans_result`` and
``transmit`` functions into the IRAM to avoid possible cache miss.
config SPI_SLAVE_ISR_IN_IRAM
bool "Place SPI slave ISR function into IRAM"
default y
select PERIPH_CTRL_FUNC_IN_IRAM
select HAL_SPI_SLAVE_FUNC_IN_IRAM
help
Place the SPI slave ISR in to IRAM to avoid possible cache miss.
Also you can forbid the ISR being disabled during flash writing
access, by add ESP_INTR_FLAG_IRAM when initializing the driver.
endmenu # SPI Configuration

View File

@ -125,7 +125,6 @@ typedef struct {
*/
} spi_bus_config_t;
/**
* @brief Initialize a SPI bus
*

View File

@ -102,7 +102,6 @@ typedef struct {
*/
} spi_device_interface_config_t;
#define SPI_TRANS_MODE_DIO (1<<0) ///< Transmit/receive data in 2-bit mode
#define SPI_TRANS_MODE_QIO (1<<1) ///< Transmit/receive data in 4-bit mode
#define SPI_TRANS_USE_RXDATA (1<<2) ///< Receive into rx_data member of spi_transaction_t instead into memory at rx_buffer.
@ -158,7 +157,6 @@ typedef struct {
uint8_t dummy_bits; ///< The dummy length in this transaction, in bits.
} spi_transaction_ext_t ;
typedef struct spi_device_t *spi_device_handle_t; ///< Handle for a device on a SPI bus
/**
* @brief Allocate a device on a SPI bus
@ -183,7 +181,6 @@ typedef struct spi_device_t *spi_device_handle_t; ///< Handle for a device on a
*/
esp_err_t spi_bus_add_device(spi_host_device_t host_id, const spi_device_interface_config_t *dev_config, spi_device_handle_t *handle);
/**
* @brief Remove a device from the SPI bus
*
@ -195,7 +192,6 @@ esp_err_t spi_bus_add_device(spi_host_device_t host_id, const spi_device_interfa
*/
esp_err_t spi_bus_remove_device(spi_device_handle_t handle);
/**
* @brief Queue a SPI transaction for interrupt transaction execution. Get the result by ``spi_device_get_trans_result``.
*
@ -217,7 +213,6 @@ esp_err_t spi_bus_remove_device(spi_device_handle_t handle);
*/
esp_err_t spi_device_queue_trans(spi_device_handle_t handle, spi_transaction_t *trans_desc, TickType_t ticks_to_wait);
/**
* @brief Get the result of a SPI transaction queued earlier by ``spi_device_queue_trans``.
*
@ -240,7 +235,6 @@ esp_err_t spi_device_queue_trans(spi_device_handle_t handle, spi_transaction_t *
*/
esp_err_t spi_device_get_trans_result(spi_device_handle_t handle, spi_transaction_t **trans_desc, TickType_t ticks_to_wait);
/**
* @brief Send a SPI transaction, wait for it to complete, and return the result
*
@ -259,7 +253,6 @@ esp_err_t spi_device_get_trans_result(spi_device_handle_t handle, spi_transactio
*/
esp_err_t spi_device_transmit(spi_device_handle_t handle, spi_transaction_t *trans_desc);
/**
* @brief Immediately start a polling transaction.
*
@ -283,7 +276,6 @@ esp_err_t spi_device_transmit(spi_device_handle_t handle, spi_transaction_t *tra
*/
esp_err_t spi_device_polling_start(spi_device_handle_t handle, spi_transaction_t *trans_desc, TickType_t ticks_to_wait);
/**
* @brief Poll until the polling transaction ends.
*
@ -301,7 +293,6 @@ esp_err_t spi_device_polling_start(spi_device_handle_t handle, spi_transaction_t
*/
esp_err_t spi_device_polling_end(spi_device_handle_t handle, TickType_t ticks_to_wait);
/**
* @brief Send a polling transaction, wait for it to complete, and return the result
*
@ -323,7 +314,6 @@ esp_err_t spi_device_polling_end(spi_device_handle_t handle, TickType_t ticks_to
*/
esp_err_t spi_device_polling_transmit(spi_device_handle_t handle, spi_transaction_t *trans_desc);
/**
* @brief Occupy the SPI bus for a device to do continuous transactions.
*

View File

@ -4,7 +4,6 @@
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _DRIVER_SPI_SLAVE_H_
#define _DRIVER_SPI_SLAVE_H_
@ -13,13 +12,11 @@
#include "freertos/semphr.h"
#include "driver/spi_common.h"
#ifdef __cplusplus
extern "C"
{
#endif
#define SPI_SLAVE_TXBIT_LSBFIRST (1<<0) ///< Transmit command/address/data LSB first instead of the default MSB first
#define SPI_SLAVE_RXBIT_LSBFIRST (1<<1) ///< Receive data LSB first instead of the default MSB first
#define SPI_SLAVE_BIT_LSBFIRST (SPI_SLAVE_TXBIT_LSBFIRST|SPI_SLAVE_RXBIT_LSBFIRST) ///< Transmit and receive LSB first
@ -65,7 +62,6 @@ typedef struct {
*/
} spi_slave_interface_config_t;
#define SPI_SLAVE_TRANS_DMA_BUFFER_ALIGN_AUTO (1<<0) ///< Automatically re-malloc dma buffer if user buffer doesn't meet hardware alignment or dma_capable, this process may loss some memory and performance
/**
@ -123,7 +119,6 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b
*/
esp_err_t spi_slave_free(spi_host_device_t host);
/**
* @brief Queue a SPI transaction for execution
*
@ -148,7 +143,6 @@ esp_err_t spi_slave_free(spi_host_device_t host);
*/
esp_err_t spi_slave_queue_trans(spi_host_device_t host, const spi_slave_transaction_t *trans_desc, TickType_t ticks_to_wait);
/**
* @brief Get the result of a SPI transaction queued earlier
*
@ -171,7 +165,6 @@ esp_err_t spi_slave_queue_trans(spi_host_device_t host, const spi_slave_transact
*/
esp_err_t spi_slave_get_trans_result(spi_host_device_t host, spi_slave_transaction_t **trans_desc, TickType_t ticks_to_wait);
/**
* @brief Do a SPI transaction
*
@ -191,7 +184,6 @@ esp_err_t spi_slave_get_trans_result(spi_host_device_t host, spi_slave_transacti
*/
esp_err_t spi_slave_transmit(spi_host_device_t host, spi_slave_transaction_t *trans_desc, TickType_t ticks_to_wait);
#ifdef __cplusplus
}
#endif

View File

@ -62,7 +62,6 @@ typedef struct {
void* arg; ///< Argument indicating this SPI Slave HD peripheral instance
} spi_slave_hd_callback_config_t;
//flags for ``spi_slave_hd_slot_config_t`` to use
#define SPI_SLAVE_HD_TXBIT_LSBFIRST (1<<0) ///< Transmit command/address/data LSB first instead of the default MSB first
#define SPI_SLAVE_HD_RXBIT_LSBFIRST (1<<1) ///< Receive data LSB first instead of the default MSB first

View File

@ -19,13 +19,11 @@
#include "esp_private/gdma.h"
#endif
#ifdef __cplusplus
extern "C"
{
#endif
#ifdef CONFIG_SPI_MASTER_ISR_IN_IRAM
#define SPI_MASTER_ISR_ATTR IRAM_ATTR
#else
@ -38,7 +36,6 @@ extern "C"
#define SPI_MASTER_ATTR
#endif
#define BUS_LOCK_DEBUG 0
#if BUS_LOCK_DEBUG
@ -88,7 +85,6 @@ typedef struct {
/// Destructor called when a bus is deinitialized.
typedef esp_err_t (*spi_destroy_func_t)(void*);
/**
* @brief Try to claim a SPI peripheral
*
@ -281,7 +277,6 @@ typedef void(*dmaworkaround_cb_t)(void *arg);
*/
bool spicommon_dmaworkaround_req_reset(int dmachan, dmaworkaround_cb_t cb, void *arg);
/**
* @brief Check if a DMA reset is requested but has not completed yet
*
@ -289,7 +284,6 @@ bool spicommon_dmaworkaround_req_reset(int dmachan, dmaworkaround_cb_t cb, void
*/
bool spicommon_dmaworkaround_reset_in_progress(void);
/**
* @brief Mark a DMA channel as idle.
*
@ -779,7 +773,6 @@ extern const spi_bus_lock_dev_handle_t g_spi_lock_main_flash_dev;
*/
esp_err_t spi_bus_lock_init_main_dev(void);
#ifdef __cplusplus
}
#endif

View File

@ -22,7 +22,6 @@
extern "C" {
#endif
/**
* @brief Reset the trans Queue of slave driver
* @note
@ -40,7 +39,6 @@ extern "C" {
*/
esp_err_t spi_slave_queue_reset(spi_host_device_t host);
/**
* @brief Reset the trans Queue from within ISR of slave driver
* @note
@ -55,7 +53,6 @@ esp_err_t spi_slave_queue_reset(spi_host_device_t host);
*/
esp_err_t spi_slave_queue_reset_isr(spi_host_device_t host);
/**
* @brief Queue a SPI transaction in ISR
* @note
@ -76,7 +73,6 @@ esp_err_t spi_slave_queue_reset_isr(spi_host_device_t host);
*/
esp_err_t spi_slave_queue_trans_isr(spi_host_device_t host, const spi_slave_transaction_t *trans_desc);
#ifdef __cplusplus
}
#endif

View File

View File

@ -17,7 +17,6 @@
#include <strings.h>
#include "esp_heap_caps.h"
/*
* This lock is designed to solve the conflicts between SPI devices (used in tasks) and
* the background operations (ISR or cache access).
@ -145,7 +144,6 @@ typedef struct spi_bus_lock_dev_t spi_bus_lock_dev_t;
typedef struct spi_bus_lock_t spi_bus_lock_t;
#define MAX_DEV_NUM 10
// Bit 29-20: lock bits, Bit 19-10: pending bits
@ -564,7 +562,9 @@ SPI_MASTER_ISR_ATTR static inline esp_err_t dev_wait(spi_bus_lock_dev_t *dev_han
{
BaseType_t ret = xSemaphoreTake(dev_handle->semphr, wait);
if (ret == pdFALSE) return ESP_ERR_TIMEOUT;
if (ret == pdFALSE) {
return ESP_ERR_TIMEOUT;
}
return ESP_OK;
}
@ -624,9 +624,13 @@ static int try_acquire_free_dev(spi_bus_lock_t *lock, bool cs_required)
esp_err_t spi_bus_lock_register_dev(spi_bus_lock_handle_t lock, spi_bus_lock_dev_config_t *config,
spi_bus_lock_dev_handle_t *out_dev_handle)
{
if (lock == NULL) return ESP_ERR_INVALID_ARG;
if (lock == NULL) {
return ESP_ERR_INVALID_ARG;
}
int id = try_acquire_free_dev(lock, config->flags & SPI_BUS_LOCK_DEV_FLAG_CS_REQUIRED);
if (id == -1) return ESP_ERR_NOT_SUPPORTED;
if (id == -1) {
return ESP_ERR_NOT_SUPPORTED;
}
spi_bus_lock_dev_t* dev_lock = (spi_bus_lock_dev_t*)heap_caps_calloc(sizeof(spi_bus_lock_dev_t), 1, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
if (dev_lock == NULL) {
@ -654,7 +658,9 @@ void spi_bus_lock_unregister_dev(spi_bus_lock_dev_handle_t dev_handle)
spi_bus_lock_t* lock = dev_handle->parent;
BUS_LOCK_DEBUG_EXECUTE_CHECK(atomic_load(&lock->dev[id]) == (intptr_t)dev_handle);
if (lock->last_dev == dev_handle) lock->last_dev = NULL;
if (lock->last_dev == dev_handle) {
lock->last_dev = NULL;
}
atomic_store(&lock->dev[id], (intptr_t)NULL);
if (dev_handle->semphr) {
@ -714,7 +720,9 @@ IRAM_ATTR esp_err_t spi_bus_lock_acquire_start(spi_bus_lock_dev_t *dev_handle, T
//block until becoming the acquiring processor (help by previous acquiring processor)
esp_err_t err = dev_wait(dev_handle, wait);
//TODO: add timeout handling here.
if (err != ESP_OK) return err;
if (err != ESP_OK) {
return err;
}
}
ESP_DRAM_LOGV(TAG, "dev %d acquired.", dev_lock_get_id(dev_handle));
@ -780,7 +788,9 @@ IRAM_ATTR esp_err_t spi_bus_lock_wait_bg_done(spi_bus_lock_dev_handle_t dev_hand
//block until becoming the acquiring processor (help by previous acquiring processor)
esp_err_t err = dev_wait(dev_handle, wait);
//TODO: add timeout handling here.
if (err != ESP_OK) return err;
if (err != ESP_OK) {
return err;
}
}
}

View File

@ -4,7 +4,6 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include "sdkconfig.h"
#include "stdatomic.h"
@ -57,7 +56,6 @@ static const char *SPI_TAG = "spi";
#define FUNC_GPIO PIN_FUNC_GPIO
typedef struct {
int host_id;
spi_destroy_func_t destroy_func;
@ -89,7 +87,6 @@ static uint8_t spi_dma_chan_enabled = 0;
static portMUX_TYPE spi_dma_spinlock = portMUX_INITIALIZER_UNLOCKED;
#endif //#if !SOC_GDMA_SUPPORTED
static inline bool is_valid_host(spi_host_device_t host)
{
#if (SOC_SPI_PERIPH_NUM == 2)
@ -330,7 +327,6 @@ esp_err_t spicommon_gdma_get_handle(spi_host_device_t host_id, gdma_channel_hand
(gdma_direction == GDMA_CHANNEL_DIRECTION_RX), \
ESP_ERR_INVALID_ARG, SPI_TAG, "GDMA Direction not supported!");
if (gdma_direction == GDMA_CHANNEL_DIRECTION_TX) {
*gdma_handle = bus_ctx[host_id]->tx_channel;
}
@ -400,9 +396,11 @@ static bool check_iomux_pins_oct(spi_host_device_t host, const spi_bus_config_t*
return false;
}
int io_nums[] = {bus_config->data0_io_num, bus_config->data1_io_num, bus_config->data2_io_num, bus_config->data3_io_num,
bus_config->sclk_io_num, bus_config->data4_io_num, bus_config->data5_io_num, bus_config->data6_io_num, bus_config->data7_io_num};
bus_config->sclk_io_num, bus_config->data4_io_num, bus_config->data5_io_num, bus_config->data6_io_num, bus_config->data7_io_num
};
int io_mux_nums[] = {SPI2_IOMUX_PIN_NUM_MOSI_OCT, SPI2_IOMUX_PIN_NUM_MISO_OCT, SPI2_IOMUX_PIN_NUM_WP_OCT, SPI2_IOMUX_PIN_NUM_HD_OCT,
SPI2_IOMUX_PIN_NUM_CLK_OCT, SPI2_IOMUX_PIN_NUM_IO4_OCT, SPI2_IOMUX_PIN_NUM_IO5_OCT, SPI2_IOMUX_PIN_NUM_IO6_OCT, SPI2_IOMUX_PIN_NUM_IO7_OCT};
SPI2_IOMUX_PIN_NUM_CLK_OCT, SPI2_IOMUX_PIN_NUM_IO4_OCT, SPI2_IOMUX_PIN_NUM_IO5_OCT, SPI2_IOMUX_PIN_NUM_IO6_OCT, SPI2_IOMUX_PIN_NUM_IO7_OCT
};
for (size_t i = 0; i < sizeof(io_nums) / sizeof(io_nums[0]); i++) {
if (io_nums[i] >= 0 && io_nums[i] != io_mux_nums[i]) {
return false;
@ -454,10 +452,12 @@ static void bus_iomux_pins_set_oct(spi_host_device_t host, const spi_bus_config_
{
assert(host == SPI2_HOST);
int io_nums[] = {bus_config->data0_io_num, bus_config->data1_io_num, bus_config->data2_io_num, bus_config->data3_io_num,
bus_config->sclk_io_num, bus_config->data4_io_num, bus_config->data5_io_num, bus_config->data6_io_num, bus_config->data7_io_num};
bus_config->sclk_io_num, bus_config->data4_io_num, bus_config->data5_io_num, bus_config->data6_io_num, bus_config->data7_io_num
};
int io_signals[] = {spi_periph_signal[host].spid_in, spi_periph_signal[host].spiq_in, spi_periph_signal[host].spiwp_in,
spi_periph_signal[host].spihd_in, spi_periph_signal[host].spiclk_in, spi_periph_signal[host].spid4_out,
spi_periph_signal[host].spid5_out, spi_periph_signal[host].spid6_out, spi_periph_signal[host].spid7_out};
spi_periph_signal[host].spid5_out, spi_periph_signal[host].spid6_out, spi_periph_signal[host].spid7_out
};
for (size_t i = 0; i < sizeof(io_nums) / sizeof(io_nums[0]); i++) {
if (io_nums[i] > 0) {
gpio_iomux_in(io_nums[i], io_signals[i]);
@ -576,7 +576,9 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf
#endif //SOC_SPI_SUPPORT_OCT
//set flags for QUAD mode according to the existence of wp and hd
if (bus_config->quadhd_io_num >= 0 && bus_config->quadwp_io_num >= 0) temp_flag |= SPICOMMON_BUSFLAG_WPHD;
if (bus_config->quadhd_io_num >= 0 && bus_config->quadwp_io_num >= 0) {
temp_flag |= SPICOMMON_BUSFLAG_WPHD;
}
if (bus_config->mosi_io_num >= 0) {
temp_flag |= SPICOMMON_BUSFLAG_MOSI;
SPI_CHECK_PIN(bus_config->mosi_io_num, "mosi", mosi_need_output);
@ -701,7 +703,8 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf
uint8_t io_signals[4][2] = {{spi_periph_signal[host].spid4_out, spi_periph_signal[host].spid4_in},
{spi_periph_signal[host].spid5_out, spi_periph_signal[host].spid5_in},
{spi_periph_signal[host].spid6_out, spi_periph_signal[host].spid6_in},
{spi_periph_signal[host].spid7_out, spi_periph_signal[host].spid7_in}};
{spi_periph_signal[host].spid7_out, spi_periph_signal[host].spid7_in}
};
for (size_t i = 0; i < sizeof(io_nums) / sizeof(io_nums[0]); i++) {
if (io_nums[i] >= 0) {
gpio_set_direction(io_nums[i], GPIO_MODE_INPUT_OUTPUT);
@ -717,7 +720,9 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf
#endif //SOC_SPI_SUPPORT_OCT
}
if (flags_o) *flags_o = temp_flag;
if (flags_o) {
*flags_o = temp_flag;
}
return ESP_OK;
}
@ -753,7 +758,9 @@ void spicommon_cs_initialize(spi_host_device_t host, int cs_io_num, int cs_num,
} else {
gpio_set_direction(cs_io_num, GPIO_MODE_INPUT);
}
if (cs_num == 0) esp_rom_gpio_connect_in_signal(cs_io_num, spi_periph_signal[host].spics_in, false);
if (cs_num == 0) {
esp_rom_gpio_connect_in_signal(cs_io_num, spi_periph_signal[host].spics_in, false);
}
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[cs_io_num]);
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[cs_io_num], FUNC_GPIO);
}
@ -776,7 +783,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;
@ -835,7 +841,9 @@ esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t *
bus_attr->rx_dma_chan = actual_rx_dma_chan;
int dma_desc_ct = (bus_config->max_transfer_sz + DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED - 1) / DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED;
if (dma_desc_ct == 0) dma_desc_ct = 1; //default to 4k when max is not given
if (dma_desc_ct == 0) {
dma_desc_ct = 1; //default to 4k when max is not given
}
bus_attr->max_transfer_sz = dma_desc_ct * DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED;
bus_attr->dmadesc_tx = heap_caps_aligned_alloc(DMA_DESC_MEM_ALIGN_SIZE, sizeof(spi_dma_desc_t) * dma_desc_ct, MALLOC_CAP_DMA);
@ -904,7 +912,9 @@ cleanup:
const spi_bus_attr_t* spi_bus_get_attr(spi_host_device_t host_id)
{
if (bus_ctx[host_id] == NULL) return NULL;
if (bus_ctx[host_id] == NULL) {
return NULL;
}
return &bus_ctx[host_id]->bus_attr;
}
@ -950,7 +960,6 @@ esp_err_t spi_bus_register_destroy_func(spi_host_device_t host_id,
return ESP_OK;
}
/*
Code for workaround for DMA issue in ESP32 v0/v1 silicon
*/

View File

@ -326,8 +326,12 @@ void spi_get_timing(bool gpio_is_used, int input_delay_ns, int eff_clk, int* dum
int timing_miso_delay;
spi_hal_cal_timing(APB_CLK_FREQ, eff_clk, gpio_is_used, input_delay_ns, &timing_dummy, &timing_miso_delay);
if (dummy_o) *dummy_o = timing_dummy;
if (cycles_remain_o) *cycles_remain_o = timing_miso_delay;
if (dummy_o) {
*dummy_o = timing_dummy;
}
if (cycles_remain_o) {
*cycles_remain_o = timing_miso_delay;
}
#else
//TODO: IDF-6578
ESP_LOGW(SPI_TAG, "This func temporary not supported for current target!");
@ -428,7 +432,9 @@ esp_err_t spi_bus_add_device(spi_host_device_t host_id, const spi_device_interfa
//Allocate memory for device
dev = malloc(sizeof(spi_device_t));
if (dev == NULL) goto nomem;
if (dev == NULL) {
goto nomem;
}
memset(dev, 0, sizeof(spi_device_t));
dev->id = freecs;
@ -492,8 +498,12 @@ esp_err_t spi_bus_add_device(spi_host_device_t host_id, const spi_device_interfa
nomem:
if (dev) {
if (dev->trans_queue) vQueueDelete(dev->trans_queue);
if (dev->ret_queue) vQueueDelete(dev->ret_queue);
if (dev->trans_queue) {
vQueueDelete(dev->trans_queue);
}
if (dev->ret_queue) {
vQueueDelete(dev->ret_queue);
}
spi_bus_lock_unregister_dev(dev->dev_lock);
}
free(dev);
@ -519,11 +529,17 @@ esp_err_t spi_bus_remove_device(spi_device_handle_t handle)
//return
int spics_io_num = handle->cfg.spics_io_num;
if (spics_io_num >= 0) spicommon_cs_free_io(spics_io_num);
if (spics_io_num >= 0) {
spicommon_cs_free_io(spics_io_num);
}
//Kill queues
if (handle->trans_queue) vQueueDelete(handle->trans_queue);
if (handle->ret_queue) vQueueDelete(handle->ret_queue);
if (handle->trans_queue) {
vQueueDelete(handle->trans_queue);
}
if (handle->ret_queue) {
vQueueDelete(handle->ret_queue);
}
spi_bus_lock_unregister_dev(handle->dev_lock);
assert(handle->host->device[handle->id] == handle);
@ -568,7 +584,9 @@ static SPI_MASTER_ISR_ATTR void spi_setup_device(spi_device_t *dev)
static SPI_MASTER_ISR_ATTR spi_device_t *get_acquiring_dev(spi_host_t *host)
{
spi_bus_lock_dev_handle_t dev_lock = spi_bus_lock_get_acquiring_dev(host->bus_attr->lock);
if (!dev_lock) return NULL;
if (!dev_lock) {
return NULL;
}
return host->device[spi_bus_lock_get_dev_id(dev_lock)];
}
@ -652,7 +670,9 @@ static void SPI_MASTER_ISR_ATTR spi_new_trans(spi_device_t *dev, spi_trans_priv_
spi_hal_prepare_data(hal, hal_dev, &hal_trans);
//Call pre-transmission callback, if any
if (dev->cfg.pre_cb) dev->cfg.pre_cb(trans);
if (dev->cfg.pre_cb) {
dev->cfg.pre_cb(trans);
}
//Kick off transfer
spi_hal_user_start(hal);
}
@ -666,7 +686,9 @@ static void SPI_MASTER_ISR_ATTR spi_post_trans(spi_host_t *host)
spi_hal_fetch_result(&host->hal);
//Call post-transaction callback, if any
spi_device_t* dev = host->device[host->cur_cs];
if (dev->cfg.post_cb) dev->cfg.post_cb(cur_trans);
if (dev->cfg.post_cb) {
dev->cfg.post_cb(cur_trans);
}
host->cur_cs = DEV_NUM_MAX;
}
@ -734,7 +756,6 @@ static void SPI_MASTER_ISR_ATTR spi_intr(void *arg)
spi_bus_lock_handle_t lock = host->bus_attr->lock;
BaseType_t trans_found = pdFALSE;
// There should be remaining requests
BUS_LOCK_DEBUG_EXECUTE_CHECK(spi_bus_lock_bg_req_exist(lock));
@ -781,7 +802,9 @@ static void SPI_MASTER_ISR_ATTR spi_intr(void *arg)
// or resume acquiring device task (if quit due to bus acquiring).
} while (!spi_bus_lock_bg_exit(lock, trans_found, &do_yield));
if (do_yield) portYIELD_FROM_ISR();
if (do_yield) {
portYIELD_FROM_ISR();
}
}
static SPI_MASTER_ISR_ATTR esp_err_t check_trans_valid(spi_device_handle_t handle, spi_transaction_t *trans_desc)
@ -936,7 +959,9 @@ clean_up:
esp_err_t SPI_MASTER_ATTR spi_device_queue_trans(spi_device_handle_t handle, spi_transaction_t *trans_desc, TickType_t ticks_to_wait)
{
esp_err_t ret = check_trans_valid(handle, trans_desc);
if (ret != ESP_OK) return ret;
if (ret != ESP_OK) {
return ret;
}
spi_host_t *host = handle->host;
@ -950,7 +975,9 @@ esp_err_t SPI_MASTER_ATTR spi_device_queue_trans(spi_device_handle_t handle, spi
spi_trans_priv_t trans_buf = { .trans = trans_desc, };
ret = setup_priv_desc(host, &trans_buf);
if (ret != ESP_OK) return ret;
if (ret != ESP_OK) {
return ret;
}
#ifdef CONFIG_PM_ENABLE
// though clock source is selectable, read/write reg and mem of spi peripherial still use APB
@ -1015,10 +1042,14 @@ esp_err_t SPI_MASTER_ATTR spi_device_transmit(spi_device_handle_t handle, spi_tr
spi_transaction_t *ret_trans;
//ToDo: check if any spi transfers in flight
ret = spi_device_queue_trans(handle, trans_desc, portMAX_DELAY);
if (ret != ESP_OK) return ret;
if (ret != ESP_OK) {
return ret;
}
ret = spi_device_get_trans_result(handle, &ret_trans, portMAX_DELAY);
if (ret != ESP_OK) return ret;
if (ret != ESP_OK) {
return ret;
}
assert(ret_trans == trans_desc);
return ESP_OK;
@ -1093,13 +1124,17 @@ esp_err_t SPI_MASTER_ISR_ATTR spi_device_polling_start(spi_device_handle_t handl
esp_err_t ret;
SPI_CHECK(ticks_to_wait == portMAX_DELAY, "currently timeout is not available for polling transactions", ESP_ERR_INVALID_ARG);
ret = check_trans_valid(handle, trans_desc);
if (ret!=ESP_OK) return ret;
if (ret != ESP_OK) {
return ret;
}
SPI_CHECK(!spi_bus_device_is_polling(handle), "Cannot send polling transaction while the previous polling transaction is not terminated.", ESP_ERR_INVALID_STATE);
spi_host_t *host = handle->host;
spi_trans_priv_t priv_polling_trans = { .trans = trans_desc, };
ret = setup_priv_desc(host, &priv_polling_trans);
if (ret!=ESP_OK) return ret;
if (ret != ESP_OK) {
return ret;
}
/* If device_acquiring_lock is set to handle, it means that the user has already
* acquired the bus thanks to the function `spi_device_acquire_bus()`.
@ -1182,7 +1217,9 @@ esp_err_t SPI_MASTER_ISR_ATTR spi_device_polling_transmit(spi_device_handle_t ha
{
esp_err_t ret;
ret = spi_device_polling_start(handle, trans_desc, portMAX_DELAY);
if (ret != ESP_OK) return ret;
if (ret != ESP_OK) {
return ret;
}
return spi_device_polling_end(handle, portMAX_DELAY);
}

View File

@ -36,7 +36,6 @@ static const char *SPI_TAG = "spi_slave";
#define SPI_CHECK(a, str, ret_val) ESP_RETURN_ON_FALSE(a, ret_val, SPI_TAG, str)
#ifdef CONFIG_SPI_SLAVE_ISR_IN_IRAM
#define SPI_SLAVE_ISR_ATTR IRAM_ATTR
#else
@ -181,7 +180,9 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b
//See how many dma descriptors we need and allocate them
int dma_desc_ct = (bus_config->max_transfer_sz + SPI_MAX_DMA_LEN - 1) / SPI_MAX_DMA_LEN;
if (dma_desc_ct == 0) dma_desc_ct = 1; //default to 4k when max is not given
if (dma_desc_ct == 0) {
dma_desc_ct = 1; //default to 4k when max is not given
}
spihost[host]->max_transfer_sz = dma_desc_ct * SPI_MAX_DMA_LEN;
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
size_t alignment;
@ -216,7 +217,9 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b
}
// The slave DMA suffers from unexpected transactions. Forbid reading if DMA is enabled by disabling the CS line.
if (spihost[host]->dma_enabled) freeze_cs(spihost[host]);
if (spihost[host]->dma_enabled) {
freeze_cs(spihost[host]);
}
#ifdef CONFIG_PM_ENABLE
err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "spi_slave",
@ -282,8 +285,12 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b
cleanup:
if (spihost[host]) {
if (spihost[host]->trans_queue) vQueueDelete(spihost[host]->trans_queue);
if (spihost[host]->ret_queue) vQueueDelete(spihost[host]->ret_queue);
if (spihost[host]->trans_queue) {
vQueueDelete(spihost[host]->trans_queue);
}
if (spihost[host]->ret_queue) {
vQueueDelete(spihost[host]->ret_queue);
}
#ifdef CONFIG_PM_ENABLE
if (spihost[host]->pm_lock) {
esp_pm_lock_release(spihost[host]->pm_lock);
@ -309,8 +316,12 @@ esp_err_t spi_slave_free(spi_host_device_t host)
{
SPI_CHECK(is_valid_host(host), "invalid host", ESP_ERR_INVALID_ARG);
SPI_CHECK(spihost[host], "host not slave", ESP_ERR_INVALID_ARG);
if (spihost[host]->trans_queue) vQueueDelete(spihost[host]->trans_queue);
if (spihost[host]->ret_queue) vQueueDelete(spihost[host]->ret_queue);
if (spihost[host]->trans_queue) {
vQueueDelete(spihost[host]->trans_queue);
}
if (spihost[host]->ret_queue) {
vQueueDelete(spihost[host]->ret_queue);
}
if (spihost[host]->dma_enabled) {
spicommon_dma_chan_free(host);
free(spihost[host]->hal.dmadesc_tx);
@ -406,7 +417,9 @@ esp_err_t SPI_SLAVE_ATTR spi_slave_queue_trans(spi_host_device_t host, const spi
SPI_CHECK(ESP_OK == spi_slave_setup_priv_trans(host, &priv_trans), "slave setup priv_trans failed", ESP_ERR_NO_MEM);
r = xQueueSend(spihost[host]->trans_queue, (void *)&priv_trans, ticks_to_wait);
if (!r) return ESP_ERR_TIMEOUT;
if (!r) {
return ESP_ERR_TIMEOUT;
}
esp_intr_enable(spihost[host]->intr);
return ESP_OK;
}
@ -512,23 +525,28 @@ esp_err_t SPI_SLAVE_ATTR spi_slave_get_trans_result(spi_host_device_t host, spi_
spi_slave_trans_priv_t priv_trans;
r = xQueueReceive(spihost[host]->ret_queue, (void *)&priv_trans, ticks_to_wait);
if (!r) return ESP_ERR_TIMEOUT;
if (!r) {
return ESP_ERR_TIMEOUT;
}
spi_slave_uninstall_priv_trans(host, &priv_trans);
*trans_desc = priv_trans.trans;
return ESP_OK;
}
esp_err_t SPI_SLAVE_ATTR spi_slave_transmit(spi_host_device_t host, spi_slave_transaction_t *trans_desc, TickType_t ticks_to_wait)
{
esp_err_t ret;
spi_slave_transaction_t *ret_trans;
//ToDo: check if any spi transfers in flight
ret = spi_slave_queue_trans(host, trans_desc, ticks_to_wait);
if (ret != ESP_OK) return ret;
if (ret != ESP_OK) {
return ret;
}
ret = spi_slave_get_trans_result(host, &ret_trans, ticks_to_wait);
if (ret != ESP_OK) return ret;
if (ret != ESP_OK) {
return ret;
}
assert(ret_trans == trans_desc);
return ESP_OK;
}
@ -556,7 +574,9 @@ static void SPI_SLAVE_ISR_ATTR spi_intr(void *arg)
bool use_dma = host->dma_enabled;
if (host->cur_trans.trans) {
// When DMA is enabled, the slave rx dma suffers from unexpected transactions. Forbid reading until transaction ready.
if (use_dma) freeze_cs(host);
if (use_dma) {
freeze_cs(host);
}
spi_slave_hal_store_result(hal);
host->cur_trans.trans->trans_len = spi_slave_hal_get_rcv_bitlen(hal);
@ -579,7 +599,9 @@ static void SPI_SLAVE_ISR_ATTR spi_intr(void *arg)
assert(ret == ESP_OK);
}
#endif
if (host->cfg.post_trans_cb) host->cfg.post_trans_cb(host->cur_trans.trans);
if (host->cfg.post_trans_cb) {
host->cfg.post_trans_cb(host->cur_trans.trans);
}
if (!(host->cfg.flags & SPI_SLAVE_NO_RETURN_RESULT)) {
xQueueSendFromISR(host->ret_queue, &host->cur_trans, &do_yield);
@ -595,7 +617,9 @@ static void SPI_SLAVE_ISR_ATTR spi_intr(void *arg)
if (spicommon_dmaworkaround_reset_in_progress()) {
//We need to wait for the reset to complete. Disable int (will be re-enabled on reset callback) and exit isr.
esp_intr_disable(host->intr);
if (do_yield) portYIELD_FROM_ISR();
if (do_yield) {
portYIELD_FROM_ISR();
}
return;
}
}
@ -637,7 +661,11 @@ static void SPI_SLAVE_ISR_ATTR spi_intr(void *arg)
//Kick off transfer
spi_slave_hal_user_start(hal);
if (host->cfg.post_setup_cb) host->cfg.post_setup_cb(priv_trans.trans);
if (host->cfg.post_setup_cb) {
host->cfg.post_setup_cb(priv_trans.trans);
}
}
if (do_yield) {
portYIELD_FROM_ISR();
}
if (do_yield) portYIELD_FROM_ISR();
}

View File

@ -234,10 +234,18 @@ esp_err_t spi_slave_hd_init(spi_host_device_t host_id, const spi_bus_config_t *b
//Init callbacks
memcpy((uint8_t *)&host->callback, (uint8_t *)&config->cb_config, sizeof(spi_slave_hd_callback_config_t));
spi_event_t event = 0;
if (host->callback.cb_buffer_tx != NULL) event |= SPI_EV_BUF_TX;
if (host->callback.cb_buffer_rx != NULL) event |= SPI_EV_BUF_RX;
if (host->callback.cb_cmd9 != NULL) event |= SPI_EV_CMD9;
if (host->callback.cb_cmdA != NULL) event |= SPI_EV_CMDA;
if (host->callback.cb_buffer_tx != NULL) {
event |= SPI_EV_BUF_TX;
}
if (host->callback.cb_buffer_rx != NULL) {
event |= SPI_EV_BUF_RX;
}
if (host->callback.cb_cmd9 != NULL) {
event |= SPI_EV_CMD9;
}
if (host->callback.cb_cmdA != NULL) {
event |= SPI_EV_CMDA;
}
spi_slave_hd_hal_enable_event_intr(&host->hal, event);
return ESP_OK;
@ -251,14 +259,28 @@ cleanup:
esp_err_t spi_slave_hd_deinit(spi_host_device_t host_id)
{
spi_slave_hd_slot_t *host = spihost[host_id];
if (host == NULL) return ESP_ERR_INVALID_ARG;
if (host == NULL) {
return ESP_ERR_INVALID_ARG;
}
if (host->tx_trans_queue) vQueueDelete(host->tx_trans_queue);
if (host->tx_ret_queue) vQueueDelete(host->tx_ret_queue);
if (host->rx_trans_queue) vQueueDelete(host->rx_trans_queue);
if (host->rx_ret_queue) vQueueDelete(host->rx_ret_queue);
if (host->tx_cnting_sem) vSemaphoreDelete(host->tx_cnting_sem);
if (host->rx_cnting_sem) vSemaphoreDelete(host->rx_cnting_sem);
if (host->tx_trans_queue) {
vQueueDelete(host->tx_trans_queue);
}
if (host->tx_ret_queue) {
vQueueDelete(host->tx_ret_queue);
}
if (host->rx_trans_queue) {
vQueueDelete(host->rx_trans_queue);
}
if (host->rx_ret_queue) {
vQueueDelete(host->rx_ret_queue);
}
if (host->tx_cnting_sem) {
vSemaphoreDelete(host->tx_cnting_sem);
}
if (host->rx_cnting_sem) {
vSemaphoreDelete(host->rx_cnting_sem);
}
esp_intr_free(host->intr);
esp_intr_free(host->intr_dma);
#ifdef CONFIG_PM_ENABLE
@ -418,7 +440,9 @@ static IRAM_ATTR void spi_slave_hd_intr_segment(void *arg)
}
portEXIT_CRITICAL_ISR(&host->int_spinlock);
if (awoken == pdTRUE) portYIELD_FROM_ISR();
if (awoken == pdTRUE) {
portYIELD_FROM_ISR();
}
}
static IRAM_ATTR void spi_slave_hd_append_tx_isr(void *arg)
@ -456,7 +480,9 @@ static IRAM_ATTR void spi_slave_hd_append_tx_isr(void *arg)
assert(ret == pdTRUE);
}
}
if (awoken==pdTRUE) portYIELD_FROM_ISR();
if (awoken == pdTRUE) {
portYIELD_FROM_ISR();
}
}
static IRAM_ATTR void spi_slave_hd_append_rx_isr(void *arg)
@ -467,7 +493,6 @@ static IRAM_ATTR void spi_slave_hd_append_rx_isr(void *arg)
BaseType_t awoken = pdFALSE;
BaseType_t ret __attribute__((unused));
spi_slave_hd_trans_priv_t ret_priv_trans;
size_t trans_len;
while (1) {
@ -502,7 +527,9 @@ static IRAM_ATTR void spi_slave_hd_append_rx_isr(void *arg)
assert(ret == pdTRUE);
}
}
if (awoken==pdTRUE) portYIELD_FROM_ISR();
if (awoken == pdTRUE) {
portYIELD_FROM_ISR();
}
}
#if SOC_GDMA_SUPPORTED

View File

@ -0,0 +1,26 @@
.spi_depends_default: &spi_depends_default
depends_components:
- esp_mm # for cache
- esp_driver_spi
- esp_driver_gpio
components/esp_driver_spi/test_apps/spi/master:
disable:
- if: SOC_GPSPI_SUPPORTED != 1
<<: *spi_depends_default
components/esp_driver_spi/test_apps/spi/param:
disable:
- if: SOC_GPSPI_SUPPORTED != 1
<<: *spi_depends_default
components/esp_driver_spi/test_apps/spi/slave:
disable:
- if: SOC_GPSPI_SUPPORTED != 1
<<: *spi_depends_default
components/esp_driver_spi/test_apps/spi/slave_hd:
disable:
- if: SOC_GPSPI_SUPPORTED != 1
- if: SOC_SPI_SUPPORT_SLAVE_HD_VER2 != 1
<<: *spi_depends_default

View File

@ -15,7 +15,7 @@ project(spi_master_test)
if(CONFIG_COMPILER_DUMP_RTL_FILES)
add_custom_target(check_test_app_sections ALL
COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py
--rtl-dirs ${CMAKE_BINARY_DIR}/esp-idf/driver/,${CMAKE_BINARY_DIR}/esp-idf/hal/
--rtl-dirs ${CMAKE_BINARY_DIR}/esp-idf/esp_driver_spi/,${CMAKE_BINARY_DIR}/esp-idf/hal/
--elf-file ${CMAKE_BINARY_DIR}/spi_master_test.elf
find-refs
--from-sections=.iram0.text

View File

@ -11,6 +11,6 @@ set(srcs
# the component can be registered as WHOLE_ARCHIVE
idf_component_register(
SRCS ${srcs}
PRIV_REQUIRES test_utils driver test_driver_utils spi_flash
PRIV_REQUIRES test_utils esp_driver_spi test_driver_utils spi_flash
WHOLE_ARCHIVE
)

View File

@ -13,7 +13,6 @@
#include "spi_flash_mmap.h"
#include "unity.h"
#if CONFIG_IDF_TARGET_ESP32
// The VSPI pins on UT_T1_ESP_FLASH are connected to a external flash
#define TEST_BUS_PIN_NUM_MISO VSPI_IOMUX_PIN_NUM_MISO
@ -269,7 +268,9 @@ static void test_bus_lock(bool test_flash)
for (;;) {
vTaskDelay(10);
if (context1.finished && context2.finished && context3.finished && context4.finished) break;
if (context1.finished && context2.finished && context3.finished && context4.finished) {
break;
}
}
TEST_ESP_OK(spi_bus_remove_device(context1.handle));
@ -289,7 +290,6 @@ TEST_CASE("spi bus lock, with flash","[spi][test_env=external_flash]")
}
#endif //CONFIG_IDF_TARGET_ESP32
TEST_CASE("spi bus lock", "[spi]")
{
test_bus_lock(false);

View File

@ -7,7 +7,6 @@
Tests for the spi_master device driver
*/
#include "sdkconfig.h"
#include "driver/spi_master.h"
#include "driver/spi_slave.h"
@ -24,7 +23,6 @@
#include "test_utils.h"
#include "test_spi_utils.h"
const static char TAG[] = "test_spi";
// There is no input-only pin except on esp32 and esp32s2
@ -75,8 +73,7 @@ static void check_spi_pre_n_for(spi_clock_source_t clock_source, int clk, int pr
* {freq, pre, n}
*/
#define TEST_CLK_TIMES 8
struct test_clk_param_group_t
{
struct test_clk_param_group_t {
uint32_t clk_param_80m[TEST_CLK_TIMES][3];
uint32_t clk_param_48m[TEST_CLK_TIMES][3];
uint32_t clk_param_40m[TEST_CLK_TIMES][3];
@ -92,7 +89,6 @@ struct test_clk_param_group_t
{{1, SOC_SPI_MAX_PRE_DIVIDER, 64}, {100000, 2, 35}, {333333, 1, 21}, {800000, 1, 9}, {900000, 1, 8}, {1100000, 1, 6}, {4000000, 1, 2,}, {7000000, 1, 1} },
};
TEST_CASE("SPI Master clockdiv calculation routines", "[spi]")
{
spi_bus_config_t buscfg = SPI_BUS_TEST_DEFAULT_CONFIG();
@ -317,7 +313,6 @@ TEST_CASE("SPI Master test", "[spi]")
TEST_ASSERT(success);
}
TEST_CASE("SPI Master test, interaction of multiple devs", "[spi]")
{
esp_err_t ret;
@ -355,7 +350,6 @@ TEST_CASE("SPI Master test, interaction of multiple devs", "[spi]")
printf("Sending to dev 2\n");
success &= spi_test(handle2, 5000);
ret = spi_bus_remove_device(handle2);
TEST_ASSERT(ret == ESP_OK);
master_free_device_bus(handle1);
@ -673,7 +667,6 @@ TEST_CASE("SPI Master no response when switch from host1 (SPI2) to host2 (SPI3)"
TEST_ESP_OK(spi_bus_free(host));
}
DRAM_ATTR static uint32_t data_dram[80] = {0};
//force to place in code area.
static const uint8_t data_drom[320 + 3] = {
@ -826,7 +819,6 @@ TEST_CASE("SPI Master DMA test: length, start, not aligned", "[spi]")
TEST_ASSERT(spi_bus_free(TEST_SPI_HOST) == ESP_OK);
}
#if (TEST_SPI_PERIPH_NUM >= 2)
//These will only be enabled on chips with 2 or more SPI peripherals
@ -1337,7 +1329,6 @@ static void fd_slave(void)
TEST_CASE_MULTIPLE_DEVICES("SPI Master: FD, DMA, Master Single Direction Test", "[spi_ms][test_env=generic_multi_device]", fd_master, fd_slave);
#endif //#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32) //TODO: IDF-3494
//NOTE: Explained in IDF-1445 | MR !14996
#if !(CONFIG_SPIRAM) || (CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL >= 16384)
/********************************************************************************
@ -1600,11 +1591,11 @@ void test_add_device_slave(void)
TEST_CASE_MULTIPLE_DEVICES("SPI_Master:Test multiple devices", "[spi_ms]", test_add_device_master, test_add_device_slave);
#if (SOC_CPU_CORES_NUM > 1) && (!CONFIG_FREERTOS_UNICORE)
#define TEST_ISR_CNT 100
static void test_master_isr_core_post_trans_cbk(spi_transaction_t *curr_trans){
static void test_master_isr_core_post_trans_cbk(spi_transaction_t *curr_trans)
{
*((int *)curr_trans->user) += esp_cpu_get_core_id();
}
@ -1640,7 +1631,6 @@ TEST_CASE("test_master_isr_pin_to_core","[spi]")
// by default the esp_intr_alloc is called on ESP_MAIN_TASK_AFFINITY_CPU0 now
TEST_ASSERT_EQUAL_UINT32(0, master_expect);
//-------------------------------------CPU1---------------------------------------
buscfg.isr_cpu_id = ESP_INTR_CPU_AFFINITY_1;

View File

@ -49,7 +49,6 @@ static void inner_connect(spi_bus_config_t bus)
//Slave MOSI(spid_in) input to `mosi_num`
spitest_gpio_input_sel(bus.mosi_io_num, FUNC_GPIO, spi_periph_signal[TEST_SLAVE_HOST].spid_in);
//Master MOSI input(spid_in) to `miso_num`, due to SIO mode, we use Master's `spid_in` to receive data
spitest_gpio_input_sel(bus.miso_io_num, FUNC_GPIO, spi_periph_signal[TEST_SPI_HOST].spid_in);
//Slave MISO output(spiq_out)
@ -76,11 +75,9 @@ TEST_CASE("SPI Single Board Test SIO", "[spi]")
spi_slave_interface_config_t slv_cfg = SPI_SLAVE_TEST_DEFAULT_CONFIG();
TEST_ESP_OK(spi_slave_initialize(TEST_SLAVE_HOST, &bus_cfg, &slv_cfg, SPI_DMA_DISABLED));
same_pin_func_sel(bus_cfg, dev_cfg, 0);
inner_connect(bus_cfg);
WORD_ALIGNED_ATTR uint8_t master_rx_buffer[320];
WORD_ALIGNED_ATTR uint8_t slave_rx_buffer[320];
@ -114,7 +111,6 @@ TEST_CASE("SPI Single Board Test SIO", "[spi]")
ESP_LOG_BUFFER_HEXDUMP("slave rx", slv_trans.rx_buffer, tlen, ESP_LOG_INFO);
TEST_ASSERT_EQUAL_HEX8_ARRAY(mst_trans.tx_buffer, slv_trans.rx_buffer, tlen);
ESP_LOGI("spi", "=========== TEST(%d) Master RX, Slave TX ==========", i);
//Slave TX
memset(&slv_trans, 0x0, sizeof(spi_slave_transaction_t));

View File

@ -378,7 +378,6 @@ static int test_freq_mode_local[] = {
#define SLAVE_EXTRA_DELAY_DMA 0
#endif
static spitest_param_set_t mode_pgroup[] = {
{
.pset_name = "Mode 0",
@ -1269,7 +1268,6 @@ TEST_SPI_MASTER_SLAVE(MODE, mode_conf, "")
#endif // #if (TEST_SPI_PERIPH_NUM >= 2)
#define TEST_STEP_LEN 96
#define TEST_STEP 2
static int s_spi_bus_freq[] = {
@ -1395,7 +1393,6 @@ static void test_slave_fd_dma(void)
TEST_CASE_MULTIPLE_DEVICES("TEST_SPI_Freq_FD_DMA", "[spi_ms][timeout=30]", test_master_fd_dma, test_slave_fd_dma);
//------------------------------------------- Full Duplex no DMA Freq test --------------------------------------
static void test_master_fd_no_dma(void)
{
@ -1511,7 +1508,6 @@ static void test_slave_fd_no_dma(void)
TEST_CASE_MULTIPLE_DEVICES("TEST_SPI_Freq_FD_no_DMA", "[spi_ms][timeout=30]", test_master_fd_no_dma, test_slave_fd_no_dma);
#if SOC_SPI_SUPPORT_SLAVE_HD_VER2
//------------------------------------------- Half Duplex with DMA Freq test --------------------------------------
static void test_master_hd_dma(void)
@ -1614,7 +1610,6 @@ static void test_slave_hd_dma(void)
TEST_CASE_MULTIPLE_DEVICES("TEST_SPI_Freq_HD_DMA", "[spi_ms][timeout=30]", test_master_hd_dma, test_slave_hd_dma);
//------------------------------------------- Half Duplex no DMA Freq test --------------------------------------
static void test_master_hd_no_dma(void)
{
@ -1717,7 +1712,6 @@ static void test_slave_hd_no_dma(void)
TEST_CASE_MULTIPLE_DEVICES("TEST_SPI_Freq_HD_no_DMA", "[spi_ms][timeout=30]", test_master_hd_no_dma, test_slave_hd_no_dma);
#endif // SOC_SPI_SUPPORT_SLAVE_HD_VER2
#if CONFIG_IDF_TARGET_ESP32
// item num should same as `s_spi_bus_freq`
static int s_master_input_delay[] = {12.5, 12.5 * 2, 12.5 * 2, 12.5 * 5, 12.5 * 5};
@ -1853,7 +1847,6 @@ static void test_slave_sio_dma(void)
TEST_CASE_MULTIPLE_DEVICES("TEST_SPI_Freq_SIO_DMA", "[spi_ms][timeout=30]", test_master_sio_dma, test_slave_sio_dma);
//------------------------------------------- SIO no DMA Freq test --------------------------------------
static void test_master_sio_no_dma(void)
{

View File

@ -15,7 +15,7 @@ project(spi_slave_test)
if(CONFIG_COMPILER_DUMP_RTL_FILES)
add_custom_target(check_test_app_sections ALL
COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py
--rtl-dirs ${CMAKE_BINARY_DIR}/esp-idf/driver/,${CMAKE_BINARY_DIR}/esp-idf/hal/
--rtl-dirs ${CMAKE_BINARY_DIR}/esp-idf/esp_driver_spi/,${CMAKE_BINARY_DIR}/esp-idf/hal/
--elf-file ${CMAKE_BINARY_DIR}/spi_slave_test.elf
find-refs
--from-sections=.iram0.text

View File

@ -211,14 +211,19 @@ static void test_hd_start(spi_device_handle_t *spi, int freq, const spitest_para
check_no_rx(ctx);
check_no_tx(ctx);
srand(9322);
for (int i = 0; i < TEST_DMA_MAX_SIZE; i++) ctx->slave_rddma_buf[i] = rand();
for (int i = 0; i < TEST_DMA_MAX_SIZE; i++) ctx->master_wrdma_buf[i] = rand();
for (int i = 0; i < TEST_DMA_MAX_SIZE; i++) {
ctx->slave_rddma_buf[i] = rand();
}
for (int i = 0; i < TEST_DMA_MAX_SIZE; i++) {
ctx->master_wrdma_buf[i] = rand();
}
int pos = rand() % TEST_DMA_MAX_SIZE;
int len = rand() % TEST_DMA_MAX_SIZE + 1;
if (pos + len > TEST_DMA_MAX_SIZE) len = TEST_DMA_MAX_SIZE - pos;
if (pos + len > TEST_DMA_MAX_SIZE) {
len = TEST_DMA_MAX_SIZE - pos;
}
ESP_LOGI("rddma_load_len", "%d", len);
ctx->tx_data = (spi_slave_hd_data_t) {
@ -238,7 +243,6 @@ static void test_hd_start(spi_device_handle_t *spi, int freq, const spitest_para
TEST_ESP_OK(err);
}
#define REG_REGION_SIZE SOC_SPI_MAXIMUM_BUFFER_SIZE
void check_no_signal(testhd_context_t* context)
@ -254,7 +258,9 @@ void test_wrdma(testhd_context_t* ctx, const spitest_param_set_t *cfg, spi_devic
{
int pos = rand() % TEST_DMA_MAX_SIZE;
int len = rand() % TEST_DMA_MAX_SIZE + 1;
if (pos+len > TEST_DMA_MAX_SIZE) len = TEST_DMA_MAX_SIZE - pos;
if (pos + len > TEST_DMA_MAX_SIZE) {
len = TEST_DMA_MAX_SIZE - pos;
}
int test_seg_size = len;//TEST_SEG_SIZE;
ESP_LOGW("test_wrdma", "len: %d, seg_size: %d", len, test_seg_size);
@ -283,7 +289,6 @@ void test_rddma(testhd_context_t* ctx, const spitest_param_set_t* cfg, spi_devic
int len;
int test_seg_size;
len = ctx->tx_data.len;
test_seg_size = TEST_SEG_SIZE;
@ -300,7 +305,9 @@ void test_rddma(testhd_context_t* ctx, const spitest_param_set_t* cfg, spi_devic
int pos = rand() % TEST_DMA_MAX_SIZE;
len = rand() % TEST_DMA_MAX_SIZE + 1;
if (pos + len > TEST_DMA_MAX_SIZE) len = TEST_DMA_MAX_SIZE - pos;
if (pos + len > TEST_DMA_MAX_SIZE) {
len = TEST_DMA_MAX_SIZE - pos;
}
ctx->tx_data = (spi_slave_hd_data_t) {
.data = &ctx->slave_rddma_buf[pos],
@ -321,8 +328,12 @@ static void test_hd_loop(const void* arg1, void* arg2)
for (int j = 0; ; j++) {
spi_device_handle_t spi;
const int freq = timing_speed_array[j];
if (freq==0) break;
if (test_cfg->freq_limit && freq > test_cfg->freq_limit) break;
if (freq == 0) {
break;
}
if (test_cfg->freq_limit && freq > test_cfg->freq_limit) {
break;
}
ESP_LOGI(MASTER_TAG, "======> %dk", freq / 1000);
@ -353,7 +364,9 @@ static void test_hd_loop(const void* arg1, void* arg2)
for (int i = 0; i < 128; i ++) {
int pos = rand() % REG_REGION_SIZE;
int len = rand() % REG_REGION_SIZE + 1;
if (len+pos>REG_REGION_SIZE) len = REG_REGION_SIZE-pos;
if (len + pos > REG_REGION_SIZE) {
len = REG_REGION_SIZE - pos;
}
memset(recv_buffer, 0xcc, sizeof(recv_buffer));
@ -395,7 +408,9 @@ static void test_hd_loop(const void* arg1, void* arg2)
for (int k = 0; k < 2; k++) {
int pos = rand() % REG_REGION_SIZE;
int len = rand() % REG_REGION_SIZE + 1;
if (len + pos > REG_REGION_SIZE) len = REG_REGION_SIZE - pos;
if (len + pos > REG_REGION_SIZE) {
len = REG_REGION_SIZE - pos;
}
printf("pos: %d, len: %d\n", pos, len);
@ -454,7 +469,8 @@ static int test_freq_hd[] = {
#define TEST_HD_IN_CONTINUOUS_MODE true
static spitest_param_set_t hd_conf[] = {
{ .pset_name = "MODE0",
{
.pset_name = "MODE0",
.freq_list = test_freq_hd,
.dup = FULL_DUPLEX,
.master_iomux = false,
@ -462,7 +478,8 @@ static spitest_param_set_t hd_conf[] = {
.slave_tv_ns = TV_WITH_ESP_SLAVE,
.mode = 0,
},
{ .pset_name = "MODE1",
{
.pset_name = "MODE1",
.freq_list = test_freq_hd,
.dup = FULL_DUPLEX,
.master_iomux = false,
@ -470,7 +487,8 @@ static spitest_param_set_t hd_conf[] = {
.slave_tv_ns = TV_WITH_ESP_SLAVE,
.mode = 1,
},
{ .pset_name = "MODE2",
{
.pset_name = "MODE2",
.freq_list = test_freq_hd,
.dup = FULL_DUPLEX,
.master_iomux = false,
@ -478,7 +496,8 @@ static spitest_param_set_t hd_conf[] = {
.slave_tv_ns = TV_WITH_ESP_SLAVE,
.mode = 2,
},
{ .pset_name = "MODE3",
{
.pset_name = "MODE3",
.freq_list = test_freq_hd,
.dup = FULL_DUPLEX,
.master_iomux = false,
@ -642,7 +661,6 @@ static void hd_master(void)
unity_wait_for_signal("slave ready");
essl_spi_wrdma(spi, master_send_buf + send_buf_size, send_buf_size, 5, 0);
unity_wait_for_signal("slave ready");
essl_spi_rddma(spi, master_recv_buf, send_buf_size, -1, 0);
spitest_cmp_or_dump(slave_send_buf, master_recv_buf, trans_len[0]);
@ -651,7 +669,6 @@ static void hd_master(void)
essl_spi_rddma(spi, master_recv_buf + send_buf_size, send_buf_size, 5, 0);
spitest_cmp_or_dump(slave_send_buf + send_buf_size, master_recv_buf + send_buf_size, trans_len[1]);
free(master_recv_buf);
free(master_send_buf);
free(slave_send_buf);
@ -750,7 +767,8 @@ TEST_CASE_MULTIPLE_DEVICES("SPI Slave HD: segment mode, master sends too long",
#define BUF_SIZE 256
static void hd_master_quad(void){
static void hd_master_quad(void)
{
spi_bus_config_t bus_cfg = {
.miso_io_num = PIN_NUM_MISO,
.mosi_io_num = PIN_NUM_MOSI,
@ -802,7 +820,8 @@ static void hd_master_quad(void){
master_free_device_bus(spi);
}
static void hd_slave_quad(void){
static void hd_slave_quad(void)
{
spi_bus_config_t bus_cfg = {
.miso_io_num = PIN_NUM_MISO,
@ -887,13 +906,12 @@ TEST_CASE_MULTIPLE_DEVICES("SPI quad hd test ", "[spi_ms][test_env=generic_multi
#endif // #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2)
//***************************************TEST FOR APPEND MODE******************************************//
#define TEST_APPEND_CACHE_SIZE 4
#define TEST_TRANS_LEN TEST_DMA_MAX_SIZE
void prepare_data(uint8_t *buff, uint32_t len, int8_t diff){
void prepare_data(uint8_t *buff, uint32_t len, int8_t diff)
{
buff[0] = random();
for (int line_index = 1; line_index < len; line_index ++) {
buff[line_index] = buff[0] + line_index * diff;
@ -989,7 +1007,9 @@ void slave_run_append(void)
}
}
printf("================Master Rx Done==================\n");
for (int i = 0; i < TEST_APPEND_CACHE_SIZE; i++) free(slave_tx_trans[i].data);
for (int i = 0; i < TEST_APPEND_CACHE_SIZE; i++) {
free(slave_tx_trans[i].data);
}
spi_slave_hd_deinit(TEST_SPI_HOST);
}

View File

@ -27,5 +27,5 @@ endif()
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${includes}
PRIV_REQUIRES ${priv_requires}
REQUIRES driver esp_driver_gpio
REQUIRES driver esp_driver_gpio esp_driver_spi
LDFRAGMENTS linker.lf)

View File

@ -41,7 +41,6 @@ components/esp_lcd/test_apps/rgb_lcd:
components/esp_lcd/test_apps/spi_lcd:
depends_components:
- esp_lcd
depends_filepatterns:
- components/driver/spi/**/*
- esp_driver_spi
disable:
- if: SOC_GPSPI_SUPPORTED != 1

View File

@ -49,7 +49,7 @@ else()
list(APPEND srcs ${cache_srcs})
set(priv_requires bootloader_support app_update soc esp_mm
driver esp_driver_gpio # TODO: IDF-8503 move spi_bus_lock to esp_hw_support component
esp_driver_gpio esp_driver_spi # TODO: IDF-8503 move spi_bus_lock to esp_hw_support component
)
endif()

View File

@ -6,13 +6,13 @@ components/spi_flash/test_apps/esp_flash:
temporary: true
reason: target esp32p4 is not supported yet # TODO: IDF-7499
depends_filepatterns:
- components/driver/spi/**/*
- components/bootloader_support/bootloader_flash/**/*
depends_components:
- esp_mm
- esp_psram
- spi_flash
- esp_driver_gpio
- esp_driver_spi
- esptool_py # Some flash related kconfigs are listed here.
components/spi_flash/test_apps/flash_encryption:
@ -53,11 +53,11 @@ components/spi_flash/test_apps/mspi_test:
temporary: true
reason: not supported yet #TODO: IDF-7556 for p4
depends_filepatterns:
- components/driver/spi/**/*
- components/bootloader_support/bootloader_flash/**/*
depends_components:
- esp_mm
- esp_psram
- spi_flash
- esp_driver_gpio
- esp_driver_spi
- esptool_py # Some flash related kconfigs are listed here.

View File

@ -110,11 +110,11 @@ INPUT = \
$(PROJECT_PATH)/components/driver/sdmmc/include/driver/sdmmc_default_configs.h \
$(PROJECT_PATH)/components/driver/sdmmc/include/driver/sdmmc_host.h \
$(PROJECT_PATH)/components/driver/sdmmc/include/driver/sdmmc_types.h \
$(PROJECT_PATH)/components/driver/spi/include/driver/sdspi_host.h \
$(PROJECT_PATH)/components/driver/spi/include/driver/spi_common.h \
$(PROJECT_PATH)/components/driver/spi/include/driver/spi_master.h \
$(PROJECT_PATH)/components/driver/spi/include/driver/spi_slave_hd.h \
$(PROJECT_PATH)/components/driver/spi/include/driver/spi_slave.h \
$(PROJECT_PATH)/components/driver/sdspi/include/driver/sdspi_host.h \
$(PROJECT_PATH)/components/esp_driver_spi/include/driver/spi_common.h \
$(PROJECT_PATH)/components/esp_driver_spi/include/driver/spi_master.h \
$(PROJECT_PATH)/components/esp_driver_spi/include/driver/spi_slave_hd.h \
$(PROJECT_PATH)/components/esp_driver_spi/include/driver/spi_slave.h \
$(PROJECT_PATH)/components/driver/temperature_sensor/include/driver/temperature_sensor.h \
$(PROJECT_PATH)/components/driver/touch_sensor/include/driver/touch_sensor_common.h \
$(PROJECT_PATH)/components/driver/twai/include/driver/twai.h \

View File

@ -8,7 +8,7 @@ Overview
The SD/SDIO/MMC driver currently supports SD memory, SDIO cards, and eMMC chips. This is a protocol level driver built on top of SDMMC and SD SPI host drivers.
SDMMC and SD SPI host drivers (:component_file:`driver/sdmmc/include/driver/sdmmc_host.h` and :component_file:`driver/spi/include/driver/sdspi_host.h`) provide API functions for:
SDMMC and SD SPI host drivers (:component_file:`driver/sdmmc/include/driver/sdmmc_host.h` and :component_file:`driver/sdspi/include/driver/sdspi_host.h`) provide API functions for:
- Sending commands to slave devices
- Sending and receiving data

View File

@ -8,6 +8,7 @@ In order to control the dependence of other components on drivers at a smaller g
- `esp_driver_gptimer` - Driver for general purpose timers
- `esp_driver_pcnt` - Driver for pulse counter
- `esp_driver_gpio` - Driver for GPIO
- `esp_driver_spi` - Driver for GPSPI
For compatibility, the original `driver`` component is still treated as an all-in-one component by registering these `esp_driver_xyz`` components as its public dependencies. In other words, you do not need to modify the CMake file of an existing project, but you now have a way to specify the specific peripheral driver that your project depends on.

View File

@ -8,7 +8,7 @@ SD/SDIO/MMC 驱动程序
SD/SDIO/MMC 驱动是一种基于 SDMMC 和 SD SPI 主机驱动的协议级驱动程序,目前已支持 SD 存储器、SDIO 卡和 eMMC 芯片。
SDMMC 主机驱动和 SD SPI 主机驱动(:component_file:`driver/sdmmc/include/driver/sdmmc_host.h` 和 :component_file:`driver/spi/include/driver/sdspi_host.h`)为以下功能提供 API
SDMMC 主机驱动和 SD SPI 主机驱动(:component_file:`driver/sdmmc/include/driver/sdmmc_host.h` 和 :component_file:`driver/sdspi/include/driver/sdspi_host.h`)为以下功能提供 API
- 发送命令至从设备
- 接收和发送数据

View File

@ -8,6 +8,7 @@
- `esp_driver_gptimer` - 通用定时器驱动
- `esp_driver_pcnt` - 脉冲计数器驱动
- `esp_driver_gpio` - GPIO 驱动
- `esp_driver_spi` - 通用 SPI 驱动
为了兼容性,原来的 `driver` 组件仍然存在,并作为一个 “all-in-one" 的组件,将以上这些 `esp_driver_xyz` 组件注册成自己的公共依赖。换句话说,你无需修改既有项目的 CMake 文件,但是你现在多了一个途径去指定你项目依赖的具体的外设驱动。

View File

@ -9,8 +9,7 @@ examples/ethernet/basic:
- lwip
- esp_event
- esp_driver_gpio
depends_filepatterns:
- components/driver/spi/**/*
- esp_driver_spi
examples/ethernet/enc28j60:
disable:
@ -23,8 +22,7 @@ examples/ethernet/enc28j60:
- lwip
- esp_event
- esp_driver_gpio
depends_filepatterns:
- components/driver/spi/**/*
- esp_driver_spi
examples/ethernet/iperf:
disable_test:
@ -38,8 +36,8 @@ examples/ethernet/iperf:
- esp_event
- console
- esp_driver_gpio
- esp_driver_spi
depends_filepatterns:
- components/driver/spi/**/*
- examples/common_components/iperf/**/*
- examples/common_components/protocol_examples_common/**/*
- examples/system/console/advanced/components/cmd_system/**/*

View File

@ -4,8 +4,8 @@ examples/network/bridge:
disable_test:
- if: IDF_TARGET != "esp32"
reason: Generic functionality, no need to be run on specific targets
depends_filepatterns:
- components/driver/spi/**/*
depends_components:
- esp_driver_spi
examples/network/eth2ap:
disable:

View File

@ -131,16 +131,14 @@ examples/peripherals/lcd/spi_lcd_touch:
- if: SOC_GPSPI_SUPPORTED != 1
depends_components:
- esp_lcd
depends_filepatterns:
- components/driver/spi/**/*
- esp_driver_spi
examples/peripherals/lcd/tjpgd:
disable:
- if: SOC_GPSPI_SUPPORTED != 1
depends_components:
- esp_lcd
depends_filepatterns:
- components/driver/spi/**/*
- esp_driver_spi
examples/peripherals/ledc:
disable:

View File

@ -7,12 +7,12 @@ idf_component_get_property(original_driver_dir driver COMPONENT_OVERRIDEN_DIR)
set(include_dirs
"${IDF_PATH}/components/esp_driver_gpio/include/driver"
"${IDF_PATH}/components/esp_driver_gpio/include"
"${IDF_PATH}/components/esp_driver_spi/include/driver"
"${IDF_PATH}/components/esp_driver_spi/include"
"${original_driver_dir}/i2c/include/driver"
"${original_driver_dir}/spi/include/driver"
"${original_driver_dir}/rmt/include/driver"
"${original_driver_dir}/usb_serial_jtag/include/driver"
"${original_driver_dir}/i2c/include"
"${original_driver_dir}/spi/include"
"${original_driver_dir}/rmt/include"
"${original_driver_dir}/usb_serial_jtag/include"
"${CMAKE_CURRENT_SOURCE_DIR}/../hal/include")
@ -21,8 +21,8 @@ idf_component_mock(INCLUDE_DIRS ${include_dirs}
REQUIRES freertos
MOCK_HEADER_FILES
${IDF_PATH}/components/esp_driver_gpio/include/driver/gpio.h
${original_driver_dir}/spi/include/driver/spi_master.h
${original_driver_dir}/spi/include/driver/spi_common.h
${IDF_PATH}/components/esp_driver_spi/include/driver/spi_master.h
${IDF_PATH}/components/esp_driver_spi/include/driver/spi_common.h
${original_driver_dir}/i2c/include/driver/i2c.h
${original_driver_dir}/rmt/include/driver/rmt_rx.h
${original_driver_dir}/rmt/include/driver/rmt_tx.h

View File

@ -35,7 +35,7 @@ set(extra_components_which_shouldnt_be_included
cxx
# [refactor-todo]: driver is a dependency of esp_pm, spi_flash, vfs, esp_wifi
# all of these should be removed from G1 except for spi_flash.
driver esp_driver_gpio esp_driver_pcnt esp_driver_gptimer
driver esp_driver_gpio esp_driver_pcnt esp_driver_gptimer esp_driver_spi
# esp_app_format is dependency of bootloader_support, app_update
esp_app_format
# esp_bootloader_format is dependency of bootloader_support, app_update