ports/esp32:a bug with Hardware SPI Initialize on ESP32-S3
Hi,all:
Problem description and analysis
- Hardware: ESP32S3
- Firmware version: esp32/GENERIC_S3 v1.19.1 (2022-06-18) or master branch
- Abstract: SPI(1) and SPI(2) need two initializations to work perfectly in each operation. If two initializations of different Baudrates are not carried out, SPI may not work.
code and pictures
- Initialize with different baudrates()
self.spi = SPI(2,baudrate=4_000_000,polarity=0, phase=0,sck=Pin(SCK,Pin.OUT),mosi=Pin(MOSI,Pin.OUT))
self.spi = SPI(2,baudrate=8_000_000,polarity=0, phase=0,sck=Pin(SCK,Pin.OUT),mosi=Pin(MOSI,Pin.OUT))

- Initialize with same baudrates(In order to reproduce the problem 100%, you also can initialize it once and run it again)
self.spi = SPI(2,baudrate=8_000_000,polarity=0, phase=0,sck=Pin(SCK,Pin.OUT),mosi=Pin(MOSI,Pin.OUT))
self.spi = SPI(2,baudrate=8_000_000,polarity=0, phase=0,sck=Pin(SCK,Pin.OUT),mosi=Pin(MOSI,Pin.OUT))

details
First time
I used the firmware V1.91.1 and found that SPI (1) initialization was abnormal. SPI(2) can work normally.
However, when I tried for the second time (after stop), I found that it could not work.
I tried to restart it and it could work again, but it still couldn't work the second time.
Then I tried various methods and accidentally found that baudrate could work after modification. So I conducted two initializations,The baudrate needs of the first initialization were different from that of the second initialization,The program could run perfectly, no matter whether it was STOP or not.
- like
self.spi = SPI(2,baudrate=4_000_000,polarity=0, phase=0,sck=Pin(SCK,Pin.OUT),mosi=Pin(MOSI,Pin.OUT))
self.spi = SPI(2,baudrate=8_000_000,polarity=0, phase=0,sck=Pin(SCK,Pin.OUT),mosi=Pin(MOSI,Pin.OUT))
I found out that lssues #8634 suffers from a similar problem and saw the initialization issue solved in #9498
The second time
I tried to use the master branch to build a new firmware to try,
and then I found that SPI(1) and SPI(2) can be initialized normally and work, but the problem still exists that the initialization needs to be twice.
ports/esp32/machine_sdcard.c: Fix ESP_ERR_INVALID_ARG on SDCard init on ESP32-S3 (Change DMA channel)
This pull request solves the problem that initialization of SDCard objects with SPI fails on ESP32-S3.
Problem
Creating SDCard object with SPI (slot=2 or 3) causes ESP_ERR_INVALID_ARG error.
[0;31mE (34340) spi: spi_bus_initialize(762): invalid dma channel, chip only support spi dma channel auto-alloc[0m
[0;31mE (34340) sdspi_host: spi_bus_initialize failed with rc=0x102[0m
The code below can reproduce this.
import os
from machine import Pin, SDCard
card = SDCard(slot=2, sck=Pin(17), miso=Pin(18), mosi=Pin(16), cs=Pin(15)) # <- ESP_ERR_INVALID_ARG
Reason
In ports/esp32/machine_sdcard.c, SPI slot configurations are defined. However, the DMA channel specified in the configuration for ESP32-S3 is inappropriate. In ESP-IDF, the only available channel for ESP32S3 is SPI_DMA_CH_AUTO=3.
esp-idf/components/driver/spi_common.c
Solution
Specifying DMA channel 3 instead of 2 fixes the problem. I have confirmed the problem and the solution on ESP32-S3-DevKitC-1 board.