# Rust needs more stack than C for the main task and for the threads esp-idf-svc # spawns internally. CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192 CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=4096 CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=4096 CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=4096 # Run the CPU at 240 MHz. # # This is the single biggest win in this file and it is free. ESP-IDF v5.5's # Kconfig defaults the ESP32-S3 to *160* MHz (see # components/esp_system/port/soc/esp32s3/Kconfig.cpu), so a stock build quietly # leaves half the CPU on the table. Camera capture, the JPEG search in # esp32-camera, lwIP and the HTTP server are all CPU-bound here, so this moves # all of them at once. CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y # ESP32-S3-N16R8: 16 MB flash, 8 MB octal PSRAM. # # DIO at 40 MHz, not the QIO/80 MHz this part is rated for: the flash on the # test module has a defective byte (see README) and quad mode pushes it over # the edge into a boot loop. Drop back to QIO/80 MHz on a healthy module. # # QIO would speed up *code* execution noticeably, since the app runs from flash # and the flash cache misses go straight to this bus. CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y CONFIG_ESPTOOLPY_FLASHMODE_DIO=y CONFIG_ESPTOOLPY_FLASHFREQ_40M=y # Code runs from flash, so instruction cache is the cheapest way to hide the # slow flash bus. 32 KB instead of the 16 KB default. CONFIG_ESP32S3_INSTRUCTION_CACHE_32KB=y # Without this ESP-IDF uses partitions_singleapp.csv, whose factory partition is # only 1 MB - smaller than the ~1.15 MB this firmware produces, so the image # overflows the partition. # # The custom table also moves the app to 0x40000, which is what keeps the image # off the module's defective flash byte; see partitions.csv for why. CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="../../../../../../partitions.csv" CONFIG_PARTITION_TABLE_OFFSET=0x8000 # Octal PSRAM is mandatory for the N16R8 module (R8 == 8 MB OPI PSRAM). The # camera frame buffers live in it, so this is what makes VGA possible. CONFIG_SPIRAM=y CONFIG_SPIRAM_MODE_OCT=y CONFIG_SPIRAM_SPEED_80M=y CONFIG_SPIRAM_USE_MALLOC=y CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384 CONFIG_SPIRAM_MEMTEST=y # Keep the WiFi and lwIP buffers in internal RAM. # # This was previously set to `y` on the reasoning that PSRAM is plentiful, which # is exactly backwards: WiFi descriptors and TCP segments are touched on every # packet, and internal SRAM is an order of magnitude faster to reach than PSRAM # behind the memory bus. Putting them in PSRAM shows up as high latency and poor # throughput no matter how much PSRAM is free. The frame buffers, which are large # and touched rarely by comparison, stay in PSRAM. CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=n CONFIG_ESP_WIFI_IRAM_OPT=y CONFIG_ESP_WIFI_RX_IRAM_OPT=y # Socket buffers sized for a video frame rather than for a text request. # # A VGA JPEG is ~20 kB. lwIP's 5760-byte default send buffer splits that into # four segments, each one a separate pass through the WiFi driver; 17408 is the # lwIP-recommended size for bulk transfers and covers a frame in one or two. CONFIG_LWIP_TCP_SND_BUF_DEFAULT=17408 CONFIG_LWIP_TCP_WND_DEFAULT=17408 # Camera component CONFIG_CAMERA_TASK_STACK_SIZE=4096 # Run the camera task on CPU1. # # The WiFi task is pinned to CPU0. esp32-camera's capture task spends its time # in short, latency-sensitive bursts (DMA completion, the JPEG marker search, # the copy into the frame buffer) and gets preempted on a shared core, which # lengthens every frame. On a two-core part there is no reason to share. CONFIG_CAMERA_CORE0=n # PSRAM DMA is left off deliberately. # # With it on, esp32-camera writes frame buffers in PSRAM straight from GDMA and # then looks for the JPEG end-of-image marker only inside the last DMA node # (1 KB here). If the marker lands outside that window the frame is thrown away # with "NO-EOI", and on this board that is most of them - after a few frames the # driver stops handing out frames at all and never recovers. # # Off, the driver DMAs into an internal-RAM bounce buffer and copies the frame # into PSRAM, which costs one extra memcpy of ~23 KB per frame and searches the # whole buffer for the marker. That is the right trade for a working stream. CONFIG_CAMERA_PSRAM_DMA=n # Largest contiguous DMA chunk the driver may ask for. CONFIG_CAMERA_DMA_BUFFER_SIZE_MAX=32768 # ESP-IDF 5.3+ links both the legacy driver/i2c.h and the new driver_ng I2C # driver, and refuses to run both in one image. esp32-camera picks one of them # for the SCCB bus; whichever it picks, the other has to stay out of the image, # so the conflict check is skipped here. CONFIG_I2C_SKIP_LEGACY_CONFLICT_CHECK=y