Taking large esp_camera images using PSRAM crashes with LoadStoreAlignment exception
Posted: Sun Dec 18, 2022 9:18 pm
I am trying to use the `esp_camera` library to take large (i.e. `FRAMESIZE_UXGA`) images from an OV2640 camera on an ESP32S2. Images this large must be stored in PSRAM, i.e. `config.fb_location = CAMERA_FB_IN_PSRAM`.
Upon executing `esp_camera_fb_get()`, a `LoadStoreAlignment` exception apparently triggered within cam_verify_jpeg_eoi occurs. This occurs at any requested resolution.
Firmware / hardware used
Minimal code required to reproduce:
Using Arduino 2.0.3:
Crash report
When run on our hardware this causes the ESP32 to crash:
Decoding the exception gives this stacktrace:
Further details, inlcuding hardware setup and things I've tried so far, are located here. The PSRAM can be tested and shown to work by making a buffer with `ps_malloc`, writing to it and reading it back prior to taking an image.
Upon executing `esp_camera_fb_get()`, a `LoadStoreAlignment` exception apparently triggered within cam_verify_jpeg_eoi occurs. This occurs at any requested resolution.
Firmware / hardware used
Minimal code required to reproduce:
Using Arduino 2.0.3:
- #include <Arduino.h>
- #include "esp_camera.h"
- #define PIN_SDA 41
- #define PIN_SCL 42
- #define PIN_CAM_D0 13
- #define PIN_CAM_D1 18
- #define PIN_CAM_D2 17
- #define PIN_CAM_D3 14
- #define PIN_CAM_D4 12
- #define PIN_CAM_D5 34
- #define PIN_CAM_D6 35
- #define PIN_CAM_D7 37
- #define PIN_CAM_PCLK 33
- #define PIN_CAM_MCLK 36
- #define PIN_CAM_VSYNC 39
- #define PIN_CAM_HSYNC 38
- #define PIN_CAM_RST 40
- bool takePicture(void)
- {
- camera_config_t config;
- config.ledc_channel = LEDC_CHANNEL_0;
- config.ledc_timer = LEDC_TIMER_0;
- config.pin_d0 = PIN_CAM_D0;
- config.pin_d1 = PIN_CAM_D1;
- config.pin_d2 = PIN_CAM_D2;
- config.pin_d3 = PIN_CAM_D3;
- config.pin_d4 = PIN_CAM_D4;
- config.pin_d5 = PIN_CAM_D5;
- config.pin_d6 = PIN_CAM_D6;
- config.pin_d7 = PIN_CAM_D7;
- config.pin_xclk = PIN_CAM_MCLK;
- config.pin_pclk = PIN_CAM_PCLK;
- config.pin_vsync = PIN_CAM_VSYNC;
- config.pin_href = PIN_CAM_HSYNC;
- config.pin_sscb_sda = PIN_SDA;
- config.pin_sscb_scl = PIN_SCL;
- config.fb_location = CAMERA_FB_IN_DRAM;
- config.pin_pwdn = -1;
- config.pin_reset = PIN_CAM_RST;
- config.xclk_freq_hz = 20000000;
- config.pixel_format = PIXFORMAT_JPEG;
- config.grab_mode = CAMERA_GRAB_LATEST;
- if (psramFound())
- {
- Serial.println("PSRAM found");
- config.fb_location = CAMERA_FB_IN_PSRAM;
- config.frame_size = FRAMESIZE_VGA; // Use a normal frame size. If config.fb_location is set to CAMERA_FB_IN_DRAM, this function succeeds.
- config.jpeg_quality = 10;
- config.fb_count = 2;
- }
- else
- {
- Serial.println("PSRAM not found");
- return false;
- }
- esp_err_t err = esp_camera_init(&config);
- if (err != ESP_OK)
- {
- Serial.printf("Camera init failed w/ err 0x %d\r\n", err);
- return false;
- }
- sensor_t* s;
- s->set_exposure_ctrl(s, true); // Want auto-exposure
- s->set_aec2(s, true); // Auto-exposure DSP mode on
- s->set_aec_value(s, 300); // Set expose time ceiling [uS]
- s->set_ae_level(s, 0); // Auto expose level = 0 (-2 to 2). Dictates the exposure algorithm.
- s->set_brightness(s, 0); // Brightness 0 (-2 to 2)
- s->set_gain_ctrl(s, true); // Want auto-gain
- s->set_agc_gain(s, 30); // Set to maximum gain ceiling (0 to 30)
- camera_fb_t* photo = esp_camera_fb_get();
- Serial.printf("Photo taken, has addr. %d\r\n", photo);
- if (photo == NULL) {
- Serial.println("Null ptr as camera framebuffer");
- return false;
- }
- err = esp_camera_deinit();
- if (err != ESP_OK)
- {
- Serial.printf("Camera deinit failed w/ err 0x%x\r\n", err);
- return false;
- }
- esp_camera_fb_return(photo);
- return true;
- }
- void setup(void)
- {
- bool success;
- Serial.begin(115200);
- success = psramInit();
- if (!success) {
- Serial.println("Error initing PSRAM");
- }
- takePicture();
- }
- void loop(void)
- {
- }
When run on our hardware this causes the ESP32 to crash:
- ...
- PSRAM found
- Guru Meditation Error: Core 0 panic'ed (LoadStoreAlignment)
- ...
- /Users/ficeto/Desktop/ESP32/ESP32S2/esp32-arduino-lib-builder/components/esp32-camera/driver/cam_hal.c:70:::0x40095555:cam_verify_jpeg_eoi
- (inlined by) cam_take at /Users/ficeto/Desktop/ESP32/ESP32S2/esp32-arduino-lib-builder/components/esp32-camera/driver/cam_hal.c:480
- /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/freertos/port/xtensa/xtensa_vectors.S:633:::0x40028390:_xt_user_exc
- /Users/ficeto/Desktop/ESP32/ESP32S2/esp32-arduino-lib-builder/components/esp32-camera/driver/cam_hal.c:68:::0x40095552:cam_verify_jpeg_eoi
- (inlined by) cam_take at /Users/ficeto/Desktop/ESP32/ESP32S2/esp32-arduino-lib-builder/components/esp32-camera/driver/cam_hal.c:480
- /Users/ficeto/Desktop/ESP32/ESP32S2/esp32-arduino-lib-builder/components/esp32-camera/driver/esp_camera.c:360:::0x40094c77:esp_camera_fb_get
- C:\Users\Chris\Project\PSRAMCameraTest.ino:98 (discriminator 2):::0x400820a4:takeDummyPicture(int)
- C:\Users\Chris\Project\PSRAMCameraTest.ino(168): error 0x40082224:takePictureUnsafe(bool)
- C:\Users\Chris\Project\PSRAMCameraTest.ino(284): error 0x40082580:setup()
- C:\Users\Chris\AppData\Local\arduino15\packages\esp32\hardware\esp32\2.0.5\cores\esp32/main.cpp(42): error 0x40087f16:loopTask(void*)
- /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/esp_system/esp_system.c:44 (discriminator 1):::0x40026de9:esp_restart_noos_dig