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 ;
@@ -251,22 +270,29 @@ static int video_stm32_dcmi_set_stream(const struct device *dev, bool enable,
251
270
return 0 ;
252
271
}
253
272
254
- data -> vbuf = k_fifo_get (& data -> fifo_in , K_NO_WAIT );
273
+ if (!config -> snapshot_mode && (CONFIG_VIDEO_BUFFER_POOL_NUM_MAX != 1 )) {
274
+ data -> vbuf = k_fifo_get (& data -> fifo_in , K_NO_WAIT );
255
275
256
- if (data -> vbuf == NULL ) {
257
- LOG_ERR ("Failed to dequeue a DCMI buffer." );
258
- return - ENOMEM ;
276
+ if (data -> vbuf == NULL ) {
277
+ data -> snapshot_mode = true;
278
+ LOG_WRN ("No buffers, assume snapshot mode." );
279
+ }
259
280
}
260
281
261
282
/* Set the frame control */
262
283
data -> hdcmi .Instance -> CR &= ~(DCMI_CR_FCRC_0 | DCMI_CR_FCRC_1 );
263
284
data -> hdcmi .Instance -> CR |= STM32_DCMI_GET_CAPTURE_RATE (data -> capture_rate );
264
285
265
- err = HAL_DCMI_Start_DMA (& data -> hdcmi , DCMI_MODE_CONTINUOUS ,
266
- (uint32_t )data -> vbuf -> buffer , data -> vbuf -> bytesused / 4 );
267
- if (err != HAL_OK ) {
268
- LOG_ERR ("Failed to start DCMI DMA" );
269
- return - EIO ;
286
+ /* don't start the DCMI DMA if we are in Snapshot mode */
287
+ if (!data -> snapshot_mode ) {
288
+ err = HAL_DCMI_Start_DMA (& data -> hdcmi , DCMI_MODE_CONTINUOUS ,
289
+ (uint32_t )data -> vbuf -> buffer , data -> vbuf -> bytesused / 4 );
290
+ if (err != HAL_OK ) {
291
+ LOG_ERR ("Failed to start DCMI DMA" );
292
+ return - EIO ;
293
+ }
294
+ } else {
295
+ LOG_DBG ("Snapshot mode active" );
270
296
}
271
297
272
298
return video_stream_start (config -> sensor_dev , type );
@@ -289,31 +315,99 @@ static int video_stm32_dcmi_enqueue(const struct device *dev, struct video_buffe
289
315
return 0 ;
290
316
}
291
317
318
+ static int video_stm32_restart_dma_after_error (struct video_stm32_dcmi_data * data ) {
319
+ LOG_DBG ("Restart DMA after Error!" );
320
+ /* Lets try to recover by stopping and maybe restart */
321
+ if (HAL_DCMI_Stop (& data -> hdcmi ) != HAL_OK ) {
322
+ LOG_WRN ("HAL_DCMI_Stop FAILED!" );
323
+ }
324
+
325
+ if (data -> snapshot_mode ) {
326
+ if (data -> vbuf != NULL ) {
327
+ k_fifo_put (& data -> fifo_in , data -> vbuf );
328
+ data -> vbuf = NULL ;
329
+ }
330
+ } else {
331
+ /* error on last transfer try to restart it */
332
+ if (HAL_DCMI_Start_DMA (& data -> hdcmi , DCMI_MODE_CONTINUOUS ,
333
+ (uint32_t )data -> vbuf -> buffer ,
334
+ data -> vbuf -> size / 4 ) != HAL_OK ) {
335
+ LOG_WRN ("Snapshot: HAL_DCMI_Start_DMA FAILED!" );
336
+ return - EIO ;
337
+ }
338
+ }
339
+ data -> restart_dma = false;
340
+ return 0 ;
341
+ }
342
+
292
343
static int video_stm32_dcmi_dequeue (const struct device * dev , struct video_buffer * * vbuf ,
293
344
k_timeout_t timeout )
294
345
{
295
346
struct video_stm32_dcmi_data * data = dev -> data ;
347
+ int err ;
348
+
349
+ if (data -> snapshot_mode ) {
350
+ /* See if we were already called and have an active buffer */
351
+ if (data -> vbuf == NULL ) {
352
+ data -> vbuf = k_fifo_get (& data -> fifo_in , K_NO_WAIT );
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 ,
359
+ (uint32_t )data -> vbuf -> buffer ,
360
+ data -> vbuf -> size / 4 ) != HAL_OK ) {
361
+ LOG_WRN ("Snapshot: HAL_DCMI_Start_DMA FAILED!" );
362
+ return - EIO ;
363
+ }
364
+ } else {
365
+ LOG_DBG ("Snapshot: restart after timeout" );
366
+ }
367
+ } else {
368
+ err = video_stm32_restart_dma_after_error (data );
369
+ if (err < 0 ) {
370
+ return err ;
371
+ }
372
+ }
296
373
297
374
* vbuf = k_fifo_get (& data -> fifo_out , timeout );
375
+
376
+ if (data -> restart_dma ) {
377
+ err = video_stm32_restart_dma_after_error (data );
378
+ if (err < 0 ) {
379
+ return err ;
380
+ }
381
+ }
382
+
298
383
if (* vbuf == NULL ) {
299
384
return - EAGAIN ;
300
385
}
301
386
387
+ if (data -> snapshot_mode ) {
388
+ if (HAL_DCMI_Stop (& data -> hdcmi ) != HAL_OK ) {
389
+ LOG_WRN ("Snapshot: HAL_DCMI_Stop FAILED!" );
390
+ }
391
+ }
302
392
return 0 ;
303
393
}
304
394
305
395
static int video_stm32_dcmi_get_caps (const struct device * dev , struct video_caps * caps )
306
396
{
307
397
const struct video_stm32_dcmi_config * config = dev -> config ;
398
+ int ret ;
399
+
400
+ ret = video_get_caps (config -> sensor_dev , caps );
308
401
309
402
/* 2 buffers are needed for DCMI_MODE_CONTINUOUS */
310
403
caps -> min_vbuf_count = 2 ;
311
404
312
405
/* DCMI produces full frames */
313
- caps -> min_line_count = caps -> max_line_count = LINE_COUNT_HEIGHT ;
406
+ caps -> min_vbuf_count = config -> snapshot_mode ? 1 : 2 ;
407
+ caps -> min_line_count = LINE_COUNT_HEIGHT ;
408
+ caps -> max_line_count = LINE_COUNT_HEIGHT ;
314
409
315
- /* Forward the message to the sensor device */
316
- return video_get_caps (config -> sensor_dev , caps );
410
+ return ret ;
317
411
}
318
412
319
413
static int video_stm32_dcmi_enum_frmival (const struct device * dev , struct video_frmival_enum * fie )
@@ -412,6 +506,20 @@ static int video_stm32_dcmi_get_frmival(const struct device *dev, struct video_f
412
506
return 0 ;
413
507
}
414
508
509
+ static int video_stm32_dcmi_set_selection (const struct device * dev , struct video_selection * sel )
510
+ {
511
+ const struct video_stm32_dcmi_config * config = dev -> config ;
512
+
513
+ return video_set_selection (config -> sensor_dev , sel );
514
+ }
515
+
516
+ static int video_stm32_dcmi_get_selection (const struct device * dev , struct video_selection * sel )
517
+ {
518
+ const struct video_stm32_dcmi_config * config = dev -> config ;
519
+
520
+ return video_get_selection (config -> sensor_dev , sel );
521
+ }
522
+
415
523
static DEVICE_API (video , video_stm32_dcmi_driver_api ) = {
416
524
.set_format = video_stm32_dcmi_set_fmt ,
417
525
.get_format = video_stm32_dcmi_get_fmt ,
@@ -422,6 +530,8 @@ static DEVICE_API(video, video_stm32_dcmi_driver_api) = {
422
530
.enum_frmival = video_stm32_dcmi_enum_frmival ,
423
531
.set_frmival = video_stm32_dcmi_set_frmival ,
424
532
.get_frmival = video_stm32_dcmi_get_frmival ,
533
+ .set_selection = video_stm32_dcmi_set_selection ,
534
+ .get_selection = video_stm32_dcmi_get_selection ,
425
535
};
426
536
427
537
static void video_stm32_dcmi_irq_config_func (const struct device * dev )
@@ -504,6 +614,7 @@ static const struct video_stm32_dcmi_config video_stm32_dcmi_config_0 = {
504
614
.irq_config = video_stm32_dcmi_irq_config_func ,
505
615
.pctrl = PINCTRL_DT_INST_DEV_CONFIG_GET (0 ),
506
616
.sensor_dev = SOURCE_DEV (0 ),
617
+ .snapshot_mode = DT_INST_PROP (0 , snapshot_mode ),
507
618
DCMI_DMA_CHANNEL (0 , PERIPHERAL , MEMORY )
508
619
};
509
620
@@ -534,6 +645,13 @@ static int video_stm32_dcmi_init(const struct device *dev)
534
645
return err ;
535
646
}
536
647
648
+ /* See if we should initialize to only support snapshot mode or not */
649
+ data -> restart_dma = false;
650
+ data -> snapshot_mode = config -> snapshot_mode ;
651
+ if (CONFIG_VIDEO_BUFFER_POOL_NUM_MAX == 1 ) {
652
+ LOG_DBG ("Only one buffer so snapshot mode only" );
653
+ data -> snapshot_mode = true;
654
+ }
537
655
data -> dev = dev ;
538
656
k_fifo_init (& data -> fifo_in );
539
657
k_fifo_init (& data -> fifo_out );
0 commit comments