espressif / arduino-esp32

Arduino core for the ESP32
GNU Lesser General Public License v2.1
12.96k stars 7.29k forks source link

ESP32-S2, S3: inherent GPIO speed limit? #6657

Closed PaintYourDragon closed 1 year ago

PaintYourDragon commented 2 years ago

Board

ESP32-S2, S3

Device Description

Adafruit Feather ESP32-S2 and S3

Hardware Configuration

Stock configuration, oscilloscope reading from pin 13 (LED)

Version

latest development Release Candidate (RC-X)

IDE Name

Arduino IDE

Operating System

macOS 12.3.1

Flash frequency

80MHz

PSRAM enabled

no

Upload speed

921600

Description

GPIO performance on ESP32-S2 and S3 seems to be sub-par, with even a tight bit-toggling loop going direct to GPIO registers only managing 8 MHz. A particular situation requires 16-24 MHz…original ESP32 could handle this, but peripherals in the new devices are different.

Minimal approach: is there something in a CPU-to-peripheral clock division that can be changed to improve this? 2X might be just adequate. Less minimal: should I be looking at the Dedicated GPIO module? Way less minimal: special peripherals…I2S? DMA?

Background: Adafruit_Protomatter library for Arduino (a HUB75 RGB LED matrix driver) intentionally uses a very brute-force, bit-bang-y approach (rather than relying on dedicated peripherals) so it’s easily ported to a broad range of devices (currently at least 8), needing only a thin shim to accommodate each chip’s timer and interrupt specifics and generally being a lot less effort to maintain. Although it’s presently able to run on S2 & S3, this GPIO bottleneck causes slow refresh. Hoping to avoid a whole separate codebase for a particular chip (e.g. the I2S HUB75 implementations for classic ESP32), if there’s a not-too-different way of boosting the GPIO throughput here.

Sketch

volatile uint32_t *set =  (volatile uint32_t *)&GPIO.out_w1ts;
volatile uint32_t *clear =  (volatile uint32_t *)&GPIO.out_w1tc;
const uint32_t bit = 1 << 13;

void setup() {
  pinMode(13, OUTPUT);
  for(;;) {
    *set = bit;
    *clear = bit;
  }
}

void loop() {}

Debug Message

No error, question only

Other Steps to Reproduce

No response

I have checked existing issues, online documentation and the Troubleshooting Guide

me-no-dev commented 2 years ago

Honestly I am surprised that you were able to do even that. Bit-banging on ESP32 should really be used only in cases where speed and timing are not required. I2S/LCD interface is probably the best option.

On the question: I, personally, am not aware of any difference between ESP32 and S3 that would cause what you see.

SuGlider commented 2 years ago

@PaintYourDragon I suggest you to use https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-I2S-DMA instead of Adafruit Library. Not sure if this library is ESP32-S2/ESP32-S3 compatible... but maybe it wi worth a try.

There is some information about SoC support at https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-I2S-DMA#esp32-supported

VojtechBartoska commented 2 years ago

Up to suggest solution above, do you still need help @PaintYourDragon?

PaintYourDragon commented 2 years ago

Thanks. I did find an ugly and probably temporary workaround for ESP32-S2 using the Dedicated GPIO peripheral (20 MHz is possible)…but which doesn’t appear to be present as a feature on the S3. Similar situation with the ESP32-HUB75-MatrixPanel-I2S-DMA library: S2 is supported, S3 is not…it appears I2S and the LCD driver are now fully distinct peripherals with their own register sets, so the Old Ways no longer work.

I suppose it’s now a matter of putting in the time to learn the ins & outs of the new device. Something mentioned in headers & docs, “octo SPI,” may be just the thing that’s needed…but the Technical Ref Manual hasn’t received its SPI chapter yet. Do you have any insights when the next manual release might come along? Thank you!

SuGlider commented 2 years ago

@me-no-dev - Can you give @PaintYourDragon some documentation links about the S3 Octo SPI?

me-no-dev commented 2 years ago

@SuGlider - I do not have any such thing beyond what is available in the TRM. OPI flash is another thing

ladyada commented 2 years ago

hiya, just popping in to say that we'll be looking at the TFT driver next!

VojtechBartoska commented 1 year ago

Can I consider this as answered @PaintYourDragon?

PaintYourDragon commented 1 year ago

Indeed, yes, thank you!

JimDrewGH commented 12 months ago

For those that are searching for a solution, read the info in the TRM for the S2 and S3 for the new CPU instructions that can access the pins directly. You can get 80MHz access to pins individually or a bunch of them through a mask. See here for some details:

https://gist.github.com/laotie/f66abc733a6473300625f5658821001a

solosky commented 7 months ago

For those that are searching for a solution, read the info in the TRM for the S2 and S3 for the new CPU instructions that can access the pins directly. You can get 80MHz access to pins individually or a bunch of them through a mask. See here for some details:

https://gist.github.com/laotie/f66abc733a6473300625f5658821001a

Tested. Not posssible be able to get 80MHz with dediceted IO PIE, maxmium speed archived only 20MHz. But the SPI could run at 80 MHz.

meesokim commented 6 months ago

For those that are searching for a solution, read the info in the TRM for the S2 and S3 for the new CPU instructions that can access the pins directly. You can get 80MHz access to pins individually or a bunch of them through a mask. See here for some details: https://gist.github.com/laotie/f66abc733a6473300625f5658821001a

Tested. Not posssible be able to get 80MHz with dediceted IO PIE, maxmium speed archived only 20MHz. But the SPI could run at 80 MHz.

Is 20Mhz limit binding to CPU frequency or it's own limit? Because ESP32s2 CPU can be overclocked to 240Mhz.

hobbytest123 commented 2 months ago

I got 120 Mhz with ESP32-S2