24
24
25
25
LOG_MODULE_REGISTER (video_stm32_dcmi , CONFIG_VIDEO_LOG_LEVEL );
26
26
27
- #if CONFIG_VIDEO_BUFFER_POOL_NUM_MAX < 2
28
- #error "The minimum required number of buffers for video_stm32 is 2 "
27
+ #if CONFIG_VIDEO_BUFFER_POOL_NUM_MAX < 1
28
+ #error "The minimum required number of buffers for video_stm32 is 1 "
29
29
#endif
30
30
31
31
typedef void (* irq_config_func_t )(const struct device * dev );
@@ -45,6 +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
50
};
49
51
50
52
struct video_stm32_dcmi_config {
@@ -53,11 +55,22 @@ struct video_stm32_dcmi_config {
53
55
const struct pinctrl_dev_config * pctrl ;
54
56
const struct device * sensor_dev ;
55
57
const struct stream dma ;
58
+ bool snapshot_mode ;
56
59
};
57
60
61
+ static void stm32_dcmi_process_dma_error (DCMI_HandleTypeDef * hdcmi )
62
+ {
63
+ struct video_stm32_dcmi_data * dev_data =
64
+ CONTAINER_OF (hdcmi , struct video_stm32_dcmi_data , hdcmi );
65
+
66
+ dev_data -> restart_dma = true;
67
+ k_fifo_cancel_wait (& dev_data -> fifo_out );
68
+ }
69
+
58
70
void HAL_DCMI_ErrorCallback (DCMI_HandleTypeDef * hdcmi )
59
71
{
60
- LOG_WRN ("%s" , __func__ );
72
+ LOG_WRN ("%s %p" , __func__ , hdcmi );
73
+ stm32_dcmi_process_dma_error (hdcmi );
61
74
}
62
75
63
76
void HAL_DCMI_FrameEventCallback (DCMI_HandleTypeDef * hdcmi )
@@ -66,8 +79,17 @@ void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi)
66
79
CONTAINER_OF (hdcmi , struct video_stm32_dcmi_data , hdcmi );
67
80
struct video_buffer * vbuf ;
68
81
69
- HAL_DCMI_Suspend (hdcmi );
82
+ if (dev_data -> snapshot_mode ) {
83
+ /* we remove the buffer from the camera and add it to fifo_out */
84
+ vbuf = dev_data -> vbuf ;
85
+ dev_data -> vbuf = NULL ;
86
+ vbuf -> timestamp = k_uptime_get_32 ();
87
+ k_fifo_put (& dev_data -> fifo_out , vbuf );
88
+ return ;
89
+ }
70
90
91
+ /* Not in snapshot_mode */
92
+ HAL_DCMI_Suspend (hdcmi );
71
93
vbuf = k_fifo_get (& dev_data -> fifo_in , K_NO_WAIT );
72
94
73
95
if (vbuf == NULL ) {
@@ -94,21 +116,18 @@ static void stm32_dcmi_isr(const struct device *dev)
94
116
static void dcmi_dma_callback (const struct device * dev , void * arg , uint32_t channel , int status )
95
117
{
96
118
DMA_HandleTypeDef * hdma = arg ;
119
+ DCMI_HandleTypeDef * hdcmi = (DCMI_HandleTypeDef * )hdma -> Parent ;
97
120
98
121
ARG_UNUSED (dev );
99
122
100
123
if (status < 0 ) {
101
124
LOG_ERR ("DMA callback error with channel %d." , channel );
125
+ stm32_dcmi_process_dma_error (hdcmi );
102
126
}
103
127
104
128
HAL_DMA_IRQHandler (hdma );
105
129
}
106
130
107
- void HAL_DMA_ErrorCallback (DMA_HandleTypeDef * hdma )
108
- {
109
- LOG_WRN ("%s" , __func__ );
110
- }
111
-
112
131
static int stm32_dma_init (const struct device * dev )
113
132
{
114
133
struct video_stm32_dcmi_data * data = dev -> data ;
@@ -259,22 +278,29 @@ static int video_stm32_dcmi_set_stream(const struct device *dev, bool enable,
259
278
return 0 ;
260
279
}
261
280
262
- data -> vbuf = k_fifo_get (& data -> fifo_in , K_NO_WAIT );
281
+ if (!config -> snapshot_mode && (CONFIG_VIDEO_BUFFER_POOL_NUM_MAX != 1 )) {
282
+ data -> vbuf = k_fifo_get (& data -> fifo_in , K_NO_WAIT );
263
283
264
- if (data -> vbuf == NULL ) {
265
- LOG_ERR ("Failed to dequeue a DCMI buffer." );
266
- return - ENOMEM ;
284
+ if (data -> vbuf == NULL ) {
285
+ data -> snapshot_mode = true;
286
+ LOG_WRN ("No buffers, assume snapshot mode." );
287
+ }
267
288
}
268
289
269
290
/* Set the frame control */
270
291
data -> hdcmi .Instance -> CR &= ~(DCMI_CR_FCRC_0 | DCMI_CR_FCRC_1 );
271
292
data -> hdcmi .Instance -> CR |= STM32_DCMI_GET_CAPTURE_RATE (data -> capture_rate );
272
293
273
- err = HAL_DCMI_Start_DMA (& data -> hdcmi , DCMI_MODE_CONTINUOUS ,
274
- (uint32_t )data -> vbuf -> buffer , data -> vbuf -> bytesused / 4 );
275
- if (err != HAL_OK ) {
276
- LOG_ERR ("Failed to start DCMI DMA" );
277
- return - EIO ;
294
+ /* don't start the DCMI DMA if we are in Snapshot mode */
295
+ if (!data -> snapshot_mode ) {
296
+ err = HAL_DCMI_Start_DMA (& data -> hdcmi , DCMI_MODE_CONTINUOUS ,
297
+ (uint32_t )data -> vbuf -> buffer , data -> vbuf -> bytesused / 4 );
298
+ if (err != HAL_OK ) {
299
+ LOG_ERR ("Failed to start DCMI DMA" );
300
+ return - EIO ;
301
+ }
302
+ } else {
303
+ LOG_DBG ("Snapshot mode active" );
278
304
}
279
305
280
306
return video_stream_start (config -> sensor_dev , type );
@@ -297,28 +323,96 @@ static int video_stm32_dcmi_enqueue(const struct device *dev, struct video_buffe
297
323
return 0 ;
298
324
}
299
325
326
+ static int video_stm32_restart_dma_after_error (struct video_stm32_dcmi_data * data ) {
327
+ LOG_DBG ("Restart DMA after Error!" );
328
+ /* Lets try to recover by stopping and maybe restart */
329
+ if (HAL_DCMI_Stop (& data -> hdcmi ) != HAL_OK ) {
330
+ LOG_WRN ("HAL_DCMI_Stop FAILED!" );
331
+ }
332
+
333
+ if (data -> snapshot_mode ) {
334
+ if (data -> vbuf != NULL ) {
335
+ k_fifo_put (& data -> fifo_in , data -> vbuf );
336
+ data -> vbuf = NULL ;
337
+ }
338
+ } else {
339
+ /* error on last transfer try to restart it */
340
+ if (HAL_DCMI_Start_DMA (& data -> hdcmi , DCMI_MODE_CONTINUOUS ,
341
+ (uint32_t )data -> vbuf -> buffer ,
342
+ data -> vbuf -> size / 4 ) != HAL_OK ) {
343
+ LOG_WRN ("Snapshot: HAL_DCMI_Start_DMA FAILED!" );
344
+ return - EIO ;
345
+ }
346
+ }
347
+ data -> restart_dma = false;
348
+ return 0 ;
349
+ }
350
+
300
351
static int video_stm32_dcmi_dequeue (const struct device * dev , struct video_buffer * * vbuf ,
301
352
k_timeout_t timeout )
302
353
{
303
354
struct video_stm32_dcmi_data * data = dev -> data ;
355
+ int err ;
356
+
357
+ if (data -> snapshot_mode ) {
358
+ /* See if we were already called and have an active buffer */
359
+ if (data -> vbuf == NULL ) {
360
+ data -> vbuf = k_fifo_get (& data -> fifo_in , K_NO_WAIT );
361
+ if (data -> vbuf == NULL ) {
362
+ LOG_WRN ("Snapshot: No Buffers available!" );
363
+ return - ENOMEM ;
364
+ }
365
+
366
+ if (HAL_DCMI_Start_DMA (& data -> hdcmi , DCMI_MODE_SNAPSHOT ,
367
+ (uint32_t )data -> vbuf -> buffer ,
368
+ data -> vbuf -> size / 4 ) != HAL_OK ) {
369
+ LOG_WRN ("Snapshot: HAL_DCMI_Start_DMA FAILED!" );
370
+ return - EIO ;
371
+ }
372
+ } else {
373
+ LOG_DBG ("Snapshot: restart after timeout" );
374
+ }
375
+ } else {
376
+ err = video_stm32_restart_dma_after_error (data );
377
+ if (err < 0 ) {
378
+ return err ;
379
+ }
380
+ }
304
381
305
382
* vbuf = k_fifo_get (& data -> fifo_out , timeout );
383
+
384
+ if (data -> restart_dma ) {
385
+ err = video_stm32_restart_dma_after_error (data );
386
+ if (err < 0 ) {
387
+ return err ;
388
+ }
389
+ }
390
+
306
391
if (* vbuf == NULL ) {
307
392
return - EAGAIN ;
308
393
}
309
394
395
+ if (data -> snapshot_mode ) {
396
+ if (HAL_DCMI_Stop (& data -> hdcmi ) != HAL_OK ) {
397
+ LOG_WRN ("Snapshot: HAL_DCMI_Stop FAILED!" );
398
+ }
399
+ }
310
400
return 0 ;
311
401
}
312
402
313
403
static int video_stm32_dcmi_get_caps (const struct device * dev , struct video_caps * caps )
314
404
{
315
405
const struct video_stm32_dcmi_config * config = dev -> config ;
406
+ int ret ;
407
+
408
+ ret = video_get_caps (config -> sensor_dev , caps );
316
409
317
410
/* DCMI produces full frames */
318
- caps -> min_line_count = caps -> max_line_count = LINE_COUNT_HEIGHT ;
411
+ caps -> min_vbuf_count = config -> snapshot_mode ? 1 : 2 ;
412
+ caps -> min_line_count = LINE_COUNT_HEIGHT ;
413
+ caps -> max_line_count = LINE_COUNT_HEIGHT ;
319
414
320
- /* Forward the message to the sensor device */
321
- return video_get_caps (config -> sensor_dev , caps );
415
+ return ret ;
322
416
}
323
417
324
418
static int video_stm32_dcmi_enum_frmival (const struct device * dev , struct video_frmival_enum * fie )
@@ -417,6 +511,20 @@ static int video_stm32_dcmi_get_frmival(const struct device *dev, struct video_f
417
511
return 0 ;
418
512
}
419
513
514
+ static int video_stm32_dcmi_set_selection (const struct device * dev , struct video_selection * sel )
515
+ {
516
+ const struct video_stm32_dcmi_config * config = dev -> config ;
517
+
518
+ return video_set_selection (config -> sensor_dev , sel );
519
+ }
520
+
521
+ static int video_stm32_dcmi_get_selection (const struct device * dev , struct video_selection * sel )
522
+ {
523
+ const struct video_stm32_dcmi_config * config = dev -> config ;
524
+
525
+ return video_get_selection (config -> sensor_dev , sel );
526
+ }
527
+
420
528
static DEVICE_API (video , video_stm32_dcmi_driver_api ) = {
421
529
.set_format = video_stm32_dcmi_set_fmt ,
422
530
.get_format = video_stm32_dcmi_get_fmt ,
@@ -427,6 +535,8 @@ static DEVICE_API(video, video_stm32_dcmi_driver_api) = {
427
535
.enum_frmival = video_stm32_dcmi_enum_frmival ,
428
536
.set_frmival = video_stm32_dcmi_set_frmival ,
429
537
.get_frmival = video_stm32_dcmi_get_frmival ,
538
+ .set_selection = video_stm32_dcmi_set_selection ,
539
+ .get_selection = video_stm32_dcmi_get_selection ,
430
540
};
431
541
432
542
static void video_stm32_dcmi_irq_config_func (const struct device * dev )
@@ -509,6 +619,7 @@ static const struct video_stm32_dcmi_config video_stm32_dcmi_config_0 = {
509
619
.irq_config = video_stm32_dcmi_irq_config_func ,
510
620
.pctrl = PINCTRL_DT_INST_DEV_CONFIG_GET (0 ),
511
621
.sensor_dev = SOURCE_DEV (0 ),
622
+ .snapshot_mode = DT_INST_PROP (0 , snapshot_mode ),
512
623
DCMI_DMA_CHANNEL (0 , PERIPHERAL , MEMORY )
513
624
};
514
625
@@ -539,6 +650,13 @@ static int video_stm32_dcmi_init(const struct device *dev)
539
650
return err ;
540
651
}
541
652
653
+ /* See if we should initialize to only support snapshot mode or not */
654
+ data -> restart_dma = false;
655
+ data -> snapshot_mode = config -> snapshot_mode ;
656
+ if (CONFIG_VIDEO_BUFFER_POOL_NUM_MAX == 1 ) {
657
+ LOG_DBG ("Only one buffer so snapshot mode only" );
658
+ data -> snapshot_mode = true;
659
+ }
542
660
data -> dev = dev ;
543
661
k_fifo_init (& data -> fifo_in );
544
662
k_fifo_init (& data -> fifo_out );
0 commit comments