Skip to content

Commit d6fbaf0

Browse files
committed
rework psram_mode frame buffer overflow check
- Do this check only in psram_mode - Improve code comment, to make clear that it will stop early on copy operations - Increase fb size by one dma_half_buffer_size in psram_mode Rationale: In psram_mode we will be called after each memory copy operation is completed, by the CAM_IN_SUC_EOF event. Since we cannot predict at this point, if the camera will copy another dma_half_buffer_size into the fb, we need to abort here, if there's not enough size in the fb for the next copy operation. This assumption means, we will abort even if this is indeed the last copy operation the camera did, and the next event will be a CAM_VSYNC, notifying us, that the copy operation is completed. Since we cannot predict this, we need one dma_half_buffer_size more space in the fb in psram_mode to allow images of the same size in psram_mode as in the regular mode.
1 parent 2368d94 commit d6fbaf0

File tree

1 file changed

+16
-8
lines changed

1 file changed

+16
-8
lines changed

driver/cam_hal.c

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -208,21 +208,25 @@ static void cam_task(void *arg)
208208
&frame_buffer_event->buf[frame_buffer_event->len],
209209
&cam_obj->dma_buffer[(cnt % cam_obj->dma_half_buffer_cnt) * cam_obj->dma_half_buffer_size],
210210
cam_obj->dma_half_buffer_size);
211+
} else {
212+
// stop if the next DMA copy would exceed the framebuffer slot
213+
// size, since we're called only after the copy occurs
214+
// This effectively reduces maximum usable frame buffer size
215+
// by one DMA operation, as we can't predict here, if the next
216+
// cam event will be a VSYNC
217+
if (cnt + 1 >= cam_obj->frame_copy_cnt) {
218+
ESP_LOGE(TAG, "DMA overflow");
219+
ll_cam_stop(cam_obj);
220+
cam_obj->state = CAM_STATE_IDLE;
221+
continue;
222+
}
211223
}
212224
//Check for JPEG SOI in the first buffer. stop if not found
213225
if (cam_obj->jpeg_mode && cnt == 0 && cam_verify_jpeg_soi(frame_buffer_event->buf, frame_buffer_event->len) != 0) {
214226
ll_cam_stop(cam_obj);
215227
cam_obj->state = CAM_STATE_IDLE;
216228
}
217229
cnt++;
218-
// stop when too many DMA copies occur so the PSRAM
219-
// framebuffer slot doesn't overflow from runaway transfers
220-
if (cnt >= cam_obj->frame_copy_cnt) {
221-
ESP_LOGE(TAG, "DMA overflow");
222-
ll_cam_stop(cam_obj);
223-
cam_obj->state = CAM_STATE_IDLE;
224-
continue;
225-
}
226230

227231
} else if (cam_event == CAM_VSYNC_EVENT) {
228232
//DBG_PIN_SET(1);
@@ -320,6 +324,9 @@ static esp_err_t cam_dma_config(const camera_config_t *config)
320324

321325
cam_obj->dma_node_cnt = (cam_obj->dma_buffer_size) / cam_obj->dma_node_buffer_size; // Number of DMA nodes
322326
cam_obj->frame_copy_cnt = cam_obj->recv_size / cam_obj->dma_half_buffer_size; // Number of interrupted copies, ping-pong copy
327+
if (cam_obj->psram_mode) {
328+
cam_obj->frame_copy_cnt++;
329+
}
323330

324331
ESP_LOGI(TAG, "buffer_size: %d, half_buffer_size: %d, node_buffer_size: %d, node_cnt: %d, total_cnt: %d",
325332
(int) cam_obj->dma_buffer_size, (int) cam_obj->dma_half_buffer_size, (int) cam_obj->dma_node_buffer_size,
@@ -338,6 +345,7 @@ static esp_err_t cam_dma_config(const camera_config_t *config)
338345
if (cam_obj->fb_size < cam_obj->recv_size) {
339346
fb_size = cam_obj->recv_size;
340347
}
348+
fb_size += cam_obj->dma_half_buffer_size;
341349
}
342350

343351
/* Allocate memory for frame buffer */

0 commit comments

Comments
 (0)