I'm trying to get the spi_master driver to work with two devices on the same bus. My problem is that when one device is half-duplex and the other is full-duplex, it doesn't behave as expected. I'm using the following code:
- #include <stdio.h>
- #include "esp_system.h"
- #include "esp_event.h"
- #include "driver/spi_master.h"
- #define TEST_MISO_PIN 19
- #define TEST_MOSI_PIN 18
- #define TEST_SCLK_PIN 5
- #define TEST_CS1_PIN 27
- #define TEST_CS2_PIN 32
- void app_main(void)
- {
- static spi_device_handle_t spi1;
- static spi_device_handle_t spi2;
- // Initialize SPI bus
- {
- spi_bus_config_t buscfg = {
- .miso_io_num = TEST_MISO_PIN,
- .mosi_io_num = TEST_MOSI_PIN,
- .sclk_io_num = TEST_SCLK_PIN,
- .quadwp_io_num = -1,
- .quadhd_io_num = -1
- };
- ESP_ERROR_CHECK(spi_bus_initialize(VSPI_HOST, &buscfg, 0));
- }
- // Setup SPI device 1 (half-duplex)
- {
- spi_device_interface_config_t devcfg = {
- .clock_speed_hz = 1*100*1000,
- .mode = 0,
- .queue_size = 1,
- .flags = SPI_DEVICE_HALFDUPLEX,
- .spics_io_num = TEST_CS1_PIN
- };
- ESP_ERROR_CHECK(spi_bus_add_device(VSPI_HOST, &devcfg, &spi1));
- }
- // Setup SPI device 2 (full-duplex, 8 addr. bits)
- {
- spi_device_interface_config_t devcfg = {
- .clock_speed_hz = 1*100*1000,
- .mode = 0,
- .queue_size = 1,
- .flags = 0,
- .command_bits = 0,
- .address_bits = 8,
- .spics_io_num = TEST_CS2_PIN
- };
- ESP_ERROR_CHECK(spi_bus_add_device(VSPI_HOST, &devcfg, &spi2));
- }
- printf("Starting in 2s...\n");
- sleep(2);
- // Do a dummy transfer on device 1
- {
- uint8_t cmd = 0x3A;
- spi_transaction_t t = {
- .length = 8,
- .tx_buffer = &cmd
- };
- spi_device_transmit(spi1, &t);
- }
- // Do a 16-bit full-duplex transfer (+8 addr. bits) on device 2
- {
- spi_transaction_t t = {
- .length = 16,
- .rxlength = 16,
- .flags = SPI_TRANS_USE_RXDATA | SPI_TRANS_USE_TXDATA
- };
- uint8_t addr = 0x00;
- t.addr = addr | 0x80;
- t.tx_data[0] = (addr+1) | 0x80;
- t.tx_data[1] = 0x00;
- t.tx_data[2] = 0x13;
- t.tx_data[3] = 0x37;
- ESP_ERROR_CHECK(spi_device_transmit(spi2, &t));
- }
- }
For debugging purposes, I have removed both of the actual SPI slaves from the bus, so the only thing that's connected to them is the ESP32. See the attached image for what my logic analyzer shows for this code.
For the second transaction, the driver seems to drive the chip for two more 8-bit cycles than expected. It looks like it's actually operating the transaction in half-duplex mode, although the device is configured as full-duplex. This happens only when I do the first dummy transaction - if I remove the first spi_device_transmit, the other transaction behaves as expected.
The logs don't seem to show anything useful:
I (28) boot: ESP-IDF v4.0-beta2-dirty 2nd stage bootloader
I (29) boot: compile time 18:44:54
I (29) boot: Enabling RNG early entropy source...
I (34) boot: SPI Speed : 40MHz
I (38) boot: SPI Mode : DIO
I (42) boot: SPI Flash Size : 2MB
I (46) boot: Partition Table:
I (50) boot: ## Label Usage Type ST Offset Length
I (57) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (65) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (72) boot: 2 factory factory app 00 00 00010000 00100000
I (80) boot: End of partition table
I (84) esp_image: segment 0: paddr=0x00010020 vaddr=0x3f400020 size=0x0717c ( 29052) map
I (103) esp_image: segment 1: paddr=0x000171a4 vaddr=0x3ffb0000 size=0x0207c ( 8316) load
I (107) esp_image: segment 2: paddr=0x00019228 vaddr=0x40080000 size=0x00400 ( 1024) load
0x40080000: _WindowOverflow4 at /opt/esp-idf/components/freertos/xtensa_vectors.S:1778
I (111) esp_image: segment 3: paddr=0x00019630 vaddr=0x40080400 size=0x069e0 ( 27104) load
I (131) esp_image: segment 4: paddr=0x00020018 vaddr=0x400d0018 size=0x14640 ( 83520) map
0x400d0018: _stext at ??:?
I (161) esp_image: segment 5: paddr=0x00034660 vaddr=0x40086de0 size=0x03aa0 ( 15008) load
0x40086de0: rtc_clk_cpu_freq_get_config at /opt/esp-idf/components/soc/esp32/rtc_clk.c:650
I (174) boot: Loaded app from partition at offset 0x10000
I (174) boot: Disabling RNG early entropy source...
I (175) cpu_start: Pro cpu up.
I (178) cpu_start: Application information:
I (183) cpu_start: Project name: app-template
I (189) cpu_start: App version: 1
I (193) cpu_start: Compile time: Jan 4 2020 18:44:43
I (199) cpu_start: ELF file SHA256: 78fef31c0db07f90...
I (205) cpu_start: ESP-IDF: v4.0-beta2-dirty
I (211) cpu_start: Starting app cpu, entry point is 0x400810a0
0x400810a0: call_start_cpu1 at /opt/esp-idf/components/esp32/cpu_start.c:272
I (0) cpu_start: App cpu up.
I (221) heap_init: Initializing. RAM available for dynamic allocation:
I (228) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (234) heap_init: At 3FFB30A8 len 0002CF58 (179 KiB): DRAM
I (240) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (247) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (253) heap_init: At 4008A880 len 00015780 (85 KiB): IRAM
I (259) cpu_start: Pro cpu start user code
I (277) spi_flash: detected chip: generic
I (278) spi_flash: flash io: dio
W (278) spi_flash: Detected size(4096k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
I (289) cpu_start: Chip Revision: 1
W (293) cpu_start: Chip revision is higher than the one configured in menuconfig. Suggest to upgrade it.
I (303) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
Starting in 2s...
For reference, I'm using an Adafruit HUZZAH32 development board and ESP-IDF 4.0-beta2.
Any ideas?