mirror of
https://github.com/espressif/esp-idf
synced 2025-03-10 01:29:21 -04:00
Merge branch 'refactor/esp_driver_spi' into 'master'
refactor(spi): make spi driver as component Closes IDF-8371 See merge request espressif/esp-idf!26549
This commit is contained in:
commit
2b173ce727
@ -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()
|
||||
|
@ -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"
|
||||
|
@ -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
|
45
components/driver/sdspi/sdspi_crc.c
Normal file
45
components/driver/sdspi/sdspi_crc.c
Normal 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);
|
||||
}
|
@ -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
|
@ -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);
|
@ -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)
|
@ -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) {
|
@ -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);
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
|
26
components/esp_driver_spi/CMakeLists.txt
Normal file
26
components/esp_driver_spi/CMakeLists.txt
Normal 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"
|
||||
)
|
61
components/esp_driver_spi/Kconfig
Normal file
61
components/esp_driver_spi/Kconfig
Normal 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
|
@ -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
|
||||
*
|
@ -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.
|
||||
*
|
@ -4,7 +4,6 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _DRIVER_SPI_SLAVE_H_
|
||||
#define _DRIVER_SPI_SLAVE_H_
|
||||
|
||||
@ -13,13 +12,11 @@
|
||||
#include "freertos/semphr.h"
|
||||
#include "driver/spi_common.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
#define SPI_SLAVE_TXBIT_LSBFIRST (1<<0) ///< Transmit command/address/data LSB first instead of the default MSB first
|
||||
#define SPI_SLAVE_RXBIT_LSBFIRST (1<<1) ///< Receive data LSB first instead of the default MSB first
|
||||
#define SPI_SLAVE_BIT_LSBFIRST (SPI_SLAVE_TXBIT_LSBFIRST|SPI_SLAVE_RXBIT_LSBFIRST) ///< Transmit and receive LSB first
|
||||
@ -65,7 +62,6 @@ typedef struct {
|
||||
*/
|
||||
} spi_slave_interface_config_t;
|
||||
|
||||
|
||||
#define SPI_SLAVE_TRANS_DMA_BUFFER_ALIGN_AUTO (1<<0) ///< Automatically re-malloc dma buffer if user buffer doesn't meet hardware alignment or dma_capable, this process may loss some memory and performance
|
||||
|
||||
/**
|
||||
@ -123,7 +119,6 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b
|
||||
*/
|
||||
esp_err_t spi_slave_free(spi_host_device_t host);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Queue a SPI transaction for execution
|
||||
*
|
||||
@ -148,7 +143,6 @@ esp_err_t spi_slave_free(spi_host_device_t host);
|
||||
*/
|
||||
esp_err_t spi_slave_queue_trans(spi_host_device_t host, const spi_slave_transaction_t *trans_desc, TickType_t ticks_to_wait);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the result of a SPI transaction queued earlier
|
||||
*
|
||||
@ -171,7 +165,6 @@ esp_err_t spi_slave_queue_trans(spi_host_device_t host, const spi_slave_transact
|
||||
*/
|
||||
esp_err_t spi_slave_get_trans_result(spi_host_device_t host, spi_slave_transaction_t **trans_desc, TickType_t ticks_to_wait);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Do a SPI transaction
|
||||
*
|
||||
@ -191,7 +184,6 @@ esp_err_t spi_slave_get_trans_result(spi_host_device_t host, spi_slave_transacti
|
||||
*/
|
||||
esp_err_t spi_slave_transmit(spi_host_device_t host, spi_slave_transaction_t *trans_desc, TickType_t ticks_to_wait);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -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
|
@ -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
|
@ -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
|
0
components/esp_driver_spi/linker.lf
Normal file
0
components/esp_driver_spi/linker.lf
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
@ -137,7 +137,7 @@ typedef struct spi_device_t spi_device_t;
|
||||
typedef struct {
|
||||
spi_transaction_t *trans;
|
||||
const uint32_t *buffer_to_send; //equals to tx_data, if SPI_TRANS_USE_RXDATA is applied; otherwise if original buffer wasn't in DMA-capable memory, this gets the address of a temporary buffer that is;
|
||||
//otherwise sets to the original buffer or NULL if no buffer is assigned.
|
||||
//otherwise sets to the original buffer or NULL if no buffer is assigned.
|
||||
uint32_t *buffer_to_rcv; // similar to buffer_to_send
|
||||
} spi_trans_priv_t;
|
||||
|
||||
@ -305,7 +305,7 @@ static esp_err_t spi_master_deinit_driver(void* arg)
|
||||
SPI_CHECK(is_valid_host(host_id), "invalid host_id", ESP_ERR_INVALID_ARG);
|
||||
|
||||
int x;
|
||||
for (x=0; x<DEV_NUM_MAX; x++) {
|
||||
for (x = 0; x < DEV_NUM_MAX; x++) {
|
||||
SPI_CHECK(host->device[x] == NULL, "not all CSses freed", ESP_ERR_INVALID_STATE);
|
||||
}
|
||||
|
||||
@ -326,8 +326,12 @@ void spi_get_timing(bool gpio_is_used, int input_delay_ns, int eff_clk, int* dum
|
||||
int timing_miso_delay;
|
||||
|
||||
spi_hal_cal_timing(APB_CLK_FREQ, eff_clk, gpio_is_used, input_delay_ns, &timing_dummy, &timing_miso_delay);
|
||||
if (dummy_o) *dummy_o = timing_dummy;
|
||||
if (cycles_remain_o) *cycles_remain_o = timing_miso_delay;
|
||||
if (dummy_o) {
|
||||
*dummy_o = timing_dummy;
|
||||
}
|
||||
if (cycles_remain_o) {
|
||||
*cycles_remain_o = timing_miso_delay;
|
||||
}
|
||||
#else
|
||||
//TODO: IDF-6578
|
||||
ESP_LOGW(SPI_TAG, "This func temporary not supported for current target!");
|
||||
@ -382,7 +386,7 @@ esp_err_t spi_bus_add_device(spi_host_device_t host_id, const spi_device_interfa
|
||||
//The hardware looks like it would support this, but actually setting cs_ena_pretrans when transferring in full
|
||||
//duplex mode does absolutely nothing on the ESP32.
|
||||
SPI_CHECK(dev_config->cs_ena_pretrans <= 1 || (dev_config->address_bits == 0 && dev_config->command_bits == 0) ||
|
||||
(dev_config->flags & SPI_DEVICE_HALFDUPLEX), "In full-duplex mode, only support cs pretrans delay = 1 and without address_bits and command_bits", ESP_ERR_INVALID_ARG);
|
||||
(dev_config->flags & SPI_DEVICE_HALFDUPLEX), "In full-duplex mode, only support cs pretrans delay = 1 and without address_bits and command_bits", ESP_ERR_INVALID_ARG);
|
||||
#endif
|
||||
|
||||
//Check post_cb status when `SPI_DEVICE_NO_RETURN_RESULT` flag is set.
|
||||
@ -428,7 +432,9 @@ esp_err_t spi_bus_add_device(spi_host_device_t host_id, const spi_device_interfa
|
||||
|
||||
//Allocate memory for device
|
||||
dev = malloc(sizeof(spi_device_t));
|
||||
if (dev == NULL) goto nomem;
|
||||
if (dev == NULL) {
|
||||
goto nomem;
|
||||
}
|
||||
memset(dev, 0, sizeof(spi_device_t));
|
||||
|
||||
dev->id = freecs;
|
||||
@ -461,7 +467,7 @@ esp_err_t spi_bus_add_device(spi_host_device_t host_id, const spi_device_interfa
|
||||
//save a pointer to device in spi_host_t
|
||||
host->device[freecs] = dev;
|
||||
//save a pointer to host in spi_device_t
|
||||
dev->host= host;
|
||||
dev->host = host;
|
||||
|
||||
//initialise the device specific configuration
|
||||
spi_hal_dev_config_t *hal_dev = &(dev->hal_dev);
|
||||
@ -486,14 +492,18 @@ esp_err_t spi_bus_add_device(spi_host_device_t host_id, const spi_device_interfa
|
||||
hal_dev->positive_cs = dev_config->flags & SPI_DEVICE_POSITIVE_CS ? 1 : 0;
|
||||
|
||||
*handle = dev;
|
||||
ESP_LOGD(SPI_TAG, "SPI%d: New device added to CS%d, effective clock: %dkHz", host_id+1, freecs, freq/1000);
|
||||
ESP_LOGD(SPI_TAG, "SPI%d: New device added to CS%d, effective clock: %dkHz", host_id + 1, freecs, freq / 1000);
|
||||
|
||||
return ESP_OK;
|
||||
|
||||
nomem:
|
||||
if (dev) {
|
||||
if (dev->trans_queue) vQueueDelete(dev->trans_queue);
|
||||
if (dev->ret_queue) vQueueDelete(dev->ret_queue);
|
||||
if (dev->trans_queue) {
|
||||
vQueueDelete(dev->trans_queue);
|
||||
}
|
||||
if (dev->ret_queue) {
|
||||
vQueueDelete(dev->ret_queue);
|
||||
}
|
||||
spi_bus_lock_unregister_dev(dev->dev_lock);
|
||||
}
|
||||
free(dev);
|
||||
@ -502,13 +512,13 @@ nomem:
|
||||
|
||||
esp_err_t spi_bus_remove_device(spi_device_handle_t handle)
|
||||
{
|
||||
SPI_CHECK(handle!=NULL, "invalid handle", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK(handle != NULL, "invalid handle", ESP_ERR_INVALID_ARG);
|
||||
//These checks aren't exhaustive; another thread could sneak in a transaction inbetween. These are only here to
|
||||
//catch design errors and aren't meant to be triggered during normal operation.
|
||||
SPI_CHECK(uxQueueMessagesWaiting(handle->trans_queue)==0, "Have unfinished transactions", ESP_ERR_INVALID_STATE);
|
||||
SPI_CHECK(uxQueueMessagesWaiting(handle->trans_queue) == 0, "Have unfinished transactions", ESP_ERR_INVALID_STATE);
|
||||
SPI_CHECK(handle->host->cur_cs == DEV_NUM_MAX || handle->host->device[handle->host->cur_cs] != handle, "Have unfinished transactions", ESP_ERR_INVALID_STATE);
|
||||
if (handle->ret_queue) {
|
||||
SPI_CHECK(uxQueueMessagesWaiting(handle->ret_queue)==0, "Have unfinished transactions", ESP_ERR_INVALID_STATE);
|
||||
SPI_CHECK(uxQueueMessagesWaiting(handle->ret_queue) == 0, "Have unfinished transactions", ESP_ERR_INVALID_STATE);
|
||||
}
|
||||
|
||||
#if SOC_SPI_SUPPORT_CLK_RC_FAST
|
||||
@ -519,11 +529,17 @@ esp_err_t spi_bus_remove_device(spi_device_handle_t handle)
|
||||
|
||||
//return
|
||||
int spics_io_num = handle->cfg.spics_io_num;
|
||||
if (spics_io_num >= 0) spicommon_cs_free_io(spics_io_num);
|
||||
if (spics_io_num >= 0) {
|
||||
spicommon_cs_free_io(spics_io_num);
|
||||
}
|
||||
|
||||
//Kill queues
|
||||
if (handle->trans_queue) vQueueDelete(handle->trans_queue);
|
||||
if (handle->ret_queue) vQueueDelete(handle->ret_queue);
|
||||
if (handle->trans_queue) {
|
||||
vQueueDelete(handle->trans_queue);
|
||||
}
|
||||
if (handle->ret_queue) {
|
||||
vQueueDelete(handle->ret_queue);
|
||||
}
|
||||
spi_bus_lock_unregister_dev(handle->dev_lock);
|
||||
|
||||
assert(handle->host->device[handle->id] == handle);
|
||||
@ -534,7 +550,7 @@ esp_err_t spi_bus_remove_device(spi_device_handle_t handle)
|
||||
|
||||
esp_err_t spi_device_get_actual_freq(spi_device_handle_t handle, int* freq_khz)
|
||||
{
|
||||
if ((spi_device_t*)handle == NULL || freq_khz == NULL) {
|
||||
if ((spi_device_t *)handle == NULL || freq_khz == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
@ -568,7 +584,9 @@ static SPI_MASTER_ISR_ATTR void spi_setup_device(spi_device_t *dev)
|
||||
static SPI_MASTER_ISR_ATTR spi_device_t *get_acquiring_dev(spi_host_t *host)
|
||||
{
|
||||
spi_bus_lock_dev_handle_t dev_lock = spi_bus_lock_get_acquiring_dev(host->bus_attr->lock);
|
||||
if (!dev_lock) return NULL;
|
||||
if (!dev_lock) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return host->device[spi_bus_lock_get_dev_id(dev_lock)];
|
||||
}
|
||||
@ -623,7 +641,7 @@ static void SPI_MASTER_ISR_ATTR spi_new_trans(spi_device_t *dev, spi_trans_priv_
|
||||
|
||||
//Set up OIO/QIO/DIO if needed
|
||||
hal_trans.line_mode.data_lines = (trans->flags & SPI_TRANS_MODE_DIO) ? 2 :
|
||||
(trans->flags & SPI_TRANS_MODE_QIO) ? 4 : 1;
|
||||
(trans->flags & SPI_TRANS_MODE_QIO) ? 4 : 1;
|
||||
#if SOC_SPI_SUPPORT_OCT
|
||||
if (trans->flags & SPI_TRANS_MODE_OCT) {
|
||||
hal_trans.line_mode.data_lines = 8;
|
||||
@ -652,7 +670,9 @@ static void SPI_MASTER_ISR_ATTR spi_new_trans(spi_device_t *dev, spi_trans_priv_
|
||||
spi_hal_prepare_data(hal, hal_dev, &hal_trans);
|
||||
|
||||
//Call pre-transmission callback, if any
|
||||
if (dev->cfg.pre_cb) dev->cfg.pre_cb(trans);
|
||||
if (dev->cfg.pre_cb) {
|
||||
dev->cfg.pre_cb(trans);
|
||||
}
|
||||
//Kick off transfer
|
||||
spi_hal_user_start(hal);
|
||||
}
|
||||
@ -666,7 +686,9 @@ static void SPI_MASTER_ISR_ATTR spi_post_trans(spi_host_t *host)
|
||||
spi_hal_fetch_result(&host->hal);
|
||||
//Call post-transaction callback, if any
|
||||
spi_device_t* dev = host->device[host->cur_cs];
|
||||
if (dev->cfg.post_cb) dev->cfg.post_cb(cur_trans);
|
||||
if (dev->cfg.post_cb) {
|
||||
dev->cfg.post_cb(cur_trans);
|
||||
}
|
||||
|
||||
host->cur_cs = DEV_NUM_MAX;
|
||||
}
|
||||
@ -734,7 +756,6 @@ static void SPI_MASTER_ISR_ATTR spi_intr(void *arg)
|
||||
spi_bus_lock_handle_t lock = host->bus_attr->lock;
|
||||
BaseType_t trans_found = pdFALSE;
|
||||
|
||||
|
||||
// There should be remaining requests
|
||||
BUS_LOCK_DEBUG_EXECUTE_CHECK(spi_bus_lock_bg_req_exist(lock));
|
||||
|
||||
@ -781,26 +802,28 @@ static void SPI_MASTER_ISR_ATTR spi_intr(void *arg)
|
||||
// or resume acquiring device task (if quit due to bus acquiring).
|
||||
} while (!spi_bus_lock_bg_exit(lock, trans_found, &do_yield));
|
||||
|
||||
if (do_yield) portYIELD_FROM_ISR();
|
||||
if (do_yield) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
|
||||
static SPI_MASTER_ISR_ATTR esp_err_t check_trans_valid(spi_device_handle_t handle, spi_transaction_t *trans_desc)
|
||||
{
|
||||
SPI_CHECK(handle!=NULL, "invalid dev handle", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK(handle != NULL, "invalid dev handle", ESP_ERR_INVALID_ARG);
|
||||
spi_host_t *host = handle->host;
|
||||
const spi_bus_attr_t* bus_attr = host->bus_attr;
|
||||
bool tx_enabled = (trans_desc->flags & SPI_TRANS_USE_TXDATA) || (trans_desc->tx_buffer);
|
||||
bool rx_enabled = (trans_desc->flags & SPI_TRANS_USE_RXDATA) || (trans_desc->rx_buffer);
|
||||
spi_transaction_ext_t *t_ext = (spi_transaction_ext_t *)trans_desc;
|
||||
bool dummy_enabled = (((trans_desc->flags & SPI_TRANS_VARIABLE_DUMMY)? t_ext->dummy_bits: handle->cfg.dummy_bits) != 0);
|
||||
bool dummy_enabled = (((trans_desc->flags & SPI_TRANS_VARIABLE_DUMMY) ? t_ext->dummy_bits : handle->cfg.dummy_bits) != 0);
|
||||
bool extra_dummy_enabled = handle->hal_dev.timing_conf.timing_dummy;
|
||||
bool is_half_duplex = ((handle->cfg.flags & SPI_DEVICE_HALFDUPLEX) != 0);
|
||||
|
||||
//check transmission length
|
||||
SPI_CHECK((trans_desc->flags & SPI_TRANS_USE_RXDATA)==0 || trans_desc->rxlength <= 32, "SPI_TRANS_USE_RXDATA only available for rxdata transfer <= 32 bits", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK((trans_desc->flags & SPI_TRANS_USE_TXDATA)==0 || trans_desc->length <= 32, "SPI_TRANS_USE_TXDATA only available for txdata transfer <= 32 bits", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK(trans_desc->length <= bus_attr->max_transfer_sz*8, "txdata transfer > host maximum", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK(trans_desc->rxlength <= bus_attr->max_transfer_sz*8, "rxdata transfer > host maximum", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK((trans_desc->flags & SPI_TRANS_USE_RXDATA) == 0 || trans_desc->rxlength <= 32, "SPI_TRANS_USE_RXDATA only available for rxdata transfer <= 32 bits", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK((trans_desc->flags & SPI_TRANS_USE_TXDATA) == 0 || trans_desc->length <= 32, "SPI_TRANS_USE_TXDATA only available for txdata transfer <= 32 bits", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK(trans_desc->length <= bus_attr->max_transfer_sz * 8, "txdata transfer > host maximum", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK(trans_desc->rxlength <= bus_attr->max_transfer_sz * 8, "rxdata transfer > host maximum", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK(is_half_duplex || trans_desc->rxlength <= trans_desc->length, "rx length > tx length in full duplex mode", ESP_ERR_INVALID_ARG);
|
||||
//check working mode
|
||||
#if SOC_SPI_SUPPORT_OCT
|
||||
@ -808,10 +831,10 @@ static SPI_MASTER_ISR_ATTR esp_err_t check_trans_valid(spi_device_handle_t handl
|
||||
SPI_CHECK(!((trans_desc->flags & SPI_TRANS_MODE_OCT) && (handle->cfg.flags & SPI_DEVICE_3WIRE)), "Incompatible when setting to both Octal mode and 3-wire-mode", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK(!((trans_desc->flags & SPI_TRANS_MODE_OCT) && !is_half_duplex), "Incompatible when setting to both Octal mode and half duplex mode", ESP_ERR_INVALID_ARG);
|
||||
#endif
|
||||
SPI_CHECK(!((trans_desc->flags & (SPI_TRANS_MODE_DIO|SPI_TRANS_MODE_QIO)) && (handle->cfg.flags & SPI_DEVICE_3WIRE)), "Incompatible when setting to both multi-line mode and 3-wire-mode", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK(!((trans_desc->flags & (SPI_TRANS_MODE_DIO|SPI_TRANS_MODE_QIO)) && !is_half_duplex), "Incompatible when setting to both multi-line mode and half duplex mode", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK(!((trans_desc->flags & (SPI_TRANS_MODE_DIO | SPI_TRANS_MODE_QIO)) && (handle->cfg.flags & SPI_DEVICE_3WIRE)), "Incompatible when setting to both multi-line mode and 3-wire-mode", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK(!((trans_desc->flags & (SPI_TRANS_MODE_DIO | SPI_TRANS_MODE_QIO)) && !is_half_duplex), "Incompatible when setting to both multi-line mode and half duplex mode", ESP_ERR_INVALID_ARG);
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
SPI_CHECK(!is_half_duplex || !bus_attr->dma_enabled || !rx_enabled || !tx_enabled, "SPI half duplex mode does not support using DMA with both MOSI and MISO phases.", ESP_ERR_INVALID_ARG );
|
||||
SPI_CHECK(!is_half_duplex || !bus_attr->dma_enabled || !rx_enabled || !tx_enabled, "SPI half duplex mode does not support using DMA with both MOSI and MISO phases.", ESP_ERR_INVALID_ARG);
|
||||
#endif
|
||||
#if !SOC_SPI_HD_BOTH_INOUT_SUPPORTED
|
||||
//On these chips, HW doesn't support using both TX and RX phases when in halfduplex mode
|
||||
@ -825,8 +848,8 @@ static SPI_MASTER_ISR_ATTR esp_err_t check_trans_valid(spi_device_handle_t handl
|
||||
SPI_CHECK(!is_half_duplex || trans_desc->rxlength != 0 || !rx_enabled, "trans rx_buffer should be NULL and SPI_TRANS_USE_RXDATA should be cleared to skip MISO phase.", ESP_ERR_INVALID_ARG);
|
||||
//In Full duplex mode, default rxlength to be the same as length, if not filled in.
|
||||
// set rxlength to length is ok, even when rx buffer=NULL
|
||||
if (trans_desc->rxlength==0 && !is_half_duplex) {
|
||||
trans_desc->rxlength=trans_desc->length;
|
||||
if (trans_desc->rxlength == 0 && !is_half_duplex) {
|
||||
trans_desc->rxlength = trans_desc->length;
|
||||
}
|
||||
//Dummy phase is not available when both data out and in are enabled, regardless of FD or HD mode.
|
||||
SPI_CHECK(!tx_enabled || !rx_enabled || !dummy_enabled || !extra_dummy_enabled, "Dummy phase is not available when both data out and in are enabled", ESP_ERR_INVALID_ARG);
|
||||
@ -846,7 +869,7 @@ static SPI_MASTER_ISR_ATTR void uninstall_priv_desc(spi_trans_priv_t* trans_buf)
|
||||
{
|
||||
spi_transaction_t *trans_desc = trans_buf->trans;
|
||||
if ((void *)trans_buf->buffer_to_send != &trans_desc->tx_data[0] &&
|
||||
trans_buf->buffer_to_send != trans_desc->tx_buffer) {
|
||||
trans_buf->buffer_to_send != trans_desc->tx_buffer) {
|
||||
free((void *)trans_buf->buffer_to_send); //force free, ignore const
|
||||
}
|
||||
// copy data from temporary DMA-capable buffer back to IRAM buffer and free the temporary one.
|
||||
@ -868,7 +891,7 @@ static SPI_MASTER_ISR_ATTR esp_err_t setup_priv_desc(spi_host_t *host, spi_trans
|
||||
|
||||
// rx memory assign
|
||||
uint32_t* rcv_ptr;
|
||||
if ( trans_desc->flags & SPI_TRANS_USE_RXDATA ) {
|
||||
if (trans_desc->flags & SPI_TRANS_USE_RXDATA) {
|
||||
rcv_ptr = (uint32_t *)&trans_desc->rx_data[0];
|
||||
} else {
|
||||
//if not use RXDATA neither rx_buffer, buffer_to_rcv assigned to NULL
|
||||
@ -877,7 +900,7 @@ static SPI_MASTER_ISR_ATTR esp_err_t setup_priv_desc(spi_host_t *host, spi_trans
|
||||
|
||||
// tx memory assign
|
||||
const uint32_t *send_ptr;
|
||||
if ( trans_desc->flags & SPI_TRANS_USE_TXDATA ) {
|
||||
if (trans_desc->flags & SPI_TRANS_USE_TXDATA) {
|
||||
send_ptr = (uint32_t *)&trans_desc->tx_data[0];
|
||||
} else {
|
||||
//if not use TXDATA neither tx_buffer, tx data assigned to NULL
|
||||
@ -895,17 +918,17 @@ static SPI_MASTER_ISR_ATTR esp_err_t setup_priv_desc(spi_host_t *host, spi_trans
|
||||
#endif
|
||||
|
||||
if (send_ptr && bus_attr->dma_enabled) {
|
||||
if ((!esp_ptr_dma_capable(send_ptr) || tx_unaligned )) {
|
||||
if ((!esp_ptr_dma_capable(send_ptr) || tx_unaligned)) {
|
||||
ESP_RETURN_ON_FALSE(!(trans_desc->flags & SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL), ESP_ERR_INVALID_ARG, SPI_TAG, "Set flag SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL but TX buffer addr&len not align to %d, or not dma_capable", alignment);
|
||||
//if txbuf in the desc not DMA-capable, or not bytes aligned to alignment, malloc a new one
|
||||
ESP_EARLY_LOGD(SPI_TAG, "Allocate TX buffer for DMA" );
|
||||
ESP_EARLY_LOGD(SPI_TAG, "Allocate TX buffer for DMA");
|
||||
tx_byte_len = (tx_byte_len + alignment - 1) & (~(alignment - 1)); // up align alignment
|
||||
uint32_t *temp = heap_caps_aligned_alloc(alignment, tx_byte_len, MALLOC_CAP_DMA);
|
||||
if (temp == NULL) {
|
||||
goto clean_up;
|
||||
}
|
||||
|
||||
memcpy( temp, send_ptr, (trans_desc->length + 7) / 8 );
|
||||
memcpy(temp, send_ptr, (trans_desc->length + 7) / 8);
|
||||
send_ptr = temp;
|
||||
}
|
||||
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
|
||||
@ -914,10 +937,10 @@ static SPI_MASTER_ISR_ATTR esp_err_t setup_priv_desc(spi_host_t *host, spi_trans
|
||||
#endif
|
||||
}
|
||||
|
||||
if (rcv_ptr && bus_attr->dma_enabled && (!esp_ptr_dma_capable(rcv_ptr) || rx_unaligned )) {
|
||||
if (rcv_ptr && bus_attr->dma_enabled && (!esp_ptr_dma_capable(rcv_ptr) || rx_unaligned)) {
|
||||
ESP_RETURN_ON_FALSE(!(trans_desc->flags & SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL), ESP_ERR_INVALID_ARG, SPI_TAG, "Set flag SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL but RX buffer addr&len not align to %d, or not dma_capable", alignment);
|
||||
//if rxbuf in the desc not DMA-capable, or not aligned to alignment, malloc a new one
|
||||
ESP_EARLY_LOGD(SPI_TAG, "Allocate RX buffer for DMA" );
|
||||
ESP_EARLY_LOGD(SPI_TAG, "Allocate RX buffer for DMA");
|
||||
rx_byte_len = (rx_byte_len + alignment - 1) & (~(alignment - 1)); // up align alignment
|
||||
rcv_ptr = heap_caps_aligned_alloc(alignment, rx_byte_len, MALLOC_CAP_DMA);
|
||||
if (rcv_ptr == NULL) {
|
||||
@ -936,11 +959,13 @@ clean_up:
|
||||
esp_err_t SPI_MASTER_ATTR spi_device_queue_trans(spi_device_handle_t handle, spi_transaction_t *trans_desc, TickType_t ticks_to_wait)
|
||||
{
|
||||
esp_err_t ret = check_trans_valid(handle, trans_desc);
|
||||
if (ret != ESP_OK) return ret;
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
spi_host_t *host = handle->host;
|
||||
|
||||
SPI_CHECK(!spi_bus_device_is_polling(handle), "Cannot queue new transaction while previous polling transaction is not terminated.", ESP_ERR_INVALID_STATE );
|
||||
SPI_CHECK(!spi_bus_device_is_polling(handle), "Cannot queue new transaction while previous polling transaction is not terminated.", ESP_ERR_INVALID_STATE);
|
||||
|
||||
/* Even when using interrupt transfer, the CS can only be kept activated if the bus has been
|
||||
* acquired with `spi_device_acquire_bus()` first. */
|
||||
@ -950,7 +975,9 @@ esp_err_t SPI_MASTER_ATTR spi_device_queue_trans(spi_device_handle_t handle, spi
|
||||
|
||||
spi_trans_priv_t trans_buf = { .trans = trans_desc, };
|
||||
ret = setup_priv_desc(host, &trans_buf);
|
||||
if (ret != ESP_OK) return ret;
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
// though clock source is selectable, read/write reg and mem of spi peripherial still use APB
|
||||
@ -985,14 +1012,14 @@ esp_err_t SPI_MASTER_ATTR spi_device_get_trans_result(spi_device_handle_t handle
|
||||
{
|
||||
BaseType_t r;
|
||||
spi_trans_priv_t trans_buf;
|
||||
SPI_CHECK(handle!=NULL, "invalid dev handle", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK(handle != NULL, "invalid dev handle", ESP_ERR_INVALID_ARG);
|
||||
bool use_dma = handle->host->bus_attr->dma_enabled;
|
||||
|
||||
//if SPI_DEVICE_NO_RETURN_RESULT is set, ret_queue will always be empty
|
||||
SPI_CHECK(!(handle->cfg.flags & SPI_DEVICE_NO_RETURN_RESULT), "API not Supported!", ESP_ERR_NOT_SUPPORTED);
|
||||
|
||||
//use the interrupt, block until return
|
||||
r=xQueueReceive(handle->ret_queue, (void*)&trans_buf, ticks_to_wait);
|
||||
r = xQueueReceive(handle->ret_queue, (void*)&trans_buf, ticks_to_wait);
|
||||
if (!r) {
|
||||
// The memory occupied by rx and tx DMA buffer destroyed only when receiving from the queue (transaction finished).
|
||||
// If timeout, wait and retry.
|
||||
@ -1015,10 +1042,14 @@ esp_err_t SPI_MASTER_ATTR spi_device_transmit(spi_device_handle_t handle, spi_tr
|
||||
spi_transaction_t *ret_trans;
|
||||
//ToDo: check if any spi transfers in flight
|
||||
ret = spi_device_queue_trans(handle, trans_desc, portMAX_DELAY);
|
||||
if (ret != ESP_OK) return ret;
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = spi_device_get_trans_result(handle, &ret_trans, portMAX_DELAY);
|
||||
if (ret != ESP_OK) return ret;
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
assert(ret_trans == trans_desc);
|
||||
return ESP_OK;
|
||||
@ -1027,8 +1058,8 @@ esp_err_t SPI_MASTER_ATTR spi_device_transmit(spi_device_handle_t handle, spi_tr
|
||||
esp_err_t SPI_MASTER_ISR_ATTR spi_device_acquire_bus(spi_device_t *device, TickType_t wait)
|
||||
{
|
||||
spi_host_t *const host = device->host;
|
||||
SPI_CHECK(wait==portMAX_DELAY, "acquire finite time not supported now.", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK(!spi_bus_device_is_polling(device), "Cannot acquire bus when a polling transaction is in progress.", ESP_ERR_INVALID_STATE );
|
||||
SPI_CHECK(wait == portMAX_DELAY, "acquire finite time not supported now.", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK(!spi_bus_device_is_polling(device), "Cannot acquire bus when a polling transaction is in progress.", ESP_ERR_INVALID_STATE);
|
||||
|
||||
esp_err_t ret = spi_bus_lock_acquire_start(device->dev_lock, wait);
|
||||
if (ret != ESP_OK) {
|
||||
@ -1062,7 +1093,7 @@ void SPI_MASTER_ISR_ATTR spi_device_release_bus(spi_device_t *dev)
|
||||
{
|
||||
spi_host_t *host = dev->host;
|
||||
|
||||
if (spi_bus_device_is_polling(dev)){
|
||||
if (spi_bus_device_is_polling(dev)) {
|
||||
ESP_EARLY_LOGE(SPI_TAG, "Cannot release bus when a polling transaction is in progress.");
|
||||
assert(0);
|
||||
}
|
||||
@ -1093,13 +1124,17 @@ esp_err_t SPI_MASTER_ISR_ATTR spi_device_polling_start(spi_device_handle_t handl
|
||||
esp_err_t ret;
|
||||
SPI_CHECK(ticks_to_wait == portMAX_DELAY, "currently timeout is not available for polling transactions", ESP_ERR_INVALID_ARG);
|
||||
ret = check_trans_valid(handle, trans_desc);
|
||||
if (ret!=ESP_OK) return ret;
|
||||
SPI_CHECK(!spi_bus_device_is_polling(handle), "Cannot send polling transaction while the previous polling transaction is not terminated.", ESP_ERR_INVALID_STATE );
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
SPI_CHECK(!spi_bus_device_is_polling(handle), "Cannot send polling transaction while the previous polling transaction is not terminated.", ESP_ERR_INVALID_STATE);
|
||||
|
||||
spi_host_t *host = handle->host;
|
||||
spi_trans_priv_t priv_polling_trans = { .trans = trans_desc, };
|
||||
ret = setup_priv_desc(host, &priv_polling_trans);
|
||||
if (ret!=ESP_OK) return ret;
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* If device_acquiring_lock is set to handle, it means that the user has already
|
||||
* acquired the bus thanks to the function `spi_device_acquire_bus()`.
|
||||
@ -1182,7 +1217,9 @@ esp_err_t SPI_MASTER_ISR_ATTR spi_device_polling_transmit(spi_device_handle_t ha
|
||||
{
|
||||
esp_err_t ret;
|
||||
ret = spi_device_polling_start(handle, trans_desc, portMAX_DELAY);
|
||||
if (ret != ESP_OK) return ret;
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return spi_device_polling_end(handle, portMAX_DELAY);
|
||||
}
|
@ -36,7 +36,6 @@ static const char *SPI_TAG = "spi_slave";
|
||||
|
||||
#define SPI_CHECK(a, str, ret_val) ESP_RETURN_ON_FALSE(a, ret_val, SPI_TAG, str)
|
||||
|
||||
|
||||
#ifdef CONFIG_SPI_SLAVE_ISR_IN_IRAM
|
||||
#define SPI_SLAVE_ISR_ATTR IRAM_ATTR
|
||||
#else
|
||||
@ -98,7 +97,7 @@ static inline bool is_valid_host(spi_host_device_t host)
|
||||
|
||||
static inline bool SPI_SLAVE_ISR_ATTR bus_is_iomux(spi_slave_t *host)
|
||||
{
|
||||
return host->flags&SPICOMMON_BUSFLAG_IOMUX_PINS;
|
||||
return host->flags & SPICOMMON_BUSFLAG_IOMUX_PINS;
|
||||
}
|
||||
|
||||
static void SPI_SLAVE_ISR_ATTR freeze_cs(spi_slave_t *host)
|
||||
@ -139,24 +138,24 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b
|
||||
esp_err_t err;
|
||||
SPI_CHECK(is_valid_host(host), "invalid host", ESP_ERR_INVALID_ARG);
|
||||
#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 || dma_chan == SPI_DMA_CH_AUTO, "invalid dma channel", ESP_ERR_INVALID_ARG );
|
||||
SPI_CHECK(dma_chan == SPI_DMA_DISABLED || dma_chan == (int)host || 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_SLAVE_ISR_IN_IRAM
|
||||
SPI_CHECK((bus_config->intr_flags & ESP_INTR_FLAG_IRAM)==0, "ESP_INTR_FLAG_IRAM should be disabled when CONFIG_SPI_SLAVE_ISR_IN_IRAM is not set.", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK((bus_config->intr_flags & ESP_INTR_FLAG_IRAM) == 0, "ESP_INTR_FLAG_IRAM should be disabled when CONFIG_SPI_SLAVE_ISR_IN_IRAM is not set.", ESP_ERR_INVALID_ARG);
|
||||
#endif
|
||||
SPI_CHECK(slave_config->spics_io_num < 0 || GPIO_IS_VALID_GPIO(slave_config->spics_io_num), "spics pin invalid", ESP_ERR_INVALID_ARG);
|
||||
|
||||
//Check post_trans_cb status when `SPI_SLAVE_NO_RETURN_RESULT` flag is set.
|
||||
if(slave_config->flags & SPI_SLAVE_NO_RETURN_RESULT) {
|
||||
if (slave_config->flags & SPI_SLAVE_NO_RETURN_RESULT) {
|
||||
SPI_CHECK(slave_config->post_trans_cb != NULL, "use feature flag 'SPI_SLAVE_NO_RETURN_RESULT' but no post_trans_cb function sets", ESP_ERR_INVALID_ARG);
|
||||
}
|
||||
|
||||
spi_chan_claimed=spicommon_periph_claim(host, "spi slave");
|
||||
spi_chan_claimed = spicommon_periph_claim(host, "spi slave");
|
||||
SPI_CHECK(spi_chan_claimed, "host already in use", ESP_ERR_INVALID_STATE);
|
||||
|
||||
spihost[host] = malloc(sizeof(spi_slave_t));
|
||||
@ -181,7 +180,9 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b
|
||||
|
||||
//See how many dma descriptors we need and allocate them
|
||||
int dma_desc_ct = (bus_config->max_transfer_sz + SPI_MAX_DMA_LEN - 1) / SPI_MAX_DMA_LEN;
|
||||
if (dma_desc_ct == 0) dma_desc_ct = 1; //default to 4k when max is not given
|
||||
if (dma_desc_ct == 0) {
|
||||
dma_desc_ct = 1; //default to 4k when max is not given
|
||||
}
|
||||
spihost[host]->max_transfer_sz = dma_desc_ct * SPI_MAX_DMA_LEN;
|
||||
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
|
||||
size_t alignment;
|
||||
@ -203,8 +204,8 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b
|
||||
spihost[host]->max_transfer_sz = SOC_SPI_MAXIMUM_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
err = spicommon_bus_initialize_io(host, bus_config, SPICOMMON_BUSFLAG_SLAVE|bus_config->flags, &spihost[host]->flags);
|
||||
if (err!=ESP_OK) {
|
||||
err = spicommon_bus_initialize_io(host, bus_config, SPICOMMON_BUSFLAG_SLAVE | bus_config->flags, &spihost[host]->flags);
|
||||
if (err != ESP_OK) {
|
||||
ret = err;
|
||||
goto cleanup;
|
||||
}
|
||||
@ -216,11 +217,13 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b
|
||||
}
|
||||
|
||||
// The slave DMA suffers from unexpected transactions. Forbid reading if DMA is enabled by disabling the CS line.
|
||||
if (spihost[host]->dma_enabled) freeze_cs(spihost[host]);
|
||||
if (spihost[host]->dma_enabled) {
|
||||
freeze_cs(spihost[host]);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "spi_slave",
|
||||
&spihost[host]->pm_lock);
|
||||
&spihost[host]->pm_lock);
|
||||
if (err != ESP_OK) {
|
||||
ret = err;
|
||||
goto cleanup;
|
||||
@ -235,7 +238,7 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto cleanup;
|
||||
}
|
||||
if(!(slave_config->flags & SPI_SLAVE_NO_RETURN_RESULT)) {
|
||||
if (!(slave_config->flags & SPI_SLAVE_NO_RETURN_RESULT)) {
|
||||
spihost[host]->ret_queue = xQueueCreate(slave_config->queue_size, sizeof(spi_slave_trans_priv_t));
|
||||
if (!spihost[host]->ret_queue) {
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
@ -282,8 +285,12 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b
|
||||
|
||||
cleanup:
|
||||
if (spihost[host]) {
|
||||
if (spihost[host]->trans_queue) vQueueDelete(spihost[host]->trans_queue);
|
||||
if (spihost[host]->ret_queue) vQueueDelete(spihost[host]->ret_queue);
|
||||
if (spihost[host]->trans_queue) {
|
||||
vQueueDelete(spihost[host]->trans_queue);
|
||||
}
|
||||
if (spihost[host]->ret_queue) {
|
||||
vQueueDelete(spihost[host]->ret_queue);
|
||||
}
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
if (spihost[host]->pm_lock) {
|
||||
esp_pm_lock_release(spihost[host]->pm_lock);
|
||||
@ -309,8 +316,12 @@ esp_err_t spi_slave_free(spi_host_device_t host)
|
||||
{
|
||||
SPI_CHECK(is_valid_host(host), "invalid host", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK(spihost[host], "host not slave", ESP_ERR_INVALID_ARG);
|
||||
if (spihost[host]->trans_queue) vQueueDelete(spihost[host]->trans_queue);
|
||||
if (spihost[host]->ret_queue) vQueueDelete(spihost[host]->ret_queue);
|
||||
if (spihost[host]->trans_queue) {
|
||||
vQueueDelete(spihost[host]->trans_queue);
|
||||
}
|
||||
if (spihost[host]->ret_queue) {
|
||||
vQueueDelete(spihost[host]->ret_queue);
|
||||
}
|
||||
if (spihost[host]->dma_enabled) {
|
||||
spicommon_dma_chan_free(host);
|
||||
free(spihost[host]->hal.dmadesc_tx);
|
||||
@ -357,10 +368,10 @@ static esp_err_t SPI_SLAVE_ISR_ATTR spi_slave_setup_priv_trans(spi_host_device_t
|
||||
uint32_t buffer_byte_len = (trans->length + 7) / 8;
|
||||
|
||||
if (spihost[host]->dma_enabled && trans->tx_buffer) {
|
||||
if ((!esp_ptr_dma_capable( trans->tx_buffer ) || ((((uint32_t)trans->tx_buffer) | buffer_byte_len) & (alignment - 1)))) {
|
||||
if ((!esp_ptr_dma_capable(trans->tx_buffer) || ((((uint32_t)trans->tx_buffer) | buffer_byte_len) & (alignment - 1)))) {
|
||||
ESP_RETURN_ON_FALSE_ISR(trans->flags & SPI_SLAVE_TRANS_DMA_BUFFER_ALIGN_AUTO, ESP_ERR_INVALID_ARG, SPI_TAG, "TX buffer addr&len not align to %d, or not dma_capable", alignment);
|
||||
//if txbuf in the desc not DMA-capable, or not align to "alignment", malloc a new one
|
||||
ESP_EARLY_LOGD(SPI_TAG, "Allocate TX buffer for DMA" );
|
||||
ESP_EARLY_LOGD(SPI_TAG, "Allocate TX buffer for DMA");
|
||||
buffer_byte_len = (buffer_byte_len + alignment - 1) & (~(alignment - 1)); // up align to "alignment"
|
||||
uint32_t *temp = heap_caps_aligned_alloc(alignment, buffer_byte_len, MALLOC_CAP_DMA);
|
||||
if (temp == NULL) {
|
||||
@ -376,11 +387,11 @@ static esp_err_t SPI_SLAVE_ISR_ATTR spi_slave_setup_priv_trans(spi_host_device_t
|
||||
if (spihost[host]->dma_enabled && trans->rx_buffer && (!esp_ptr_dma_capable(trans->rx_buffer) || ((((uint32_t)trans->rx_buffer) | (trans->length + 7) / 8) & (alignment - 1)))) {
|
||||
ESP_RETURN_ON_FALSE_ISR(trans->flags & SPI_SLAVE_TRANS_DMA_BUFFER_ALIGN_AUTO, ESP_ERR_INVALID_ARG, SPI_TAG, "RX buffer addr&len not align to %d, or not dma_capable", alignment);
|
||||
//if rxbuf in the desc not DMA-capable, or not align to "alignment", malloc a new one
|
||||
ESP_EARLY_LOGD(SPI_TAG, "Allocate RX buffer for DMA" );
|
||||
ESP_EARLY_LOGD(SPI_TAG, "Allocate RX buffer for DMA");
|
||||
buffer_byte_len = (buffer_byte_len + alignment - 1) & (~(alignment - 1)); // up align to "alignment"
|
||||
priv_trans->rx_buffer = heap_caps_aligned_alloc(alignment, buffer_byte_len, MALLOC_CAP_DMA);
|
||||
if (priv_trans->rx_buffer == NULL) {
|
||||
free (priv_trans->tx_buffer);
|
||||
free(priv_trans->tx_buffer);
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
}
|
||||
@ -393,12 +404,12 @@ esp_err_t SPI_SLAVE_ATTR spi_slave_queue_trans(spi_host_device_t host, const spi
|
||||
BaseType_t r;
|
||||
SPI_CHECK(is_valid_host(host), "invalid host", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK(spihost[host], "host not slave", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK(spihost[host]->dma_enabled == 0 || trans_desc->tx_buffer==NULL || esp_ptr_dma_capable(trans_desc->tx_buffer),
|
||||
"txdata not in DMA-capable memory", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK(spihost[host]->dma_enabled == 0 || trans_desc->rx_buffer==NULL ||
|
||||
(esp_ptr_dma_capable(trans_desc->rx_buffer) && esp_ptr_word_aligned(trans_desc->rx_buffer) &&
|
||||
(trans_desc->length%4==0)),
|
||||
"rxdata not in DMA-capable memory or not WORD aligned", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK(spihost[host]->dma_enabled == 0 || trans_desc->tx_buffer == NULL || esp_ptr_dma_capable(trans_desc->tx_buffer),
|
||||
"txdata not in DMA-capable memory", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK(spihost[host]->dma_enabled == 0 || trans_desc->rx_buffer == NULL ||
|
||||
(esp_ptr_dma_capable(trans_desc->rx_buffer) && esp_ptr_word_aligned(trans_desc->rx_buffer) &&
|
||||
(trans_desc->length % 4 == 0)),
|
||||
"rxdata not in DMA-capable memory or not WORD aligned", ESP_ERR_INVALID_ARG);
|
||||
|
||||
SPI_CHECK(trans_desc->length <= spihost[host]->max_transfer_sz * 8, "data transfer > host maximum", ESP_ERR_INVALID_ARG);
|
||||
|
||||
@ -406,7 +417,9 @@ esp_err_t SPI_SLAVE_ATTR spi_slave_queue_trans(spi_host_device_t host, const spi
|
||||
SPI_CHECK(ESP_OK == spi_slave_setup_priv_trans(host, &priv_trans), "slave setup priv_trans failed", ESP_ERR_NO_MEM);
|
||||
|
||||
r = xQueueSend(spihost[host]->trans_queue, (void *)&priv_trans, ticks_to_wait);
|
||||
if (!r) return ESP_ERR_TIMEOUT;
|
||||
if (!r) {
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
esp_intr_enable(spihost[host]->intr);
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -434,7 +447,7 @@ esp_err_t SPI_SLAVE_ATTR spi_slave_queue_reset(spi_host_device_t host)
|
||||
spi_ll_set_int_stat(spihost[host]->hal.hw);
|
||||
|
||||
spi_slave_trans_priv_t trans;
|
||||
while( uxQueueMessagesWaiting(spihost[host]->trans_queue)) {
|
||||
while (uxQueueMessagesWaiting(spihost[host]->trans_queue)) {
|
||||
xQueueReceive(spihost[host]->trans_queue, &trans, 0);
|
||||
spi_slave_uninstall_priv_trans(host, &trans);
|
||||
}
|
||||
@ -455,17 +468,17 @@ esp_err_t SPI_SLAVE_ISR_ATTR spi_slave_queue_trans_isr(spi_host_device_t host, c
|
||||
uint32_t buffer_byte_len = (trans_desc->length + 7) / 8;
|
||||
|
||||
ESP_RETURN_ON_FALSE_ISR(\
|
||||
(trans_desc->tx_buffer && \
|
||||
esp_ptr_dma_capable(trans_desc->tx_buffer) && \
|
||||
((((uint32_t)trans_desc->tx_buffer) | buffer_byte_len) & (alignment - 1)) == 0), \
|
||||
ESP_ERR_INVALID_ARG, SPI_TAG, "txdata addr & len not align to %d bytes or not dma_capable", alignment\
|
||||
);
|
||||
(trans_desc->tx_buffer && \
|
||||
esp_ptr_dma_capable(trans_desc->tx_buffer) && \
|
||||
((((uint32_t)trans_desc->tx_buffer) | buffer_byte_len) & (alignment - 1)) == 0), \
|
||||
ESP_ERR_INVALID_ARG, SPI_TAG, "txdata addr & len not align to %d bytes or not dma_capable", alignment\
|
||||
);
|
||||
ESP_RETURN_ON_FALSE_ISR(\
|
||||
(trans_desc->rx_buffer && \
|
||||
esp_ptr_dma_capable(trans_desc->rx_buffer) && \
|
||||
((((uint32_t)trans_desc->rx_buffer) | buffer_byte_len) & (alignment - 1)) == 0), \
|
||||
ESP_ERR_INVALID_ARG, SPI_TAG, "rxdata addr & len not align to %d bytes or not dma_capable", alignment\
|
||||
);
|
||||
(trans_desc->rx_buffer && \
|
||||
esp_ptr_dma_capable(trans_desc->rx_buffer) && \
|
||||
((((uint32_t)trans_desc->rx_buffer) | buffer_byte_len) & (alignment - 1)) == 0), \
|
||||
ESP_ERR_INVALID_ARG, SPI_TAG, "rxdata addr & len not align to %d bytes or not dma_capable", alignment\
|
||||
);
|
||||
}
|
||||
|
||||
spi_slave_trans_priv_t priv_trans = {
|
||||
@ -490,7 +503,7 @@ esp_err_t SPI_SLAVE_ISR_ATTR spi_slave_queue_reset_isr(spi_host_device_t host)
|
||||
|
||||
spi_slave_trans_priv_t trans;
|
||||
BaseType_t do_yield = pdFALSE;
|
||||
while( pdFALSE == xQueueIsQueueEmptyFromISR(spihost[host]->trans_queue)) {
|
||||
while (pdFALSE == xQueueIsQueueEmptyFromISR(spihost[host]->trans_queue)) {
|
||||
xQueueReceiveFromISR(spihost[host]->trans_queue, &trans, &do_yield);
|
||||
spi_slave_uninstall_priv_trans(host, &trans);
|
||||
}
|
||||
@ -512,23 +525,28 @@ esp_err_t SPI_SLAVE_ATTR spi_slave_get_trans_result(spi_host_device_t host, spi_
|
||||
|
||||
spi_slave_trans_priv_t priv_trans;
|
||||
r = xQueueReceive(spihost[host]->ret_queue, (void *)&priv_trans, ticks_to_wait);
|
||||
if (!r) return ESP_ERR_TIMEOUT;
|
||||
if (!r) {
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
spi_slave_uninstall_priv_trans(host, &priv_trans);
|
||||
*trans_desc = priv_trans.trans;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t SPI_SLAVE_ATTR spi_slave_transmit(spi_host_device_t host, spi_slave_transaction_t *trans_desc, TickType_t ticks_to_wait)
|
||||
{
|
||||
esp_err_t ret;
|
||||
spi_slave_transaction_t *ret_trans;
|
||||
//ToDo: check if any spi transfers in flight
|
||||
ret = spi_slave_queue_trans(host, trans_desc, ticks_to_wait);
|
||||
if (ret != ESP_OK) return ret;
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
ret = spi_slave_get_trans_result(host, &ret_trans, ticks_to_wait);
|
||||
if (ret != ESP_OK) return ret;
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
assert(ret_trans == trans_desc);
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -556,7 +574,9 @@ static void SPI_SLAVE_ISR_ATTR spi_intr(void *arg)
|
||||
bool use_dma = host->dma_enabled;
|
||||
if (host->cur_trans.trans) {
|
||||
// When DMA is enabled, the slave rx dma suffers from unexpected transactions. Forbid reading until transaction ready.
|
||||
if (use_dma) freeze_cs(host);
|
||||
if (use_dma) {
|
||||
freeze_cs(host);
|
||||
}
|
||||
|
||||
spi_slave_hal_store_result(hal);
|
||||
host->cur_trans.trans->trans_len = spi_slave_hal_get_rcv_bitlen(hal);
|
||||
@ -579,9 +599,11 @@ static void SPI_SLAVE_ISR_ATTR spi_intr(void *arg)
|
||||
assert(ret == ESP_OK);
|
||||
}
|
||||
#endif
|
||||
if (host->cfg.post_trans_cb) host->cfg.post_trans_cb(host->cur_trans.trans);
|
||||
if (host->cfg.post_trans_cb) {
|
||||
host->cfg.post_trans_cb(host->cur_trans.trans);
|
||||
}
|
||||
|
||||
if(!(host->cfg.flags & SPI_SLAVE_NO_RETURN_RESULT)) {
|
||||
if (!(host->cfg.flags & SPI_SLAVE_NO_RETURN_RESULT)) {
|
||||
xQueueSendFromISR(host->ret_queue, &host->cur_trans, &do_yield);
|
||||
}
|
||||
host->cur_trans.trans = NULL;
|
||||
@ -595,7 +617,9 @@ static void SPI_SLAVE_ISR_ATTR spi_intr(void *arg)
|
||||
if (spicommon_dmaworkaround_reset_in_progress()) {
|
||||
//We need to wait for the reset to complete. Disable int (will be re-enabled on reset callback) and exit isr.
|
||||
esp_intr_disable(host->intr);
|
||||
if (do_yield) portYIELD_FROM_ISR();
|
||||
if (do_yield) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -637,7 +661,11 @@ static void SPI_SLAVE_ISR_ATTR spi_intr(void *arg)
|
||||
|
||||
//Kick off transfer
|
||||
spi_slave_hal_user_start(hal);
|
||||
if (host->cfg.post_setup_cb) host->cfg.post_setup_cb(priv_trans.trans);
|
||||
if (host->cfg.post_setup_cb) {
|
||||
host->cfg.post_setup_cb(priv_trans.trans);
|
||||
}
|
||||
}
|
||||
if (do_yield) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
if (do_yield) portYIELD_FROM_ISR();
|
||||
}
|
@ -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);
|
26
components/esp_driver_spi/test_apps/.build-test-rules.yml
Normal file
26
components/esp_driver_spi/test_apps/.build-test-rules.yml
Normal file
@ -0,0 +1,26 @@
|
||||
.spi_depends_default: &spi_depends_default
|
||||
depends_components:
|
||||
- esp_mm # for cache
|
||||
- esp_driver_spi
|
||||
- esp_driver_gpio
|
||||
|
||||
components/esp_driver_spi/test_apps/spi/master:
|
||||
disable:
|
||||
- if: SOC_GPSPI_SUPPORTED != 1
|
||||
<<: *spi_depends_default
|
||||
|
||||
components/esp_driver_spi/test_apps/spi/param:
|
||||
disable:
|
||||
- if: SOC_GPSPI_SUPPORTED != 1
|
||||
<<: *spi_depends_default
|
||||
|
||||
components/esp_driver_spi/test_apps/spi/slave:
|
||||
disable:
|
||||
- if: SOC_GPSPI_SUPPORTED != 1
|
||||
<<: *spi_depends_default
|
||||
|
||||
components/esp_driver_spi/test_apps/spi/slave_hd:
|
||||
disable:
|
||||
- if: SOC_GPSPI_SUPPORTED != 1
|
||||
- if: SOC_SPI_SUPPORT_SLAVE_HD_VER2 != 1
|
||||
<<: *spi_depends_default
|
@ -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
|
@ -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
|
||||
)
|
@ -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,
|
||||
};
|
@ -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)
|
||||
/********************************************************************************
|
||||
@ -1600,15 +1591,15 @@ void test_add_device_slave(void)
|
||||
|
||||
TEST_CASE_MULTIPLE_DEVICES("SPI_Master:Test multiple devices", "[spi_ms]", test_add_device_master, test_add_device_slave);
|
||||
|
||||
|
||||
#if (SOC_CPU_CORES_NUM > 1) && (!CONFIG_FREERTOS_UNICORE)
|
||||
|
||||
#define TEST_ISR_CNT 100
|
||||
static void test_master_isr_core_post_trans_cbk(spi_transaction_t *curr_trans){
|
||||
static void test_master_isr_core_post_trans_cbk(spi_transaction_t *curr_trans)
|
||||
{
|
||||
*((int *)curr_trans->user) += esp_cpu_get_core_id();
|
||||
}
|
||||
|
||||
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 +1631,6 @@ TEST_CASE("test_master_isr_pin_to_core","[spi]")
|
||||
// by default the esp_intr_alloc is called on ESP_MAIN_TASK_AFFINITY_CPU0 now
|
||||
TEST_ASSERT_EQUAL_UINT32(0, master_expect);
|
||||
|
||||
|
||||
//-------------------------------------CPU1---------------------------------------
|
||||
buscfg.isr_cpu_id = ESP_INTR_CPU_AFFINITY_1;
|
||||
|
||||
@ -1696,7 +1686,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);
|
@ -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));
|
@ -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)
|
||||
{
|
@ -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
|
@ -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();
|
||||
@ -652,7 +652,7 @@ static IRAM_ATTR void spi_queue_reset_in_isr(void)
|
||||
|
||||
uint8_t *slave_isr_send = heap_caps_aligned_alloc(64, TEST_BUFFER_SZ, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
|
||||
uint8_t *slave_isr_recv = heap_caps_aligned_alloc(64, TEST_BUFFER_SZ, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
|
||||
uint8_t *dummy_data = heap_caps_aligned_alloc(64, 64*2, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
|
||||
uint8_t *dummy_data = heap_caps_aligned_alloc(64, 64 * 2, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
|
||||
uint8_t *slave_isr_exp = heap_caps_malloc(TEST_BUFFER_SZ, MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL);
|
||||
get_tx_buffer(1001, slave_isr_exp, slave_isr_send, TEST_BUFFER_SZ);
|
||||
get_tx_buffer(1001, dummy_data, dummy_data + 64, 64);
|
@ -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);
|
||||
}
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -8,6 +8,7 @@ In order to control the dependence of other components on drivers at a smaller g
|
||||
- `esp_driver_gptimer` - Driver for general purpose timers
|
||||
- `esp_driver_pcnt` - Driver for pulse counter
|
||||
- `esp_driver_gpio` - Driver for GPIO
|
||||
- `esp_driver_spi` - Driver for GPSPI
|
||||
|
||||
For compatibility, the original `driver`` component is still treated as an all-in-one component by registering these `esp_driver_xyz`` components as its public dependencies. In other words, you do not need to modify the CMake file of an existing project, but you now have a way to specify the specific peripheral driver that your project depends on.
|
||||
|
||||
|
@ -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:
|
||||
|
||||
- 发送命令至从设备
|
||||
- 接收和发送数据
|
||||
|
@ -8,6 +8,7 @@
|
||||
- `esp_driver_gptimer` - 通用定时器驱动
|
||||
- `esp_driver_pcnt` - 脉冲计数器驱动
|
||||
- `esp_driver_gpio` - GPIO 驱动
|
||||
- `esp_driver_spi` - 通用 SPI 驱动
|
||||
|
||||
为了兼容性,原来的 `driver` 组件仍然存在,并作为一个 “all-in-one" 的组件,将以上这些 `esp_driver_xyz` 组件注册成自己的公共依赖。换句话说,你无需修改既有项目的 CMake 文件,但是你现在多了一个途径去指定你项目依赖的具体的外设驱动。
|
||||
|
||||
|
@ -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/**/*
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user