SPI Master slow

IfaeEngineer
Posts: 1
Joined: Fri Dec 03, 2021 11:30 am

SPI Master slow

Postby IfaeEngineer » Mon Dec 13, 2021 5:00 pm

Hi,

I have to read an adc (ad7490) through SPI. I've been doing some tests reading it by polling, but it seems that the ESP is not fast enough. I do not understand what I am doing wrong. The ADC, on paper, can hold rates up to 870Ksps (@3.3V), but I can only achieve 100Ksps using the ESP32 SPI master driver.

Can somebody tell me, how should we use the SPI master driver to achieve the maximum throughput?

Thank you all!

Simplified code (with this version we only achieve 27ksps):
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include "driver/spi_common_internal.h"
  4. #include "driver/spi_master.h"
  5. #include "freertos/FreeRTOS.h"
  6.  
  7. #include "hal/spi_hal.h"
  8. #define ADC_HOST SPI3_HOST
  9. #define PIN_MISO 23
  10. #define PIN_MOSI 18
  11. #define PIN_SCLK 5
  12.  
  13. #define PIN_CS_ADC1 32
  14.  
  15. #define FREQ_ADC1 16*1000*1000
  16.  
  17. spi_bus_config_t buscfg = {
  18.     .miso_io_num = PIN_MISO,
  19.     .mosi_io_num = PIN_MOSI,
  20.     .sclk_io_num = PIN_SCLK,
  21.     .quadwp_io_num = -1,
  22.     .quadhd_io_num = -1,
  23.     .max_transfer_sz = 16,
  24. };
  25. spi_device_interface_config_t adc1_devcfg = {
  26.     .clock_speed_hz = FREQ_ADC1,
  27.     .mode = 0,
  28.     .spics_io_num = PIN_CS_ADC1,
  29.     .queue_size = 16,
  30.     .command_bits = 0,
  31.     .address_bits = 0,
  32. };
  33.  
  34. spi_device_handle_t adc1_spi;
  35.  
  36. esp_err_t ad7490_dummy(spi_device_handle_t spi)
  37. {
  38.     spi_transaction_t t;
  39.     uint16_t data = 0xffff;
  40.  
  41.     memset(&t, 0, sizeof(spi_transaction_t));
  42.     //Write has to set a 0 at addr, but is already 0
  43.  
  44.     t.length = 16;
  45.     t.tx_buffer = &data;
  46.  
  47.     return spi_device_transmit(spi, &t);
  48. }
  49.  
  50. esp_err_t ad7490_setup_sequencer(spi_device_handle_t spi)
  51. {
  52.     uint16_t cr = ((1<<11) | (1<<10) | (15<<6) | (3<<4) | (1<<3) | (1<<1) | 1) << 4;
  53.     uint16_t data = SPI_SWAP_DATA_TX(cr, 16);
  54.     spi_transaction_t t;
  55.  
  56.     memset(&t, 0, sizeof(spi_transaction_t));
  57.  
  58.     t.length = 16;
  59.     t.tx_buffer = &data;
  60.  
  61.     return spi_device_transmit(spi, &t);
  62. }
  63.  
  64. esp_err_t ad7490_read_polling(spi_device_handle_t spi, uint16_t *val)
  65. {
  66.     spi_transaction_t t;
  67.     esp_err_t ret;
  68.  
  69.     memset(&t, 0, sizeof(spi_transaction_t));
  70.  
  71.     t.flags = SPI_DEVICE_NO_DUMMY; // To send the W=0
  72.     t.length = 16;
  73.     t.rx_buffer = val;
  74.  
  75.     ret = spi_device_polling_transmit(spi, &t);
  76.     ESP_ERROR_CHECK(ret);
  77.  
  78.     *val = SPI_SWAP_DATA_RX(*val, 16);
  79.  
  80.     return ret;
  81. }
  82.  
  83. void read16_polling(spi_device_handle_t spi, uint16_t reads[16])
  84. {
  85.     uint8_t i;
  86.     uint16_t val;
  87.  
  88.     // ESP_ERROR_CHECK( spi_device_acquire_bus(spi, portMAX_DELAY) );
  89.  
  90.     for (i=0; i < 16; i++) {
  91.         ESP_ERROR_CHECK( ad7490_read_polling(spi, &val) );
  92.         reads[i] = SPI_SWAP_DATA_RX(val, 16) & 0x0fff;
  93.     }
  94.  
  95.     // spi_device_release_bus(spi);
  96. }
  97.  
  98. void app_main() {
  99.     printf("----[ Read Polling Test ]----\n");
  100.  
  101.     esp_err_t ret;
  102.  
  103.     printf("Initializing bus SPI%d...\n", ADC_HOST+1);
  104.     ret = spi_bus_initialize(ADC_HOST, &buscfg, SPI_DMA_DISABLED);
  105.     ESP_ERROR_CHECK(ret);
  106.  
  107.     printf("Initializing SPI device ADC1 @ %.2f kHz...\n", (float)FREQ_ADC1/1000);
  108.     ret = spi_bus_add_device(ADC_HOST, &adc1_devcfg, &adc1_spi);
  109.     ESP_ERROR_CHECK(ret);
  110.  
  111.     printf("Powering up AD7940...\n");
  112.     ret = ad7490_dummy(adc1_spi);
  113.     ESP_ERROR_CHECK(ret);
  114.  
  115.     ret = ad7490_setup_sequencer(adc1_spi);
  116.     ESP_ERROR_CHECK(ret);
  117.  
  118.     uint16_t reads1[16];
  119.     uint16_t i;
  120.     uint64_t t;
  121.  
  122.     t = esp_timer_get_time();
  123.     ESP_ERROR_CHECK( spi_device_acquire_bus(adc1_spi, portMAX_DELAY) );
  124.  
  125.     for (i=0; i < 2000; i++) {
  126.         read16_polling(adc1_spi, reads1);
  127.     }
  128.     spi_device_release_bus(adc1_spi);
  129.     t = esp_timer_get_time() - t;
  130.  
  131.     printf("%u reads in %llu us (%.3f kSPS)\n", 16*i, t, (float)(16*i*1000) / t);
  132.  
  133.     ESP_ERROR_CHECK( spi_bus_remove_device(adc1_spi) );
  134.     ESP_ERROR_CHECK( spi_bus_free(ADC_HOST) );
  135. }

Who is online

Users browsing this forum: Baidu [Spider] and 153 guests