ESP32 IDF SPI slave not receiving any data

error404
Posts: 12
Joined: Thu May 12, 2022 8:54 am

ESP32 IDF SPI slave not receiving any data

Postby error404 » Thu May 12, 2022 9:31 am

µC: ESP32-WROVER-E
Board: Custom board
IDF: v4.4.1

Hi, I'm currently trying to receive data via SPI on the ESP32 (Slave), sent by a STM32 (Master).
There's no CS and no Handshake available, so there are only CLK, MOSI and MISO.
The data sent by the master (0xAFFECAFE) seems correct to me:
D0 = CLK = GPIO18
D1 = MOSI = GPIO23
D2 = MISO = GPIO19
SCR01.PNG
SCR01.PNG (24.95 KiB) Viewed 4547 times

Source-Code for the ESP32:
  1. #include "spi_ex.h"
  2. #include "gpio_ex.h"
  3. #include "com.h"
  4. #include "string.h"
  5.  
  6. #define _SPI_EX_BUF_SIZE    128
  7.  
  8. spi_bus_config_t spi_ex_config[SOC_SPI_PERIPH_NUM] = {
  9.     [SPI3_HOST] = {
  10.         .mosi_io_num = COM_SPI_MOSI_GPIO, // = 23
  11.         .miso_io_num = COM_SPI_MISO_GPIO, // = 19
  12.         .sclk_io_num = COM_SPI_CLK_GPIO,  // = 18
  13.         .quadwp_io_num = -1,
  14.         .quadhd_io_num = -1
  15.      }
  16. };
  17.  
  18. spi_slave_interface_config_t spi_ex_slaveConfig[SOC_SPI_PERIPH_NUM] = {
  19.     [SPI3_HOST] = {
  20.         .mode = 0, //CPOL = 0, CPHA = 0
  21.         .spics_io_num = -1,
  22.         .queue_size = 3,
  23.         .flags = 0,
  24.         .post_setup_cb = spi_ex_setupCplt,
  25.         .post_trans_cb = spi_ex_transactionCplt
  26.     }
  27. };
  28.  
  29. WORD_ALIGNED_ATTR uint8_t spi_ex_3txBuf[_SPI_EX_BUF_SIZE] = { 0 };
  30. WORD_ALIGNED_ATTR uint8_t spi_ex_3rxBuf[_SPI_EX_BUF_SIZE] = { 0 };
  31.  
  32. spi_slave_transaction_t spi_ex_slaveTransaction[SOC_SPI_PERIPH_NUM] = {
  33.     [SPI3_HOST] = {
  34.         .length = _SPI_EX_BUF_SIZE * 8,
  35.         .tx_buffer = spi_ex_3txBuf,
  36.         .rx_buffer = spi_ex_3rxBuf
  37.     }
  38. };
  39.  
  40. bool spi_ex_isInitialized[SOC_SPI_PERIPH_NUM] = { false };
  41.  
  42. void spi_ex_init(spi_host_device_t spi_num)
  43. {
  44.     if (spi_ex_isInitialized[spi_num])
  45.     {
  46.         return;
  47.     }
  48.  
  49.     ESP_ERROR_CHECK(spi_slave_initialize(spi_num, &spi_ex_config[spi_num], &spi_ex_slaveConfig[spi_num], SPI_DMA_CH_AUTO));
  50.    
  51.     memset(spi_ex_3txBuf, 0x55, sizeof(uint8_t) * _SPI_EX_BUF_SIZE);
  52.    
  53.     spi_ex_isInitialized[spi_num] = true;
  54. }
  55.  
  56. void spi_ex_mainLoop(void)
  57. {
  58.     ESP_ERROR_CHECK(spi_slave_transmit(SPI3_HOST, &spi_ex_slaveTransaction[SPI3_HOST], portMAX_DELAY));
  59. }
  60.  
  61. void spi_ex_setupCplt(spi_slave_transaction_t *trans)
  62. {
  63.  
  64. }
  65.  
  66. void spi_ex_transactionCplt(spi_slave_transaction_t *trans)
  67. {
  68.  
  69. }

(I can control the sending on the master by pressing a button)
What happens is, that spi_slave_transmit get's called and then spi_ex_setupCplt. After that I'm sending 0xAFFECAFE from the master by hand, but it seems like it hasn't any effect on the slave. spi_slave_transmit keeps blocking and neither spi_ex_setupCplt nor spi_ex_transactionCplt are getting called.

If I'm correct, I should also see 0x55555555 on the MISO line while sending, since I filled spi_ex_3txBuf with 0x55, but it's low during the transaction.

I've read the whole description (https://docs.espressif.com/projects/esp ... slave.html) and had a look at the example (https://github.com/espressif/esp-idf/bl ... app_main.c), but i cannot get it working.

Thanks in advance!

ESP_Sprite
Posts: 9757
Joined: Thu Nov 26, 2015 4:08 am

Re: ESP32 IDF SPI slave not receiving any data

Postby ESP_Sprite » Thu May 12, 2022 1:19 pm

Decently sure you need a CS.

error404
Posts: 12
Joined: Thu May 12, 2022 8:54 am

Re: ESP32 IDF SPI slave not receiving any data

Postby error404 » Thu May 12, 2022 1:28 pm

Thanks for your quick response.

Is there a way without using a GPIO for that?

ESP_Sprite
Posts: 9757
Joined: Thu Nov 26, 2015 4:08 am

Re: ESP32 IDF SPI slave not receiving any data

Postby ESP_Sprite » Fri May 13, 2022 1:51 am

I might be mistaken, but I'm decently sure the SPI slave uses the CS signal as a thing to start and end a transmission. You can 'hardcode' the CS signal to be always active without a GPIO to match (using the GPIO matrix, you can hardwire it to be always 1) but the SPI slave would never detect the end of a transmission.

error404
Posts: 12
Joined: Thu May 12, 2022 8:54 am

Re: ESP32 IDF SPI slave not receiving any data

Postby error404 » Fri May 13, 2022 6:00 am

I tried pulling a GPIO to low (CS is active low) and selected it as CS, but it isn't working.
I'll try using a CS line from the master to the slave, but it will take a while since we have to modify our custom board. => Sharing my results later!

But I think in general this implementation is just incorrect. CS isn't edge-triggered, it is level controlled. If low => listen to me ; If high => ignore me.
When the chip select pin is held in the inactive state, the chip or device is "deaf", and pays no heed to changes in the state of its other input pins; it holds its outputs in the high impedance state, so other chips can drive those signals. When the chip select pin is held in the active state, the chip or device assumes that any input changes it "hears" are meant for it, and responds as if it is the only chip on the bus.
Source: https://en.wikipedia.org/wiki/Chip_select

So far it has been possible to permanently pull CS low with every SPI slave I have used.

ESP_Sprite
Posts: 9757
Joined: Thu Nov 26, 2015 4:08 am

Re: ESP32 IDF SPI slave not receiving any data

Postby ESP_Sprite » Fri May 13, 2022 1:21 pm

It is not purely a listen/don't listen; generally on SPI a CS going low also indicates a start of transaction, that is, the transaction restarts at bit 0. The fact that the ESP32 also reacts to the CS line going up may be a bit unusual, but the fact that it's edge triggered is pretty common.

error404
Posts: 12
Joined: Thu May 12, 2022 8:54 am

Re: ESP32 IDF SPI slave not receiving any data

Postby error404 » Mon May 16, 2022 6:15 am

Let me share my results with you:

At first the most important info: You need a CS for an ESP32 as a SPI slave, if you don't want to overcomplicate your software.

1st issue I had:
What the ESP32 IDF really needs is the end of the transaction as a rising edge on CS. Else it doesn't know when the transaction is completed. Usually the length of a SPI transaction is fixed for slaves (8-32bit), but with IDF you could theoretically (if the buffer is large enough) receive "endless" bits in one transaction. For microcontroller to microcontroller communication this is kind of nice (I have to admit that), but since it is very unusual it cost me a lot of time debugging.
Without a CS line the data is received into the receive buffer and the data in the transmit buffer is transmitted, but you will never get a callback and spi_slave_transmit keeps blocking. Maybe you could use spi_slave_queue_trans and constantly check the receive buffer for data, but that is what i mean with "overcomplicating software".
=>Since it's very unusual to use CS like that, it would be nice to mention that in the documentation (https://docs.espressif.com/projects/esp ... slave.html). "spi_slave_interface_config_t" => "spics_io_num"

2nd issue:
SPI3 wasn't working at all. I replaced it with SPI2 and everything started working... I really don't know why, since I even used the IOMUX pins for SPI3. Now with SPI2 I'm using the same pins, but via the GPIO matrix, which is a bit slower.
=> If you have any idea why, please let me know. I haven't figured out yet, how to use SPI3 with the IOMUX pins.

My source code didn't change (except for replacing SPI3 with SPI2), so I'm not sharing an updated version.

Thank you for your help so far! You saved me a lot of time.

Who is online

Users browsing this forum: Majestic-12 [Bot] and 372 guests