@@ -477,47 +477,65 @@ void cam_start(void)
477
477
camera_fb_t * cam_take (TickType_t timeout )
478
478
{
479
479
camera_fb_t * dma_buffer = NULL ;
480
- TickType_t start = xTaskGetTickCount ();
481
- xQueueReceive (cam_obj -> frame_buffer_queue , (void * )& dma_buffer , timeout );
480
+ const TickType_t start = xTaskGetTickCount ();
482
481
#if CONFIG_IDF_TARGET_ESP32S3
483
- // Currently (22.01.2024) there is a bug in ESP-IDF v5.2, that causes
484
- // GDMA to fall into a strange state if it is running while WiFi STA is connecting.
485
- // This code tries to reset GDMA if frame is not received, to try and help with
486
- // this case. It is possible to have some side effects too, though none come to mind
487
- if (!dma_buffer ) {
488
- ll_cam_dma_reset (cam_obj );
489
- xQueueReceive (cam_obj -> frame_buffer_queue , (void * )& dma_buffer , timeout );
490
- }
482
+ uint16_t dma_reset_counter = 0 ;
483
+ static const uint8_t MAX_GDMA_RESETS = 3 ;
484
+ #endif
485
+
486
+ for (;;)
487
+ {
488
+ TickType_t elapsed = xTaskGetTickCount () - start ; /* TickType_t is unsigned so rollover is safe */
489
+ if (elapsed >= timeout ) {
490
+ ESP_LOGW (TAG , "Failed to get frame: timeout" );
491
+ return NULL ;
492
+ }
493
+ TickType_t remaining = timeout - elapsed ;
494
+
495
+ if (xQueueReceive (cam_obj -> frame_buffer_queue , (void * )& dma_buffer , remaining ) == pdFALSE ) {
496
+ continue ;
497
+ }
498
+
499
+ if (!dma_buffer ) {
500
+ /* Work-around for ESP32-S3 GDMA freeze when Wi-Fi STA starts.
501
+ * See esp32-camera commit 984999f (issue #620). */
502
+ #if CONFIG_IDF_TARGET_ESP32S3
503
+ if (dma_reset_counter < MAX_GDMA_RESETS ) {
504
+ ll_cam_dma_reset (cam_obj );
505
+ dma_reset_counter ++ ;
506
+ continue ; /* retry with queue timeout */
507
+ }
508
+ if (dma_reset_counter == MAX_GDMA_RESETS ) {
509
+ ESP_LOGW (TAG , "Giving up GDMA reset after %u tries" , dma_reset_counter );
510
+ dma_reset_counter ++ ; /* suppress further logs */
511
+ }
512
+ #else
513
+ /* Early warning for misbehaving sensors on other chips */
514
+ ESP_LOGW (TAG , "Unexpected NULL frame on %s" , CONFIG_IDF_TARGET );
491
515
#endif
492
- if (dma_buffer ) {
493
- if (cam_obj -> jpeg_mode ){
494
- // find the end marker for JPEG. Data after that can be discarded
516
+ vTaskDelay (1 ); /* immediate yield once resets are done */
517
+ continue ; /* go to top of loop */
518
+ }
519
+
520
+ if (cam_obj -> jpeg_mode ) {
521
+ /* find the end marker for JPEG. Data after that can be discarded */
495
522
int offset_e = cam_verify_jpeg_eoi (dma_buffer -> buf , dma_buffer -> len );
496
523
if (offset_e >= 0 ) {
497
- // adjust buffer length
498
524
dma_buffer -> len = offset_e + sizeof (JPEG_EOI_MARKER );
499
525
return dma_buffer ;
500
- } else {
501
- ESP_LOGW (TAG , "NO-EOI" );
502
- cam_give (dma_buffer );
503
- TickType_t ticks_spent = xTaskGetTickCount () - start ;
504
- if (ticks_spent >= timeout ) {
505
- return NULL ; /* We are out of time */
506
- }
507
- return cam_take (timeout - ticks_spent );//recurse!!!!
508
526
}
509
- } else if (cam_obj -> psram_mode && cam_obj -> in_bytes_per_pixel != cam_obj -> fb_bytes_per_pixel ){
510
- //currently this is used only for YUV to GRAYSCALE
527
+
528
+ ESP_LOGW (TAG , "NO-EOI" );
529
+ cam_give (dma_buffer );
530
+ continue ; /* wait for another frame */
531
+ } else if (cam_obj -> psram_mode &&
532
+ cam_obj -> in_bytes_per_pixel != cam_obj -> fb_bytes_per_pixel ) {
533
+ /* currently used only for YUV to GRAYSCALE */
511
534
dma_buffer -> len = ll_cam_memcpy (cam_obj , dma_buffer -> buf , dma_buffer -> buf , dma_buffer -> len );
512
535
}
536
+
513
537
return dma_buffer ;
514
- } else {
515
- ESP_LOGW (TAG , "Failed to get the frame on time!" );
516
- // #if CONFIG_IDF_TARGET_ESP32S3
517
- // ll_cam_dma_print_state(cam_obj);
518
- // #endif
519
538
}
520
- return NULL ;
521
539
}
522
540
523
541
void cam_give (camera_fb_t * dma_buffer )
@@ -539,4 +557,4 @@ void cam_give_all(void) {
539
557
bool cam_get_available_frames (void )
540
558
{
541
559
return 0 < uxQueueMessagesWaiting (cam_obj -> frame_buffer_queue );
542
- }
560
+ }
0 commit comments