refactor(spi): make spi driver as component

This commit is contained in:
Armando
2023-10-19 14:38:32 +08:00
parent c8c7f999ef
commit fca46eac52
80 changed files with 637 additions and 601 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,13 +66,12 @@ 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);
uint8_t *data, uint32_t rx_length, bool need_stop_command);
static esp_err_t start_command_write_blocks(slot_info_t *slot, sdspi_hw_cmd_t *cmd,
const uint8_t *data, uint32_t tx_length, bool multi_block, bool stop_trans);
const uint8_t *data, uint32_t tx_length, bool multi_block, bool stop_trans);
static esp_err_t start_command_default(slot_info_t *slot, int flags, sdspi_hw_cmd_t *cmd);
@@ -189,7 +187,7 @@ static void go_idle_clockout(slot_info_t *slot)
uint8_t data[12];
memset(data, 0xff, sizeof(data));
spi_transaction_t t = {
.length = 10*8,
.length = 10 * 8,
.tx_buffer = data,
.rx_buffer = data,
};
@@ -276,17 +274,19 @@ esp_err_t sdspi_host_remove_device(sdspi_dev_handle_t handle)
return ESP_ERR_INVALID_ARG;
}
deinit_slot(slot);
deinit_slot(slot);
return ESP_OK;
}
//only the slots locally stored can be deinit in this function.
esp_err_t sdspi_host_deinit(void)
{
for (size_t i = 0; i < sizeof(s_slots)/sizeof(s_slots[0]); ++i) {
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);
}
@@ -514,8 +514,8 @@ static esp_err_t start_command_default(slot_info_t *slot, int flags, sdspi_hw_cm
{
size_t cmd_size = SDSPI_CMD_R1_SIZE;
if ((flags & SDSPI_CMD_FLAG_RSP_R1) ||
(flags & SDSPI_CMD_FLAG_NORSP) ||
(flags & SDSPI_CMD_FLAG_RSP_R1B )) {
(flags & SDSPI_CMD_FLAG_NORSP) ||
(flags & SDSPI_CMD_FLAG_RSP_R1B)) {
cmd_size = SDSPI_CMD_R1_SIZE;
} else if (flags & SDSPI_CMD_FLAG_RSP_R2) {
cmd_size = SDSPI_CMD_R2_SIZE;
@@ -529,7 +529,7 @@ static esp_err_t start_command_default(slot_info_t *slot, int flags, sdspi_hw_cm
cmd_size = SDSPI_CMD_R7_SIZE;
}
//add extra clocks to avoid polling
cmd_size += (SDSPI_NCR_MAX_SIZE-SDSPI_NCR_MIN_SIZE);
cmd_size += (SDSPI_NCR_MAX_SIZE - SDSPI_NCR_MIN_SIZE);
spi_transaction_t t = {
.flags = 0,
.length = cmd_size * 8,
@@ -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);
@@ -594,7 +596,7 @@ static esp_err_t poll_busy(slot_info_t *slot, int timeout_ms, bool polling)
return ESP_OK;
}
}
} while(esp_timer_get_time() < t_end);
} while (esp_timer_get_time() < t_end);
ESP_LOGD(TAG, "%s: timeout", __func__);
return ESP_ERR_TIMEOUT;
}
@@ -629,7 +631,7 @@ static esp_err_t poll_data_token(slot_info_t *slot, uint8_t *extra_ptr, size_t *
}
if (rd_data != 0xff && rd_data != 0) {
ESP_LOGD(TAG, "%s: received 0x%02x while waiting for data",
__func__, rd_data);
__func__, rd_data);
return ESP_ERR_INVALID_RESPONSE;
}
}
@@ -648,10 +650,14 @@ 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;
while (true) {
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)
@@ -705,7 +710,7 @@ static esp_err_t shift_cmd_response(sdspi_hw_cmd_t* cmd, int sent_bytes)
* expense of one extra temporary buffer.
*/
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)
uint8_t *data, uint32_t rx_length, bool need_stop_command)
{
spi_transaction_t t_command = {
.length = (SDSPI_CMD_R1_SIZE + SDSPI_RESPONSE_MAX_DELAY) * 8,
@@ -838,7 +843,7 @@ static esp_err_t start_command_read_blocks(slot_info_t *slot, sdspi_hw_cmd_t *cm
* It's also different that stop transmission token is not needed in the SDIO mode.
*/
static esp_err_t start_command_write_blocks(slot_info_t *slot, sdspi_hw_cmd_t *cmd,
const uint8_t *data, uint32_t tx_length, bool multi_block, bool stop_trans)
const uint8_t *data, uint32_t tx_length, bool multi_block, bool stop_trans)
{
if (card_write_protected(slot)) {
ESP_LOGW(TAG, "%s: card write protected", __func__);
@@ -846,7 +851,7 @@ static esp_err_t start_command_write_blocks(slot_info_t *slot, sdspi_hw_cmd_t *c
}
// Send the minimum length that is sure to get the complete response
// SD cards always return R1 (1bytes), SDIO returns R5 (2 bytes)
const int send_bytes = SDSPI_CMD_R5_SIZE+SDSPI_NCR_MAX_SIZE-SDSPI_NCR_MIN_SIZE;
const int send_bytes = SDSPI_CMD_R5_SIZE + SDSPI_NCR_MAX_SIZE - SDSPI_NCR_MIN_SIZE;
spi_transaction_t t_command = {
.length = send_bytes * 8,
@@ -866,7 +871,7 @@ static esp_err_t start_command_write_blocks(slot_info_t *slot, sdspi_hw_cmd_t *c
}
uint8_t start_token = multi_block ?
TOKEN_BLOCK_START_WRITE_MULTI : TOKEN_BLOCK_START;
TOKEN_BLOCK_START_WRITE_MULTI : TOKEN_BLOCK_START;
while (tx_length > 0) {
// Write block start token
@@ -909,7 +914,7 @@ static esp_err_t start_command_write_blocks(slot_info_t *slot, sdspi_hw_cmd_t *c
spi_transaction_t t_crc_rsp = {
.length = size_crc_response * 8,
.flags = SPI_TRANS_USE_TXDATA|SPI_TRANS_USE_RXDATA,
.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA,
};
memset(t_crc_rsp.tx_data, 0xff, 4);
memcpy(t_crc_rsp.tx_data, &crc, sizeof(crc));
@@ -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

@@ -22,7 +22,7 @@ static bool s_app_cmd;
static uint8_t sdspi_msg_crc7(sdspi_hw_cmd_t* hw_cmd)
{
const size_t bytes_to_crc = offsetof(sdspi_hw_cmd_t, arguments) +
sizeof(hw_cmd->arguments); /* can't take address of bit fields */
sizeof(hw_cmd->arguments); /* can't take address of bit fields */
return sdspi_crc7((const uint8_t *)hw_cmd, bytes_to_crc);
}
@@ -128,7 +128,7 @@ esp_err_t sdspi_host_do_transaction(int slot, sdmmc_command_t *cmdinfo)
} else if (s_app_cmd && cmdinfo->opcode == SD_APP_SD_STATUS) {
flags |= SDSPI_CMD_FLAG_RSP_R2;
} else if (!s_app_cmd && cmdinfo->opcode == MMC_GO_IDLE_STATE &&
!(cmdinfo->flags & SCF_RSP_R1)) {
!(cmdinfo->flags & SCF_RSP_R1)) {
/* used to send CMD0 without expecting a response */
flags |= SDSPI_CMD_FLAG_NORSP;
} else if (!s_app_cmd && cmdinfo->opcode == SD_IO_SEND_OP_COND) {
@@ -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 {
@@ -148,7 +152,7 @@ esp_err_t sdspi_host_do_transaction(int slot, sdmmc_command_t *cmdinfo)
// Send the command and get the response.
esp_err_t ret = sdspi_host_start_command(slot, &hw_cmd,
cmdinfo->data, cmdinfo->datalen, flags);
cmdinfo->data, cmdinfo->datalen, flags);
// Extract response bytes and store them into cmdinfo structure
if (ret == ESP_OK) {

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

@@ -69,12 +69,12 @@ extern "C"
* @brief SPI DMA channels
*/
typedef enum {
SPI_DMA_DISABLED = 0, ///< Do not enable DMA for SPI
SPI_DMA_DISABLED = 0, ///< Do not enable DMA for SPI
#if CONFIG_IDF_TARGET_ESP32
SPI_DMA_CH1 = 1, ///< Enable DMA, select DMA Channel 1
SPI_DMA_CH2 = 2, ///< Enable DMA, select DMA Channel 2
SPI_DMA_CH1 = 1, ///< Enable DMA, select DMA Channel 1
SPI_DMA_CH2 = 2, ///< Enable DMA, select DMA Channel 2
#endif
SPI_DMA_CH_AUTO = 3, ///< Enable DMA, channel is automatically selected by driver
SPI_DMA_CH_AUTO = 3, ///< Enable DMA, channel is automatically selected by driver
} spi_common_dma_t;
#if __cplusplus
@@ -95,21 +95,21 @@ typedef spi_common_dma_t spi_dma_chan_t;
*/
typedef struct {
union {
int mosi_io_num; ///< GPIO pin for Master Out Slave In (=spi_d) signal, or -1 if not used.
int data0_io_num; ///< GPIO pin for spi data0 signal in quad/octal mode, or -1 if not used.
int mosi_io_num; ///< GPIO pin for Master Out Slave In (=spi_d) signal, or -1 if not used.
int data0_io_num; ///< GPIO pin for spi data0 signal in quad/octal mode, or -1 if not used.
};
union {
int miso_io_num; ///< GPIO pin for Master In Slave Out (=spi_q) signal, or -1 if not used.
int data1_io_num; ///< GPIO pin for spi data1 signal in quad/octal mode, or -1 if not used.
int miso_io_num; ///< GPIO pin for Master In Slave Out (=spi_q) signal, or -1 if not used.
int data1_io_num; ///< GPIO pin for spi data1 signal in quad/octal mode, or -1 if not used.
};
int sclk_io_num; ///< GPIO pin for SPI Clock signal, or -1 if not used.
union {
int quadwp_io_num; ///< GPIO pin for WP (Write Protect) signal, or -1 if not used.
int data2_io_num; ///< GPIO pin for spi data2 signal in quad/octal mode, or -1 if not used.
int quadwp_io_num; ///< GPIO pin for WP (Write Protect) signal, or -1 if not used.
int data2_io_num; ///< GPIO pin for spi data2 signal in quad/octal mode, or -1 if not used.
};
union {
int quadhd_io_num; ///< GPIO pin for HD (Hold) signal, or -1 if not used.
int data3_io_num; ///< GPIO pin for spi data3 signal in quad/octal mode, or -1 if not used.
int quadhd_io_num; ///< GPIO pin for HD (Hold) signal, or -1 if not used.
int data3_io_num; ///< GPIO pin for spi data3 signal in quad/octal mode, or -1 if not used.
};
int data4_io_num; ///< GPIO pin for spi data4 signal in octal mode, or -1 if not used.
int data5_io_num; ///< GPIO pin for spi data5 signal in octal mode, or -1 if not used.
@@ -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
@@ -123,7 +120,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 +144,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 +166,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 +185,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
@@ -333,7 +331,7 @@ SPI_MASTER_ATTR static inline void req_core(spi_bus_lock_dev_t *dev_handle)
// Though `acquired_dev` is critical resource, `dev_handle == lock->acquired_dev`
// is a stable statement unless `acquire_start` or `acquire_end` is called by current
// device.
if (dev_handle == lock->acquiring_dev){
if (dev_handle == lock->acquiring_dev) {
// Set the REQ bit and check BG bits if we are the acquiring processor.
// If the BG bits were not active before, invoke the BG again.
@@ -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;
}
@@ -607,7 +607,7 @@ static int try_acquire_free_dev(spi_bus_lock_t *lock, bool cs_required)
break;
}
}
return ((i == lock->periph_cs_num)? -1: i);
return ((i == lock->periph_cs_num) ? -1 : i);
} else {
int i;
for (i = DEV_NUM_MAX - 1; i >= 0; i--) {
@@ -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) {
@@ -683,7 +689,7 @@ void spi_bus_lock_set_bg_control(spi_bus_lock_handle_t lock, bg_ctrl_func_t bg_e
IRAM_ATTR int spi_bus_lock_get_dev_id(spi_bus_lock_dev_handle_t dev_handle)
{
return (dev_handle? dev_lock_get_id(dev_handle): -1);
return (dev_handle ? dev_lock_get_id(dev_handle) : -1);
}
//will be called when cache disabled
@@ -692,9 +698,9 @@ IRAM_ATTR bool spi_bus_lock_touch(spi_bus_lock_dev_handle_t dev_handle)
spi_bus_lock_dev_t* last_dev = dev_handle->parent->last_dev;
dev_handle->parent->last_dev = dev_handle;
if (last_dev != dev_handle) {
int last_dev_id = (last_dev? dev_lock_get_id(last_dev): -1);
int last_dev_id = (last_dev ? dev_lock_get_id(last_dev) : -1);
ESP_DRAM_LOGV(TAG, "SPI dev changed from %d to %d",
last_dev_id, dev_lock_get_id(dev_handle));
last_dev_id, dev_lock_get_id(dev_handle));
}
return (dev_handle != last_dev);
}
@@ -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;
@@ -72,12 +70,12 @@ typedef struct {
//Periph 1 is 'claimed' by SPI flash code.
static atomic_bool spi_periph_claimed[SOC_SPI_PERIPH_NUM] = { ATOMIC_VAR_INIT(true), ATOMIC_VAR_INIT(false),
#if (SOC_SPI_PERIPH_NUM >= 3)
ATOMIC_VAR_INIT(false),
ATOMIC_VAR_INIT(false),
#endif
#if (SOC_SPI_PERIPH_NUM >= 4)
ATOMIC_VAR_INIT(false),
ATOMIC_VAR_INIT(false),
#endif
};
};
static const char* spi_claiming_func[3] = {NULL, NULL, NULL};
static spicommon_bus_context_t s_mainbus = SPI_MAIN_BUS_DEFAULT();
@@ -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)
@@ -112,7 +109,7 @@ bool spicommon_periph_claim(spi_host_device_t host, const char* source)
spi_ll_reset_register(host);
}
} else {
ESP_EARLY_LOGE(SPI_TAG, "SPI%d already claimed by %s.", host+1, spi_claiming_func[host]);
ESP_EARLY_LOGE(SPI_TAG, "SPI%d already claimed by %s.", host + 1, spi_claiming_func[host]);
}
return ret;
}
@@ -217,7 +214,7 @@ static esp_err_t alloc_dma_chan(spi_host_device_t host_id, spi_dma_chan_t dma_ch
if (dma_chan == SPI_DMA_CH_AUTO) {
#if CONFIG_IDF_TARGET_ESP32
for (int i = 1; i < SOC_SPI_DMA_CHAN_NUM+1; i++) {
for (int i = 1; i < SOC_SPI_DMA_CHAN_NUM + 1; i++) {
success = claim_dma_chan(i, &actual_dma_chan);
if (success) {
break;
@@ -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;
}
@@ -355,15 +351,15 @@ static esp_err_t dma_chan_free(spi_host_device_t host_id)
portENTER_CRITICAL(&spi_dma_spinlock);
spi_dma_chan_enabled &= ~BIT(dma_chan);
#if SPI_LL_DMA_SHARED
PERIPH_RCC_RELEASE_ATOMIC(get_dma_periph(dma_chan), ref_count) {
if (ref_count == 0) {
spi_dma_ll_enable_bus_clock(host_id, false);
}
}
#else
SPI_COMMON_RCC_CLOCK_ATOMIC() {
PERIPH_RCC_RELEASE_ATOMIC(get_dma_periph(dma_chan), ref_count) {
if (ref_count == 0) {
spi_dma_ll_enable_bus_clock(host_id, false);
}
}
#else
SPI_COMMON_RCC_CLOCK_ATOMIC() {
spi_dma_ll_enable_bus_clock(host_id, false);
}
#endif
portEXIT_CRITICAL(&spi_dma_spinlock);
@@ -400,10 +396,12 @@ 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};
for (size_t i = 0; i < sizeof(io_nums)/sizeof(io_nums[0]); i++) {
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;
}
@@ -414,24 +412,24 @@ static bool check_iomux_pins_oct(spi_host_device_t host, const spi_bus_config_t*
static bool check_iomux_pins_quad(spi_host_device_t host, const spi_bus_config_t* bus_config)
{
if (bus_config->sclk_io_num>=0 &&
bus_config->sclk_io_num != spi_periph_signal[host].spiclk_iomux_pin) {
if (bus_config->sclk_io_num >= 0 &&
bus_config->sclk_io_num != spi_periph_signal[host].spiclk_iomux_pin) {
return false;
}
if (bus_config->quadwp_io_num>=0 &&
bus_config->quadwp_io_num != spi_periph_signal[host].spiwp_iomux_pin) {
if (bus_config->quadwp_io_num >= 0 &&
bus_config->quadwp_io_num != spi_periph_signal[host].spiwp_iomux_pin) {
return false;
}
if (bus_config->quadhd_io_num>=0 &&
bus_config->quadhd_io_num != spi_periph_signal[host].spihd_iomux_pin) {
if (bus_config->quadhd_io_num >= 0 &&
bus_config->quadhd_io_num != spi_periph_signal[host].spihd_iomux_pin) {
return false;
}
if (bus_config->mosi_io_num >= 0 &&
bus_config->mosi_io_num != spi_periph_signal[host].spid_iomux_pin) {
bus_config->mosi_io_num != spi_periph_signal[host].spid_iomux_pin) {
return false;
}
if (bus_config->miso_io_num>=0 &&
bus_config->miso_io_num != spi_periph_signal[host].spiq_iomux_pin) {
if (bus_config->miso_io_num >= 0 &&
bus_config->miso_io_num != spi_periph_signal[host].spiq_iomux_pin) {
return false;
}
return true;
@@ -454,11 +452,13 @@ 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};
for (size_t i = 0; i < sizeof(io_nums)/sizeof(io_nums[0]); i++) {
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
};
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]);
// In Octal mode use function channel 2
@@ -526,15 +526,15 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf
bool miso_need_output;
bool mosi_need_output;
bool sclk_need_output;
if ((flags&SPICOMMON_BUSFLAG_MASTER) != 0) {
if ((flags & SPICOMMON_BUSFLAG_MASTER) != 0) {
//initial for master
miso_need_output = ((flags&SPICOMMON_BUSFLAG_DUAL) != 0) ? true : false;
miso_need_output = ((flags & SPICOMMON_BUSFLAG_DUAL) != 0) ? true : false;
mosi_need_output = true;
sclk_need_output = true;
} else {
//initial for slave
miso_need_output = true;
mosi_need_output = ((flags&SPICOMMON_BUSFLAG_DUAL) != 0) ? true : false;
mosi_need_output = ((flags & SPICOMMON_BUSFLAG_DUAL) != 0) ? true : false;
sclk_need_output = false;
}
@@ -542,14 +542,14 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf
const bool hd_need_output = true;
//check pin capabilities
if (bus_config->sclk_io_num>=0) {
if (bus_config->sclk_io_num >= 0) {
temp_flag |= SPICOMMON_BUSFLAG_SCLK;
SPI_CHECK_PIN(bus_config->sclk_io_num, "sclk", sclk_need_output);
}
if (bus_config->quadwp_io_num>=0) {
if (bus_config->quadwp_io_num >= 0) {
SPI_CHECK_PIN(bus_config->quadwp_io_num, "wp", wp_need_output);
}
if (bus_config->quadhd_io_num>=0) {
if (bus_config->quadhd_io_num >= 0) {
SPI_CHECK_PIN(bus_config->quadhd_io_num, "hd", hd_need_output);
}
#if SOC_SPI_SUPPORT_OCT
@@ -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);
@@ -586,8 +588,8 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf
SPI_CHECK_PIN(bus_config->miso_io_num, "miso", miso_need_output);
}
//set flags for DUAL mode according to output-capability of MOSI and MISO pins.
if ( (bus_config->mosi_io_num < 0 || GPIO_IS_VALID_OUTPUT_GPIO(bus_config->mosi_io_num)) &&
(bus_config->miso_io_num < 0 || GPIO_IS_VALID_OUTPUT_GPIO(bus_config->miso_io_num)) ) {
if ((bus_config->mosi_io_num < 0 || GPIO_IS_VALID_OUTPUT_GPIO(bus_config->mosi_io_num)) &&
(bus_config->miso_io_num < 0 || GPIO_IS_VALID_OUTPUT_GPIO(bus_config->miso_io_num))) {
temp_flag |= SPICOMMON_BUSFLAG_DUAL;
}
@@ -603,7 +605,7 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf
missing_flag &= ~SPICOMMON_BUSFLAG_MASTER;//don't check this flag
if (missing_flag != 0) {
//check pins existence
//check pins existence
if (missing_flag & SPICOMMON_BUSFLAG_SCLK) {
ESP_LOGE(SPI_TAG, "sclk pin required.");
}
@@ -633,13 +635,13 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf
if (use_iomux) {
//All SPI iomux pin selections resolve to 1, so we put that here instead of trying to figure
//out which FUNC_GPIOx_xSPIxx to grab; they all are defined to 1 anyway.
ESP_LOGD(SPI_TAG, "SPI%d use iomux pins.", host+1);
ESP_LOGD(SPI_TAG, "SPI%d use iomux pins.", host + 1);
bus_iomux_pins_set(host, bus_config);
} else {
//Use GPIO matrix
ESP_LOGD(SPI_TAG, "SPI%d use gpio matrix.", host+1);
ESP_LOGD(SPI_TAG, "SPI%d use gpio matrix.", host + 1);
if (bus_config->mosi_io_num >= 0) {
if (mosi_need_output || (temp_flag&SPICOMMON_BUSFLAG_DUAL)) {
if (mosi_need_output || (temp_flag & SPICOMMON_BUSFLAG_DUAL)) {
gpio_set_direction(bus_config->mosi_io_num, GPIO_MODE_INPUT_OUTPUT);
esp_rom_gpio_connect_out_signal(bus_config->mosi_io_num, spi_periph_signal[host].spid_out, false, false);
} else {
@@ -652,7 +654,7 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[bus_config->mosi_io_num], FUNC_GPIO);
}
if (bus_config->miso_io_num >= 0) {
if (miso_need_output || (temp_flag&SPICOMMON_BUSFLAG_DUAL)) {
if (miso_need_output || (temp_flag & SPICOMMON_BUSFLAG_DUAL)) {
gpio_set_direction(bus_config->miso_io_num, GPIO_MODE_INPUT_OUTPUT);
esp_rom_gpio_connect_out_signal(bus_config->miso_io_num, spi_periph_signal[host].spiq_out, false, false);
} else {
@@ -699,9 +701,10 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf
if ((flags & SPICOMMON_BUSFLAG_OCTAL) == SPICOMMON_BUSFLAG_OCTAL) {
int io_nums[] = {bus_config->data4_io_num, bus_config->data5_io_num, bus_config->data6_io_num, bus_config->data7_io_num};
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].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}
};
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;
}
@@ -730,7 +735,7 @@ esp_err_t spicommon_bus_free_io_cfg(const spi_bus_config_t *bus_cfg)
bus_cfg->quadwp_io_num,
bus_cfg->quadhd_io_num,
};
for (int i = 0; i < sizeof(pin_array)/sizeof(int); i ++) {
for (int i = 0; i < sizeof(pin_array) / sizeof(int); i ++) {
const int io = pin_array[i];
if (GPIO_IS_VALID_GPIO(io)) {
gpio_reset_pin(io);
@@ -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;
@@ -799,15 +805,15 @@ esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t *
SPI_CHECK(is_valid_host(host_id), "invalid host_id", ESP_ERR_INVALID_ARG);
SPI_CHECK(bus_ctx[host_id] == NULL, "SPI bus already initialized.", ESP_ERR_INVALID_STATE);
#ifdef CONFIG_IDF_TARGET_ESP32
SPI_CHECK(dma_chan >= SPI_DMA_DISABLED && dma_chan <= SPI_DMA_CH_AUTO, "invalid dma channel", ESP_ERR_INVALID_ARG );
SPI_CHECK(dma_chan >= SPI_DMA_DISABLED && dma_chan <= SPI_DMA_CH_AUTO, "invalid dma channel", ESP_ERR_INVALID_ARG);
#elif CONFIG_IDF_TARGET_ESP32S2
SPI_CHECK( dma_chan == SPI_DMA_DISABLED || dma_chan == (int)host_id || dma_chan == SPI_DMA_CH_AUTO, "invalid dma channel", ESP_ERR_INVALID_ARG );
SPI_CHECK(dma_chan == SPI_DMA_DISABLED || dma_chan == (int)host_id || dma_chan == SPI_DMA_CH_AUTO, "invalid dma channel", ESP_ERR_INVALID_ARG);
#elif SOC_GDMA_SUPPORTED
SPI_CHECK( dma_chan == SPI_DMA_DISABLED || dma_chan == SPI_DMA_CH_AUTO, "invalid dma channel, chip only support spi dma channel auto-alloc", ESP_ERR_INVALID_ARG );
SPI_CHECK(dma_chan == SPI_DMA_DISABLED || dma_chan == SPI_DMA_CH_AUTO, "invalid dma channel, chip only support spi dma channel auto-alloc", ESP_ERR_INVALID_ARG);
#endif
SPI_CHECK((bus_config->intr_flags & (ESP_INTR_FLAG_HIGH|ESP_INTR_FLAG_EDGE|ESP_INTR_FLAG_INTRDISABLED))==0, "intr flag not allowed", ESP_ERR_INVALID_ARG);
SPI_CHECK((bus_config->intr_flags & (ESP_INTR_FLAG_HIGH | ESP_INTR_FLAG_EDGE | ESP_INTR_FLAG_INTRDISABLED)) == 0, "intr flag not allowed", ESP_ERR_INVALID_ARG);
#ifndef CONFIG_SPI_MASTER_ISR_IN_IRAM
SPI_CHECK((bus_config->intr_flags & ESP_INTR_FLAG_IRAM)==0, "ESP_INTR_FLAG_IRAM should be disabled when CONFIG_SPI_MASTER_ISR_IN_IRAM is not set.", ESP_ERR_INVALID_ARG);
SPI_CHECK((bus_config->intr_flags & ESP_INTR_FLAG_IRAM) == 0, "ESP_INTR_FLAG_IRAM should be disabled when CONFIG_SPI_MASTER_ISR_IN_IRAM is not set.", ESP_ERR_INVALID_ARG);
#endif
bool spi_chan_claimed = spicommon_periph_claim(host_id, "spi master");
@@ -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);
@@ -867,7 +875,7 @@ esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t *
#ifdef CONFIG_PM_ENABLE
err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "spi_master",
&bus_attr->pm_lock);
&bus_attr->pm_lock);
if (err != ESP_OK) {
goto cleanup;
}
@@ -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
*/
@@ -967,7 +976,7 @@ bool IRAM_ATTR spicommon_dmaworkaround_req_reset(int dmachan, dmaworkaround_cb_t
int otherchan = (dmachan == 1) ? 2 : 1;
bool ret;
portENTER_CRITICAL_ISR(&dmaworkaround_mux);
if (dmaworkaround_channels_busy[otherchan-1]) {
if (dmaworkaround_channels_busy[otherchan - 1]) {
//Other channel is busy. Call back when it's done.
dmaworkaround_cb = cb;
dmaworkaround_cb_arg = arg;
@@ -975,7 +984,7 @@ bool IRAM_ATTR spicommon_dmaworkaround_req_reset(int dmachan, dmaworkaround_cb_t
ret = false;
} else {
//Reset DMA
periph_module_reset( PERIPH_SPI_DMA_MODULE );
periph_module_reset(PERIPH_SPI_DMA_MODULE);
ret = true;
}
portEXIT_CRITICAL_ISR(&dmaworkaround_mux);
@@ -990,10 +999,10 @@ bool IRAM_ATTR spicommon_dmaworkaround_reset_in_progress(void)
void IRAM_ATTR spicommon_dmaworkaround_idle(int dmachan)
{
portENTER_CRITICAL_ISR(&dmaworkaround_mux);
dmaworkaround_channels_busy[dmachan-1] = 0;
dmaworkaround_channels_busy[dmachan - 1] = 0;
if (dmaworkaround_waiting_for_chan == dmachan) {
//Reset DMA
periph_module_reset( PERIPH_SPI_DMA_MODULE );
periph_module_reset(PERIPH_SPI_DMA_MODULE);
dmaworkaround_waiting_for_chan = 0;
//Call callback
dmaworkaround_cb(dmaworkaround_cb_arg);
@@ -1005,7 +1014,7 @@ void IRAM_ATTR spicommon_dmaworkaround_idle(int dmachan)
void IRAM_ATTR spicommon_dmaworkaround_transfer_active(int dmachan)
{
portENTER_CRITICAL_ISR(&dmaworkaround_mux);
dmaworkaround_channels_busy[dmachan-1] = 1;
dmaworkaround_channels_busy[dmachan - 1] = 1;
portEXIT_CRITICAL_ISR(&dmaworkaround_mux);
}
#endif //#if CONFIG_IDF_TARGET_ESP32

View File

@@ -198,12 +198,12 @@ esp_err_t spi_slave_hd_init(spi_host_device_t host_id, const spi_bus_config_t *b
if (!host->append_mode) {
//Seg mode
ret = esp_intr_alloc(spicommon_irqsource_for_host(host_id), 0, spi_slave_hd_intr_segment,
(void *)host, &host->intr);
(void *)host, &host->intr);
if (ret != ESP_OK) {
goto cleanup;
}
ret = esp_intr_alloc(spicommon_irqdma_source_for_host(host_id), 0, spi_slave_hd_intr_segment,
(void *)host, &host->intr_dma);
(void *)host, &host->intr_dma);
if (ret != ESP_OK) {
goto cleanup;
}
@@ -212,7 +212,7 @@ esp_err_t spi_slave_hd_init(spi_host_device_t host_id, const spi_bus_config_t *b
//On ESP32S2, `cmd7` and `cmd8` interrupts registered as spi rx & tx interrupt are from SPI DMA interrupt source.
//although the `cmd7` and `cmd8` interrupt on spi are registered independently here
ret = esp_intr_alloc(spicommon_irqsource_for_host(host_id), 0, spi_slave_hd_intr_append,
(void *)host, &host->intr);
(void *)host, &host->intr);
if (ret != ESP_OK) {
goto cleanup;
}
@@ -225,7 +225,7 @@ esp_err_t spi_slave_hd_init(spi_host_device_t host_id, const spi_bus_config_t *b
gdma_register_tx_event_callbacks(host->gdma_handle_tx, &tx_cbs, host);
#else
ret = esp_intr_alloc(spicommon_irqdma_source_for_host(host_id), 0, spi_slave_hd_intr_append,
(void *)host, &host->intr_dma);
(void *)host, &host->intr_dma);
if (ret != ESP_OK) {
goto cleanup;
}
@@ -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
@@ -569,7 +596,7 @@ static esp_err_t s_spi_slave_hd_setup_priv_trans(spi_host_device_t host, spi_sla
if (((uint32_t)orig_trans->data) | (byte_len & (alignment - 1))) {
ESP_RETURN_ON_FALSE(orig_trans->flags & SPI_SLAVE_HD_TRANS_DMA_BUFFER_ALIGN_AUTO, ESP_ERR_INVALID_ARG, TAG, "data buffer addr&len not align to %d, or not dma_capable", alignment);
byte_len = (byte_len + alignment - 1) & (~(alignment - 1)); // up align to alignment
ESP_LOGD(TAG, "Re-allocate %s buffer of len %ld for DMA", (chan == SPI_SLAVE_CHAN_TX)?"TX":"RX", byte_len);
ESP_LOGD(TAG, "Re-allocate %s buffer of len %ld for DMA", (chan == SPI_SLAVE_CHAN_TX) ? "TX" : "RX", byte_len);
priv_trans->aligned_buffer = heap_caps_aligned_alloc(64, byte_len, MALLOC_CAP_DMA);
if (priv_trans->aligned_buffer == NULL) {
return ESP_ERR_NO_MEM;
@@ -615,7 +642,7 @@ esp_err_t spi_slave_hd_queue_trans(spi_host_device_t host_id, spi_slave_chan_t c
SPIHD_CHECK(chan == SPI_SLAVE_CHAN_TX || chan == SPI_SLAVE_CHAN_RX, "Invalid channel", ESP_ERR_INVALID_ARG);
spi_slave_hd_trans_priv_t hd_priv_trans = {.trans = trans};
SPIHD_CHECK( ESP_OK == s_spi_slave_hd_setup_priv_trans(host_id, &hd_priv_trans, chan), "No mem to allocate new cache buffer", ESP_ERR_NO_MEM);
SPIHD_CHECK(ESP_OK == s_spi_slave_hd_setup_priv_trans(host_id, &hd_priv_trans, chan), "No mem to allocate new cache buffer", ESP_ERR_NO_MEM);
if (chan == SPI_SLAVE_CHAN_TX) {
BaseType_t ret = xQueueSend(host->tx_trans_queue, &hd_priv_trans, timeout);
@@ -669,7 +696,7 @@ esp_err_t spi_slave_hd_append_trans(spi_host_device_t host_id, spi_slave_chan_t
SPIHD_CHECK(chan == SPI_SLAVE_CHAN_TX || chan == SPI_SLAVE_CHAN_RX, "Invalid channel", ESP_ERR_INVALID_ARG);
spi_slave_hd_trans_priv_t hd_priv_trans = {.trans = trans};
SPIHD_CHECK( ESP_OK == s_spi_slave_hd_setup_priv_trans(host_id, &hd_priv_trans, chan), "No mem to allocate new cache buffer", ESP_ERR_NO_MEM);
SPIHD_CHECK(ESP_OK == s_spi_slave_hd_setup_priv_trans(host_id, &hd_priv_trans, chan), "No mem to allocate new cache buffer", ESP_ERR_NO_MEM);
if (chan == SPI_SLAVE_CHAN_TX) {
BaseType_t ret = xSemaphoreTake(host->tx_cnting_sem, timeout);

View File

@@ -0,0 +1,16 @@
components/esp_driver_spi/test_apps/spi/master:
disable:
- if: SOC_GPSPI_SUPPORTED != 1
components/esp_driver_spi/test_apps/spi/param:
disable:
- if: SOC_GPSPI_SUPPORTED != 1
components/esp_driver_spi/test_apps/spi/slave:
disable:
- if: SOC_GPSPI_SUPPORTED != 1
components/esp_driver_spi/test_apps/spi/slave_hd:
disable:
- if: SOC_GPSPI_SUPPORTED != 1
- if: SOC_SPI_SUPPORT_SLAVE_HD_VER2 != 1

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
@@ -50,21 +49,21 @@ const static char TAG[] = "test_spi";
void spi_task1(void* arg)
{
//task1 send 50 polling transactions, acquire the bus and send another 50
int count=0;
int count = 0;
spi_transaction_t t = {
.flags = SPI_TRANS_USE_TXDATA,
.tx_data = { 0x80, 0x12, 0x34, 0x56 },
.length = 4*8,
.length = 4 * 8,
};
spi_device_handle_t handle = ((task_context_t*)arg)->handle;
for( int j = 0; j < 50; j ++ ) {
TEST_ESP_OK(spi_device_polling_transmit( handle, &t ));
ESP_LOGI(TAG, "task1:%d", count++ );
for (int j = 0; j < 50; j ++) {
TEST_ESP_OK(spi_device_polling_transmit(handle, &t));
ESP_LOGI(TAG, "task1:%d", count++);
}
TEST_ESP_OK(spi_device_acquire_bus( handle, portMAX_DELAY ));
for( int j = 0; j < 50; j ++ ) {
TEST_ESP_OK(spi_device_polling_transmit( handle, &t ));
ESP_LOGI(TAG, "task1:%d", count++ );
TEST_ESP_OK(spi_device_acquire_bus(handle, portMAX_DELAY));
for (int j = 0; j < 50; j ++) {
TEST_ESP_OK(spi_device_polling_transmit(handle, &t));
ESP_LOGI(TAG, "task1:%d", count++);
}
spi_device_release_bus(handle);
ESP_LOGI(TAG, "task1 terminates");
@@ -74,29 +73,29 @@ void spi_task1(void* arg)
void spi_task2(void* arg)
{
int count=0;
int count = 0;
//task2 acquire the bus, send 50 polling transactions and then 50 non-polling
spi_transaction_t t = {
.flags = SPI_TRANS_USE_TXDATA,
.tx_data = { 0x80, 0x12, 0x34, 0x56 },
.length = 4*8,
.length = 4 * 8,
};
spi_transaction_t *ret_t;
spi_device_handle_t handle = ((task_context_t*)arg)->handle;
TEST_ESP_OK(spi_device_acquire_bus( handle, portMAX_DELAY ));
TEST_ESP_OK(spi_device_acquire_bus(handle, portMAX_DELAY));
for (int i = 0; i < 50; i ++) {
TEST_ESP_OK(spi_device_polling_transmit(handle, &t));
ESP_LOGI( TAG, "task2: %d", count++ );
ESP_LOGI(TAG, "task2: %d", count++);
}
for( int j = 0; j < 50; j ++ ) {
for (int j = 0; j < 50; j ++) {
TEST_ESP_OK(spi_device_queue_trans(handle, &t, portMAX_DELAY));
}
for( int j = 0; j < 50; j ++ ) {
for (int j = 0; j < 50; j ++) {
TEST_ESP_OK(spi_device_get_trans_result(handle, &ret_t, portMAX_DELAY));
assert(ret_t == &t);
ESP_LOGI( TAG, "task2: %d", count++ );
ESP_LOGI(TAG, "task2: %d", count++);
}
spi_device_release_bus(handle);
vTaskDelay(1);
@@ -108,24 +107,24 @@ void spi_task2(void* arg)
void spi_task3(void* arg)
{
//task3 send 30 polling transactions, acquire the bus, send 20 polling transactions and then 50 non-polling
int count=0;
int count = 0;
spi_transaction_t t = {
.flags = SPI_TRANS_USE_TXDATA,
.tx_data = { 0x80, 0x12, 0x34, 0x56 },
.length = 4*8,
.length = 4 * 8,
};
spi_transaction_t *ret_t;
spi_device_handle_t handle = ((task_context_t*)arg)->handle;
for (int i = 0; i < 30; i ++) {
TEST_ESP_OK(spi_device_polling_transmit(handle, &t));
ESP_LOGI( TAG, "task3: %d", count++ );
ESP_LOGI(TAG, "task3: %d", count++);
}
TEST_ESP_OK(spi_device_acquire_bus( handle, portMAX_DELAY ));
TEST_ESP_OK(spi_device_acquire_bus(handle, portMAX_DELAY));
for (int i = 0; i < 20; i ++) {
TEST_ESP_OK(spi_device_polling_transmit(handle, &t));
ESP_LOGI( TAG, "task3: %d", count++ );
ESP_LOGI(TAG, "task3: %d", count++);
}
for (int j = 0; j < 50; j++) {
@@ -147,11 +146,11 @@ static void write_large_buffer(esp_flash_t *chip, const esp_partition_t *part, c
{
printf("Erasing chip %p, %d bytes\n", chip, length);
TEST_ESP_OK(esp_flash_erase_region(chip, part->address, (length + SPI_FLASH_SEC_SIZE) & ~(SPI_FLASH_SEC_SIZE - 1)) );
TEST_ESP_OK(esp_flash_erase_region(chip, part->address, (length + SPI_FLASH_SEC_SIZE) & ~(SPI_FLASH_SEC_SIZE - 1)));
printf("Writing chip %p, %d bytes from source %p\n", chip, length, source);
// note writing to unaligned address
TEST_ESP_OK(esp_flash_write(chip, source, part->address + 1, length) );
TEST_ESP_OK(esp_flash_write(chip, source, part->address + 1, length));
printf("Write done.\n");
}
@@ -161,18 +160,18 @@ static void read_and_check(esp_flash_t *chip, const esp_partition_t *part, const
printf("Checking chip %p, %d bytes\n", chip, length);
uint8_t *buf = malloc(length);
TEST_ASSERT_NOT_NULL(buf);
TEST_ESP_OK(esp_flash_read(chip, buf, part->address + 1, length) );
TEST_ESP_OK(esp_flash_read(chip, buf, part->address + 1, length));
TEST_ASSERT_EQUAL_HEX8_ARRAY(source, buf, length);
free(buf);
// check nothing was written at beginning or end
uint8_t ends[8];
TEST_ESP_OK(esp_flash_read(chip, ends, part->address, sizeof(ends)) );
TEST_ESP_OK(esp_flash_read(chip, ends, part->address, sizeof(ends)));
TEST_ASSERT_EQUAL_HEX8(0xFF, ends[0]);
TEST_ASSERT_EQUAL_HEX8(source[0], ends[1]);
TEST_ESP_OK(esp_flash_read(chip, ends, part->address + length, sizeof(ends)) );
TEST_ESP_OK(esp_flash_read(chip, ends, part->address + length, sizeof(ends)));
TEST_ASSERT_EQUAL_HEX8(source[length - 1], ends[0]);
TEST_ASSERT_EQUAL_HEX8(0xFF, ends[1]);
@@ -210,18 +209,18 @@ void spi_task4(void* arg)
static void test_bus_lock(bool test_flash)
{
task_context_t context1={};
task_context_t context2={};
task_context_t context3={};
task_context_t context4={};
task_context_t context1 = {};
task_context_t context2 = {};
task_context_t context3 = {};
task_context_t context4 = {};
TaskHandle_t task1, task2, task3, task4;
esp_err_t ret;
spi_bus_config_t buscfg=SPI_BUS_TEST_DEFAULT_CONFIG();
spi_bus_config_t buscfg = SPI_BUS_TEST_DEFAULT_CONFIG();
buscfg.miso_io_num = TEST_BUS_PIN_NUM_MISO;
buscfg.mosi_io_num = TEST_BUS_PIN_NUM_MOSI;
buscfg.sclk_io_num = TEST_BUS_PIN_NUM_CLK;
spi_device_interface_config_t devcfg=SPI_DEVICE_TEST_DEFAULT_CONFIG();
spi_device_interface_config_t devcfg = SPI_DEVICE_TEST_DEFAULT_CONFIG();
devcfg.queue_size = 100;
//Initialize the SPI bus and 3 devices
@@ -258,18 +257,20 @@ static void test_bus_lock(bool test_flash)
}
ESP_LOGI(TAG, "Start testing...");
xTaskCreate( spi_task1, "task1", 4096, &context1, 0, &task1 );
xTaskCreate( spi_task2, "task2", 4096, &context2, 0, &task2 );
xTaskCreate( spi_task3, "task3", 4096, &context3, 0, &task3 );
xTaskCreate(spi_task1, "task1", 4096, &context1, 0, &task1);
xTaskCreate(spi_task2, "task2", 4096, &context2, 0, &task2);
xTaskCreate(spi_task3, "task3", 4096, &context3, 0, &task3);
if (test_flash) {
xTaskCreate( spi_task4, "task4", 2048, &context4, 0, &task4 );
xTaskCreate(spi_task4, "task4", 2048, &context4, 0, &task4);
} else {
context4.finished = true;
}
for(;;){
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));
@@ -278,19 +279,18 @@ static void test_bus_lock(bool test_flash)
if (test_flash) {
TEST_ESP_OK(spi_bus_remove_flash_device(chip));
}
TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST) );
TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST));
}
#if CONFIG_IDF_TARGET_ESP32
// no need this case in other target, only esp32 need buslock to split MSPI and GPSPI2 action
TEST_CASE("spi bus lock, with flash","[spi][test_env=external_flash]")
TEST_CASE("spi bus lock, with flash", "[spi][test_env=external_flash]")
{
test_bus_lock(true);
}
#endif //CONFIG_IDF_TARGET_ESP32
TEST_CASE("spi bus lock","[spi]")
TEST_CASE("spi bus lock", "[spi]")
{
test_bus_lock(false);
}
@@ -327,7 +327,7 @@ TEST_CASE("spi master can be used on SPI1", "[spi]")
{
spi_device_interface_config_t dev_cfg = {
.mode = 1,
.clock_speed_hz = 1*1000*1000,
.clock_speed_hz = 1 * 1000 * 1000,
.spics_io_num = -1,
.queue_size = 1,
};

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();
@@ -148,12 +144,12 @@ TEST_CASE("SPI Master clockdiv calculation routines", "[spi]")
#if SOC_SPI_SUPPORT_CLK_XTAL
esp_clk_tree_src_get_freq_hz(SPI_CLK_SRC_XTAL, ESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX, &clock_source_hz);
printf("\nTest clock source XTAL = %ld\n", clock_source_hz);
if((40 * 1000 * 1000) == clock_source_hz){
if ((40 * 1000 * 1000) == clock_source_hz) {
for (int i = 0; i < TEST_CLK_TIMES; i++) {
check_spi_pre_n_for(SPI_CLK_SRC_XTAL, test_clk_param.clk_param_40m[i][0], test_clk_param.clk_param_40m[i][1], test_clk_param.clk_param_40m[i][2]);
}
}
if((32 * 1000 * 1000) == clock_source_hz){
if ((32 * 1000 * 1000) == clock_source_hz) {
for (int i = 0; i < TEST_CLK_TIMES; i++) {
check_spi_pre_n_for(SPI_CLK_SRC_XTAL, test_clk_param.clk_param_32m[i][0], test_clk_param.clk_param_32m[i][1], test_clk_param.clk_param_32m[i][2]);
}
@@ -164,12 +160,12 @@ TEST_CASE("SPI Master clockdiv calculation routines", "[spi]")
#if SOC_SPI_SUPPORT_CLK_RC_FAST
esp_clk_tree_src_get_freq_hz(SPI_CLK_SRC_RC_FAST, ESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX, &clock_source_hz);
printf("\nTest clock source RC_FAST = %ld\n", clock_source_hz);
if((17500000) == clock_source_hz){
if ((17500000) == clock_source_hz) {
for (int i = 0; i < TEST_CLK_TIMES; i++) {
check_spi_pre_n_for(SPI_CLK_SRC_RC_FAST, test_clk_param.clk_param_17m[i][0], test_clk_param.clk_param_17m[i][1], test_clk_param.clk_param_17m[i][2]);
}
}
if((7000000) == clock_source_hz){
if ((7000000) == clock_source_hz) {
for (int i = 0; i < TEST_CLK_TIMES; i++) {
check_spi_pre_n_for(SPI_CLK_SRC_RC_FAST, test_clk_param.clk_param_7m[i][0], test_clk_param.clk_param_7m[i][1], test_clk_param.clk_param_7m[i][2]);
}
@@ -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);
@@ -440,9 +434,9 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]")
.max_transfer_sz = 8, .flags = flags_expected
};
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected | SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
TEST_ASSERT_EQUAL_HEX32(flags_expected, flags_o);
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected | SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
TEST_ASSERT_EQUAL_HEX32(flags_expected, flags_o);
ESP_LOGI(TAG, "test 4 iomux output pins...");
flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_IOMUX_PINS | SPICOMMON_BUSFLAG_DUAL;
@@ -451,9 +445,9 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]")
.max_transfer_sz = 8, .flags = flags_expected
};
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected | SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
TEST_ASSERT_EQUAL_HEX32(flags_expected, flags_o);
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected | SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
TEST_ASSERT_EQUAL_HEX32(flags_expected, flags_o);
ESP_LOGI(TAG, "test 6 output pins...");
flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_QUAD | SPICOMMON_BUSFLAG_GPIO_PINS;
@@ -463,9 +457,9 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]")
.max_transfer_sz = 8, .flags = flags_expected
};
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected | SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
TEST_ASSERT_EQUAL_HEX32(flags_expected, flags_o);
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected | SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
TEST_ASSERT_EQUAL_HEX32(flags_expected, flags_o);
ESP_LOGI(TAG, "test 4 output pins...");
flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_DUAL | SPICOMMON_BUSFLAG_GPIO_PINS;
@@ -475,9 +469,9 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]")
.max_transfer_sz = 8, .flags = flags_expected
};
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected | SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
TEST_ASSERT_EQUAL_HEX32(flags_expected, flags_o);
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected | SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
TEST_ASSERT_EQUAL_HEX32(flags_expected, flags_o);
#if TEST_SOC_HAS_INPUT_ONLY_PINS //There is no input-only pin on esp32c3 and esp32s3, so this test could be ignored.
ESP_LOGI(TAG, "test master 5 output pins and MOSI on input-only pin...");
@@ -487,7 +481,7 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]")
.max_transfer_sz = 8, .flags = flags_expected
};
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected | SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
TEST_ASSERT_EQUAL_HEX32(flags_expected, flags_o);
ESP_LOGI(TAG, "test slave 5 output pins and MISO on input-only pin...");
flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_WPHD | SPICOMMON_BUSFLAG_GPIO_PINS;
@@ -496,7 +490,7 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]")
.max_transfer_sz = 8, .flags = flags_expected
};
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected | SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
TEST_ASSERT_EQUAL_HEX32(flags_expected, flags_o);
ESP_LOGI(TAG, "test master 3 output pins and MOSI on input-only pin...");
flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_GPIO_PINS;
@@ -506,7 +500,7 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]")
.max_transfer_sz = 8, .flags = flags_expected
};
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected | SPICOMMON_BUSFLAG_MASTER, &flags_o));
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
TEST_ASSERT_EQUAL_HEX32(flags_expected, flags_o);
ESP_LOGI(TAG, "test slave 3 output pins and MISO on input-only pin...");
flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_GPIO_PINS;
@@ -515,7 +509,7 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]")
.max_transfer_sz = 8, .flags = flags_expected
};
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, flags_expected | SPICOMMON_BUSFLAG_SLAVE, &flags_o));
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
TEST_ASSERT_EQUAL_HEX32(flags_expected, flags_o);
//There is no input-only pin on esp32c3 and esp32s3, so this test could be ignored.
#endif //#if TEST_SOC_HAS_INPUT_ONLY_PINS
@@ -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] = {
@@ -789,36 +782,36 @@ TEST_CASE("SPI Master DMA test: length, start, not aligned", "[spi]")
//connect MOSI to two devices breaks the output, fix it.
spitest_gpio_output_sel(buscfg.mosi_io_num, FUNC_GPIO, spi_periph_signal[TEST_SPI_HOST].spid_out);
for ( int i = 0; i < 8; i ++ ) {
memset( rx_buf, 0x66, sizeof(rx_buf));
for (int i = 0; i < 8; i ++) {
memset(rx_buf, 0x66, sizeof(rx_buf));
spi_transaction_t t = {};
t.length = 8 * (i + 1);
t.rxlength = 0;
t.tx_buffer = tx_buf + 2 * i;
t.rx_buffer = rx_buf + i;
if ( i == 1 ) {
if (i == 1) {
//test set no start
t.rx_buffer = NULL;
} else if ( i == 2 ) {
} else if (i == 2) {
//test rx length != tx_length
t.rxlength = t.length - 8;
}
spi_device_transmit( spi, &t );
spi_device_transmit(spi, &t);
for ( int i = 0; i < 16; i ++ ) {
for (int i = 0; i < 16; i ++) {
printf("%02X ", rx_buf[i]);
}
printf("\n");
if ( i == 1 ) {
if (i == 1) {
// no rx, skip check
} else if ( i == 2 ) {
} else if (i == 2) {
//test rx length = tx length-1
TEST_ASSERT_EQUAL_HEX8_ARRAY(t.tx_buffer, t.rx_buffer, t.length / 8 - 1 );
TEST_ASSERT_EQUAL_HEX8_ARRAY(t.tx_buffer, t.rx_buffer, t.length / 8 - 1);
} else {
//normal check
TEST_ASSERT_EQUAL_HEX8_ARRAY(t.tx_buffer, t.rx_buffer, t.length / 8 );
TEST_ASSERT_EQUAL_HEX8_ARRAY(t.tx_buffer, t.rx_buffer, t.length / 8);
}
}
@@ -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
@@ -881,7 +873,7 @@ void test_cmd_addr(spi_slave_task_context_t *slave_context, bool lsb_first)
#ifdef CONFIG_IDF_TARGET_ESP32
addr_bits = 56 - 8 * i;
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
//ESP32S2 only supportes up to 32 bits address
//ESP32S2 only supportes up to 32 bits address
addr_bits = 28 - 4 * i;
#endif
int round_up = (cmd_bits + addr_bits + 7) / 8 * 8;
@@ -897,7 +889,7 @@ void test_cmd_addr(spi_slave_task_context_t *slave_context, bool lsb_first)
.address_bits = addr_bits,
};
ESP_LOGI( MASTER_TAG, "===== test%d =====", i );
ESP_LOGI(MASTER_TAG, "===== test%d =====", i);
ESP_LOGI(MASTER_TAG, "cmd_bits: %d, addr_bits: %d", cmd_bits, addr_bits);
TEST_ESP_OK(spi_device_transmit(spi, (spi_transaction_t *)&trans));
//wait for both master and slave end
@@ -964,10 +956,10 @@ void test_cmd_addr(spi_slave_task_context_t *slave_context, bool lsb_first)
TEST_CASE("SPI master variable cmd & addr test", "[spi]")
{
spi_slave_task_context_t slave_context = {};
esp_err_t err = init_slave_context( &slave_context, TEST_SLAVE_HOST );
TEST_ASSERT( err == ESP_OK );
esp_err_t err = init_slave_context(&slave_context, TEST_SLAVE_HOST);
TEST_ASSERT(err == ESP_OK);
TaskHandle_t handle_slave;
xTaskCreate( spitest_slave_task, "spi_slave", 4096, &slave_context, 0, &handle_slave);
xTaskCreate(spitest_slave_task, "spi_slave", 4096, &slave_context, 0, &handle_slave);
//initial slave, mode 0, no dma
int dma_chan = 0;
@@ -976,12 +968,12 @@ TEST_CASE("SPI master variable cmd & addr test", "[spi]")
spi_slave_interface_config_t slvcfg = SPI_SLAVE_TEST_DEFAULT_CONFIG();
slvcfg.mode = slave_mode;
//Initialize SPI slave interface
TEST_ESP_OK( spi_slave_initialize(TEST_SLAVE_HOST, &slv_buscfg, &slvcfg, dma_chan) );
TEST_ESP_OK(spi_slave_initialize(TEST_SLAVE_HOST, &slv_buscfg, &slvcfg, dma_chan));
test_cmd_addr(&slave_context, false);
test_cmd_addr(&slave_context, true);
vTaskDelete( handle_slave );
vTaskDelete(handle_slave);
handle_slave = 0;
deinit_slave_context(&slave_context);
@@ -1225,12 +1217,12 @@ static void fd_master(void)
//Master FD DMA, RX without TX Test
for (int i = 0; i < TEST_NUM; i++) {
// 1. Master FD DMA, only receive, with NULL tx_buffer
get_tx_buffer(FD_SEED1+i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
get_tx_buffer(FD_SEED1 + i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
memset(mst_recv_buf, 0x0, FD_TEST_BUF_SIZE);
master_only_rx_trans(spi, mst_recv_buf, slv_send_buf, FD_TEST_BUF_SIZE);
//2. Master FD DMA with TX and RX
get_tx_buffer(FD_SEED2+i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
get_tx_buffer(FD_SEED2 + i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
memset(mst_recv_buf, 0x0, FD_TEST_BUF_SIZE);
master_both_trans(spi, mst_send_buf, mst_recv_buf, slv_send_buf, FD_TEST_BUF_SIZE);
}
@@ -1238,11 +1230,11 @@ static void fd_master(void)
//Master FD DMA, TX without RX Test
for (int i = 0; i < TEST_NUM; i++) {
// 1. Master FD DMA, only send, with NULL rx_buffer
get_tx_buffer(FD_SEED3+i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
get_tx_buffer(FD_SEED3 + i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
master_only_tx_trans(spi, mst_send_buf, FD_TEST_BUF_SIZE);
//2. Master FD DMA with TX and RX
get_tx_buffer(FD_SEED4+i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
get_tx_buffer(FD_SEED4 + i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
memset(mst_recv_buf, 0x0, FD_TEST_BUF_SIZE);
master_both_trans(spi, mst_send_buf, mst_recv_buf, slv_send_buf, FD_TEST_BUF_SIZE);
}
@@ -1307,23 +1299,23 @@ static void fd_slave(void)
for (int i = 0; i < TEST_NUM; i++) {
//1. Slave TX without RX (rx_buffer == NULL)
get_tx_buffer(FD_SEED1+i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
get_tx_buffer(FD_SEED1 + i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
slave_only_tx_trans(slv_send_buf, FD_TEST_BUF_SIZE);
//2. Slave both TX and RX
get_tx_buffer(FD_SEED2+i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
get_tx_buffer(FD_SEED2 + i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
memset(slv_recv_buf, 0x0, FD_TEST_BUF_SIZE);
slave_both_trans(slv_send_buf, slv_recv_buf, mst_send_buf, FD_TEST_BUF_SIZE);
}
for (int i = 0; i < TEST_NUM; i++) {
// 1. Slave RX without TX (tx_buffer == NULL)
get_tx_buffer(FD_SEED3+i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
get_tx_buffer(FD_SEED3 + i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
memset(slv_recv_buf, 0x0, FD_TEST_BUF_SIZE);
slave_only_rx_trans(slv_recv_buf, mst_send_buf, FD_TEST_BUF_SIZE);
//2. Slave both TX and RX
get_tx_buffer(FD_SEED4+i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
get_tx_buffer(FD_SEED4 + i, mst_send_buf, slv_send_buf, FD_TEST_BUF_SIZE);
memset(slv_recv_buf, 0x0, FD_TEST_BUF_SIZE);
slave_both_trans(slv_send_buf, slv_recv_buf, mst_send_buf, FD_TEST_BUF_SIZE);
}
@@ -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)
/********************************************************************************
@@ -1604,11 +1595,12 @@ TEST_CASE_MULTIPLE_DEVICES("SPI_Master:Test multiple devices", "[spi_ms]", test_
#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();
}
TEST_CASE("test_master_isr_pin_to_core","[spi]")
TEST_CASE("test_master_isr_pin_to_core", "[spi]")
{
spi_device_handle_t dev0;
uint32_t master_send;
@@ -1640,7 +1632,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;
@@ -1696,7 +1687,7 @@ static IRAM_ATTR void test_master_iram(void)
spi_flash_disable_interrupts_caches_and_other_cpu();
flag_trans_done = false;
spi_device_queue_trans(dev_handle, &trans_cfg, portMAX_DELAY);
while(!flag_trans_done) {
while (!flag_trans_done) {
// waitting for transaction done and return from ISR
}
spi_device_get_trans_result(dev_handle, &ret_trans, portMAX_DELAY);

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

@@ -50,7 +50,7 @@ static void local_test_init(void **arg)
spitest_context_t *context = (spitest_context_t *)*arg;
TEST_ASSERT(context != NULL);
context->slave_context = (spi_slave_task_context_t) {};
esp_err_t err = init_slave_context( &context->slave_context, TEST_SLAVE_HOST);
esp_err_t err = init_slave_context(&context->slave_context, TEST_SLAVE_HOST);
TEST_ASSERT(err == ESP_OK);
xTaskCreate(spitest_slave_task, "spi_slave", 4096, &context->slave_context, 0, &context->handle_slave);
@@ -213,16 +213,16 @@ static void local_test_loop(const void *arg1, void *arg2)
bool failed = false;
//check master data
if (check_master_data && memcmp(slave_trans.tx_buffer, t->rx_buffer, (len + 7) / 8) != 0 ) {
if (check_master_data && memcmp(slave_trans.tx_buffer, t->rx_buffer, (len + 7) / 8) != 0) {
failed = true;
}
//check slave data and length
//currently the rcv_len can be in range of [t->length-1, t->length+3]
if ( rcv_len < len - 1 || rcv_len > len + 4) {
if (rcv_len < len - 1 || rcv_len > len + 4) {
failed = true;
}
if (check_slave_data && memcmp(t->tx_buffer, slave_trans.rx_buffer, (len + 7) / 8) != 0 ) {
if (check_slave_data && memcmp(t->tx_buffer, slave_trans.rx_buffer, (len + 7) / 8) != 0) {
failed = true;
}
@@ -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",
@@ -795,7 +794,7 @@ static void test_master_loop(const void *arg1, void *arg2)
const int *timing_speed_array = test_cfg->freq_list;
ESP_LOGI(MASTER_TAG, "****************** %s ***************", test_cfg->pset_name);
for (int i = 0; ; i++ ) {
for (int i = 0; ; i++) {
const int freq = timing_speed_array[i];
if (freq == 0) {
break;
@@ -809,21 +808,21 @@ static void test_master_loop(const void *arg1, void *arg2)
unity_wait_for_signal("Slave ready");
for ( int j = 0; j < test_cfg->test_size; j ++ ) {
for (int j = 0; j < test_cfg->test_size; j ++) {
//wait for both master and slave end
ESP_LOGI( MASTER_TAG, "=> test%d", j );
ESP_LOGI(MASTER_TAG, "=> test%d", j);
//send master tx data
vTaskDelay(20);
spi_transaction_t *t = &context->master_trans[j];
TEST_ESP_OK (spi_device_transmit(spi, t) );
TEST_ESP_OK(spi_device_transmit(spi, t));
int len = get_trans_len(test_cfg->dup, t);
if (TEST_LOG_DBUG) {
spitest_master_print_data(t, len);
}
size_t rcv_len;
slave_rxdata_t *rcv_data = xRingbufferReceive( context->slave_context.data_received, &rcv_len, portMAX_DELAY );
slave_rxdata_t *rcv_data = xRingbufferReceive(context->slave_context.data_received, &rcv_len, portMAX_DELAY);
if (TEST_LOG_DBUG) {
spitest_slave_print_data(rcv_data, false);
}
@@ -840,7 +839,7 @@ static void test_master_loop(const void *arg1, void *arg2)
check_len, check_slave_data));
}
//clean
vRingbufferReturnItem( context->slave_context.data_received, rcv_data );
vRingbufferReturnItem(context->slave_context.data_received, rcv_data);
}
master_free_device_bus(spi);
}
@@ -854,17 +853,17 @@ static void test_slave_init(void **arg)
spitest_context_t *context = (spitest_context_t *)*arg;
TEST_ASSERT(context != NULL);
context->slave_context = (spi_slave_task_context_t) {};
esp_err_t err = init_slave_context( &context->slave_context, TEST_SPI_HOST);
TEST_ASSERT( err == ESP_OK );
esp_err_t err = init_slave_context(&context->slave_context, TEST_SPI_HOST);
TEST_ASSERT(err == ESP_OK);
unity_wait_for_signal("Master ready");
xTaskCreate( spitest_slave_task, "spi_slave", 4096, &context->slave_context, 0, &context->handle_slave);
xTaskCreate(spitest_slave_task, "spi_slave", 4096, &context->slave_context, 0, &context->handle_slave);
}
static void test_slave_deinit(void *arg)
{
spitest_context_t *context = (spitest_context_t *)arg;
vTaskDelete( context->handle_slave );
vTaskDelete(context->handle_slave);
context->handle_slave = 0;
deinit_slave_context(&context->slave_context);
@@ -905,7 +904,7 @@ static void test_slave_loop(const void *arg1, void *arg2)
spitest_init_transactions(pset, context);
const int *timing_speed_array = pset->freq_list;
for (int i = 0; ; i++ ) {
for (int i = 0; ; i++) {
const int freq = timing_speed_array[i];
if (freq == 0) {
break;
@@ -920,16 +919,16 @@ static void test_slave_loop(const void *arg1, void *arg2)
//prepare slave tx data
for (int i = 0; i < pset->test_size; i ++) {
xQueueSend( context->slave_context.data_to_send, &context->slave_trans[i], portMAX_DELAY );
xQueueSend(context->slave_context.data_to_send, &context->slave_trans[i], portMAX_DELAY);
//memcpy(context->master_trans[i].rx_buffer, context->slave_trans[i].start, (context->master_trans[i].length+7)/8);
}
vTaskDelay(50 / portTICK_PERIOD_MS);
unity_send_signal("Slave ready");
for ( int i = 0; i < pset->test_size; i ++ ) {
for (int i = 0; i < pset->test_size; i ++) {
//wait for both master and slave end
ESP_LOGI( MASTER_TAG, "===== test%d =====", i );
ESP_LOGI(MASTER_TAG, "===== test%d =====", i);
//send master tx data
vTaskDelay(20);
@@ -940,7 +939,7 @@ static void test_slave_loop(const void *arg1, void *arg2)
}
size_t rcv_len;
slave_rxdata_t *rcv_data = xRingbufferReceive( context->slave_context.data_received, &rcv_len, portMAX_DELAY );
slave_rxdata_t *rcv_data = xRingbufferReceive(context->slave_context.data_received, &rcv_len, portMAX_DELAY);
if (TEST_LOG_DBUG) {
spitest_slave_print_data(rcv_data, true);
}
@@ -951,7 +950,7 @@ static void test_slave_loop(const void *arg1, void *arg2)
const bool check_len = true;
TEST_ESP_OK(spitest_check_data(len, t, rcv_data, check_master_data, check_len, check_slave_data));
//clean
vRingbufferReturnItem( context->slave_context.data_received, rcv_data );
vRingbufferReturnItem(context->slave_context.data_received, rcv_data);
}
TEST_ASSERT(spi_slave_free(TEST_SPI_HOST) == ESP_OK);
}
@@ -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

@@ -36,13 +36,13 @@ static WORD_ALIGNED_ATTR uint8_t slave_rxbuf[320];
static const uint8_t master_send[] = { 0x93, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0xaa, 0xcc, 0xff, 0xee, 0x55, 0x77, 0x88, 0x43 };
static const uint8_t slave_send[] = { 0xaa, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x13, 0x57, 0x9b, 0xdf, 0x24, 0x68, 0xac, 0xe0 };
static inline void int_connect( uint32_t gpio, uint32_t sigo, uint32_t sigi )
static inline void int_connect(uint32_t gpio, uint32_t sigo, uint32_t sigi)
{
esp_rom_gpio_connect_out_signal( gpio, sigo, false, false );
esp_rom_gpio_connect_in_signal( gpio, sigi, false );
esp_rom_gpio_connect_out_signal(gpio, sigo, false, false);
esp_rom_gpio_connect_in_signal(gpio, sigi, false);
}
static void master_init( spi_device_handle_t *spi)
static void master_init(spi_device_handle_t *spi)
{
esp_err_t ret;
spi_bus_config_t buscfg = {
@@ -101,15 +101,15 @@ static void custom_setup(void)
memset(slave_rxbuf, 0, sizeof(slave_rxbuf));
//Initialize SPI Master
master_init( &spi );
master_init(&spi);
//Initialize SPI Slave
slave_init();
//Do internal connections
int_connect( PIN_NUM_MOSI, spi_periph_signal[TEST_SPI_HOST].spid_out, spi_periph_signal[TEST_SLAVE_HOST].spiq_in );
int_connect( PIN_NUM_MISO, spi_periph_signal[TEST_SLAVE_HOST].spiq_out, spi_periph_signal[TEST_SPI_HOST].spid_in );
int_connect( PIN_NUM_CS, spi_periph_signal[TEST_SPI_HOST].spics_out[0], spi_periph_signal[TEST_SLAVE_HOST].spics_in );
int_connect( PIN_NUM_CLK, spi_periph_signal[TEST_SPI_HOST].spiclk_out, spi_periph_signal[TEST_SLAVE_HOST].spiclk_in );
int_connect(PIN_NUM_MOSI, spi_periph_signal[TEST_SPI_HOST].spid_out, spi_periph_signal[TEST_SLAVE_HOST].spiq_in);
int_connect(PIN_NUM_MISO, spi_periph_signal[TEST_SLAVE_HOST].spiq_out, spi_periph_signal[TEST_SPI_HOST].spid_in);
int_connect(PIN_NUM_CS, spi_periph_signal[TEST_SPI_HOST].spics_out[0], spi_periph_signal[TEST_SLAVE_HOST].spics_in);
int_connect(PIN_NUM_CLK, spi_periph_signal[TEST_SPI_HOST].spiclk_out, spi_periph_signal[TEST_SLAVE_HOST].spiclk_in);
}
static void custom_teardown(void)
@@ -125,7 +125,7 @@ TEST_CASE("test fullduplex slave with only RX direction", "[spi]")
memcpy(master_txbuf, master_send, sizeof(master_send));
for ( int i = 0; i < 4; i ++ ) {
for (int i = 0; i < 4; i ++) {
//slave send
spi_slave_transaction_t slave_t;
spi_slave_transaction_t *out;
@@ -136,29 +136,29 @@ TEST_CASE("test fullduplex slave with only RX direction", "[spi]")
slave_t.flags |= SPI_SLAVE_TRANS_DMA_BUFFER_ALIGN_AUTO;
// Colorize RX buffer with known pattern
memset( slave_rxbuf, 0x66, sizeof(slave_rxbuf));
memset(slave_rxbuf, 0x66, sizeof(slave_rxbuf));
TEST_ESP_OK(spi_slave_queue_trans(TEST_SLAVE_HOST, &slave_t, portMAX_DELAY));
//send
spi_transaction_t t = {};
t.length = 32 * (i + 1);
if ( t.length != 0 ) {
if (t.length != 0) {
t.tx_buffer = master_txbuf;
t.rx_buffer = NULL;
}
spi_device_transmit( spi, (spi_transaction_t *)&t );
spi_device_transmit(spi, (spi_transaction_t *)&t);
//wait for end
TEST_ESP_OK(spi_slave_get_trans_result(TEST_SLAVE_HOST, &out, portMAX_DELAY));
//show result
ESP_LOGI(SLAVE_TAG, "trans_len: %d", slave_t.trans_len);
ESP_LOG_BUFFER_HEX( "master tx", t.tx_buffer, t.length / 8 );
ESP_LOG_BUFFER_HEX( "slave rx", slave_t.rx_buffer, (slave_t.trans_len + 7) / 8);
ESP_LOG_BUFFER_HEX("master tx", t.tx_buffer, t.length / 8);
ESP_LOG_BUFFER_HEX("slave rx", slave_t.rx_buffer, (slave_t.trans_len + 7) / 8);
TEST_ASSERT_EQUAL_HEX8_ARRAY( t.tx_buffer, slave_t.rx_buffer, t.length / 8 );
TEST_ASSERT_EQUAL( t.length, slave_t.trans_len );
TEST_ASSERT_EQUAL_HEX8_ARRAY(t.tx_buffer, slave_t.rx_buffer, t.length / 8);
TEST_ASSERT_EQUAL(t.length, slave_t.trans_len);
}
custom_teardown();
@@ -172,7 +172,7 @@ TEST_CASE("test fullduplex slave with only TX direction", "[spi]")
memcpy(slave_txbuf, slave_send, sizeof(slave_send));
for ( int i = 0; i < 4; i ++ ) {
for (int i = 0; i < 4; i ++) {
//slave send
spi_slave_transaction_t slave_t;
spi_slave_transaction_t *out;
@@ -183,29 +183,29 @@ TEST_CASE("test fullduplex slave with only TX direction", "[spi]")
slave_t.flags |= SPI_SLAVE_TRANS_DMA_BUFFER_ALIGN_AUTO;
// Colorize RX buffer with known pattern
memset( master_rxbuf, 0x66, sizeof(master_rxbuf));
memset(master_rxbuf, 0x66, sizeof(master_rxbuf));
TEST_ESP_OK(spi_slave_queue_trans(TEST_SLAVE_HOST, &slave_t, portMAX_DELAY));
//send
spi_transaction_t t = {};
t.length = 32 * (i + 1);
if ( t.length != 0 ) {
if (t.length != 0) {
t.tx_buffer = NULL;
t.rx_buffer = master_rxbuf;
}
spi_device_transmit( spi, (spi_transaction_t *)&t );
spi_device_transmit(spi, (spi_transaction_t *)&t);
//wait for end
TEST_ESP_OK(spi_slave_get_trans_result(TEST_SLAVE_HOST, &out, portMAX_DELAY));
//show result
ESP_LOGI(SLAVE_TAG, "trans_len: %d", slave_t.trans_len);
ESP_LOG_BUFFER_HEX( "master rx", t.rx_buffer, t.length / 8 );
ESP_LOG_BUFFER_HEX( "slave tx", slave_t.tx_buffer, (slave_t.trans_len + 7) / 8);
ESP_LOG_BUFFER_HEX("master rx", t.rx_buffer, t.length / 8);
ESP_LOG_BUFFER_HEX("slave tx", slave_t.tx_buffer, (slave_t.trans_len + 7) / 8);
TEST_ASSERT_EQUAL_HEX8_ARRAY( slave_t.tx_buffer, t.rx_buffer, t.length / 8 );
TEST_ASSERT_EQUAL( t.length, slave_t.trans_len );
TEST_ASSERT_EQUAL_HEX8_ARRAY(slave_t.tx_buffer, t.rx_buffer, t.length / 8);
TEST_ASSERT_EQUAL(t.length, slave_t.trans_len);
}
custom_teardown();
@@ -220,7 +220,7 @@ TEST_CASE("test slave send unaligned", "[spi]")
memcpy(master_txbuf, master_send, sizeof(master_send));
memcpy(slave_txbuf, slave_send, sizeof(slave_send));
for ( int i = 0; i < 4; i ++ ) {
for (int i = 0; i < 4; i ++) {
//slave send
spi_slave_transaction_t slave_t;
spi_slave_transaction_t *out;
@@ -231,33 +231,33 @@ TEST_CASE("test slave send unaligned", "[spi]")
slave_t.flags |= SPI_SLAVE_TRANS_DMA_BUFFER_ALIGN_AUTO;
// Colorize RX buffers with known pattern
memset( master_rxbuf, 0x66, sizeof(master_rxbuf));
memset( slave_rxbuf, 0x66, sizeof(slave_rxbuf));
memset(master_rxbuf, 0x66, sizeof(master_rxbuf));
memset(slave_rxbuf, 0x66, sizeof(slave_rxbuf));
TEST_ESP_OK(spi_slave_queue_trans(TEST_SLAVE_HOST, &slave_t, portMAX_DELAY));
//send
spi_transaction_t t = {};
t.length = 32 * (i + 1);
if ( t.length != 0 ) {
if (t.length != 0) {
t.tx_buffer = master_txbuf + i;
t.rx_buffer = master_rxbuf + i;
}
spi_device_transmit( spi, (spi_transaction_t *)&t );
spi_device_transmit(spi, (spi_transaction_t *)&t);
//wait for end
TEST_ESP_OK(spi_slave_get_trans_result(TEST_SLAVE_HOST, &out, portMAX_DELAY));
//show result
ESP_LOGI(SLAVE_TAG, "trans_len: %d", slave_t.trans_len);
ESP_LOG_BUFFER_HEX( "master tx", t.tx_buffer, t.length / 8 );
ESP_LOG_BUFFER_HEX( "master rx", t.rx_buffer, t.length / 8 );
ESP_LOG_BUFFER_HEX( "slave tx", slave_t.tx_buffer, (slave_t.trans_len + 7) / 8);
ESP_LOG_BUFFER_HEX( "slave rx", slave_t.rx_buffer, (slave_t.trans_len + 7) / 8);
ESP_LOG_BUFFER_HEX("master tx", t.tx_buffer, t.length / 8);
ESP_LOG_BUFFER_HEX("master rx", t.rx_buffer, t.length / 8);
ESP_LOG_BUFFER_HEX("slave tx", slave_t.tx_buffer, (slave_t.trans_len + 7) / 8);
ESP_LOG_BUFFER_HEX("slave rx", slave_t.rx_buffer, (slave_t.trans_len + 7) / 8);
TEST_ASSERT_EQUAL_HEX8_ARRAY( t.tx_buffer, slave_t.rx_buffer, t.length / 8 );
TEST_ASSERT_EQUAL_HEX8_ARRAY( slave_t.tx_buffer, t.rx_buffer, t.length / 8 );
TEST_ASSERT_EQUAL( t.length, slave_t.trans_len );
TEST_ASSERT_EQUAL_HEX8_ARRAY(t.tx_buffer, slave_t.rx_buffer, t.length / 8);
TEST_ASSERT_EQUAL_HEX8_ARRAY(slave_t.tx_buffer, t.rx_buffer, t.length / 8);
TEST_ASSERT_EQUAL(t.length, slave_t.trans_len);
}
custom_teardown();

View File

@@ -48,16 +48,16 @@ static uint32_t get_hd_flags(void)
ESP_LOGI("io mode", "%d", flag_id);
switch (flag_id) {
case 1:
return SPI_TRANS_MODE_DIO;
case 2:
return SPI_TRANS_MODE_DIO | SPI_TRANS_MODE_DIOQIO_ADDR;
case 3:
return SPI_TRANS_MODE_QIO;
case 4:
return SPI_TRANS_MODE_QIO | SPI_TRANS_MODE_DIOQIO_ADDR;
default:
return 0;
case 1:
return SPI_TRANS_MODE_DIO;
case 2:
return SPI_TRANS_MODE_DIO | SPI_TRANS_MODE_DIOQIO_ADDR;
case 3:
return SPI_TRANS_MODE_QIO;
case 4:
return SPI_TRANS_MODE_QIO | SPI_TRANS_MODE_DIOQIO_ADDR;
default:
return 0;
}
}
@@ -79,7 +79,7 @@ void config_single_board_test_pin(void)
static void init_master_hd(spi_device_handle_t* spi, const spitest_param_set_t* config, int freq)
{
spi_bus_config_t bus_cfg = SPI_BUS_TEST_DEFAULT_CONFIG();
bus_cfg.max_transfer_sz = TEST_DMA_MAX_SIZE*30;
bus_cfg.max_transfer_sz = TEST_DMA_MAX_SIZE * 30;
bus_cfg.quadhd_io_num = PIN_NUM_HD;
bus_cfg.quadwp_io_num = PIN_NUM_WP;
#if defined(TEST_MASTER_GPIO_MATRIX) && CONFIG_IDF_TARGET_ESP32S2
@@ -101,7 +101,7 @@ static void init_master_hd(spi_device_handle_t* spi, const spitest_param_set_t*
static void init_slave_hd(int mode, bool append_mode, const spi_slave_hd_callback_config_t* callback)
{
spi_bus_config_t bus_cfg = SPI_BUS_TEST_DEFAULT_CONFIG();
bus_cfg.max_transfer_sz = TEST_DMA_MAX_SIZE*30;
bus_cfg.max_transfer_sz = TEST_DMA_MAX_SIZE * 30;
bus_cfg.quadwp_io_num = -1;
bus_cfg.quadhd_io_num = -1;
#ifdef TEST_SLAVE_GPIO_MATRIX
@@ -116,18 +116,18 @@ static void init_slave_hd(int mode, bool append_mode, const spi_slave_hd_callbac
if (callback) {
slave_hd_cfg.cb_config = *callback;
} else {
slave_hd_cfg.cb_config = (spi_slave_hd_callback_config_t){};
slave_hd_cfg.cb_config = (spi_slave_hd_callback_config_t) {};
}
TEST_ESP_OK(spi_slave_hd_init(TEST_SLAVE_HOST, &bus_cfg, &slave_hd_cfg));
}
static void test_hd_init(void** arg)
{
TEST_ASSERT(*arg==NULL);
TEST_ASSERT(*arg == NULL);
*arg = heap_caps_malloc(sizeof(testhd_context_t), MALLOC_CAP_DMA);
assert(((int)arg%4)==0);
assert(((int)arg % 4) == 0);
testhd_context_t* context = (testhd_context_t*)*arg;
TEST_ASSERT(context!=NULL);
TEST_ASSERT(context != NULL);
context->ev_rdbuf = xSemaphoreCreateBinary();
context->ev_wrbuf = xSemaphoreCreateBinary();
@@ -143,7 +143,7 @@ static void test_hd_deinit(void* arg)
esp_err_t wait_wrbuf_sig(testhd_context_t* context, TickType_t wait)
{
BaseType_t r = xSemaphoreTake(context->ev_wrbuf, wait);
if (r==pdTRUE) {
if (r == pdTRUE) {
return ESP_OK;
} else {
return ESP_ERR_TIMEOUT;
@@ -153,7 +153,7 @@ esp_err_t wait_wrbuf_sig(testhd_context_t* context, TickType_t wait)
esp_err_t wait_rdbuf_sig(testhd_context_t* context, TickType_t wait)
{
BaseType_t r = xSemaphoreTake(context->ev_rdbuf, wait);
if (r==pdTRUE) {
if (r == pdTRUE) {
return ESP_OK;
} else {
return ESP_ERR_TIMEOUT;
@@ -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)
@@ -253,8 +257,10 @@ void check_no_signal(testhd_context_t* context)
void test_wrdma(testhd_context_t* ctx, const spitest_param_set_t *cfg, spi_device_handle_t spi)
{
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;
int len = rand() % TEST_DMA_MAX_SIZE + 1;
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;
@@ -299,8 +304,10 @@ void test_rddma(testhd_context_t* ctx, const spitest_param_set_t* cfg, spi_devic
spitest_cmp_or_dump(data_expected, ctx->master_rddma_buf, len);
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;
len = rand() % TEST_DMA_MAX_SIZE + 1;
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);
@@ -333,8 +344,8 @@ static void test_hd_loop(const void* arg1, void* arg2)
uint8_t recv_buffer[REG_REGION_SIZE];
srand(123);
uint32_t mem[(REG_REGION_SIZE/4)];
for (int i = 0; i < (REG_REGION_SIZE/4); i++) {
uint32_t mem[(REG_REGION_SIZE / 4)];
for (int i = 0; i < (REG_REGION_SIZE / 4); i++) {
mem[i] = rand();
}
mem_ptr = (uint8_t*)mem;
@@ -344,16 +355,18 @@ static void test_hd_loop(const void* arg1, void* arg2)
spi_slave_hd_write_buffer(TEST_SLAVE_HOST, 0, (uint8_t *) mem, SOC_SPI_MAXIMUM_BUFFER_SIZE);
srand(123);
for (int i = 0; i < (REG_REGION_SIZE/4); i++) {
for (int i = 0; i < (REG_REGION_SIZE / 4); i++) {
TEST_ASSERT(mem[i] == rand());
}
check_no_signal(context);
test_rddma(context, test_cfg, spi);
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;
int pos = rand() % REG_REGION_SIZE;
int len = rand() % REG_REGION_SIZE + 1;
if (len + pos > REG_REGION_SIZE) {
len = REG_REGION_SIZE - pos;
}
memset(recv_buffer, 0xcc, sizeof(recv_buffer));
@@ -389,13 +402,15 @@ static void test_hd_loop(const void* arg1, void* arg2)
srand(466);
for (int i = 0; i < 64; i ++) {
ESP_LOGI("temp_i", "^^^^^^^^^^^^^^^^ %d ^^^^^^^^^^", i);
for (int j = 0; j < (REG_REGION_SIZE/4); j++) {
for (int j = 0; j < (REG_REGION_SIZE / 4); j++) {
mem[j] = rand();
}
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,37 +469,41 @@ 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,
.slave_iomux = false,
.slave_tv_ns = TV_WITH_ESP_SLAVE,
.mode = 0,
.dup = FULL_DUPLEX,
.master_iomux = false,
.slave_iomux = false,
.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,
.slave_iomux = false,
.slave_tv_ns = TV_WITH_ESP_SLAVE,
.mode = 1,
.dup = FULL_DUPLEX,
.master_iomux = false,
.slave_iomux = false,
.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,
.slave_iomux = false,
.slave_tv_ns = TV_WITH_ESP_SLAVE,
.mode = 2,
.dup = FULL_DUPLEX,
.master_iomux = false,
.slave_iomux = false,
.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,
.slave_iomux = false,
.slave_tv_ns = TV_WITH_ESP_SLAVE,
.mode = 3,
.dup = FULL_DUPLEX,
.master_iomux = false,
.slave_iomux = false,
.slave_tv_ns = TV_WITH_ESP_SLAVE,
.mode = 3,
},
};
TEST_SPI_HD(HD, hd_conf);
@@ -500,7 +519,7 @@ TEST_CASE("test spi slave hd segment mode, master too long", "[spi][spi_slv_hd]"
{
spi_device_handle_t spi;
spitest_param_set_t *cfg = &hd_conf[0];
int freq = 100*1000; // the frequency should be small enough for the slave to prepare new trans
int freq = 100 * 1000; // the frequency should be small enough for the slave to prepare new trans
init_master_hd(&spi, cfg, freq);
@@ -519,8 +538,8 @@ TEST_CASE("test spi slave hd segment mode, master too long", "[spi][spi_slv_hd]"
memset(slave_recv_buf, 0xcc, send_buf_size * 2);
memset(master_recv_buf, 0xcc, send_buf_size * 2);
srand (939);
for (int i = 0; i< send_buf_size * 2; i++) {
srand(939);
for (int i = 0; i < send_buf_size * 2; i++) {
master_send_buf[i] = rand();
slave_send_buf[i] = rand();
}
@@ -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,
@@ -788,7 +806,7 @@ static void hd_master_quad(void){
essl_spi_rddma(spi, master_recv_buf, BUF_SIZE / 2, -1, SPI_TRANS_MODE_QIO);
unity_wait_for_signal("slave ready");
essl_spi_rddma(spi, master_recv_buf+ BUF_SIZE / 2, BUF_SIZE / 2, -1, SPI_TRANS_MODE_QIO);
essl_spi_rddma(spi, master_recv_buf + BUF_SIZE / 2, BUF_SIZE / 2, -1, SPI_TRANS_MODE_QIO);
ESP_LOG_BUFFER_HEX("slave send", slave_send_buf, BUF_SIZE);
ESP_LOG_BUFFER_HEX("master recv", master_recv_buf, BUF_SIZE);
@@ -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,
@@ -839,7 +858,7 @@ static void hd_slave_quad(void){
.len = (trans_len + 3) & (~3),
},
{
.data = slave_recv_buf+BUF_SIZE/2,
.data = slave_recv_buf + BUF_SIZE / 2,
.len = (trans_len + 3) & (~3),
},
//send
@@ -847,8 +866,8 @@ static void hd_slave_quad(void){
.data = slave_send_buf,
.len = (trans_len + 3) & (~3),
},
{
.data = slave_send_buf+BUF_SIZE/2,
{
.data = slave_send_buf + BUF_SIZE / 2,
.len = (trans_len + 3) & (~3),
},
};
@@ -887,15 +906,14 @@ 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 ++) {
for (int line_index = 1; line_index < len; line_index ++) {
buff[line_index] = buff[0] + line_index * diff;
}
}
@@ -916,7 +934,7 @@ void slave_run_append(void)
// append some data first
for (uint32_t cache_instans = 0; cache_instans < TEST_APPEND_CACHE_SIZE; cache_instans++) {
int trans_len = 16 << (cache_instans+1);
int trans_len = 16 << (cache_instans + 1);
if (trans_len > TEST_TRANS_LEN) {
trans_len = TEST_TRANS_LEN;
}
@@ -959,7 +977,7 @@ void slave_run_append(void)
//------------------------------------tx direction------------------------------
spi_slave_hd_data_t slave_tx_trans[TEST_APPEND_CACHE_SIZE] = {};
for (uint32_t cache_instans = 0; cache_instans < TEST_APPEND_CACHE_SIZE; cache_instans ++) {
int trans_len = 16 << (cache_instans+1);
int trans_len = 16 << (cache_instans + 1);
if (trans_len >= TEST_TRANS_LEN) {
trans_len = TEST_TRANS_LEN;
}
@@ -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,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

@@ -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