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:
Code: Sketch.cpp Select all
#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:
Code: log Select all
...
PSRAM found
Guru Meditation Error: Core 0 panic'ed (LoadStoreAlignment)
...
Code: stacktrace Select all
/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