I did some hardcore experimentation with the ESP32-S3 ADC's a while back. Rather than using the official libraries (which themselves contained a few bugs and hacks) I made a lot of headway by starting from scratch and setting up the raw peripheral registers myself. Actually prefer it that way, without all the abstraction underneath.

Wrangled out some decent results at an impressive 80kHz sample rate in continuous mode, using DMA for near-zero CPU involvement. Here's a plot captured at the time (along with an analog probe for comparison): https://imgur.com/a/5zfy9LZ

I'm not sure if [m]any other people have done this, and one day I'd love to get around to posting sample code along with a little writeup.

It was a real uphill battle to get there. Discovered and reported dozen[s] of errata in documentation to EspressIf (most of which was acknowledged and queued for correction in their next Technical Reference Manual update, although I admit after a couple months I stopped checking to see if surfaced). Lots of undocumented bits had to be deciphered (including basic ones in SYSTEM_PERIP_RST_EN0_REG and SYSTEM_PERIP_CLK_EN0_REG to reset the ADC peripheral and enable it's clock, and power control bits in SENS_SAR_POWER_XPD_SAR_REG).

ADC2 is write-off for anything high-speed, as the entire digi controller was 'dropped' from support due to bad silicon (there's some interesting history and trends if you read up on ADC errata across earlier ESP32 models - it's clear EspressIf really struggled with analog, but they're inching forward with progress as the lineup evolves). Unfortunately when they yanked the documentation for it, they went a little overboard and removed some whole sections that relate to the still-working ADC1 (e.g. all mention of APB_SARADC1_DATA_STATUS_REG, which stores the most recently sampled ADC1 result, was lost in collateral damage).

Other minor documentation pains included mistakes in DMA descriptors, subtly incorrect command sequencing in the ADC Pattern Table (that one cost a couple evenings of debugging to track down), incorrect and sometimes senseless information referring to the use of a flag in GDMA_OUT_AUTO_WRBACK_CHn for a receive channel, ADC_ATTEN_DB_11 constant being used all over the place even though it's actually 12dB (granted that's a nitpick), unintuitive and undocumented behavior that seems in some circumstances to cause GDMA to not move onto the next descriptor until DMA_IN_SUC_EOF is generated, certain actions like pausing and resuming DMA (e.g. for diagnostic instrumentation code to retrieve a consistent snapshot of all the involved registers) seems to corrupt the descriptor pointer (that one might turn out to be by design), and other little mistakes like copy/paste errors or other ambiguities. That all said, it's still not the worst documentation I've seen.

Hardware ADC calibration can significantly improve results, but it's unfortunately buried under undocumented ROM functions required to initialize and enable the feature (via an undocumented I2C configuration bus); without this my readings were off by ~50%. (There's something called an "Internal Calibration Bus" which sadly isn't mentioned once in the docs).

All in all a fun project, though in retrospect it would have taken a lot less time to get up and running with a dedicated ADC chip in my BOM.