@@ -45,8 +45,8 @@ struct video_stm32_dcmi_data {
45
45
struct k_fifo fifo_in ;
46
46
struct k_fifo fifo_out ;
47
47
struct video_buffer * vbuf ;
48
- bool snapshot_mode : 1 ;
49
- bool restart_dma : 1 ;
48
+ uint32_t snapshot_start_time ;
49
+ bool snapshot_mode ;
50
50
};
51
51
52
52
struct video_stm32_dcmi_config {
@@ -56,15 +56,29 @@ struct video_stm32_dcmi_config {
56
56
const struct device * sensor_dev ;
57
57
const struct stream dma ;
58
58
bool snapshot_mode ;
59
+ int snapshot_timeout ;
59
60
};
60
61
61
62
static void stm32_dcmi_process_dma_error (DCMI_HandleTypeDef * hdcmi )
62
63
{
63
64
struct video_stm32_dcmi_data * dev_data =
64
65
CONTAINER_OF (hdcmi , struct video_stm32_dcmi_data , hdcmi );
65
66
66
- dev_data -> restart_dma = true;
67
- k_fifo_cancel_wait (& dev_data -> fifo_out );
67
+ LOG_WRN ("Restart DMA after Error!" );
68
+
69
+ /* Lets try to recover by stopping and restart */
70
+ if (HAL_DCMI_Stop (& dev_data -> hdcmi ) != HAL_OK ) {
71
+ LOG_WRN ("HAL_DCMI_Stop FAILED!" );
72
+ return ;
73
+ }
74
+
75
+ if (HAL_DCMI_Start_DMA (& dev_data -> hdcmi ,
76
+ dev_data -> snapshot_mode ? DCMI_MODE_SNAPSHOT : DCMI_MODE_CONTINUOUS ,
77
+ (uint32_t )dev_data -> vbuf -> buffer ,
78
+ dev_data -> vbuf -> size / 4 ) != HAL_OK ) {
79
+ LOG_WRN ("Continuous: HAL_DCMI_Start_DMA FAILED!" );
80
+ return ;
81
+ }
68
82
}
69
83
70
84
void HAL_DCMI_ErrorCallback (DCMI_HandleTypeDef * hdcmi )
@@ -85,6 +99,7 @@ void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi)
85
99
dev_data -> vbuf = NULL ;
86
100
vbuf -> timestamp = k_uptime_get_32 ();
87
101
k_fifo_put (& dev_data -> fifo_out , vbuf );
102
+ LOG_DBG ("event SH put: %p" , vbuf );
88
103
return ;
89
104
}
90
105
@@ -270,7 +285,7 @@ static int video_stm32_dcmi_set_stream(const struct device *dev, bool enable,
270
285
return 0 ;
271
286
}
272
287
273
- if (!config -> snapshot_mode && (CONFIG_VIDEO_BUFFER_POOL_NUM_MAX != 1 )) {
288
+ if (!data -> snapshot_mode && (CONFIG_VIDEO_BUFFER_POOL_NUM_MAX != 1 )) {
274
289
data -> vbuf = k_fifo_get (& data -> fifo_in , K_NO_WAIT );
275
290
276
291
if (data -> vbuf == NULL ) {
@@ -302,7 +317,6 @@ static int video_stm32_dcmi_enqueue(const struct device *dev, struct video_buffe
302
317
{
303
318
struct video_stm32_dcmi_data * data = dev -> data ;
304
319
const uint32_t buffer_size = data -> fmt .pitch * data -> fmt .height ;
305
-
306
320
if (buffer_size > vbuf -> size ) {
307
321
return - EINVAL ;
308
322
}
@@ -315,82 +329,88 @@ static int video_stm32_dcmi_enqueue(const struct device *dev, struct video_buffe
315
329
return 0 ;
316
330
}
317
331
318
- static int video_stm32_restart_dma_after_error (struct video_stm32_dcmi_data * data )
332
+ static int video_stm32_dcmi_snapshot (const struct device * dev , struct video_buffer * * vbuf ,
333
+ k_timeout_t timeout )
319
334
{
320
- LOG_DBG ("Restart DMA after Error!" );
321
- /* Lets try to recover by stopping and maybe restart */
322
- if (HAL_DCMI_Stop (& data -> hdcmi ) != HAL_OK ) {
323
- LOG_WRN ("HAL_DCMI_Stop FAILED!" );
324
- }
335
+ struct video_stm32_dcmi_data * data = dev -> data ;
336
+ const struct video_stm32_dcmi_config * config = dev -> config ;
325
337
326
- if (data -> snapshot_mode ) {
327
- if (data -> vbuf != NULL ) {
328
- k_fifo_put (& data -> fifo_in , data -> vbuf );
329
- data -> vbuf = NULL ;
338
+ LOG_DBG ("dequeue snapshot: %p %llu\n" , data -> vbuf , timeout .ticks );
339
+
340
+ /* See if we were already called and have an active buffer */
341
+ if (data -> vbuf == NULL ) {
342
+ /* check first to see if we already have a buffer returned */
343
+ * vbuf = k_fifo_get (& data -> fifo_out , K_NO_WAIT );
344
+ if (* vbuf != NULL ) {
345
+ LOG_DBG ("k_fifo_get returned: %p\n" , * vbuf );
346
+ if (HAL_DCMI_Stop (& data -> hdcmi ) != HAL_OK ) {
347
+ LOG_WRN ("Snapshot: HAL_DCMI_Stop FAILED!" );
348
+ }
349
+ return 0 ;
330
350
}
331
- } else {
332
- /* error on last transfer try to restart it */
333
- if (HAL_DCMI_Start_DMA (& data -> hdcmi , DCMI_MODE_CONTINUOUS ,
351
+ data -> vbuf = k_fifo_get (& data -> fifo_in , K_NO_WAIT );
352
+ LOG_DBG ("\tcamera buf: %p\n" , data -> vbuf );
353
+ if (data -> vbuf == NULL ) {
354
+ LOG_WRN ("Snapshot: No Buffers available!" );
355
+ return - ENOMEM ;
356
+ }
357
+
358
+ if (HAL_DCMI_Start_DMA (& data -> hdcmi , DCMI_MODE_SNAPSHOT ,
334
359
(uint32_t )data -> vbuf -> buffer ,
335
360
data -> vbuf -> size / 4 ) != HAL_OK ) {
336
361
LOG_WRN ("Snapshot: HAL_DCMI_Start_DMA FAILED!" );
337
362
return - EIO ;
338
363
}
364
+
365
+ /* remember when we started this request */
366
+ data -> snapshot_start_time = k_uptime_get_32 ();
339
367
}
340
- data -> restart_dma = false;
341
- return 0 ;
342
- }
343
368
344
- static int video_stm32_dcmi_dequeue (const struct device * dev , struct video_buffer * * vbuf ,
345
- k_timeout_t timeout )
346
- {
347
- struct video_stm32_dcmi_data * data = dev -> data ;
348
- int err ;
369
+ * vbuf = k_fifo_get (& data -> fifo_out , timeout );
370
+ LOG_DBG ("k_fifo_get returned: %p\n" , * vbuf );
349
371
350
- if (data -> snapshot_mode ) {
351
- /* See if we were already called and have an active buffer */
352
- if (data -> vbuf == NULL ) {
353
- data -> vbuf = k_fifo_get (& data -> fifo_in , K_NO_WAIT );
354
- if (data -> vbuf == NULL ) {
355
- LOG_WRN ("Snapshot: No Buffers available!" );
356
- return - ENOMEM ;
372
+ if (* vbuf == NULL ) {
373
+ uint32_t time_since_start_time =
374
+ (uint32_t )(k_uptime_get_32 () - data -> snapshot_start_time );
375
+ if (time_since_start_time > config -> snapshot_timeout ) {
376
+ LOG_WRN ("Snapshot: Timed out!" );
377
+ if (HAL_DCMI_Stop (& data -> hdcmi ) != HAL_OK ) {
378
+ LOG_WRN ("Snapshot: HAL_DCMI_Stop FAILED!" );
379
+ }
380
+ /* verify it did not come in during this procuessing */
381
+ * vbuf = k_fifo_get (& data -> fifo_out , K_NO_WAIT );
382
+ if (* vbuf ) {
383
+ return 0 ;
357
384
}
358
385
359
- if (HAL_DCMI_Start_DMA (& data -> hdcmi , DCMI_MODE_SNAPSHOT ,
360
- (uint32_t )data -> vbuf -> buffer ,
361
- data -> vbuf -> size / 4 ) != HAL_OK ) {
362
- LOG_WRN ("Snapshot: HAL_DCMI_Start_DMA FAILED!" );
363
- return - EIO ;
386
+ if (data -> vbuf != NULL ) {
387
+ k_fifo_put (& data -> fifo_in , data -> vbuf );
388
+ data -> vbuf = NULL ;
364
389
}
365
- } else {
366
- LOG_DBG ("Snapshot: restart after timeout" );
367
- }
368
- } else {
369
- err = video_stm32_restart_dma_after_error (data );
370
- if (err < 0 ) {
371
- return err ;
372
390
}
373
- }
374
-
375
- * vbuf = k_fifo_get (& data -> fifo_out , timeout );
376
391
377
- if (data -> restart_dma ) {
378
- err = video_stm32_restart_dma_after_error (data );
379
- if (err < 0 ) {
380
- return err ;
381
- }
392
+ return - EAGAIN ;
382
393
}
383
394
384
- if (* vbuf == NULL ) {
385
- return - EAGAIN ;
395
+ if (HAL_DCMI_Stop ( & data -> hdcmi ) != HAL_OK ) {
396
+ LOG_WRN ( "Snapshot: HAL_DCMI_Stop FAILED!" ) ;
386
397
}
398
+ return 0 ;
399
+ }
400
+
401
+ static int video_stm32_dcmi_dequeue (const struct device * dev , struct video_buffer * * vbuf ,
402
+ k_timeout_t timeout )
403
+ {
404
+ struct video_stm32_dcmi_data * data = dev -> data ;
387
405
388
406
if (data -> snapshot_mode ) {
389
- if (HAL_DCMI_Stop (& data -> hdcmi ) != HAL_OK ) {
390
- LOG_WRN ("Snapshot: HAL_DCMI_Stop FAILED!" );
391
- }
407
+ return video_stm32_dcmi_snapshot (dev , vbuf , timeout );
392
408
}
393
- return 0 ;
409
+
410
+ * vbuf = k_fifo_get (& data -> fifo_out , timeout );
411
+ LOG_DBG ("k_fifo_get returned: %p\n" , * vbuf );
412
+
413
+ return (* vbuf == NULL ) ? - EAGAIN : 0 ;
394
414
}
395
415
396
416
static int video_stm32_dcmi_get_caps (const struct device * dev , struct video_caps * caps )
@@ -616,6 +636,7 @@ static const struct video_stm32_dcmi_config video_stm32_dcmi_config_0 = {
616
636
.pctrl = PINCTRL_DT_INST_DEV_CONFIG_GET (0 ),
617
637
.sensor_dev = SOURCE_DEV (0 ),
618
638
.snapshot_mode = DT_INST_PROP (0 , snapshot_mode ),
639
+ .snapshot_timeout = DT_INST_PROP (0 , snapshot_timeout ),
619
640
DCMI_DMA_CHANNEL (0 , PERIPHERAL , MEMORY )
620
641
};
621
642
@@ -647,7 +668,6 @@ static int video_stm32_dcmi_init(const struct device *dev)
647
668
}
648
669
649
670
/* See if we should initialize to only support snapshot mode or not */
650
- data -> restart_dma = false;
651
671
data -> snapshot_mode = config -> snapshot_mode ;
652
672
if (CONFIG_VIDEO_BUFFER_POOL_NUM_MAX == 1 ) {
653
673
LOG_DBG ("Only one buffer so snapshot mode only" );
0 commit comments