espressif / esp-idf

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

MOSI line always high on RX, when SPI_DEVICE_3WIRE mode used. (IDFGH-6121) #7800

Open DrZlo13 opened 3 years ago

DrZlo13 commented 3 years ago

Environment

Problem Description

Spi master in [SPI_DEVICE_3WIRE | SPI_DEVICE_HALFDUPLEX] mode does not setup MOSI pin for input, regardless of the use of DMA or not. I use a small resistor from MOSI to the ground to check it, without connecting anything besides resistor.

.-------------.
|             |
|             |
|        SCLK o--------------X
|             |
|             |
|             |
|        MOSI o-------o------X
|             |       |
|             |      .-.
|             |      | | 
|             |      | | 300
|             |      '-'
|             |       |
|             |     -----
|             |      ---
'-------------'       -

Expected Behavior

uint8_t data = 0;
spi_transaction_t swd_spi_transaction_rx = {
    .rxlength = 8,
    .tx_buffer = NULL,
    .rx_buffer = &data,
};
spi_device_polling_transmit(swd_spi_device, &swd_spi_transaction_rx);

data = 0x00

Actual Behavior

uint8_t data = 0;
spi_transaction_t swd_spi_transaction_rx = {
    .rxlength = 8,
    .tx_buffer = NULL,
    .rx_buffer = &data,
};
spi_device_polling_transmit(swd_spi_device, &swd_spi_transaction_rx);
/* No matter, spi_device_polling_transmit or spi_device_transmit is used */

data = 0xFF all the time

Code to reproduce this issue

static spi_device_handle_t swd_spi_device;

// config bus
spi_bus_config_t swd_spi_pins = {
    .mosi_io_num = 2, // SWD I/O
    .miso_io_num = -1,
    .sclk_io_num = 1, // SWD CLK
    .quadwp_io_num = -1,
    .quadhd_io_num = -1,
};
ESP_ERROR_CHECK(spi_bus_initialize(HSPI_HOST, &swd_spi_pins, SPI_DMA_DISABLED));

// add device to bus with config
spi_device_interface_config_t swd_spi_config = {
    .clock_speed_hz = 10 * 1000,
    .spics_io_num = -1,
    .flags = SPI_DEVICE_3WIRE | SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_BIT_LSBFIRST,
    .queue_size = 24,
};
ESP_ERROR_CHECK(spi_bus_add_device(HSPI_HOST, &swd_spi_config, &swd_spi_device));

uint8_t data = 0;
spi_transaction_t swd_spi_transaction_tx = {
    .length = 8,
    .tx_buffer = &data,
    .rx_buffer = NULL,
};
ESP_ERROR_CHECK(spi_device_polling_transmit(swd_spi_device, &swd_spi_transaction_tx));

data = 0;
spi_transaction_t swd_spi_transaction_rx = {
    .rxlength = 8,
    .tx_buffer = NULL,
    .rx_buffer = &data,
};
ESP_ERROR_CHECK(spi_device_polling_transmit(swd_spi_device, &swd_spi_transaction_rx));

What I tried

Nothing changes, I still get all the bits read as 1. Also, I connected the oscilloscope and a logical analyzer, MOSI line always high on rx transaction.

DrZlo13 commented 3 years ago

I think #4810 is related.

DrZlo13 commented 3 years ago

@Alvin1Zhang any updates?

DrZlo13 commented 2 years ago

Any updates?

DrZlo13 commented 2 years ago

Still nothing?

CheemsThx commented 2 years ago

ESP-IDF版本为v4.3.1

我的三线SPI初始化是这样的

// Configuration for the SPI bus
    spi_bus_config_t buscfg = {
        .mosi_io_num = BLE_MOSI_MISO,
        .miso_io_num = -1,
        .sclk_io_num = BLE_SCK,
        .quadwp_io_num = -1,
        .quadhd_io_num = -1};

    // Configuration for the SPI device on the other side of the bus
    spi_device_interface_config_t devcfg = {
        .command_bits = 0,
        .address_bits = 0,
        .dummy_bits = 0,
        .clock_speed_hz = 80000,  // SPI_MASTER_FREQ_8M
        .duty_cycle_pos = 128,    // 50% duty cycle
        .mode = 0,
        .spics_io_num = BLE_CSN,
        .cs_ena_posttrans = 3,
        .queue_size = 3,
        .flags = SPI_DEVICE_3WIRE,
    };
    spi_bus_initialize(SENDER_HOST, &buscfg, SPI_DMA_DISABLED);
    spi_bus_add_device(SENDER_HOST, &devcfg, &handle);

在驱动层'esp-idf/components/driver/spi_common.c'的'spicommon_bus_initialize_io'函数修改代码,初始化MOSI引脚为开漏上拉模式

        ESP_LOGD(SPI_TAG, "SPI%d use gpio matrix.", host+1);
        if (bus_config->mosi_io_num >= 0) {
            if (mosi_need_output || (temp_flag&SPICOMMON_BUSFLAG_DUAL)) {
                gpio_set_direction(bus_config->mosi_io_num, GPIO_MODE_INPUT_OUTPUT_OD);//
                gpio_set_pull_mode(bus_config->mosi_io_num,GPIO_PULLUP_ONLY);
                esp_rom_gpio_connect_out_signal(bus_config->mosi_io_num, spi_periph_signal[host].spid_out, false, false);
            } else {
                gpio_set_direction(bus_config->mosi_io_num, GPIO_MODE_INPUT);
            }
            esp_rom_gpio_connect_in_signal(bus_config->mosi_io_num, spi_periph_signal[host].spid_in, false);
#if CONFIG_IDF_TARGET_ESP32S2
            PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[bus_config->mosi_io_num]);
#endif
            gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[bus_config->mosi_io_num], FUNC_GPIO);
        }

在常规读取时,通过'sendbuf[1] = 0xff;'使第二阶段拉高

uint8_t SPI_Read_Reg(uint8_t reg) {
    uint8_t temp0 = 0;
    sendbuf[0] = reg;
    sendbuf[1] = 0xff;//

    t.length = 16;
    t.rxlength = 0;
    t.tx_buffer = sendbuf;
    t.rx_buffer = recvbuf;
    spi_device_polling_transmit(handle, &t);

    temp0 = recvbuf[1];
    return temp0;
}

MOSI的上拉能力决定着SPI速度,具体通过示波器观察,适当加大上拉电流

yanivbi1 commented 2 years ago

hello any update on this issue?

peturdainn commented 1 year ago

I have just started a project with 3-wire SPI and looking at the oscilloscope signals I believe I'm hitting this problem as well

LennartF22 commented 2 weeks ago

I can confirm this. Some remarks:

It seems like the OE signal for the data pin is simply not disabled during read phases, but maybe 3-wire SPI is simply not supported at all with the SPI3 peripheral? It is not explicitly mentioned that it is supported for SPI3 in the reference manual, but on the other hand, it does not mention that 3-wire SPI is not supported on SPI3 anywhere I searched either (register descriptions, ESP-IDF online documentation, etc.), and the other ESP32 variants do support 3-wire SPI on SPI3.

It would be nice to finally get an official response to this. If 3-wire SPI is actually not supported with SPI3 on the ESP32-S2, this should probably mentioned somewhere explicitly, and it should also be checked by the spi_bus_add_device function, to avoid future confusion.