mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'fix/spi_polling_speed_test' into 'master'
spi: speed up polling performance and fix several tests Closes #33 See merge request idf/esp-idf!3530
This commit is contained in:
commit
5bcd864430
@ -135,7 +135,6 @@ We have two bits to control the interrupt:
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/ringbuf.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/soc_memory_layout.h"
|
||||
#include "soc/dport_reg.h"
|
||||
@ -709,7 +708,7 @@ static SPI_MASTER_ISR_ATTR esp_err_t device_acquire_bus_internal(spi_device_t *h
|
||||
|
||||
/* This function check for whether the ISR is done, if not, block until semaphore given.
|
||||
*/
|
||||
static inline esp_err_t device_wait_for_isr_idle(spi_device_t *handle, TickType_t wait)
|
||||
static inline SPI_MASTER_ISR_ATTR esp_err_t device_wait_for_isr_idle(spi_device_t *handle, TickType_t wait)
|
||||
{
|
||||
//quickly skip if the isr is already free
|
||||
if (!handle->host->isr_free) {
|
||||
@ -767,7 +766,7 @@ static SPI_MASTER_ISR_ATTR void device_release_bus_internal(spi_host_t *host)
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool device_is_polling(spi_device_t *handle)
|
||||
static inline SPI_MASTER_ISR_ATTR bool device_is_polling(spi_device_t *handle)
|
||||
{
|
||||
return atomic_load(&handle->host->acquire_cs) == handle->id && handle->host->polling;
|
||||
}
|
||||
@ -1088,7 +1087,7 @@ static void SPI_MASTER_ISR_ATTR spi_intr(void *arg)
|
||||
if (do_yield) portYIELD_FROM_ISR();
|
||||
}
|
||||
|
||||
static esp_err_t check_trans_valid(spi_device_handle_t handle, spi_transaction_t *trans_desc)
|
||||
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_host_t *host = handle->host;
|
||||
@ -1112,7 +1111,7 @@ static esp_err_t check_trans_valid(spi_device_handle_t handle, spi_transaction_t
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static SPI_MASTER_ATTR void uninstall_priv_desc(spi_trans_priv_t* trans_buf)
|
||||
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] &&
|
||||
@ -1131,7 +1130,7 @@ static SPI_MASTER_ATTR void uninstall_priv_desc(spi_trans_priv_t* trans_buf)
|
||||
}
|
||||
}
|
||||
|
||||
static SPI_MASTER_ATTR esp_err_t setup_priv_desc(spi_transaction_t *trans_desc, spi_trans_priv_t* new_desc, bool isdma)
|
||||
static SPI_MASTER_ISR_ATTR esp_err_t setup_priv_desc(spi_transaction_t *trans_desc, spi_trans_priv_t* new_desc, bool isdma)
|
||||
{
|
||||
*new_desc = (spi_trans_priv_t) { .trans = trans_desc, };
|
||||
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/ringbuf.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/soc_memory_layout.h"
|
||||
#include "soc/dport_reg.h"
|
||||
|
@ -507,7 +507,6 @@ TEST_CASE("SPI Master no response when switch from host1 (HSPI) to host2 (VSPI)"
|
||||
TEST_ASSERT(spi_bus_free(host) == ESP_OK);
|
||||
}
|
||||
|
||||
IRAM_ATTR static uint32_t data_iram[80];
|
||||
DRAM_ATTR static uint32_t data_dram[80]={0};
|
||||
//force to place in code area.
|
||||
static const uint8_t data_drom[320+3] = {
|
||||
@ -544,13 +543,24 @@ TEST_CASE("SPI Master DMA test, TX and RX in different regions", "[spi]")
|
||||
#ifdef CONFIG_SPIRAM_SUPPORT
|
||||
//test psram if enabled
|
||||
ESP_LOGI(TAG, "testing PSRAM...");
|
||||
uint32_t* data_malloc = (uint32_t*)heap_caps_calloc(1, 324, MALLOC_CAP_SPIRAM);
|
||||
uint32_t* data_malloc = (uint32_t*)heap_caps_malloc(324, MALLOC_CAP_SPIRAM);
|
||||
TEST_ASSERT(esp_ptr_external_ram(data_malloc));
|
||||
#else
|
||||
uint32_t* data_malloc = (uint32_t*)heap_caps_calloc(1, 324, MALLOC_CAP_DMA);
|
||||
uint32_t* data_malloc = (uint32_t*)heap_caps_malloc(324, MALLOC_CAP_DMA);
|
||||
TEST_ASSERT(esp_ptr_in_dram(data_malloc));
|
||||
#endif
|
||||
|
||||
TEST_ASSERT(data_malloc != NULL);
|
||||
|
||||
//refer to soc_memory_layout.c
|
||||
uint32_t* data_iram = (uint32_t*)heap_caps_malloc(324, MALLOC_CAP_EXEC);
|
||||
TEST_ASSERT(data_iram != NULL);
|
||||
|
||||
ESP_LOGI(TAG, "iram: %p, dram: %p", data_iram, data_dram);
|
||||
ESP_LOGI(TAG, "drom: %p, malloc: %p", data_drom, data_malloc);
|
||||
TEST_ASSERT(esp_ptr_in_dram(data_dram));
|
||||
TEST_ASSERT(esp_ptr_in_iram(data_iram));
|
||||
TEST_ASSERT(esp_ptr_in_drom(data_drom));
|
||||
|
||||
srand(52);
|
||||
for (int i = 0; i < 320/4; i++) {
|
||||
data_iram[i] = rand();
|
||||
@ -577,8 +587,6 @@ TEST_CASE("SPI Master DMA test, TX and RX in different regions", "[spi]")
|
||||
static spi_transaction_t trans[TEST_REGION_SIZE];
|
||||
int x;
|
||||
|
||||
ESP_LOGI(TAG, "iram: %p, dram: %p", data_iram, data_dram);
|
||||
ESP_LOGI(TAG, "drom: %p, malloc: %p", data_drom, data_malloc);
|
||||
|
||||
memset(trans, 0, sizeof(trans));
|
||||
|
||||
@ -619,6 +627,7 @@ TEST_CASE("SPI Master DMA test, TX and RX in different regions", "[spi]")
|
||||
TEST_ASSERT(spi_bus_remove_device(spi) == ESP_OK);
|
||||
TEST_ASSERT(spi_bus_free(HSPI_HOST) == ESP_OK);
|
||||
free(data_malloc);
|
||||
free(data_iram);
|
||||
}
|
||||
|
||||
//this part tests 3 DMA issues in master mode, full-duplex in IDF2.1
|
||||
@ -1350,9 +1359,26 @@ static void sorted_array_insert(uint32_t* array, int* size, uint32_t item)
|
||||
|
||||
#define TEST_TIMES 11
|
||||
|
||||
TEST_CASE("spi_speed","[spi]")
|
||||
static IRAM_ATTR void spi_transmit_measure(spi_device_handle_t spi, spi_transaction_t* trans, uint32_t* t_flight)
|
||||
{
|
||||
RECORD_TIME_PREPARE();
|
||||
spi_device_transmit(spi, trans); // prime the flash cache
|
||||
RECORD_TIME_START();
|
||||
spi_device_transmit(spi, trans);
|
||||
RECORD_TIME_END(t_flight);
|
||||
}
|
||||
|
||||
static IRAM_ATTR void spi_transmit_polling_measure(spi_device_handle_t spi, spi_transaction_t* trans, uint32_t* t_flight)
|
||||
{
|
||||
RECORD_TIME_PREPARE();
|
||||
spi_device_polling_transmit(spi, trans); // prime the flash cache
|
||||
RECORD_TIME_START();
|
||||
spi_device_polling_transmit(spi, trans);
|
||||
RECORD_TIME_END(t_flight);
|
||||
}
|
||||
|
||||
TEST_CASE("spi_speed","[spi]")
|
||||
{
|
||||
uint32_t t_flight;
|
||||
//to get rid of the influence of randomly interrupts, we measured the performance by median value
|
||||
uint32_t t_flight_sorted[TEST_TIMES];
|
||||
@ -1372,16 +1398,13 @@ TEST_CASE("spi_speed","[spi]")
|
||||
//record flight time by isr, with DMA
|
||||
t_flight_num = 0;
|
||||
for (int i = 0; i < TEST_TIMES; i++) {
|
||||
spi_device_transmit(spi, &trans); // prime the flash cache
|
||||
RECORD_TIME_START();
|
||||
spi_device_transmit(spi, &trans);
|
||||
RECORD_TIME_END(&t_flight);
|
||||
spi_transmit_measure(spi, &trans, &t_flight);
|
||||
sorted_array_insert(t_flight_sorted, &t_flight_num, t_flight);
|
||||
}
|
||||
TEST_PERFORMANCE_LESS_THAN(SPI_PER_TRANS_NO_POLLING, "%d us", t_flight_sorted[(TEST_TIMES+1)/2]);
|
||||
for (int i = 0; i < TEST_TIMES; i++) {
|
||||
ESP_LOGI(TAG, "%d", t_flight_sorted[i]);
|
||||
}
|
||||
TEST_PERFORMANCE_LESS_THAN(SPI_PER_TRANS_NO_POLLING, "%d us", t_flight_sorted[(TEST_TIMES+1)/2]);
|
||||
|
||||
//acquire the bus to send polling transactions faster
|
||||
ret = spi_device_acquire_bus(spi, portMAX_DELAY);
|
||||
@ -1390,16 +1413,13 @@ TEST_CASE("spi_speed","[spi]")
|
||||
//record flight time by polling and with DMA
|
||||
t_flight_num = 0;
|
||||
for (int i = 0; i < TEST_TIMES; i++) {
|
||||
spi_device_polling_transmit(spi, &trans); // prime the flash cache
|
||||
RECORD_TIME_START();
|
||||
spi_device_polling_transmit(spi, &trans);
|
||||
RECORD_TIME_END(&t_flight);
|
||||
spi_transmit_polling_measure(spi, &trans, &t_flight);
|
||||
sorted_array_insert(t_flight_sorted, &t_flight_num, t_flight);
|
||||
}
|
||||
TEST_PERFORMANCE_LESS_THAN(SPI_PER_TRANS_POLLING, "%d us", t_flight_sorted[(TEST_TIMES+1)/2]);
|
||||
for (int i = 0; i < TEST_TIMES; i++) {
|
||||
ESP_LOGI(TAG, "%d", t_flight_sorted[i]);
|
||||
}
|
||||
TEST_PERFORMANCE_LESS_THAN(SPI_PER_TRANS_POLLING, "%d us", t_flight_sorted[(TEST_TIMES+1)/2]);
|
||||
|
||||
//release the bus
|
||||
spi_device_release_bus(spi);
|
||||
@ -1410,16 +1430,13 @@ TEST_CASE("spi_speed","[spi]")
|
||||
//record flight time by isr, without DMA
|
||||
t_flight_num = 0;
|
||||
for (int i = 0; i < TEST_TIMES; i++) {
|
||||
spi_device_transmit(spi, &trans); // prime the flash cache
|
||||
RECORD_TIME_START();
|
||||
spi_device_transmit(spi, &trans);
|
||||
RECORD_TIME_END(&t_flight);
|
||||
spi_transmit_measure(spi, &trans, &t_flight);
|
||||
sorted_array_insert(t_flight_sorted, &t_flight_num, t_flight);
|
||||
}
|
||||
TEST_PERFORMANCE_LESS_THAN( SPI_PER_TRANS_NO_POLLING_NO_DMA, "%d us", t_flight_sorted[(TEST_TIMES+1)/2]);
|
||||
for (int i = 0; i < TEST_TIMES; i++) {
|
||||
ESP_LOGI(TAG, "%d", t_flight_sorted[i]);
|
||||
}
|
||||
TEST_PERFORMANCE_LESS_THAN( SPI_PER_TRANS_NO_POLLING_NO_DMA, "%d us", t_flight_sorted[(TEST_TIMES+1)/2]);
|
||||
|
||||
//acquire the bus to send polling transactions faster
|
||||
ret = spi_device_acquire_bus(spi, portMAX_DELAY);
|
||||
@ -1427,16 +1444,13 @@ TEST_CASE("spi_speed","[spi]")
|
||||
//record flight time by polling, without DMA
|
||||
t_flight_num = 0;
|
||||
for (int i = 0; i < TEST_TIMES; i++) {
|
||||
spi_device_polling_transmit(spi, &trans); // prime the flash cache
|
||||
RECORD_TIME_START();
|
||||
spi_device_polling_transmit(spi, &trans);
|
||||
RECORD_TIME_END(&t_flight);
|
||||
spi_transmit_polling_measure(spi, &trans, &t_flight);
|
||||
sorted_array_insert(t_flight_sorted, &t_flight_num, t_flight);
|
||||
}
|
||||
TEST_PERFORMANCE_LESS_THAN(SPI_PER_TRANS_POLLING_NO_DMA, "%d us", t_flight_sorted[(TEST_TIMES+1)/2]);
|
||||
for (int i = 0; i < TEST_TIMES; i++) {
|
||||
ESP_LOGI(TAG, "%d", t_flight_sorted[i]);
|
||||
}
|
||||
TEST_PERFORMANCE_LESS_THAN(SPI_PER_TRANS_POLLING_NO_DMA, "%d us", t_flight_sorted[(TEST_TIMES+1)/2]);
|
||||
|
||||
//release the bus
|
||||
spi_device_release_bus(spi);
|
||||
|
@ -59,16 +59,18 @@
|
||||
#define APP_CPU_NUM (1)
|
||||
|
||||
/* Overall memory map */
|
||||
#define SOC_IROM_LOW 0x400D0000
|
||||
#define SOC_IROM_HIGH 0x40400000
|
||||
#define SOC_DROM_LOW 0x3F400000
|
||||
#define SOC_DROM_HIGH 0x3F800000
|
||||
#define SOC_RTC_IRAM_LOW 0x400C0000
|
||||
#define SOC_RTC_IRAM_HIGH 0x400C2000
|
||||
#define SOC_RTC_DATA_LOW 0x50000000
|
||||
#define SOC_RTC_DATA_HIGH 0x50002000
|
||||
#define SOC_EXTRAM_DATA_LOW 0x3F800000
|
||||
#define SOC_EXTRAM_DATA_HIGH 0x3FC00000
|
||||
#define SOC_IROM_LOW 0x400D0000
|
||||
#define SOC_IROM_HIGH 0x40400000
|
||||
#define SOC_DROM_LOW 0x3F400000
|
||||
#define SOC_DROM_HIGH 0x3F800000
|
||||
#define SOC_DRAM_LOW 0x3FAE0000
|
||||
#define SOC_DRAM_HIGH 0x40000000
|
||||
#define SOC_RTC_IRAM_LOW 0x400C0000
|
||||
#define SOC_RTC_IRAM_HIGH 0x400C2000
|
||||
#define SOC_RTC_DATA_LOW 0x50000000
|
||||
#define SOC_RTC_DATA_HIGH 0x50002000
|
||||
#define SOC_EXTRAM_DATA_LOW 0x3F800000
|
||||
#define SOC_EXTRAM_DATA_HIGH 0x3FC00000
|
||||
|
||||
|
||||
#define DR_REG_DPORT_BASE 0x3ff00000
|
||||
@ -130,7 +132,7 @@
|
||||
|
||||
//Registers Operation {{
|
||||
#define ETS_UNCACHED_ADDR(addr) (addr)
|
||||
#define ETS_CACHED_ADDR(addr) (addr)
|
||||
#define ETS_CACHED_ADDR(addr) (addr)
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
#define BIT(nr) (1UL << (nr))
|
||||
|
@ -173,3 +173,15 @@ inline static bool IRAM_ATTR esp_ptr_internal(const void *p) {
|
||||
inline static bool IRAM_ATTR esp_ptr_external_ram(const void *p) {
|
||||
return ((intptr_t)p >= SOC_EXTRAM_DATA_LOW && (intptr_t)p < SOC_EXTRAM_DATA_HIGH);
|
||||
}
|
||||
|
||||
inline static bool IRAM_ATTR esp_ptr_in_iram(const void *p) {
|
||||
return ((intptr_t)p >= SOC_IRAM_LOW && (intptr_t)p < SOC_IRAM_HIGH);
|
||||
}
|
||||
|
||||
inline static bool IRAM_ATTR esp_ptr_in_drom(const void *p) {
|
||||
return ((intptr_t)p >= SOC_DROM_LOW && (intptr_t)p < SOC_DROM_HIGH);
|
||||
}
|
||||
|
||||
inline static bool IRAM_ATTR esp_ptr_in_dram(const void *p) {
|
||||
return ((intptr_t)p >= SOC_DRAM_LOW && (intptr_t)p < SOC_DRAM_HIGH);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user