Page 1 of 1

Can't get quad SPI work on the slave side, ESP32-S3

Posted: Fri May 24, 2024 12:08 pm
by Slinisa
I have two ESP32-S3s connected to each other and I'm trying to send data from one to the other. I have verified with the oscilloscope that the master side is sending the data correctly on all four data lines and SCK/CS. After that I configured the slave like this:

Code: Select all

typedef struct SPI_settings_s{
	spi_host_device_t host;
	spi_device_handle_t spi;
	int dma_chan;
	spi_slave_interface_config_t devcfg;
	spi_bus_config_t buscfg;
}SPI_settings_t;

static SPI_settings_t SPI_settings = {
		.host = SPI2_HOST,
		.dma_chan = NULL,//SPI_DMA_CH_AUTO,
		.devcfg = {
				.spics_io_num = GPIO_NUM_11, //CS pin
				.queue_size = 8,
				.mode = 0,
        			.post_trans_cb = receiveSPI
		},
		.buscfg = {
				.data0_io_num = GPIO_NUM_9,
				.data1_io_num = GPIO_NUM_8,
				.sclk_io_num = GPIO_NUM_10,
				.data2_io_num = GPIO_NUM_7,
				.data3_io_num = GPIO_NUM_6,
				.data4_io_num = -1,
				.data5_io_num = -1,
				.data6_io_num = -1,
				.data7_io_num = -1,
				.max_transfer_sz = 16,
       	 			.flags = SPICOMMON_BUSFLAG_SLAVE | SPICOMMON_BUSFLAG_GPIO_PINS | SPICOMMON_BUSFLAG_QUAD
		}
};

void IRAM_ATTR receiveSPI(spi_slave_transaction_t *trans)
{
    uint32_t addr=tmpbuf[0];//*buff>>8;
    writetorow(addr,&vRAM[0x400+rowypos]);
    rowypos+=80;
    if(rowypos>=4800) rowypos=0;
    spi_slave_queue_trans(SPI_settings.host, &t,0);
}
I verified that the code by the fact callback receiveSPI() is called twice per second, which is the exact rate the master is sending. The problem is that the data is wrong.
I could see that the oscilloscope is behaving strangely on the second data line (data1_io_num) in a way that it doesn't have discreet values 0V/3V but also something in between. Also the data received is 1 byte instead of 4. I realized that the SPI is not configured as QUAD but common SPI with MISO/MOSI lines and the second line is actually behaving as MISO instead of just input data line. I confirmed that this is the case by disabling all but the first data line (data0_io_num) and it really behaves like single data line SPI.
When I tried setting data2_io_num and data3_io_num by setting them to -1, after initializing SPI bus I get this error:
E (15) spi: both wp and hd required.
Which means it IS configuring bus as QUAD, but still receiving behaves like standard SPI.

The bus is configured like this:

Code: Select all

  if(!spi_slave_initialize(SPI_settings.host, &SPI_settings.buscfg, &SPI_settings.devcfg, SPI_settings.dma_chan)) {
      t.length = 32; //length is in bits
      t.trans_len=32;
      t.rx_buffer = (uint8_t*)tmpbuf;
      t.tx_buffer = NULL;
  }
  else while(1){}
  spi_slave_queue_trans(SPI_settings.host, &t,0); // the first SPI queue trans, after that the ISP takes care of itself
I noticed that, unlike the master side, there is no spi_bus_add_device() which adds the device on the master side as QUAD so I might be missing something, but I can't find anything equivalent to it in the spi_slave.h
I'm struggling with this for days and would appreciate any help.