Skip to content

Commit 877e5e9

Browse files
authored
Merge pull request #778 from RubenKelevra/bugfix/ensure_cache_coherency_before_returning_image_in_psram-mode
cam_hal: drop caches for psram_mode frames before hand-off to application
2 parents 9f66ed2 + d0a8751 commit 877e5e9

File tree

1 file changed

+31
-20
lines changed

1 file changed

+31
-20
lines changed

driver/cam_hal.c

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,24 @@ static inline size_t dcache_line_size(void)
9292
#endif
9393
}
9494

95+
/*
96+
* Invalidate CPU data cache lines that cover a region in PSRAM which
97+
* has just been written by DMA. This guarantees subsequent CPU reads
98+
* fetch the fresh data from PSRAM rather than stale cache contents.
99+
* Both address and length are aligned to the data cache line size.
100+
*/
101+
static inline void cam_drop_psram_cache(void *addr, size_t len)
102+
{
103+
size_t line = dcache_line_size();
104+
if (line == 0) {
105+
line = 32; /* sane fallback */
106+
}
107+
uintptr_t start = (uintptr_t)addr & ~(line - 1);
108+
size_t sync_len = (len + ((uintptr_t)addr - start) + line - 1) & ~(line - 1);
109+
esp_cache_msync((void *)start, sync_len,
110+
ESP_CACHE_MSYNC_FLAG_DIR_M2C | ESP_CACHE_MSYNC_FLAG_INVALIDATE);
111+
}
112+
95113
/* Throttle repeated warnings printed from tight loops / ISRs.
96114
*
97115
* counter – static DRAM/IRAM uint16_t you pass in
@@ -256,15 +274,7 @@ static void cam_task(void *arg)
256274
probe_len = CAM_SOI_PROBE_BYTES;
257275
}
258276
/* Invalidate cache lines for the DMA buffer before probing */
259-
size_t line = dcache_line_size();
260-
if (line == 0) {
261-
line = 32; /* sane fallback */
262-
}
263-
uintptr_t addr = (uintptr_t)frame_buffer_event->buf;
264-
uintptr_t start = addr & ~(line - 1);
265-
size_t sync_len = (probe_len + (addr - start) + line - 1) & ~(line - 1);
266-
esp_cache_msync((void *)start, sync_len,
267-
ESP_CACHE_MSYNC_FLAG_DIR_M2C | ESP_CACHE_MSYNC_FLAG_INVALIDATE);
277+
cam_drop_psram_cache(frame_buffer_event->buf, probe_len);
268278

269279
uint8_t soi_probe[CAM_SOI_PROBE_BYTES];
270280
memcpy(soi_probe, frame_buffer_event->buf, probe_len);
@@ -684,15 +694,7 @@ camera_fb_t *cam_take(TickType_t timeout)
684694
if (probe_len == 0) {
685695
goto skip_eoi_check;
686696
}
687-
size_t line = dcache_line_size();
688-
if (line == 0) {
689-
line = 32; /* sane fallback */
690-
}
691-
uintptr_t addr = (uintptr_t)(dma_buffer->buf + dma_buffer->len - probe_len);
692-
uintptr_t start = addr & ~(line - 1);
693-
size_t sync_len = (probe_len + (addr - start) + line - 1) & ~(line - 1);
694-
esp_cache_msync((void *)start, sync_len,
695-
ESP_CACHE_MSYNC_FLAG_DIR_M2C | ESP_CACHE_MSYNC_FLAG_INVALIDATE);
697+
cam_drop_psram_cache(dma_buffer->buf + dma_buffer->len - probe_len, probe_len);
696698

697699
uint8_t eoi_probe[CAM_EOI_PROBE_BYTES];
698700
memcpy(eoi_probe, dma_buffer->buf + dma_buffer->len - probe_len, probe_len);
@@ -704,13 +706,17 @@ camera_fb_t *cam_take(TickType_t timeout)
704706
offset_e = cam_verify_jpeg_eoi(dma_buffer->buf, dma_buffer->len);
705707
}
706708

707-
skip_eoi_check:
708-
709709
if (offset_e >= 0) {
710710
dma_buffer->len = offset_e + sizeof(JPEG_EOI_MARKER);
711+
if (cam_obj->psram_mode) {
712+
/* DMA may bypass cache, ensure full frame is visible */
713+
cam_drop_psram_cache(dma_buffer->buf, dma_buffer->len);
714+
}
711715
return dma_buffer;
712716
}
713717

718+
skip_eoi_check:
719+
714720
CAM_WARN_THROTTLE(warn_eoi_miss_cnt,
715721
"NO-EOI - JPEG end marker missing");
716722
cam_give(dma_buffer);
@@ -721,6 +727,11 @@ camera_fb_t *cam_take(TickType_t timeout)
721727
dma_buffer->len = ll_cam_memcpy(cam_obj, dma_buffer->buf, dma_buffer->buf, dma_buffer->len);
722728
}
723729

730+
if (cam_obj->psram_mode) {
731+
/* DMA may bypass cache, ensure full frame is visible to the app */
732+
cam_drop_psram_cache(dma_buffer->buf, dma_buffer->len);
733+
}
734+
724735
return dma_buffer;
725736
}
726737
}

0 commit comments

Comments
 (0)