espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
13.85k stars 7.32k forks source link

Incorrect behaviour for SPI Slave in mode 3 on esp32 (non-dma) (IDFGH-6011) #7698

Open ariscop opened 3 years ago

ariscop commented 3 years ago

esp-idf uses these values for spi slave mode 3, as specified in the reference manual:

        hw->pin.ck_idle_edge = 0;
        hw->user.ck_i_edge = 0;
        hw->ctrl2.miso_delay_mode = 1;
        hw->ctrl2.miso_delay_num = 0;
        hw->ctrl2.mosi_delay_mode = 0;
        hw->ctrl2.mosi_delay_num = 0;

This results in mosi being sampled during the launch edge, which is mentioned in the slave driver documentation and can be confirmed by altering mosi_delay_num, but this behaviour is not mentioned in the reference manual

The following values:

>       hw->pin.ck_idle_edge = 1;
>       hw->user.ck_i_edge = 1;
        hw->ctrl2.miso_delay_mode = 1;
        hw->ctrl2.miso_delay_num = 0;
        hw->ctrl2.mosi_delay_mode = 0;
        hw->ctrl2.mosi_delay_num = 0;

Appear to behave as expected, with data shifted on the launch (falling) edge and sampled on the latch (rising) edge

Not submitting a patch as it's unclear if this is correct; Ideally the reference manual would be updated to clarify how the various settings work, though i imagine this is a fairly low priority issue

The spi master and protocol involved (specifically, a gameboy color link port) requires 8 bit transactions; As a result no testing has been done with dma enabled

nx518 commented 3 years ago

I did some test with two ESP32-WROOM32 Evalboards and esp-idf/examples/peripherals/spi_slave, one as sender and one as receiver. Seems that changing spi_ll.h does improve the mode3 behaviour. I tried 3 different settings: spi_timings Best is:

hw->pin.ck_idle_edge = 1;
hw->user.ck_i_edge = 1;
hw->ctrl2.miso_delay_mode = 0;

Still not perfect though. In another project I´m having issues with the SPI-Master with the esp32s3 in mode 3, which led me here.

ariscop commented 3 years ago

@nx518 the spi examples use dma by default, might be worth trying without dma as cpha=1 modes appear to have some strangeness when used with dma

Without a timebase, the cs setup time looks a bit short; As @Icarus113 suggests in #7825 setting cs_ena_pretrans and cs_ena_posttrans may help

Your 3rd example also looks like it should work, if not you can it by setting miso_delay_num

JoanPons23 commented 2 years ago

Hi, I found the same problem with the SPI slave in mode 3. It took me a while to figure out that both the user manual and the esp-idf configuration file, spi_ll.h, were wrong. In order not to modify the latest version of Expressif, I decided to make an amendment directly to my code and set the two bits explicitly.

if (slvcfg.mode == 3)
{
    REG_SET_BIT(SPI_PIN_REG(spi_config->rcvHost + 1), SPI_CK_IDLE_EDGE); // As 'hw->pin.ck_idle_edge = 1;'
    REG_SET_BIT(SPI_USER_REG(spi_config->rcvHost + 1), SPI_CK_I_EDGE);   // As 'hw->user.ck_i_edge = 1;'
}

Now it does what it should.