@@ -92,6 +92,24 @@ static inline size_t dcache_line_size(void)
92
92
#endif
93
93
}
94
94
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
+
95
113
/* Throttle repeated warnings printed from tight loops / ISRs.
96
114
*
97
115
* counter – static DRAM/IRAM uint16_t you pass in
@@ -256,15 +274,7 @@ static void cam_task(void *arg)
256
274
probe_len = CAM_SOI_PROBE_BYTES ;
257
275
}
258
276
/* 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 );
268
278
269
279
uint8_t soi_probe [CAM_SOI_PROBE_BYTES ];
270
280
memcpy (soi_probe , frame_buffer_event -> buf , probe_len );
@@ -684,15 +694,7 @@ camera_fb_t *cam_take(TickType_t timeout)
684
694
if (probe_len == 0 ) {
685
695
goto skip_eoi_check ;
686
696
}
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 );
696
698
697
699
uint8_t eoi_probe [CAM_EOI_PROBE_BYTES ];
698
700
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)
704
706
offset_e = cam_verify_jpeg_eoi (dma_buffer -> buf , dma_buffer -> len );
705
707
}
706
708
707
- skip_eoi_check :
708
-
709
709
if (offset_e >= 0 ) {
710
710
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
+ }
711
715
return dma_buffer ;
712
716
}
713
717
718
+ skip_eoi_check :
719
+
714
720
CAM_WARN_THROTTLE (warn_eoi_miss_cnt ,
715
721
"NO-EOI - JPEG end marker missing" );
716
722
cam_give (dma_buffer );
@@ -721,6 +727,11 @@ camera_fb_t *cam_take(TickType_t timeout)
721
727
dma_buffer -> len = ll_cam_memcpy (cam_obj , dma_buffer -> buf , dma_buffer -> buf , dma_buffer -> len );
722
728
}
723
729
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
+
724
735
return dma_buffer ;
725
736
}
726
737
}
0 commit comments