1 /**
2 ******************************************************************************
3 * @file stm32l4xx_hal_dcmi.c
4 * @author MCD Application Team
5 * @brief DCMI HAL module driver
6 * This file provides firmware functions to manage the following
7 * functionalities of the Digital Camera Interface (DCMI) peripheral:
8 * + Initialization and de-initialization functions
9 * + IO operation functions
10 * + Peripheral Control functions
11 * + Peripheral State and Error functions
12 *
13 @verbatim
14 ==============================================================================
15 ##### How to use this driver #####
16 ==============================================================================
17 [..]
18 The sequence below describes how to use this driver to capture images
19 from a camera module connected to the DCMI Interface.
20 This sequence does not take into account the configuration of the
21 camera module, which should be made before configuring and enabling
22 the DCMI to capture images.
23
24 (#) Program the required configuration through the following parameters:
25 horizontal and vertical polarity, pixel clock polarity, capture rate,
26 synchronization mode, frame delimiter codes, data width, byte and line
27 selection using HAL_DCMI_Init() function.
28
29 (#) Optionally select JPEG mode; in that case, only the polarity
30 and the capture mode parameters need to be set.
31
32 (#) Capture mode can be either snapshot or continuous mode.
33
34 (#) Configure the DMA_Handle to transfer data from DCMI DR
35 register to the destination memory buffer.
36
37 -@- In snapshot mode, the interface transfers a single frame through DMA. In
38 continuous mode, the DMA must be set in circular mode to ensure a continuous
39 flow of images data samples.
40
41 (#) Program the transfer configuration through the following parameters:
42 DCMI mode, destination memory buffer address and data length then
43 enable capture using HAL_DCMI_Start_DMA() function.
44
45 (#) Whether in continuous or snapshot mode, data length parameter must be
46 equal to the frame size.
47
48 (#) When the frame size is unknown beforehand (e.g. JPEG case), data length must
49 be large enough to ensure the capture of a frame.
50
51 (#) If the frame size is larger than the maximum DMA transfer length (i.e. 65535),
52 (++) the DMA must be configured in circular mode, either for snapshot or continuous
53 capture mode,
54 (++) during capture, the driver copies the image data samples from DCMI DR register
55 at the end of the final destination buffer used as a work buffer,
56 (++) at each DMA half (respectively complete) transfer interrupt, the first
57 (resp. second) half of the work buffer is copied to the final destination thru
58 a second DMA channel.
59 (++) Parameters of this second DMA channel are contained in the memory to memory DMA
60 handle "DMAM2M_Handle", itself field of the DCMI handle structure.
61 (++) This memory to memory transfer has length half that of the work buffer and is
62 carried out in normal mode (not in circular mode).
63
64 (#) Optionally, configure and enable the CROP feature to select a
65 rectangular window from the received image using HAL_DCMI_ConfigCrop()
66 and HAL_DCMI_EnableCrop() functions. Use HAL_DCMI_DisableCrop() to
67 disable this feature.
68
69 (#) The capture can be stopped with HAL_DCMI_Stop() function.
70
71 (#) To control the DCMI state, use the function HAL_DCMI_GetState().
72
73 (#) To read the DCMI error code, use the function HAL_DCMI_GetError().
74
75 [..]
76 (@) When the frame size is less than the maximum DMA transfer length (i.e. 65535)
77 and when in snapshot mode, user must make sure the FRAME interrupt is disabled.
78 This allows to avoid corner cases where the FRAME interrupt might be triggered
79 before the DMA transfer completion interrupt. In this specific configuration,
80 the driver checks the FRAME capture flag after the DMA transfer end and calls
81 HAL_DCMI_FrameEventCallback() if the flag is set.
82
83 *** DCMI HAL driver macros list ***
84 =============================================
85 [..]
86 Below the list of most used macros in DCMI HAL driver.
87
88 (+) __HAL_DCMI_ENABLE: Enable the DCMI peripheral.
89 (+) __HAL_DCMI_DISABLE: Disable the DCMI peripheral.
90 (+) __HAL_DCMI_GET_FLAG: Get the DCMI pending flags.
91 (+) __HAL_DCMI_CLEAR_FLAG: Clear the DCMI pending flags.
92 (+) __HAL_DCMI_ENABLE_IT: Enable the specified DCMI interrupts.
93 (+) __HAL_DCMI_DISABLE_IT: Disable the specified DCMI interrupts.
94 (+) __HAL_DCMI_GET_IT_SOURCE: Check whether the specified DCMI interrupt has occurred or not.
95
96 *** Callback registration ***
97 =============================
98
99 The compilation define USE_HAL_DCMI_REGISTER_CALLBACKS when set to 1
100 allows the user to configure dynamically the driver callbacks.
101 Use functions @ref HAL_DCMI_RegisterCallback() to register a user callback.
102
103 Function @ref HAL_DCMI_RegisterCallback() allows to register following callbacks:
104 (+) FrameEventCallback : DCMI Frame Event.
105 (+) VsyncEventCallback : DCMI Vsync Event.
106 (+) LineEventCallback : DCMI Line Event.
107 (+) ErrorCallback : DCMI error.
108 (+) MspInitCallback : DCMI MspInit.
109 (+) MspDeInitCallback : DCMI MspDeInit.
110 This function takes as parameters the HAL peripheral handle, the callback ID
111 and a pointer to the user callback function.
112
113 Use function @ref HAL_DCMI_UnRegisterCallback() to reset a callback to the default
114 weak (surcharged) function.
115 @ref HAL_DCMI_UnRegisterCallback() takes as parameters the HAL peripheral handle,
116 and the callback ID.
117 This function allows to reset following callbacks:
118 (+) FrameEventCallback : DCMI Frame Event.
119 (+) VsyncEventCallback : DCMI Vsync Event.
120 (+) LineEventCallback : DCMI Line Event.
121 (+) ErrorCallback : DCMI error.
122 (+) MspInitCallback : DCMI MspInit.
123 (+) MspDeInitCallback : DCMI MspDeInit.
124
125 By default, after the @ref HAL_DCMI_Init and if the state is HAL_DCMI_STATE_RESET
126 all callbacks are reset to the corresponding legacy weak (surcharged) functions:
127 examples @ref FrameEventCallback(), @ref HAL_DCMI_ErrorCallback().
128 Exception done for MspInit and MspDeInit callbacks that are respectively
129 reset to the legacy weak (surcharged) functions in the @ref HAL_DCMI_Init
130 and @ref HAL_DCMI_DeInit only when these callbacks are null (not registered beforehand).
131 If not, MspInit or MspDeInit are not null, the @ref HAL_DCMI_Init and @ref HAL_DCMI_DeInit
132 keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
133
134 Callbacks can be registered/unregistered in READY state only.
135 Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
136 in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
137 during the Init/DeInit.
138 In that case first register the MspInit/MspDeInit user callbacks
139 using @ref HAL_DCMI_RegisterCallback before calling @ref HAL_DCMI_DeInit
140 or @ref HAL_DCMI_Init function.
141
142 When the compilation define USE_HAL_DCMI_REGISTER_CALLBACKS is set to 0 or
143 not defined, the callback registering feature is not available
144 and weak (surcharged) callbacks are used.
145
146 @endverbatim
147 ******************************************************************************
148 * @attention
149 *
150 * <h2><center>© Copyright (c) 2017 STMicroelectronics.
151 * All rights reserved.</center></h2>
152 *
153 * This software component is licensed by ST under BSD 3-Clause license,
154 * the "License"; You may not use this file except in compliance with the
155 * License. You may obtain a copy of the License at:
156 * opensource.org/licenses/BSD-3-Clause
157 *
158 ******************************************************************************
159 */
160
161 /* Includes ------------------------------------------------------------------*/
162 #include "stm32l4xx_hal.h"
163
164 #ifdef HAL_DCMI_MODULE_ENABLED
165 #if defined (DCMI)
166
167 /** @addtogroup STM32L4xx_HAL_Driver
168 * @{
169 */
170 /** @defgroup DCMI DCMI
171 * @brief DCMI HAL module driver
172 * @{
173 */
174
175 /* Private typedef -----------------------------------------------------------*/
176 /* Private define ------------------------------------------------------------*/
177 /** @defgroup DCMI_Private_Constants DCMI Private Constants
178 * @{
179 */
180
181 /** @defgroup DCMI_Stop_TimeOut DCMI Stop TimeOut
182 * @{
183 */
184 #define DCMI_TIMEOUT_STOP ((uint32_t)1000U) /*!< 1s */
185 /**
186 * @}
187 */
188
189 #define NPRIME 16U
190
191 /**
192 * @}
193 */
194 /* Private macro -------------------------------------------------------------*/
195 /* Private variables ---------------------------------------------------------*/
196 /* Private function prototypes -----------------------------------------------*/
197 /** @addtogroup DCMI_Private_Functions DCMI Private Functions
198 * @{
199 */
200 static void DCMI_DMAXferCplt(DMA_HandleTypeDef *hdma);
201 static void DCMI_DMAHalfXferCplt(DMA_HandleTypeDef *hdma);
202 static void DCMI_DMAError(DMA_HandleTypeDef *hdma);
203 static uint32_t DCMI_TransferSize(uint32_t InputSize);
204 /**
205 * @}
206 */
207 /* Exported functions --------------------------------------------------------*/
208
209 /** @defgroup DCMI_Exported_Functions DCMI Exported Functions
210 * @{
211 */
212
213 /** @defgroup DCMI_Exported_Functions_Group1 Initialization and Configuration functions
214 * @brief Initialization and Configuration functions
215 *
216 @verbatim
217 ===============================================================================
218 ##### Initialization and Configuration functions #####
219 ===============================================================================
220 [..] This section provides functions allowing to:
221 (+) Initialize and configure the DCMI
222 (+) De-initialize the DCMI
223
224 @endverbatim
225 * @{
226 */
227
228 /**
229 * @brief Initialize the DCMI according to the specified
230 * parameters in the DCMI_InitTypeDef and create the associated handle.
231 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
232 * the configuration information for DCMI.
233 * @note By default, all interruptions are enabled (line end, frame end, overrun,
234 * VSYNC and embedded synchronization error interrupts).
235 * @retval HAL status
236 */
HAL_DCMI_Init(DCMI_HandleTypeDef * hdcmi)237 HAL_StatusTypeDef HAL_DCMI_Init(DCMI_HandleTypeDef *hdcmi)
238 {
239 /* Check the DCMI peripheral state */
240 if(hdcmi == NULL)
241 {
242 return HAL_ERROR;
243 }
244
245 /* Check function parameters */
246 assert_param(IS_DCMI_ALL_INSTANCE(hdcmi->Instance));
247 assert_param(IS_DCMI_SYNCHRO(hdcmi->Init.SynchroMode));
248 assert_param(IS_DCMI_PCKPOLARITY(hdcmi->Init.PCKPolarity));
249 assert_param(IS_DCMI_VSPOLARITY(hdcmi->Init.VSPolarity));
250 assert_param(IS_DCMI_HSPOLARITY(hdcmi->Init.HSPolarity));
251 assert_param(IS_DCMI_CAPTURE_RATE(hdcmi->Init.CaptureRate));
252 assert_param(IS_DCMI_EXTENDED_DATA(hdcmi->Init.ExtendedDataMode));
253 assert_param(IS_DCMI_MODE_JPEG(hdcmi->Init.JPEGMode));
254
255 assert_param(IS_DCMI_BYTE_SELECT_MODE(hdcmi->Init.ByteSelectMode));
256 assert_param(IS_DCMI_BYTE_SELECT_START(hdcmi->Init.ByteSelectStart));
257 assert_param(IS_DCMI_LINE_SELECT_MODE(hdcmi->Init.LineSelectMode));
258 assert_param(IS_DCMI_LINE_SELECT_START(hdcmi->Init.LineSelectStart));
259
260 if(hdcmi->State == HAL_DCMI_STATE_RESET)
261 {
262 /* Allocate lock resource and initialize it */
263 hdcmi->Lock = HAL_UNLOCKED;
264
265 /* Init the DCMI Callback settings */
266 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
267 hdcmi->FrameEventCallback = HAL_DCMI_FrameEventCallback; /* Legacy weak FrameEventCallback */
268 hdcmi->VsyncEventCallback = HAL_DCMI_VsyncEventCallback; /* Legacy weak VsyncEventCallback */
269 hdcmi->LineEventCallback = HAL_DCMI_LineEventCallback; /* Legacy weak LineEventCallback */
270 hdcmi->ErrorCallback = HAL_DCMI_ErrorCallback; /* Legacy weak ErrorCallback */
271
272 if(hdcmi->MspInitCallback == NULL)
273 {
274 /* Legacy weak MspInit Callback */
275 hdcmi->MspInitCallback = HAL_DCMI_MspInit;
276 }
277 /* Initialize the low level hardware (MSP) */
278 hdcmi->MspInitCallback(hdcmi);
279 #else
280 /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
281 HAL_DCMI_MspInit(hdcmi);
282 #endif /* (USE_HAL_DCMI_REGISTER_CALLBACKS) */
283 }
284
285 /* Change the DCMI state */
286 hdcmi->State = HAL_DCMI_STATE_BUSY;
287
288 /* Disable DCMI IP before setting the configuration register */
289 __HAL_DCMI_DISABLE(hdcmi);
290
291 if (hdcmi->Init.ExtendedDataMode != DCMI_EXTEND_DATA_8B)
292 {
293 /* Byte select mode must be programmed to the reset value if the extended mode
294 is not set to 8-bit data capture on every pixel clock */
295 hdcmi->Init.ByteSelectMode = DCMI_BSM_ALL;
296 }
297
298 /* Set DCMI parameters */
299 hdcmi->Instance->CR &= ~(DCMI_CR_PCKPOL | DCMI_CR_HSPOL | DCMI_CR_VSPOL | DCMI_CR_EDM_0 |\
300 DCMI_CR_EDM_1 | DCMI_CR_FCRC_0 | DCMI_CR_FCRC_1 | DCMI_CR_JPEG |\
301 DCMI_CR_ESS | DCMI_CR_BSM_0 | DCMI_CR_BSM_1 | DCMI_CR_OEBS |\
302 DCMI_CR_LSM | DCMI_CR_OELS);
303
304 hdcmi->Instance->CR |= (uint32_t)(hdcmi->Init.SynchroMode | hdcmi->Init.CaptureRate |\
305 hdcmi->Init.VSPolarity | hdcmi->Init.HSPolarity |\
306 hdcmi->Init.PCKPolarity | hdcmi->Init.ExtendedDataMode |\
307 hdcmi->Init.JPEGMode | hdcmi->Init.ByteSelectMode |\
308 hdcmi->Init.ByteSelectStart | hdcmi->Init.LineSelectMode |\
309 hdcmi->Init.LineSelectStart);
310
311 if(hdcmi->Init.SynchroMode == DCMI_SYNCHRO_EMBEDDED)
312 {
313 hdcmi->Instance->ESCR = (((uint32_t)hdcmi->Init.SynchroCode.FrameStartCode) |\
314 ((uint32_t)hdcmi->Init.SynchroCode.LineStartCode << DCMI_ESCR_LSC_Pos)|\
315 ((uint32_t)hdcmi->Init.SynchroCode.LineEndCode << DCMI_ESCR_LEC_Pos) |\
316 ((uint32_t)hdcmi->Init.SynchroCode.FrameEndCode << DCMI_ESCR_FEC_Pos));
317 }
318
319 /* By default, enable all interrupts. The user may disable the unwanted ones
320 in resorting to __HAL_DCMI_DISABLE_IT() macro before invoking HAL_DCMI_Start_DMA().
321 Enabled interruptions are
322 - end of line
323 - end of frame
324 - data reception overrun
325 - frame synchronization signal VSYNC
326 - synchronization error */
327 __HAL_DCMI_ENABLE_IT(hdcmi, DCMI_IT_FRAME|DCMI_IT_OVR|DCMI_IT_ERR|DCMI_IT_VSYNC|DCMI_IT_LINE);
328
329 /* Update error code */
330 hdcmi->ErrorCode = HAL_DCMI_ERROR_NONE;
331
332 /* Initialize the DCMI state*/
333 hdcmi->State = HAL_DCMI_STATE_READY;
334
335 return HAL_OK;
336 }
337
338 /**
339 * @brief De-initialize the DCMI peripheral, reset control registers to
340 * their default values.
341 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
342 * the configuration information for DCMI.
343 * @retval HAL status
344 */
HAL_DCMI_DeInit(DCMI_HandleTypeDef * hdcmi)345 HAL_StatusTypeDef HAL_DCMI_DeInit(DCMI_HandleTypeDef *hdcmi)
346 {
347 /* Before aborting any DCMI transfer, check
348 first whether or not DCMI clock is enabled */
349 if (__HAL_RCC_DCMI_IS_CLK_ENABLED())
350 {
351 if (HAL_DCMI_Stop(hdcmi) != HAL_OK)
352 {
353 /* Issue when stopping DCMI IP */
354 return HAL_ERROR;
355 }
356 }
357
358 /* Reset DCMI control register */
359 hdcmi->Instance->CR = 0;
360
361 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
362 if(hdcmi->MspDeInitCallback == NULL)
363 {
364 hdcmi->MspDeInitCallback = HAL_DCMI_MspDeInit;
365 }
366 /* De-Initialize the low level hardware (MSP) */
367 hdcmi->MspDeInitCallback(hdcmi);
368 #else
369 /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
370 HAL_DCMI_MspDeInit(hdcmi);
371 #endif /* (USE_HAL_DCMI_REGISTER_CALLBACKS) */
372
373 /* Update error code */
374 hdcmi->ErrorCode = HAL_DCMI_ERROR_NONE;
375
376 /* Initialize the DCMI state*/
377 hdcmi->State = HAL_DCMI_STATE_RESET;
378
379 /* Release Lock */
380 __HAL_UNLOCK(hdcmi);
381
382 return HAL_OK;
383 }
384
385 /**
386 * @brief Initialize the DCMI MSP.
387 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
388 * the configuration information for DCMI.
389 * @retval None
390 */
HAL_DCMI_MspInit(DCMI_HandleTypeDef * hdcmi)391 __weak void HAL_DCMI_MspInit(DCMI_HandleTypeDef* hdcmi)
392 {
393 /* Prevent unused argument(s) compilation warning */
394 UNUSED(hdcmi);
395
396 /* NOTE : This function should not be modified; when the callback is needed,
397 the HAL_DCMI_MspInit() callback can be implemented in the user file
398 */
399 }
400
401 /**
402 * @brief De-initialize the DCMI MSP.
403 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
404 * the configuration information for DCMI.
405 * @retval None
406 */
HAL_DCMI_MspDeInit(DCMI_HandleTypeDef * hdcmi)407 __weak void HAL_DCMI_MspDeInit(DCMI_HandleTypeDef* hdcmi)
408 {
409 /* Prevent unused argument(s) compilation warning */
410 UNUSED(hdcmi);
411
412 /* NOTE : This function should not be modified; when the callback is needed,
413 the HAL_DCMI_MspDeInit() callback can be implemented in the user file
414 */
415 }
416
417 /**
418 * @}
419 */
420
421 /** @defgroup DCMI_Exported_Functions_Group2 IO operation functions
422 * @brief IO operation functions
423 *
424 @verbatim
425 ===============================================================================
426 ##### IO operation functions #####
427 ===============================================================================
428 [..] This section provides functions allowing to:
429 (+) Configure destination address and data length,
430 enable DCMI DMA request and DCMI capture.
431 (+) Stop DCMI capture.
432 (+) Handle DCMI interrupt request.
433
434 [..] A set of callbacks is provided:
435 (+) HAL_DCMI_ErrorCallback()
436 (+) HAL_DCMI_LineEventCallback()
437 (+) HAL_DCMI_VsyncEventCallback()
438 (+) HAL_DCMI_FrameEventCallback()
439
440
441 @endverbatim
442 * @{
443 */
444
445 /**
446 * @brief Enable DCMI capture in DMA mode.
447 * @param hdcmi Pointer to a DCMI_HandleTypeDef structure that contains
448 * the configuration information for DCMI.
449 * @param DCMI_Mode DCMI capture mode snapshot or continuous grab.
450 * @param pData The destination memory buffer address.
451 * @param Length The length of capture to be transferred (in 32-bit words).
452 * @note In case of length larger than 65535 (0xFFFF is the DMA maximum transfer length),
453 * the API uses the end of the destination buffer as a work area: HAL_DCMI_Start_DMA()
454 * initiates a circular DMA transfer from DCMI DR to the ad-hoc work buffer and each
455 * half and complete transfer interrupt triggers a copy from the work buffer to
456 * the final destination pData thru a second DMA channel.
457 * @note Following HAL_DCMI_Init() call, all interruptions are enabled (line end,
458 * frame end, overrun, VSYNC and embedded synchronization error interrupts).
459 * User can disable unwanted interrupts thru __HAL_DCMI_DISABLE_IT() macro
460 * before invoking HAL_DCMI_Start_DMA().
461 * @note For length less than 0xFFFF (DMA maximum transfer length) and in snapshot mode,
462 * frame interrupt is disabled before DMA transfer. FRAME capture flag is checked
463 * in DCMI_DMAXferCplt callback at the end of the DMA transfer. If flag is set,
464 * HAL_DCMI_FrameEventCallback() API is called.
465 * @retval HAL status
466 */
HAL_DCMI_Start_DMA(DCMI_HandleTypeDef * hdcmi,uint32_t DCMI_Mode,uint32_t pData,uint32_t Length)467 HAL_StatusTypeDef HAL_DCMI_Start_DMA(DCMI_HandleTypeDef* hdcmi, uint32_t DCMI_Mode, uint32_t pData, uint32_t Length)
468 {
469 uint32_t circular_copy_length;
470
471 /* Check capture parameter */
472 assert_param(IS_DCMI_CAPTURE_MODE(DCMI_Mode));
473
474 /* Process Locked */
475 __HAL_LOCK(hdcmi);
476
477 /* Lock the DCMI peripheral state */
478 hdcmi->State = HAL_DCMI_STATE_BUSY;
479
480 /* Configure the DCMI Mode and enable the DCMI IP at the same time */
481 MODIFY_REG(hdcmi->Instance->CR, (DCMI_CR_CM|DCMI_CR_ENABLE), (DCMI_Mode|DCMI_CR_ENABLE));
482
483 /* Set the DMA conversion complete callback */
484 hdcmi->DMA_Handle->XferCpltCallback = DCMI_DMAXferCplt;
485
486 /* Set the DMA error callback */
487 hdcmi->DMA_Handle->XferErrorCallback = DCMI_DMAError;
488
489 /* Set the dma abort callback */
490 hdcmi->DMA_Handle->XferAbortCallback = NULL;
491
492 if(Length <= 0xFFFFU)
493 {
494 hdcmi->XferCount = 0; /* Mark as direct transfer from DCMI_DR register to final destination buffer */
495
496 /* Enable the DMA channel */
497 if (HAL_DMA_Start_IT(hdcmi->DMA_Handle, (uint32_t)&hdcmi->Instance->DR, (uint32_t)pData, Length) != HAL_OK)
498 {
499 /* Update error code */
500 hdcmi->ErrorCode |= HAL_DCMI_ERROR_DMA;
501
502 /* Set state back to Ready */
503 hdcmi->State = HAL_DCMI_STATE_READY;
504
505 /* Process Unlocked */
506 __HAL_UNLOCK(hdcmi);
507
508 return HAL_ERROR;
509 }
510 }
511 else /* Capture length is longer than DMA maximum transfer size */
512 {
513 /* Set DMA in circular mode */
514 hdcmi->DMA_Handle->Init.Mode = DMA_CIRCULAR;
515
516 /* Set the DMA half transfer complete callback */
517 hdcmi->DMA_Handle->XferHalfCpltCallback = DCMI_DMAHalfXferCplt;
518
519 /* Initialize transfer parameters */
520 hdcmi->XferSize = Length; /* Store the complete transfer length in DCMI handle */
521 hdcmi->pBuffPtr = pData; /* Final destination buffer pointer */
522
523 circular_copy_length = DCMI_TransferSize(Length);
524
525 /* Check if issue in intermediate length computation */
526 if (circular_copy_length == 0U)
527 {
528 /* Set state back to Ready */
529 hdcmi->State = HAL_DCMI_STATE_READY;
530
531 /* Process Unlocked */
532 __HAL_UNLOCK(hdcmi);
533
534 return HAL_ERROR;
535 }
536
537 /* Store the number of half - intermediate buffer copies needed */
538 hdcmi->XferCount = 2U * ((Length / circular_copy_length) - 1U);
539 /* Store the half-buffer copy length */
540 hdcmi->HalfCopyLength = circular_copy_length / 2U;
541
542 /* DCMI DR samples in circular mode will be copied
543 at the end of the final buffer.
544 Now compute the circular buffer start address. */
545 /* Start by pointing at the final buffer */
546 hdcmi->pCircularBuffer = pData;
547 /* Update pCircularBuffer in "moving" at the end of the final
548 buffer, don't forger to convert in bytes to compute exact address */
549 hdcmi->pCircularBuffer += 4U * (((Length / circular_copy_length) - 1U) * circular_copy_length);
550
551 /* Initiate the circular DMA transfer from DCMI IP to final buffer end */
552 if ( HAL_DMA_Start_IT(hdcmi->DMA_Handle, (uint32_t)&hdcmi->Instance->DR, (uint32_t)hdcmi->pCircularBuffer, circular_copy_length) != HAL_OK)
553 {
554 /* Update error code */
555 hdcmi->ErrorCode |= HAL_DCMI_ERROR_DMA;
556
557 /* Set state back to Ready */
558 hdcmi->State = HAL_DCMI_STATE_READY;
559
560 /* Process Unlocked */
561 __HAL_UNLOCK(hdcmi);
562
563 return HAL_ERROR;
564 }
565 }
566
567 /* Enable Capture */
568 SET_BIT(hdcmi->Instance->CR, DCMI_CR_CAPTURE);
569
570 /* Release Lock */
571 __HAL_UNLOCK(hdcmi);
572
573 /* Return function status */
574 return HAL_OK;
575 }
576
577 /**
578 * @brief Disable DCMI capture in DMA mode.
579 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
580 * the configuration information for DCMI.
581 * @retval HAL status
582 */
HAL_DCMI_Stop(DCMI_HandleTypeDef * hdcmi)583 HAL_StatusTypeDef HAL_DCMI_Stop(DCMI_HandleTypeDef* hdcmi)
584 {
585 uint32_t tickstart;
586 HAL_StatusTypeDef status = HAL_OK;
587
588 /* Process locked */
589 __HAL_LOCK(hdcmi);
590
591 /* Lock the DCMI peripheral state */
592 hdcmi->State = HAL_DCMI_STATE_BUSY;
593
594 /* Disable Capture */
595 CLEAR_BIT(hdcmi->Instance->CR, DCMI_CR_CAPTURE);
596
597 /* Get tick */
598 tickstart = HAL_GetTick();
599
600 /* Check if the DCMI capture is effectively disabled */
601 while((hdcmi->Instance->CR & DCMI_CR_CAPTURE) != 0U)
602 {
603 if((HAL_GetTick() - tickstart ) > DCMI_TIMEOUT_STOP)
604 {
605 /* Update error code */
606 hdcmi->ErrorCode |= HAL_DCMI_ERROR_TIMEOUT;
607
608 status = HAL_TIMEOUT;
609 break;
610 }
611 }
612
613 /* Disable the DMA */
614 if (HAL_DMA_Abort(hdcmi->DMA_Handle) != HAL_OK)
615 {
616 DCMI_DMAError(hdcmi->DMA_Handle);
617 }
618
619 /* Disable DCMI IP */
620 __HAL_DCMI_DISABLE(hdcmi);
621
622 /* Change DCMI state */
623 hdcmi->State = HAL_DCMI_STATE_READY;
624
625 /* Process Unlocked */
626 __HAL_UNLOCK(hdcmi);
627
628 /* Return function status */
629 return status;
630 }
631
632 /**
633 * @brief Suspend DCMI capture.
634 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
635 * the configuration information for DCMI.
636 * @retval HAL status
637 */
HAL_DCMI_Suspend(DCMI_HandleTypeDef * hdcmi)638 HAL_StatusTypeDef HAL_DCMI_Suspend(DCMI_HandleTypeDef* hdcmi)
639 {
640 uint32_t tickstart;
641
642 /* Process locked */
643 __HAL_LOCK(hdcmi);
644
645 if(hdcmi->State == HAL_DCMI_STATE_BUSY)
646 {
647 /* Change DCMI state */
648 hdcmi->State = HAL_DCMI_STATE_SUSPENDED;
649
650 /* Disable Capture */
651 CLEAR_BIT(hdcmi->Instance->CR, DCMI_CR_CAPTURE);
652
653 /* Get tick */
654 tickstart = HAL_GetTick();
655
656 /* Check if the DCMI capture is effectively disabled */
657 while((hdcmi->Instance->CR & DCMI_CR_CAPTURE) != 0U)
658 {
659 if((HAL_GetTick() - tickstart ) > DCMI_TIMEOUT_STOP)
660 {
661 /* Update error code */
662 hdcmi->ErrorCode |= HAL_DCMI_ERROR_TIMEOUT;
663
664 /* Change DCMI state */
665 hdcmi->State = HAL_DCMI_STATE_READY;
666
667 /* Process Unlocked */
668 __HAL_UNLOCK(hdcmi);
669
670 return HAL_TIMEOUT;
671 }
672 }
673 }
674
675 /* Process Unlocked */
676 __HAL_UNLOCK(hdcmi);
677
678 /* Return function status */
679 return HAL_OK;
680 }
681
682 /**
683 * @brief Resume DCMI capture.
684 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
685 * the configuration information for DCMI.
686 * @retval HAL status
687 */
HAL_DCMI_Resume(DCMI_HandleTypeDef * hdcmi)688 HAL_StatusTypeDef HAL_DCMI_Resume(DCMI_HandleTypeDef* hdcmi)
689 {
690 /* Process locked */
691 __HAL_LOCK(hdcmi);
692
693 if(hdcmi->State == HAL_DCMI_STATE_SUSPENDED)
694 {
695 /* Change DCMI state */
696 hdcmi->State = HAL_DCMI_STATE_BUSY;
697
698 /* Enable Capture */
699 SET_BIT(hdcmi->Instance->CR, DCMI_CR_CAPTURE);
700 }
701
702 /* Process Unlocked */
703 __HAL_UNLOCK(hdcmi);
704
705 return HAL_OK;
706 }
707
708 /**
709 * @brief Handle DCMI interrupt request.
710 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
711 * the configuration information for the DCMI.
712 * @retval None
713 */
HAL_DCMI_IRQHandler(DCMI_HandleTypeDef * hdcmi)714 void HAL_DCMI_IRQHandler(DCMI_HandleTypeDef *hdcmi)
715 {
716 uint32_t misflags = READ_REG(hdcmi->Instance->MISR);
717
718 /* Synchronization error interrupt management *******************************/
719 if ((misflags & DCMI_MIS_ERR_MIS) != 0x0U)
720 {
721 /* Clear the Synchronization error flag */
722 __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_ERRRI);
723
724 /* Update error code */
725 hdcmi->ErrorCode |= HAL_DCMI_ERROR_SYNC;
726 }
727
728 /* Overflow interrupt management ********************************************/
729 if ((misflags & DCMI_MIS_OVR_MIS) != 0x0U)
730 {
731 /* Clear the Overflow flag */
732 __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_OVRRI);
733
734 /* Update error code */
735 hdcmi->ErrorCode |= HAL_DCMI_ERROR_OVR;
736 }
737
738 if (hdcmi->ErrorCode != HAL_DCMI_ERROR_NONE)
739 {
740 /* Change DCMI state */
741 hdcmi->State = HAL_DCMI_STATE_READY;
742
743 /* Set the overflow callback */
744 hdcmi->DMA_Handle->XferAbortCallback = DCMI_DMAError;
745
746 /* Abort the DMA Transfer */
747 if (HAL_DMA_Abort_IT(hdcmi->DMA_Handle) != HAL_OK)
748 {
749 DCMI_DMAError(hdcmi->DMA_Handle);
750 }
751 }
752
753 /* Line Interrupt management ************************************************/
754 if ((misflags & DCMI_MIS_LINE_MIS) != 0x0U)
755 {
756 /* Clear the Line interrupt flag */
757 __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_LINERI);
758
759 /* Line interrupt Event Callback */
760 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
761 /*Call registered DCMI line event callback*/
762 hdcmi->LineEventCallback(hdcmi);
763 #else
764 HAL_DCMI_LineEventCallback(hdcmi);
765 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
766 }
767
768 /* VSYNC interrupt management ***********************************************/
769 if ((misflags & DCMI_MIS_VSYNC_MIS) != 0x0U)
770 {
771 /* Clear the VSYNC flag */
772 __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_VSYNCRI);
773
774 /* VSYNC Event Callback */
775 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
776 /*Call registered DCMI vsync event callback*/
777 hdcmi->VsyncEventCallback(hdcmi);
778 #else
779 HAL_DCMI_VsyncEventCallback(hdcmi);
780 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
781 }
782
783 /* End of Frame interrupt management ****************************************/
784 if ((misflags & DCMI_MIS_FRAME_MIS) != 0x0U)
785 {
786 /* Disable the Line interrupt when using snapshot mode */
787 if ((hdcmi->Instance->CR & DCMI_CR_CM) == DCMI_MODE_SNAPSHOT)
788 {
789 __HAL_DCMI_DISABLE_IT(hdcmi, DCMI_IT_LINE|DCMI_IT_VSYNC|DCMI_IT_ERR|DCMI_IT_OVR);
790 /* Change the DCMI state */
791 hdcmi->State = HAL_DCMI_STATE_READY;
792 }
793
794 /* Clear the End of Frame flag */
795 __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_FRAMERI);
796
797 /* Frame Event Callback */
798 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
799 /*Call registered DCMI frame event callback*/
800 hdcmi->FrameEventCallback(hdcmi);
801 #else
802 HAL_DCMI_FrameEventCallback(hdcmi);
803 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
804 }
805 }
806
807 /**
808 * @brief Error DCMI callback.
809 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
810 * the configuration information for DCMI.
811 * @retval None
812 */
HAL_DCMI_ErrorCallback(DCMI_HandleTypeDef * hdcmi)813 __weak void HAL_DCMI_ErrorCallback(DCMI_HandleTypeDef *hdcmi)
814 {
815 /* Prevent unused argument(s) compilation warning */
816 UNUSED(hdcmi);
817
818 /* NOTE : This function should not be modified; when the callback is needed,
819 the HAL_DCMI_ErrorCallback() callback can be implemented in the user file.
820 */
821 }
822
823 /**
824 * @brief Line Event callback.
825 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
826 * the configuration information for DCMI.
827 * @retval None
828 */
HAL_DCMI_LineEventCallback(DCMI_HandleTypeDef * hdcmi)829 __weak void HAL_DCMI_LineEventCallback(DCMI_HandleTypeDef *hdcmi)
830 {
831 /* Prevent unused argument(s) compilation warning */
832 UNUSED(hdcmi);
833
834 /* NOTE : This function should not be modified; when the callback is needed,
835 the HAL_DCMI_LineEventCallback() callback can be implemented in the user file.
836 */
837 }
838
839 /**
840 * @brief VSYNC Event callback.
841 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
842 * the configuration information for DCMI.
843 * @retval None
844 */
HAL_DCMI_VsyncEventCallback(DCMI_HandleTypeDef * hdcmi)845 __weak void HAL_DCMI_VsyncEventCallback(DCMI_HandleTypeDef *hdcmi)
846 {
847 /* Prevent unused argument(s) compilation warning */
848 UNUSED(hdcmi);
849
850 /* NOTE : This function should not be modified; when the callback is needed,
851 the HAL_DCMI_VsyncEventCallback() callback can be implemented in the user file.
852 */
853 }
854
855 /**
856 * @brief Frame Event callback.
857 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
858 * the configuration information for DCMI.
859 * @retval None
860 */
HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef * hdcmi)861 __weak void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi)
862 {
863 /* Prevent unused argument(s) compilation warning */
864 UNUSED(hdcmi);
865
866 /* NOTE : This function should not be modified; when the callback is needed,
867 the HAL_DCMI_FrameEventCallback() callback can be implemented in the user file.
868 */
869 }
870 /**
871 * @}
872 */
873
874
875 /** @defgroup DCMI_Exported_Functions_Group3 Peripheral Control functions
876 * @brief Peripheral Control functions
877 *
878 @verbatim
879 ===============================================================================
880 ##### Peripheral Control functions #####
881 ===============================================================================
882 [..] This section provides functions allowing to:
883 (+) Configure the crop feature.
884 (+) Enable/Disable the crop feature.
885 (+) Configure the synchronization delimiters unmasks.
886 (+) Enable/Disable user-specified DCMI interrupts.
887
888 @endverbatim
889 * @{
890 */
891
892 /**
893 * @brief Configure the DCMI crop window coordinates.
894 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
895 * the configuration information for DCMI.
896 * @param X0 DCMI window crop window X offset (number of pixels clocks to count before the capture).
897 * @param Y0 DCMI window crop window Y offset (image capture starts with this line number, previous
898 * line data are ignored).
899 * @param XSize DCMI crop window horizontal size (in number of pixels per line).
900 * @param YSize DCMI crop window vertical size (in lines count).
901 * @note For all the parameters, the actual value is the input data + 1 (e.g. YSize = 0x0 means 1 line,
902 * YSize = 0x1 means 2 lines, ...)
903 * @retval HAL status
904 */
HAL_DCMI_ConfigCrop(DCMI_HandleTypeDef * hdcmi,uint32_t X0,uint32_t Y0,uint32_t XSize,uint32_t YSize)905 HAL_StatusTypeDef HAL_DCMI_ConfigCrop(DCMI_HandleTypeDef *hdcmi, uint32_t X0, uint32_t Y0, uint32_t XSize, uint32_t YSize)
906 {
907 /* Check the parameters */
908 assert_param(IS_DCMI_WINDOW_COORDINATE(X0));
909 assert_param(IS_DCMI_WINDOW_HEIGHT(Y0));
910 assert_param(IS_DCMI_WINDOW_COORDINATE(XSize));
911 assert_param(IS_DCMI_WINDOW_COORDINATE(YSize));
912
913 /* Process Locked */
914 __HAL_LOCK(hdcmi);
915
916 /* Lock the DCMI peripheral state */
917 hdcmi->State = HAL_DCMI_STATE_BUSY;
918
919 /* Configure CROP */
920 MODIFY_REG(hdcmi->Instance->CWSIZER, (DCMI_CWSIZE_VLINE|DCMI_CWSIZE_CAPCNT), (XSize | (YSize << DCMI_CWSIZE_VLINE_Pos)));
921 MODIFY_REG(hdcmi->Instance->CWSTRTR, (DCMI_CWSTRT_VST|DCMI_CWSTRT_HOFFCNT), (X0 | (Y0 << DCMI_CWSTRT_VST_Pos)));
922
923 /* Initialize the DCMI state*/
924 hdcmi->State = HAL_DCMI_STATE_READY;
925
926 /* Process Unlocked */
927 __HAL_UNLOCK(hdcmi);
928
929 return HAL_OK;
930 }
931
932 /**
933 * @brief Disable the crop feature.
934 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
935 * the configuration information for DCMI.
936 * @retval HAL status
937 */
HAL_DCMI_DisableCrop(DCMI_HandleTypeDef * hdcmi)938 HAL_StatusTypeDef HAL_DCMI_DisableCrop(DCMI_HandleTypeDef *hdcmi)
939 {
940 /* Process Locked */
941 __HAL_LOCK(hdcmi);
942
943 /* Lock the DCMI peripheral state */
944 hdcmi->State = HAL_DCMI_STATE_BUSY;
945
946 /* Disable DCMI Crop feature */
947 CLEAR_BIT(hdcmi->Instance->CR, DCMI_CR_CROP);
948
949 /* Change the DCMI state*/
950 hdcmi->State = HAL_DCMI_STATE_READY;
951
952 /* Process Unlocked */
953 __HAL_UNLOCK(hdcmi);
954
955 return HAL_OK;
956 }
957
958 /**
959 * @brief Enable the crop feature.
960 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
961 * the configuration information for DCMI.
962 * @retval HAL status
963 */
HAL_DCMI_EnableCrop(DCMI_HandleTypeDef * hdcmi)964 HAL_StatusTypeDef HAL_DCMI_EnableCrop(DCMI_HandleTypeDef *hdcmi)
965 {
966 /* Process Locked */
967 __HAL_LOCK(hdcmi);
968
969 /* Lock the DCMI peripheral state */
970 hdcmi->State = HAL_DCMI_STATE_BUSY;
971
972 /* Enable DCMI Crop feature */
973 SET_BIT(hdcmi->Instance->CR, DCMI_CR_CROP);
974
975 /* Change the DCMI state*/
976 hdcmi->State = HAL_DCMI_STATE_READY;
977
978 /* Process Unlocked */
979 __HAL_UNLOCK(hdcmi);
980
981 return HAL_OK;
982 }
983
984 /**
985 * @brief Set embedded synchronization delimiters unmasks.
986 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
987 * the configuration information for DCMI.
988 * @param SyncUnmask pointer to a DCMI_SyncUnmaskTypeDef structure that contains
989 * the embedded synchronization delimiters unmasks.
990 * @retval HAL status
991 */
HAL_DCMI_ConfigSyncUnmask(DCMI_HandleTypeDef * hdcmi,DCMI_SyncUnmaskTypeDef * SyncUnmask)992 HAL_StatusTypeDef HAL_DCMI_ConfigSyncUnmask(DCMI_HandleTypeDef *hdcmi, DCMI_SyncUnmaskTypeDef *SyncUnmask)
993 {
994 /* Process Locked */
995 __HAL_LOCK(hdcmi);
996
997 /* Lock the DCMI peripheral state */
998 hdcmi->State = HAL_DCMI_STATE_BUSY;
999
1000 /* Write DCMI embedded synchronization unmask register */
1001 hdcmi->Instance->ESUR = (((uint32_t)SyncUnmask->FrameStartUnmask) |\
1002 ((uint32_t)SyncUnmask->LineStartUnmask << DCMI_ESUR_LSU_Pos)|\
1003 ((uint32_t)SyncUnmask->LineEndUnmask << DCMI_ESUR_LEU_Pos)|\
1004 ((uint32_t)SyncUnmask->FrameEndUnmask << DCMI_ESUR_FEU_Pos));
1005
1006 /* Change the DCMI state*/
1007 hdcmi->State = HAL_DCMI_STATE_READY;
1008
1009 /* Process Unlocked */
1010 __HAL_UNLOCK(hdcmi);
1011
1012 return HAL_OK;
1013 }
1014
1015
1016
1017
1018 /**
1019 * @}
1020 */
1021
1022 /** @defgroup DCMI_Exported_Functions_Group4 Peripheral State functions
1023 * @brief Peripheral State functions
1024 *
1025 @verbatim
1026 ===============================================================================
1027 ##### Peripheral State and Errors functions #####
1028 ===============================================================================
1029 [..]
1030 This subsection provides functions allowing to
1031 (+) Check the DCMI state.
1032 (+) Get the specific DCMI error flag.
1033
1034 @endverbatim
1035 * @{
1036 */
1037
1038 /**
1039 * @brief Return the DCMI state.
1040 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
1041 * the configuration information for DCMI.
1042 * @retval HAL state
1043 */
HAL_DCMI_GetState(DCMI_HandleTypeDef * hdcmi)1044 HAL_DCMI_StateTypeDef HAL_DCMI_GetState(DCMI_HandleTypeDef *hdcmi)
1045 {
1046 return hdcmi->State;
1047 }
1048
1049 /**
1050 * @brief Return the DCMI error code.
1051 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
1052 * the configuration information for DCMI.
1053 * @retval DCMI Error Code
1054 */
HAL_DCMI_GetError(DCMI_HandleTypeDef * hdcmi)1055 uint32_t HAL_DCMI_GetError(DCMI_HandleTypeDef *hdcmi)
1056 {
1057 return hdcmi->ErrorCode;
1058 }
1059
1060 /**
1061 * @}
1062 */
1063
1064 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
1065 /**
1066 * @brief DCMI Callback registering
1067 * @param hdcmi dcmi handle
1068 * @param CallbackID dcmi Callback ID
1069 * @param pCallback pointer to dcmi Callback function
1070 * @retval status
1071 */
HAL_DCMI_RegisterCallback(DCMI_HandleTypeDef * hdcmi,HAL_DCMI_CallbackIDTypeDef CallbackID,pDCMI_CallbackTypeDef pCallback)1072 HAL_StatusTypeDef HAL_DCMI_RegisterCallback(DCMI_HandleTypeDef *hdcmi, HAL_DCMI_CallbackIDTypeDef CallbackID, pDCMI_CallbackTypeDef pCallback)
1073 {
1074 HAL_StatusTypeDef status = HAL_OK;
1075
1076 if(pCallback == NULL)
1077 {
1078 /* update the error code */
1079 hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
1080 /* update return status */
1081 status = HAL_ERROR;
1082 }
1083 else
1084 {
1085 if(hdcmi->State == HAL_DCMI_STATE_READY)
1086 {
1087 switch (CallbackID)
1088 {
1089 case HAL_DCMI_FRAME_EVENT_CB_ID :
1090 hdcmi->FrameEventCallback = pCallback;
1091 break;
1092
1093 case HAL_DCMI_VSYNC_EVENT_CB_ID :
1094 hdcmi->VsyncEventCallback = pCallback;
1095 break;
1096
1097 case HAL_DCMI_LINE_EVENT_CB_ID :
1098 hdcmi->LineEventCallback = pCallback;
1099 break;
1100
1101 case HAL_DCMI_ERROR_CB_ID :
1102 hdcmi->ErrorCallback = pCallback;
1103 break;
1104
1105 case HAL_DCMI_MSPINIT_CB_ID :
1106 hdcmi->MspInitCallback = pCallback;
1107 break;
1108
1109 case HAL_DCMI_MSPDEINIT_CB_ID :
1110 hdcmi->MspDeInitCallback = pCallback;
1111 break;
1112
1113 default :
1114 /* Return error status */
1115 status = HAL_ERROR;
1116 break;
1117 }
1118 }
1119 else if(hdcmi->State == HAL_DCMI_STATE_RESET)
1120 {
1121 switch (CallbackID)
1122 {
1123 case HAL_DCMI_MSPINIT_CB_ID :
1124 hdcmi->MspInitCallback = pCallback;
1125 break;
1126
1127 case HAL_DCMI_MSPDEINIT_CB_ID :
1128 hdcmi->MspDeInitCallback = pCallback;
1129 break;
1130
1131 default :
1132 /* update the error code */
1133 hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
1134 /* update return status */
1135 status = HAL_ERROR;
1136 break;
1137 }
1138 }
1139 else
1140 {
1141 /* update the error code */
1142 hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
1143 /* update return status */
1144 status = HAL_ERROR;
1145 }
1146 }
1147
1148 return status;
1149 }
1150
1151 /**
1152 * @brief DCMI Callback Unregistering
1153 * @param hdcmi dcmi handle
1154 * @param CallbackID dcmi Callback ID
1155 * @retval status
1156 */
HAL_DCMI_UnRegisterCallback(DCMI_HandleTypeDef * hdcmi,HAL_DCMI_CallbackIDTypeDef CallbackID)1157 HAL_StatusTypeDef HAL_DCMI_UnRegisterCallback(DCMI_HandleTypeDef *hdcmi, HAL_DCMI_CallbackIDTypeDef CallbackID)
1158 {
1159 HAL_StatusTypeDef status = HAL_OK;
1160
1161 if(hdcmi->State == HAL_DCMI_STATE_READY)
1162 {
1163 switch (CallbackID)
1164 {
1165 case HAL_DCMI_FRAME_EVENT_CB_ID :
1166 hdcmi->FrameEventCallback = HAL_DCMI_FrameEventCallback; /* Legacy weak FrameEventCallback */
1167 break;
1168
1169 case HAL_DCMI_VSYNC_EVENT_CB_ID :
1170 hdcmi->VsyncEventCallback = HAL_DCMI_VsyncEventCallback; /* Legacy weak VsyncEventCallback */
1171 break;
1172
1173 case HAL_DCMI_LINE_EVENT_CB_ID :
1174 hdcmi->LineEventCallback = HAL_DCMI_LineEventCallback; /* Legacy weak LineEventCallback */
1175 break;
1176
1177 case HAL_DCMI_ERROR_CB_ID :
1178 hdcmi->ErrorCallback = HAL_DCMI_ErrorCallback; /* Legacy weak ErrorCallback */
1179 break;
1180
1181 case HAL_DCMI_MSPINIT_CB_ID :
1182 hdcmi->MspInitCallback = HAL_DCMI_MspInit;
1183 break;
1184
1185 case HAL_DCMI_MSPDEINIT_CB_ID :
1186 hdcmi->MspDeInitCallback = HAL_DCMI_MspDeInit;
1187 break;
1188
1189 default :
1190 /* update the error code */
1191 hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
1192 /* update return status */
1193 status = HAL_ERROR;
1194 break;
1195 }
1196 }
1197 else if(hdcmi->State == HAL_DCMI_STATE_RESET)
1198 {
1199 switch (CallbackID)
1200 {
1201 case HAL_DCMI_MSPINIT_CB_ID :
1202 hdcmi->MspInitCallback = HAL_DCMI_MspInit;
1203 break;
1204
1205 case HAL_DCMI_MSPDEINIT_CB_ID :
1206 hdcmi->MspDeInitCallback = HAL_DCMI_MspDeInit;
1207 break;
1208
1209 default :
1210 /* update the error code */
1211 hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
1212 /* update return status */
1213 status = HAL_ERROR;
1214 break;
1215 }
1216 }
1217 else
1218 {
1219 /* update the error code */
1220 hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
1221 /* update return status */
1222 status = HAL_ERROR;
1223 }
1224
1225 return status;
1226 }
1227 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
1228
1229 /**
1230 * @}
1231 */
1232
1233 /* Private functions ---------------------------------------------------------*/
1234 /** @defgroup DCMI_Private_Functions DCMI Private Functions
1235 * @{
1236 */
1237
1238 /**
1239 * @brief DMA conversion complete callback.
1240 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
1241 * the configuration information for the specified DMA module.
1242 * @note When the size of the frame being captured by the DCMI peripheral is
1243 * larger than 0xFFFF (DMA maximum transfer length), this API initiates
1244 * another DMA transfer to copy the second half of the work buffer
1245 * associated to the DCMI handle to the final destination buffer.
1246 * @retval None
1247 */
DCMI_DMAXferCplt(DMA_HandleTypeDef * hdma)1248 static void DCMI_DMAXferCplt(DMA_HandleTypeDef *hdma)
1249 {
1250 uint32_t loop_length; /* transfer length */
1251 uint32_t * tmpBuffer_Dest;
1252 uint32_t * tmpBuffer_Orig;
1253 uint32_t temp;
1254
1255 DCMI_HandleTypeDef* hdcmi = ( DCMI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
1256
1257
1258 if(hdcmi->XferCount != 0U)
1259 {
1260 /* Manage second half buffer copy in case of big transfer */
1261
1262 /* Decrement half-copies counter */
1263 hdcmi->XferCount--;
1264
1265 /* Point at DCMI final destination */
1266 tmpBuffer_Dest = (uint32_t *)hdcmi->pBuffPtr;
1267
1268 /* Point at DCMI circular buffer mid-location */
1269 tmpBuffer_Orig = (uint32_t *)hdcmi->pCircularBuffer;
1270 temp = (uint32_t) (tmpBuffer_Orig);
1271 temp += hdcmi->HalfCopyLength;
1272 tmpBuffer_Orig = (uint32_t *) temp;
1273
1274 /* copy half the buffer size */
1275 loop_length = hdcmi->HalfCopyLength;
1276
1277 /* Save next entry to write at next half DMA transfer interruption */
1278 hdcmi->pBuffPtr += (uint32_t) loop_length*4U;
1279 hdcmi->XferSize -= hdcmi->HalfCopyLength;
1280
1281 /* Data copy from work buffer to final destination buffer */
1282 /* Enable the DMA Channel */
1283 if (HAL_DMA_Start_IT(hdcmi->DMAM2M_Handle, (uint32_t) tmpBuffer_Orig, (uint32_t) tmpBuffer_Dest, loop_length) != HAL_OK)
1284 {
1285 /* Update error code */
1286 hdcmi->ErrorCode |= HAL_DCMI_ERROR_DMA;
1287
1288 /* Change DCMI state */
1289 hdcmi->State = HAL_DCMI_STATE_READY;
1290
1291 /* Process Unlocked */
1292 __HAL_UNLOCK(hdcmi);
1293
1294 /* DCMI error Callback */
1295 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
1296 /*Call registered DCMI error callback*/
1297 hdcmi->ErrorCallback(hdcmi);
1298 #else
1299 HAL_DCMI_ErrorCallback(hdcmi);
1300 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
1301 }
1302 }
1303 else
1304 {
1305 /* if End of frame IT is disabled */
1306 if((hdcmi->Instance->IER & DCMI_IT_FRAME) == 0x0U)
1307 {
1308 /* If End of Frame flag is set */
1309 if(__HAL_DCMI_GET_FLAG(hdcmi, (uint32_t)DCMI_FLAG_FRAMERI) != 0x0UL)
1310 {
1311 /* Clear the End of Frame flag */
1312 __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_FRAMERI);
1313
1314 /* When snapshot mode, disable Vsync, Error and Overrun interrupts */
1315 if((hdcmi->Instance->CR & DCMI_CR_CM) == DCMI_MODE_SNAPSHOT)
1316 {
1317 /* Disable the Vsync, Error and Overrun interrupts */
1318 __HAL_DCMI_DISABLE_IT(hdcmi, DCMI_IT_LINE | DCMI_IT_VSYNC | DCMI_IT_ERR | DCMI_IT_OVR);
1319
1320 hdcmi->State = HAL_DCMI_STATE_READY;
1321
1322 /* Process Unlocked */
1323 __HAL_UNLOCK(hdcmi);
1324 }
1325
1326 /* Frame Event Callback */
1327 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
1328 /*Call registered DCMI frame event callback*/
1329 hdcmi->FrameEventCallback(hdcmi);
1330 #else
1331 HAL_DCMI_FrameEventCallback(hdcmi);
1332 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
1333 }
1334 }
1335 }
1336 }
1337
1338
1339 /**
1340 * @brief DMA Half Transfer complete callback.
1341 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
1342 * the configuration information for the specified DMA module.
1343 * @note When the size of the frame being captured by the DCMI peripheral is
1344 * larger than 0xFFFF (DMA maximum transfer length), this API initiates
1345 * another DMA transfer to copy the first half of the work buffer
1346 * associated to the DCMI handle to the final destination buffer.
1347 * @retval None
1348 */
DCMI_DMAHalfXferCplt(DMA_HandleTypeDef * hdma)1349 static void DCMI_DMAHalfXferCplt(DMA_HandleTypeDef *hdma)
1350 {
1351 uint32_t loop_length; /* transfer length */
1352 uint32_t * tmpBuffer_Dest;
1353 uint32_t * tmpBuffer_Orig;
1354
1355 DCMI_HandleTypeDef* hdcmi = ( DCMI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
1356
1357 if(hdcmi->XferCount != 0U)
1358 {
1359 /* Manage first half buffer copy in case of big transfer */
1360
1361 /* Decrement half-copies counter */
1362 hdcmi->XferCount--;
1363
1364 /* Point at DCMI final destination */
1365 tmpBuffer_Dest = (uint32_t *)hdcmi->pBuffPtr;
1366
1367 /* Point at DCMI circular buffer start */
1368 tmpBuffer_Orig = (uint32_t *)hdcmi->pCircularBuffer;
1369
1370 /* copy half the buffer size */
1371 loop_length = hdcmi->HalfCopyLength;
1372
1373 /* Save next entry to write at next DMA transfer interruption */
1374 hdcmi->pBuffPtr += (uint32_t) loop_length*4U;
1375 hdcmi->XferSize -= hdcmi->HalfCopyLength;
1376
1377 /* Data copy from work buffer to final destination buffer */
1378 /* Enable the DMA Channel */
1379 if (HAL_DMA_Start_IT(hdcmi->DMAM2M_Handle, (uint32_t) tmpBuffer_Orig, (uint32_t) tmpBuffer_Dest, loop_length) != HAL_OK)
1380 {
1381 /* Update error code */
1382 hdcmi->ErrorCode |= HAL_DCMI_ERROR_DMA;
1383
1384 /* Change DCMI state */
1385 hdcmi->State = HAL_DCMI_STATE_READY;
1386
1387 /* Process Unlocked */
1388 __HAL_UNLOCK(hdcmi);
1389
1390 /* DCMI error Callback */
1391 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
1392 /*Call registered DCMI error callback*/
1393 hdcmi->ErrorCallback(hdcmi);
1394 #else
1395 HAL_DCMI_ErrorCallback(hdcmi);
1396 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
1397 }
1398 }
1399 }
1400
1401 /**
1402 * @brief DMA error callback
1403 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
1404 * the configuration information for the specified DMA module.
1405 * @retval None
1406 */
DCMI_DMAError(DMA_HandleTypeDef * hdma)1407 static void DCMI_DMAError(DMA_HandleTypeDef *hdma)
1408 {
1409 DCMI_HandleTypeDef* hdcmi = ( DCMI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
1410
1411 /* Update error code */
1412 hdcmi->ErrorCode |= HAL_DCMI_ERROR_DMA;
1413
1414 /* Change DCMI state */
1415 hdcmi->State = HAL_DCMI_STATE_READY;
1416
1417 /* DCMI error Callback */
1418 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
1419 /*Call registered DCMI error callback*/
1420 hdcmi->ErrorCallback(hdcmi);
1421 #else
1422 HAL_DCMI_ErrorCallback(hdcmi);
1423 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
1424 }
1425
1426 /**
1427 * @brief Sub-buffers transfer size computation.
1428 * @note In the case of a frame size larger than the maximum DMA transfer length (0xFFFF),
1429 * the tranfer from DCMI DR register to the final output buffer is carried out by a sequence
1430 * of intermediate sub-copies to temporary buffers of size less than 0xFFFF.
1431 * To optimize the number of DMA transfers, the API computes the temporary buffer
1432 * size so that the latter is an even number less than 0xFFFF, that divides the final
1433 * buffer size and is as high as possible. The API implements a sub-optimum solution for
1434 * complexity's sake.
1435 * @note InputSize MUST be even.
1436 * @param InputSize full buffer size (in 32-bit words)
1437 * @retval Transfer size (in 32-bit words)
1438 */
DCMI_TransferSize(uint32_t InputSize)1439 static uint32_t DCMI_TransferSize(uint32_t InputSize)
1440 {
1441 uint32_t j = 1;
1442 uint32_t temp = InputSize;
1443 uint32_t aPrime[NPRIME] = {0};
1444 uint32_t output = 2; /* Want a result which is an even number */
1445 uint32_t PrimeArray[NPRIME] = { 1UL, 2UL, 3UL, 5UL,
1446 7UL, 11UL, 13UL, 17UL,
1447 19UL, 23UL, 29UL, 31UL,
1448 37UL, 41UL, 43UL, 47UL};
1449
1450
1451 /* Develop InputSize in product of prime numbers */
1452
1453 while (j < NPRIME)
1454 {
1455 if (temp < PrimeArray[j])
1456 {
1457 break;
1458 }
1459 while ((temp % PrimeArray[j]) == 0U)
1460 {
1461 aPrime[j]++;
1462 temp /= PrimeArray[j];
1463 }
1464 j++;
1465 }
1466
1467 /* Search for the biggest even divisor less or equal to 0xFFFE = 65534 */
1468 aPrime[1] -= 1U; /* output is initialized to 2, so don't count dividor 2 twice */
1469
1470 /* The algorithm below yields a sub-optimal solution
1471 but in an acceptable time. */
1472 j = NPRIME-1U;
1473 while ((j > 0U) && (output <= 0xFFFEU))
1474 {
1475 while (aPrime[j] > 0U)
1476 {
1477 if ((output * PrimeArray[j]) > 0xFFFEU)
1478 {
1479 break;
1480 }
1481 else
1482 {
1483 output *= PrimeArray[j];
1484 aPrime[j]--;
1485 }
1486 }
1487 j--;
1488 }
1489
1490
1491
1492 return output;
1493 }
1494
1495
1496 /**
1497 * @}
1498 */
1499
1500 /**
1501 * @}
1502 */
1503
1504 /**
1505 * @}
1506 */
1507
1508 #endif /* DCMI */
1509 #endif /* HAL_DCMI_MODULE_ENABLED */
1510
1511 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
1512