Skip to content

Commit 1d950f1

Browse files
committed
fix jpeg soi check for psram_mode (DMA)
- Added a configurable probe length for PSRAM JPEG validation via CAM_SOI_PROBE_BYTES - For PSRAM mode, CAM_SOI_PROBE_BYTES is copied from the first DMA block into a stack buffer and validated by cam_verify_jpeg_soi() to verify that it's a valid jpeg image before continuing the capture. - Reading from PSRAM directly with cam_verify_jpeg_soi() is here avoided due to latency of small operations done by cam_verify_jpeg_soi().
1 parent 2368d94 commit 1d950f1

File tree

1 file changed

+61
-3
lines changed

1 file changed

+61
-3
lines changed

driver/cam_hal.c

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "rom/ets_sys.h"
2525
#else
2626
#include "esp_timer.h"
27+
#include "esp_cache.h"
2728
#if CONFIG_IDF_TARGET_ESP32
2829
#include "esp32/rom/ets_sys.h" // will be removed in idf v5.0
2930
#elif CONFIG_IDF_TARGET_ESP32S2
@@ -56,6 +57,17 @@ static portMUX_TYPE g_psram_dma_lock = portMUX_INITIALIZER_UNLOCKED;
5657
#define CAM_LOG_SPAM_EVERY_FRAME 0 /* set to 1 to restore old behaviour */
5758
#endif
5859

60+
/* Number of bytes copied to SRAM for SOI validation when capturing
61+
* directly to PSRAM. Tunable to probe more of the frame start if needed. */
62+
#ifndef CAM_SOI_PROBE_BYTES
63+
#define CAM_SOI_PROBE_BYTES 32
64+
#endif
65+
66+
/*
67+
* PSRAM DMA may bypass the CPU cache. Always call esp_cache_msync() on the
68+
* SOI probe region so cached reads see the data written by DMA.
69+
*/
70+
5971
/* Throttle repeated warnings printed from tight loops / ISRs.
6072
*
6173
* counter – static DRAM/IRAM uint16_t you pass in
@@ -209,11 +221,57 @@ static void cam_task(void *arg)
209221
&cam_obj->dma_buffer[(cnt % cam_obj->dma_half_buffer_cnt) * cam_obj->dma_half_buffer_size],
210222
cam_obj->dma_half_buffer_size);
211223
}
224+
212225
//Check for JPEG SOI in the first buffer. stop if not found
213-
if (cam_obj->jpeg_mode && cnt == 0 && cam_verify_jpeg_soi(frame_buffer_event->buf, frame_buffer_event->len) != 0) {
214-
ll_cam_stop(cam_obj);
215-
cam_obj->state = CAM_STATE_IDLE;
226+
if (cam_obj->jpeg_mode && cnt == 0) {
227+
if (cam_obj->psram_mode) {
228+
/* dma_half_buffer_size already in BYTES (see ll_cam_memcpy()) */
229+
size_t probe_len = cam_obj->dma_half_buffer_size;
230+
/* clamp to avoid copying past the end of soi_probe */
231+
if (probe_len > CAM_SOI_PROBE_BYTES) {
232+
probe_len = CAM_SOI_PROBE_BYTES;
233+
}
234+
/* Invalidate cache lines for the DMA buffer before probing */
235+
size_t line = esp_cache_get_line_size_by_addr(frame_buffer_event->buf);
236+
uintptr_t addr = (uintptr_t)frame_buffer_event->buf;
237+
uintptr_t start = addr & ~(line - 1);
238+
size_t sync_len = (probe_len + (addr - start) + line - 1) & ~(line - 1);
239+
esp_cache_msync((void *)start, sync_len,
240+
ESP_CACHE_MSYNC_FLAG_DIR_M2C | ESP_CACHE_MSYNC_FLAG_INVALIDATE);
241+
242+
uint8_t soi_probe[CAM_SOI_PROBE_BYTES];
243+
memcpy(soi_probe, frame_buffer_event->buf, probe_len);
244+
int soi_off = cam_verify_jpeg_soi(soi_probe, probe_len);
245+
if (soi_off != 0) {
246+
static uint16_t warn_psram_soi_cnt = 0;
247+
if (soi_off > 0) {
248+
CAM_WARN_THROTTLE(warn_psram_soi_cnt,
249+
"NO-SOI - JPEG start marker not at pos 0 (PSRAM)");
250+
} else {
251+
CAM_WARN_THROTTLE(warn_psram_soi_cnt,
252+
"NO-SOI - JPEG start marker missing (PSRAM)");
253+
}
254+
ll_cam_stop(cam_obj);
255+
cam_obj->state = CAM_STATE_IDLE;
256+
DBG_PIN_SET(0);
257+
continue;
258+
}
259+
} else {
260+
int soi_off = cam_verify_jpeg_soi(frame_buffer_event->buf, frame_buffer_event->len);
261+
if (soi_off != 0) {
262+
if (soi_off > 0) {
263+
static uint16_t warn_soi_bad_cnt = 0;
264+
CAM_WARN_THROTTLE(warn_soi_bad_cnt,
265+
"NO-SOI - JPEG start marker not at pos 0");
266+
}
267+
ll_cam_stop(cam_obj);
268+
cam_obj->state = CAM_STATE_IDLE;
269+
DBG_PIN_SET(0);
270+
continue;
271+
}
272+
}
216273
}
274+
217275
cnt++;
218276
// stop when too many DMA copies occur so the PSRAM
219277
// framebuffer slot doesn't overflow from runaway transfers

0 commit comments

Comments
 (0)