spi_master: speed up polling performance by putting into IRAM

This commit is contained in:
Michael (XIAO Xufeng) 2018-10-22 15:25:41 +08:00
parent d0361a32d7
commit 90d229eb6d
3 changed files with 31 additions and 28 deletions

View file

@ -135,7 +135,6 @@ We have two bits to control the interrupt:
#include "freertos/semphr.h" #include "freertos/semphr.h"
#include "freertos/xtensa_api.h" #include "freertos/xtensa_api.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "freertos/ringbuf.h"
#include "soc/soc.h" #include "soc/soc.h"
#include "soc/soc_memory_layout.h" #include "soc/soc_memory_layout.h"
#include "soc/dport_reg.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. /* 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 //quickly skip if the isr is already free
if (!handle->host->isr_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; 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(); 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_CHECK(handle!=NULL, "invalid dev handle", ESP_ERR_INVALID_ARG);
spi_host_t *host = handle->host; 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; 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; spi_transaction_t *trans_desc = trans_buf->trans;
if ((void *)trans_buf->buffer_to_send != &trans_desc->tx_data[0] && 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, }; *new_desc = (spi_trans_priv_t) { .trans = trans_desc, };

View file

@ -29,7 +29,6 @@
#include "freertos/semphr.h" #include "freertos/semphr.h"
#include "freertos/xtensa_api.h" #include "freertos/xtensa_api.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "freertos/ringbuf.h"
#include "soc/soc.h" #include "soc/soc.h"
#include "soc/soc_memory_layout.h" #include "soc/soc_memory_layout.h"
#include "soc/dport_reg.h" #include "soc/dport_reg.h"

View file

@ -1359,9 +1359,26 @@ static void sorted_array_insert(uint32_t* array, int* size, uint32_t item)
#define TEST_TIMES 11 #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(); 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; uint32_t t_flight;
//to get rid of the influence of randomly interrupts, we measured the performance by median value //to get rid of the influence of randomly interrupts, we measured the performance by median value
uint32_t t_flight_sorted[TEST_TIMES]; uint32_t t_flight_sorted[TEST_TIMES];
@ -1381,16 +1398,13 @@ TEST_CASE("spi_speed","[spi]")
//record flight time by isr, with DMA //record flight time by isr, with DMA
t_flight_num = 0; t_flight_num = 0;
for (int i = 0; i < TEST_TIMES; i++) { for (int i = 0; i < TEST_TIMES; i++) {
spi_device_transmit(spi, &trans); // prime the flash cache spi_transmit_measure(spi, &trans, &t_flight);
RECORD_TIME_START();
spi_device_transmit(spi, &trans);
RECORD_TIME_END(&t_flight);
sorted_array_insert(t_flight_sorted, &t_flight_num, 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++) { for (int i = 0; i < TEST_TIMES; i++) {
ESP_LOGI(TAG, "%d", t_flight_sorted[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 //acquire the bus to send polling transactions faster
ret = spi_device_acquire_bus(spi, portMAX_DELAY); ret = spi_device_acquire_bus(spi, portMAX_DELAY);
@ -1399,16 +1413,13 @@ TEST_CASE("spi_speed","[spi]")
//record flight time by polling and with DMA //record flight time by polling and with DMA
t_flight_num = 0; t_flight_num = 0;
for (int i = 0; i < TEST_TIMES; i++) { for (int i = 0; i < TEST_TIMES; i++) {
spi_device_polling_transmit(spi, &trans); // prime the flash cache spi_transmit_polling_measure(spi, &trans, &t_flight);
RECORD_TIME_START();
spi_device_polling_transmit(spi, &trans);
RECORD_TIME_END(&t_flight);
sorted_array_insert(t_flight_sorted, &t_flight_num, 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++) { for (int i = 0; i < TEST_TIMES; i++) {
ESP_LOGI(TAG, "%d", t_flight_sorted[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 //release the bus
spi_device_release_bus(spi); spi_device_release_bus(spi);
@ -1419,16 +1430,13 @@ TEST_CASE("spi_speed","[spi]")
//record flight time by isr, without DMA //record flight time by isr, without DMA
t_flight_num = 0; t_flight_num = 0;
for (int i = 0; i < TEST_TIMES; i++) { for (int i = 0; i < TEST_TIMES; i++) {
spi_device_transmit(spi, &trans); // prime the flash cache spi_transmit_measure(spi, &trans, &t_flight);
RECORD_TIME_START();
spi_device_transmit(spi, &trans);
RECORD_TIME_END(&t_flight);
sorted_array_insert(t_flight_sorted, &t_flight_num, 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++) { for (int i = 0; i < TEST_TIMES; i++) {
ESP_LOGI(TAG, "%d", t_flight_sorted[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 //acquire the bus to send polling transactions faster
ret = spi_device_acquire_bus(spi, portMAX_DELAY); ret = spi_device_acquire_bus(spi, portMAX_DELAY);
@ -1436,16 +1444,13 @@ TEST_CASE("spi_speed","[spi]")
//record flight time by polling, without DMA //record flight time by polling, without DMA
t_flight_num = 0; t_flight_num = 0;
for (int i = 0; i < TEST_TIMES; i++) { for (int i = 0; i < TEST_TIMES; i++) {
spi_device_polling_transmit(spi, &trans); // prime the flash cache spi_transmit_polling_measure(spi, &trans, &t_flight);
RECORD_TIME_START();
spi_device_polling_transmit(spi, &trans);
RECORD_TIME_END(&t_flight);
sorted_array_insert(t_flight_sorted, &t_flight_num, 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++) { for (int i = 0; i < TEST_TIMES; i++) {
ESP_LOGI(TAG, "%d", t_flight_sorted[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 //release the bus
spi_device_release_bus(spi); spi_device_release_bus(spi);