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 ******************************************************************************
14 * @attention
15 *
16 * Copyright (c) 2017 STMicroelectronics.
17 * All rights reserved.
18 *
19 * This software is licensed under terms that can be found in the LICENSE file
20 * in the root directory of this software component.
21 * If no LICENSE file comes with this software, it is provided AS-IS.
22 *
23 ******************************************************************************
24 @verbatim
25 ==============================================================================
26 ##### How to use this driver #####
27 ==============================================================================
28 [..]
29 The sequence below describes how to use this driver to capture images
30 from a camera module connected to the DCMI Interface.
31 This sequence does not take into account the configuration of the
32 camera module, which should be made before configuring and enabling
33 the DCMI to capture images.
34
35 (#) Program the required configuration through the following parameters:
36 horizontal and vertical polarity, pixel clock polarity, capture rate,
37 synchronization mode, frame delimiter codes, data width, byte and line
38 selection using HAL_DCMI_Init() function.
39
40 (#) Optionally select JPEG mode; in that case, only the polarity
41 and the capture mode parameters need to be set.
42
43 (#) Capture mode can be either snapshot or continuous mode.
44
45 (#) Configure the DMA_Handle to transfer data from DCMI DR
46 register to the destination memory buffer.
47
48 -@- In snapshot mode, the interface transfers a single frame through DMA. In
49 continuous mode, the DMA must be set in circular mode to ensure a continuous
50 flow of images data samples.
51
52 (#) Program the transfer configuration through the following parameters:
53 DCMI mode, destination memory buffer address and data length then
54 enable capture using HAL_DCMI_Start_DMA() function.
55
56 (#) Whether in continuous or snapshot mode, data length parameter must be
57 equal to the frame size.
58
59 (#) When the frame size is unknown beforehand (e.g. JPEG case), data length must
60 be large enough to ensure the capture of a frame.
61
62 (#) If the frame size is larger than the maximum DMA transfer length (i.e. 65535),
63 (++) the DMA must be configured in circular mode, either for snapshot or continuous
64 capture mode,
65 (++) during capture, the driver copies the image data samples from DCMI DR register
66 at the end of the final destination buffer used as a work buffer,
67 (++) at each DMA half (respectively complete) transfer interrupt, the first
68 (resp. second) half of the work buffer is copied to the final destination through
69 a second DMA channel.
70 (++) Parameters of this second DMA channel are contained in the memory to memory DMA
71 handle "DMAM2M_Handle", itself field of the DCMI handle structure.
72 (++) This memory to memory transfer has length half that of the work buffer and is
73 carried out in normal mode (not in circular mode).
74
75 (#) Optionally, configure and enable the CROP feature to select a
76 rectangular window from the received image using HAL_DCMI_ConfigCrop()
77 and HAL_DCMI_EnableCrop() functions. Use HAL_DCMI_DisableCrop() to
78 disable this feature.
79
80 (#) The capture can be stopped with HAL_DCMI_Stop() function.
81
82 (#) To control the DCMI state, use the function HAL_DCMI_GetState().
83
84 (#) To read the DCMI error code, use the function HAL_DCMI_GetError().
85
86 [..]
87 (@) When the frame size is less than the maximum DMA transfer length (i.e. 65535)
88 and when in snapshot mode, user must make sure the FRAME interrupt is disabled.
89 This allows to avoid corner cases where the FRAME interrupt might be triggered
90 before the DMA transfer completion interrupt. In this specific configuration,
91 the driver checks the FRAME capture flag after the DMA transfer end and calls
92 HAL_DCMI_FrameEventCallback() if the flag is set.
93
94 *** DCMI HAL driver macros list ***
95 =============================================
96 [..]
97 Below the list of most used macros in DCMI HAL driver.
98
99 (+) __HAL_DCMI_ENABLE: Enable the DCMI peripheral.
100 (+) __HAL_DCMI_DISABLE: Disable the DCMI peripheral.
101 (+) __HAL_DCMI_GET_FLAG: Get the DCMI pending flags.
102 (+) __HAL_DCMI_CLEAR_FLAG: Clear the DCMI pending flags.
103 (+) __HAL_DCMI_ENABLE_IT: Enable the specified DCMI interrupts.
104 (+) __HAL_DCMI_DISABLE_IT: Disable the specified DCMI interrupts.
105 (+) __HAL_DCMI_GET_IT_SOURCE: Check whether the specified DCMI interrupt has occurred or not.
106
107 *** Callback registration ***
108 =============================
109
110 The compilation define USE_HAL_DCMI_REGISTER_CALLBACKS when set to 1
111 allows the user to configure dynamically the driver callbacks.
112 Use functions @ref HAL_DCMI_RegisterCallback() to register a user callback.
113
114 Function @ref HAL_DCMI_RegisterCallback() allows to register following callbacks:
115 (+) FrameEventCallback : DCMI Frame Event.
116 (+) VsyncEventCallback : DCMI Vsync Event.
117 (+) LineEventCallback : DCMI Line Event.
118 (+) ErrorCallback : DCMI error.
119 (+) MspInitCallback : DCMI MspInit.
120 (+) MspDeInitCallback : DCMI MspDeInit.
121 This function takes as parameters the HAL peripheral handle, the callback ID
122 and a pointer to the user callback function.
123
124 Use function @ref HAL_DCMI_UnRegisterCallback() to reset a callback to the default
125 weak (surcharged) function.
126 @ref HAL_DCMI_UnRegisterCallback() takes as parameters the HAL peripheral handle,
127 and the callback ID.
128 This function allows to reset following callbacks:
129 (+) FrameEventCallback : DCMI Frame Event.
130 (+) VsyncEventCallback : DCMI Vsync Event.
131 (+) LineEventCallback : DCMI Line Event.
132 (+) ErrorCallback : DCMI error.
133 (+) MspInitCallback : DCMI MspInit.
134 (+) MspDeInitCallback : DCMI MspDeInit.
135
136 By default, after the @ref HAL_DCMI_Init and if the state is HAL_DCMI_STATE_RESET
137 all callbacks are reset to the corresponding legacy weak (surcharged) functions:
138 examples @ref FrameEventCallback(), @ref HAL_DCMI_ErrorCallback().
139 Exception done for MspInit and MspDeInit callbacks that are respectively
140 reset to the legacy weak (surcharged) functions in the @ref HAL_DCMI_Init
141 and @ref HAL_DCMI_DeInit only when these callbacks are null (not registered beforehand).
142 If not, MspInit or MspDeInit are not null, the @ref HAL_DCMI_Init and @ref HAL_DCMI_DeInit
143 keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
144
145 Callbacks can be registered/unregistered in READY state only.
146 Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
147 in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
148 during the Init/DeInit.
149 In that case first register the MspInit/MspDeInit user callbacks
150 using @ref HAL_DCMI_RegisterCallback before calling @ref HAL_DCMI_DeInit
151 or @ref HAL_DCMI_Init function.
152
153 When the compilation define USE_HAL_DCMI_REGISTER_CALLBACKS is set to 0 or
154 not defined, the callback registering feature is not available
155 and weak (surcharged) callbacks are used.
156
157 @endverbatim
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 through 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 through __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 /* Save initial values for continuous mode case */
543 hdcmi->XferCount_0 = hdcmi->XferCount;
544 hdcmi->XferSize_0 = hdcmi->XferSize;
545 hdcmi->pBuffPtr_0 = hdcmi->pBuffPtr;
546
547 /* DCMI DR samples in circular mode will be copied
548 at the end of the final buffer.
549 Now compute the circular buffer start address. */
550 /* Start by pointing at the final buffer */
551 hdcmi->pCircularBuffer = pData;
552 /* Update pCircularBuffer in "moving" at the end of the final
553 buffer, don't forger to convert in bytes to compute exact address */
554 hdcmi->pCircularBuffer += 4U * (((Length / circular_copy_length) - 1U) * circular_copy_length);
555
556 /* Initiate the circular DMA transfer from DCMI IP to final buffer end */
557 if ( HAL_DMA_Start_IT(hdcmi->DMA_Handle, (uint32_t)&hdcmi->Instance->DR, (uint32_t)hdcmi->pCircularBuffer, circular_copy_length) != HAL_OK)
558 {
559 /* Update error code */
560 hdcmi->ErrorCode |= HAL_DCMI_ERROR_DMA;
561
562 /* Set state back to Ready */
563 hdcmi->State = HAL_DCMI_STATE_READY;
564
565 /* Process Unlocked */
566 __HAL_UNLOCK(hdcmi);
567
568 return HAL_ERROR;
569 }
570 }
571
572 /* Enable Capture */
573 SET_BIT(hdcmi->Instance->CR, DCMI_CR_CAPTURE);
574
575 /* Release Lock */
576 __HAL_UNLOCK(hdcmi);
577
578 /* Return function status */
579 return HAL_OK;
580 }
581
582 /**
583 * @brief Disable DCMI capture in DMA mode.
584 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
585 * the configuration information for DCMI.
586 * @retval HAL status
587 */
HAL_DCMI_Stop(DCMI_HandleTypeDef * hdcmi)588 HAL_StatusTypeDef HAL_DCMI_Stop(DCMI_HandleTypeDef* hdcmi)
589 {
590 uint32_t tickstart;
591 HAL_StatusTypeDef status = HAL_OK;
592
593 /* Process locked */
594 __HAL_LOCK(hdcmi);
595
596 /* Lock the DCMI peripheral state */
597 hdcmi->State = HAL_DCMI_STATE_BUSY;
598
599 /* Disable Capture */
600 CLEAR_BIT(hdcmi->Instance->CR, DCMI_CR_CAPTURE);
601
602 /* Get tick */
603 tickstart = HAL_GetTick();
604
605 /* Check if the DCMI capture is effectively disabled */
606 while((hdcmi->Instance->CR & DCMI_CR_CAPTURE) != 0U)
607 {
608 if((HAL_GetTick() - tickstart ) > DCMI_TIMEOUT_STOP)
609 {
610 /* Update error code */
611 hdcmi->ErrorCode |= HAL_DCMI_ERROR_TIMEOUT;
612
613 status = HAL_TIMEOUT;
614 break;
615 }
616 }
617
618 /* Disable the DMA */
619 if (HAL_DMA_Abort(hdcmi->DMA_Handle) != HAL_OK)
620 {
621 DCMI_DMAError(hdcmi->DMA_Handle);
622 }
623
624 /* Disable DCMI IP */
625 __HAL_DCMI_DISABLE(hdcmi);
626
627 /* Change DCMI state */
628 hdcmi->State = HAL_DCMI_STATE_READY;
629
630 /* Process Unlocked */
631 __HAL_UNLOCK(hdcmi);
632
633 /* Return function status */
634 return status;
635 }
636
637 /**
638 * @brief Suspend DCMI capture.
639 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
640 * the configuration information for DCMI.
641 * @retval HAL status
642 */
HAL_DCMI_Suspend(DCMI_HandleTypeDef * hdcmi)643 HAL_StatusTypeDef HAL_DCMI_Suspend(DCMI_HandleTypeDef* hdcmi)
644 {
645 uint32_t tickstart;
646
647 /* Process locked */
648 __HAL_LOCK(hdcmi);
649
650 if(hdcmi->State == HAL_DCMI_STATE_BUSY)
651 {
652 /* Change DCMI state */
653 hdcmi->State = HAL_DCMI_STATE_SUSPENDED;
654
655 /* Disable Capture */
656 CLEAR_BIT(hdcmi->Instance->CR, DCMI_CR_CAPTURE);
657
658 /* Get tick */
659 tickstart = HAL_GetTick();
660
661 /* Check if the DCMI capture is effectively disabled */
662 while((hdcmi->Instance->CR & DCMI_CR_CAPTURE) != 0U)
663 {
664 if((HAL_GetTick() - tickstart ) > DCMI_TIMEOUT_STOP)
665 {
666 /* Update error code */
667 hdcmi->ErrorCode |= HAL_DCMI_ERROR_TIMEOUT;
668
669 /* Change DCMI state */
670 hdcmi->State = HAL_DCMI_STATE_READY;
671
672 /* Process Unlocked */
673 __HAL_UNLOCK(hdcmi);
674
675 return HAL_TIMEOUT;
676 }
677 }
678 }
679
680 /* Process Unlocked */
681 __HAL_UNLOCK(hdcmi);
682
683 /* Return function status */
684 return HAL_OK;
685 }
686
687 /**
688 * @brief Resume DCMI capture.
689 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
690 * the configuration information for DCMI.
691 * @retval HAL status
692 */
HAL_DCMI_Resume(DCMI_HandleTypeDef * hdcmi)693 HAL_StatusTypeDef HAL_DCMI_Resume(DCMI_HandleTypeDef* hdcmi)
694 {
695 /* Process locked */
696 __HAL_LOCK(hdcmi);
697
698 if(hdcmi->State == HAL_DCMI_STATE_SUSPENDED)
699 {
700 /* Change DCMI state */
701 hdcmi->State = HAL_DCMI_STATE_BUSY;
702
703 /* Enable Capture */
704 SET_BIT(hdcmi->Instance->CR, DCMI_CR_CAPTURE);
705 }
706
707 /* Process Unlocked */
708 __HAL_UNLOCK(hdcmi);
709
710 return HAL_OK;
711 }
712
713 /**
714 * @brief Handle DCMI interrupt request.
715 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
716 * the configuration information for the DCMI.
717 * @retval None
718 */
HAL_DCMI_IRQHandler(DCMI_HandleTypeDef * hdcmi)719 void HAL_DCMI_IRQHandler(DCMI_HandleTypeDef *hdcmi)
720 {
721 uint32_t misflags = READ_REG(hdcmi->Instance->MISR);
722
723 /* Synchronization error interrupt management *******************************/
724 if ((misflags & DCMI_MIS_ERR_MIS) != 0x0U)
725 {
726 /* Clear the Synchronization error flag */
727 __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_ERRRI);
728
729 /* Update error code */
730 hdcmi->ErrorCode |= HAL_DCMI_ERROR_SYNC;
731 }
732
733 /* Overflow interrupt management ********************************************/
734 if ((misflags & DCMI_MIS_OVR_MIS) != 0x0U)
735 {
736 /* Clear the Overflow flag */
737 __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_OVRRI);
738
739 /* Update error code */
740 hdcmi->ErrorCode |= HAL_DCMI_ERROR_OVR;
741 }
742
743 if (hdcmi->ErrorCode != HAL_DCMI_ERROR_NONE)
744 {
745 /* Change DCMI state */
746 hdcmi->State = HAL_DCMI_STATE_READY;
747
748 /* Set the overflow callback */
749 hdcmi->DMA_Handle->XferAbortCallback = DCMI_DMAError;
750
751 /* Abort the DMA Transfer */
752 if (HAL_DMA_Abort_IT(hdcmi->DMA_Handle) != HAL_OK)
753 {
754 DCMI_DMAError(hdcmi->DMA_Handle);
755 }
756 }
757
758 /* Line Interrupt management ************************************************/
759 if ((misflags & DCMI_MIS_LINE_MIS) != 0x0U)
760 {
761 /* Clear the Line interrupt flag */
762 __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_LINERI);
763
764 /* Line interrupt Event Callback */
765 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
766 /*Call registered DCMI line event callback*/
767 hdcmi->LineEventCallback(hdcmi);
768 #else
769 HAL_DCMI_LineEventCallback(hdcmi);
770 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
771 }
772
773 /* VSYNC interrupt management ***********************************************/
774 if ((misflags & DCMI_MIS_VSYNC_MIS) != 0x0U)
775 {
776 /* Clear the VSYNC flag */
777 __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_VSYNCRI);
778
779 /* VSYNC Event Callback */
780 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
781 /*Call registered DCMI vsync event callback*/
782 hdcmi->VsyncEventCallback(hdcmi);
783 #else
784 HAL_DCMI_VsyncEventCallback(hdcmi);
785 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
786 }
787
788 /* End of Frame interrupt management ****************************************/
789 if ((misflags & DCMI_MIS_FRAME_MIS) != 0x0U)
790 {
791 /* Disable the Line interrupt when using snapshot mode */
792 if ((hdcmi->Instance->CR & DCMI_CR_CM) == DCMI_MODE_SNAPSHOT)
793 {
794 __HAL_DCMI_DISABLE_IT(hdcmi, DCMI_IT_LINE|DCMI_IT_VSYNC|DCMI_IT_ERR|DCMI_IT_OVR);
795 /* Change the DCMI state */
796 hdcmi->State = HAL_DCMI_STATE_READY;
797 }
798
799 /* Clear the End of Frame flag */
800 __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_FRAMERI);
801
802 /* Frame Event Callback */
803 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
804 /*Call registered DCMI frame event callback*/
805 hdcmi->FrameEventCallback(hdcmi);
806 #else
807 HAL_DCMI_FrameEventCallback(hdcmi);
808 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
809 }
810 }
811
812 /**
813 * @brief Error DCMI callback.
814 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
815 * the configuration information for DCMI.
816 * @retval None
817 */
HAL_DCMI_ErrorCallback(DCMI_HandleTypeDef * hdcmi)818 __weak void HAL_DCMI_ErrorCallback(DCMI_HandleTypeDef *hdcmi)
819 {
820 /* Prevent unused argument(s) compilation warning */
821 UNUSED(hdcmi);
822
823 /* NOTE : This function should not be modified; when the callback is needed,
824 the HAL_DCMI_ErrorCallback() callback can be implemented in the user file.
825 */
826 }
827
828 /**
829 * @brief Line Event callback.
830 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
831 * the configuration information for DCMI.
832 * @retval None
833 */
HAL_DCMI_LineEventCallback(DCMI_HandleTypeDef * hdcmi)834 __weak void HAL_DCMI_LineEventCallback(DCMI_HandleTypeDef *hdcmi)
835 {
836 /* Prevent unused argument(s) compilation warning */
837 UNUSED(hdcmi);
838
839 /* NOTE : This function should not be modified; when the callback is needed,
840 the HAL_DCMI_LineEventCallback() callback can be implemented in the user file.
841 */
842 }
843
844 /**
845 * @brief VSYNC Event callback.
846 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
847 * the configuration information for DCMI.
848 * @retval None
849 */
HAL_DCMI_VsyncEventCallback(DCMI_HandleTypeDef * hdcmi)850 __weak void HAL_DCMI_VsyncEventCallback(DCMI_HandleTypeDef *hdcmi)
851 {
852 /* Prevent unused argument(s) compilation warning */
853 UNUSED(hdcmi);
854
855 /* NOTE : This function should not be modified; when the callback is needed,
856 the HAL_DCMI_VsyncEventCallback() callback can be implemented in the user file.
857 */
858 }
859
860 /**
861 * @brief Frame Event callback.
862 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
863 * the configuration information for DCMI.
864 * @retval None
865 */
HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef * hdcmi)866 __weak void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi)
867 {
868 /* Prevent unused argument(s) compilation warning */
869 UNUSED(hdcmi);
870
871 /* NOTE : This function should not be modified; when the callback is needed,
872 the HAL_DCMI_FrameEventCallback() callback can be implemented in the user file.
873 */
874 }
875 /**
876 * @}
877 */
878
879
880 /** @defgroup DCMI_Exported_Functions_Group3 Peripheral Control functions
881 * @brief Peripheral Control functions
882 *
883 @verbatim
884 ===============================================================================
885 ##### Peripheral Control functions #####
886 ===============================================================================
887 [..] This section provides functions allowing to:
888 (+) Configure the crop feature.
889 (+) Enable/Disable the crop feature.
890 (+) Configure the synchronization delimiters unmasks.
891 (+) Enable/Disable user-specified DCMI interrupts.
892
893 @endverbatim
894 * @{
895 */
896
897 /**
898 * @brief Configure the DCMI crop window coordinates.
899 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
900 * the configuration information for DCMI.
901 * @param X0 DCMI window crop window X offset (number of pixels clocks to count before the capture).
902 * @param Y0 DCMI window crop window Y offset (image capture starts with this line number, previous
903 * line data are ignored).
904 * @param XSize DCMI crop window horizontal size (in number of pixels per line).
905 * @param YSize DCMI crop window vertical size (in lines count).
906 * @note For all the parameters, the actual value is the input data + 1 (e.g. YSize = 0x0 means 1 line,
907 * YSize = 0x1 means 2 lines, ...)
908 * @retval HAL status
909 */
HAL_DCMI_ConfigCrop(DCMI_HandleTypeDef * hdcmi,uint32_t X0,uint32_t Y0,uint32_t XSize,uint32_t YSize)910 HAL_StatusTypeDef HAL_DCMI_ConfigCrop(DCMI_HandleTypeDef *hdcmi, uint32_t X0, uint32_t Y0, uint32_t XSize, uint32_t YSize)
911 {
912 /* Check the parameters */
913 assert_param(IS_DCMI_WINDOW_COORDINATE(X0));
914 assert_param(IS_DCMI_WINDOW_HEIGHT(Y0));
915 assert_param(IS_DCMI_WINDOW_COORDINATE(XSize));
916 assert_param(IS_DCMI_WINDOW_COORDINATE(YSize));
917
918 /* Process Locked */
919 __HAL_LOCK(hdcmi);
920
921 /* Lock the DCMI peripheral state */
922 hdcmi->State = HAL_DCMI_STATE_BUSY;
923
924 /* Configure CROP */
925 MODIFY_REG(hdcmi->Instance->CWSIZER, (DCMI_CWSIZE_VLINE|DCMI_CWSIZE_CAPCNT), (XSize | (YSize << DCMI_CWSIZE_VLINE_Pos)));
926 MODIFY_REG(hdcmi->Instance->CWSTRTR, (DCMI_CWSTRT_VST|DCMI_CWSTRT_HOFFCNT), (X0 | (Y0 << DCMI_CWSTRT_VST_Pos)));
927
928 /* Initialize the DCMI state*/
929 hdcmi->State = HAL_DCMI_STATE_READY;
930
931 /* Process Unlocked */
932 __HAL_UNLOCK(hdcmi);
933
934 return HAL_OK;
935 }
936
937 /**
938 * @brief Disable the crop feature.
939 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
940 * the configuration information for DCMI.
941 * @retval HAL status
942 */
HAL_DCMI_DisableCrop(DCMI_HandleTypeDef * hdcmi)943 HAL_StatusTypeDef HAL_DCMI_DisableCrop(DCMI_HandleTypeDef *hdcmi)
944 {
945 /* Process Locked */
946 __HAL_LOCK(hdcmi);
947
948 /* Lock the DCMI peripheral state */
949 hdcmi->State = HAL_DCMI_STATE_BUSY;
950
951 /* Disable DCMI Crop feature */
952 CLEAR_BIT(hdcmi->Instance->CR, DCMI_CR_CROP);
953
954 /* Change the DCMI state*/
955 hdcmi->State = HAL_DCMI_STATE_READY;
956
957 /* Process Unlocked */
958 __HAL_UNLOCK(hdcmi);
959
960 return HAL_OK;
961 }
962
963 /**
964 * @brief Enable the crop feature.
965 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
966 * the configuration information for DCMI.
967 * @retval HAL status
968 */
HAL_DCMI_EnableCrop(DCMI_HandleTypeDef * hdcmi)969 HAL_StatusTypeDef HAL_DCMI_EnableCrop(DCMI_HandleTypeDef *hdcmi)
970 {
971 /* Process Locked */
972 __HAL_LOCK(hdcmi);
973
974 /* Lock the DCMI peripheral state */
975 hdcmi->State = HAL_DCMI_STATE_BUSY;
976
977 /* Enable DCMI Crop feature */
978 SET_BIT(hdcmi->Instance->CR, DCMI_CR_CROP);
979
980 /* Change the DCMI state*/
981 hdcmi->State = HAL_DCMI_STATE_READY;
982
983 /* Process Unlocked */
984 __HAL_UNLOCK(hdcmi);
985
986 return HAL_OK;
987 }
988
989 /**
990 * @brief Set embedded synchronization delimiters unmasks.
991 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
992 * the configuration information for DCMI.
993 * @param SyncUnmask pointer to a DCMI_SyncUnmaskTypeDef structure that contains
994 * the embedded synchronization delimiters unmasks.
995 * @retval HAL status
996 */
HAL_DCMI_ConfigSyncUnmask(DCMI_HandleTypeDef * hdcmi,DCMI_SyncUnmaskTypeDef * SyncUnmask)997 HAL_StatusTypeDef HAL_DCMI_ConfigSyncUnmask(DCMI_HandleTypeDef *hdcmi, DCMI_SyncUnmaskTypeDef *SyncUnmask)
998 {
999 /* Process Locked */
1000 __HAL_LOCK(hdcmi);
1001
1002 /* Lock the DCMI peripheral state */
1003 hdcmi->State = HAL_DCMI_STATE_BUSY;
1004
1005 /* Write DCMI embedded synchronization unmask register */
1006 hdcmi->Instance->ESUR = (((uint32_t)SyncUnmask->FrameStartUnmask) |\
1007 ((uint32_t)SyncUnmask->LineStartUnmask << DCMI_ESUR_LSU_Pos)|\
1008 ((uint32_t)SyncUnmask->LineEndUnmask << DCMI_ESUR_LEU_Pos)|\
1009 ((uint32_t)SyncUnmask->FrameEndUnmask << DCMI_ESUR_FEU_Pos));
1010
1011 /* Change the DCMI state*/
1012 hdcmi->State = HAL_DCMI_STATE_READY;
1013
1014 /* Process Unlocked */
1015 __HAL_UNLOCK(hdcmi);
1016
1017 return HAL_OK;
1018 }
1019
1020
1021
1022
1023 /**
1024 * @}
1025 */
1026
1027 /** @defgroup DCMI_Exported_Functions_Group4 Peripheral State functions
1028 * @brief Peripheral State functions
1029 *
1030 @verbatim
1031 ===============================================================================
1032 ##### Peripheral State and Errors functions #####
1033 ===============================================================================
1034 [..]
1035 This subsection provides functions allowing to
1036 (+) Check the DCMI state.
1037 (+) Get the specific DCMI error flag.
1038
1039 @endverbatim
1040 * @{
1041 */
1042
1043 /**
1044 * @brief Return the DCMI state.
1045 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
1046 * the configuration information for DCMI.
1047 * @retval HAL state
1048 */
HAL_DCMI_GetState(DCMI_HandleTypeDef * hdcmi)1049 HAL_DCMI_StateTypeDef HAL_DCMI_GetState(DCMI_HandleTypeDef *hdcmi)
1050 {
1051 return hdcmi->State;
1052 }
1053
1054 /**
1055 * @brief Return the DCMI error code.
1056 * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains
1057 * the configuration information for DCMI.
1058 * @retval DCMI Error Code
1059 */
HAL_DCMI_GetError(DCMI_HandleTypeDef * hdcmi)1060 uint32_t HAL_DCMI_GetError(DCMI_HandleTypeDef *hdcmi)
1061 {
1062 return hdcmi->ErrorCode;
1063 }
1064
1065 /**
1066 * @}
1067 */
1068
1069 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
1070 /**
1071 * @brief DCMI Callback registering
1072 * @param hdcmi dcmi handle
1073 * @param CallbackID dcmi Callback ID
1074 * @param pCallback pointer to dcmi Callback function
1075 * @retval status
1076 */
HAL_DCMI_RegisterCallback(DCMI_HandleTypeDef * hdcmi,HAL_DCMI_CallbackIDTypeDef CallbackID,pDCMI_CallbackTypeDef pCallback)1077 HAL_StatusTypeDef HAL_DCMI_RegisterCallback(DCMI_HandleTypeDef *hdcmi, HAL_DCMI_CallbackIDTypeDef CallbackID, pDCMI_CallbackTypeDef pCallback)
1078 {
1079 HAL_StatusTypeDef status = HAL_OK;
1080
1081 if(pCallback == NULL)
1082 {
1083 /* update the error code */
1084 hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
1085 /* update return status */
1086 status = HAL_ERROR;
1087 }
1088 else
1089 {
1090 if(hdcmi->State == HAL_DCMI_STATE_READY)
1091 {
1092 switch (CallbackID)
1093 {
1094 case HAL_DCMI_FRAME_EVENT_CB_ID :
1095 hdcmi->FrameEventCallback = pCallback;
1096 break;
1097
1098 case HAL_DCMI_VSYNC_EVENT_CB_ID :
1099 hdcmi->VsyncEventCallback = pCallback;
1100 break;
1101
1102 case HAL_DCMI_LINE_EVENT_CB_ID :
1103 hdcmi->LineEventCallback = pCallback;
1104 break;
1105
1106 case HAL_DCMI_ERROR_CB_ID :
1107 hdcmi->ErrorCallback = pCallback;
1108 break;
1109
1110 case HAL_DCMI_MSPINIT_CB_ID :
1111 hdcmi->MspInitCallback = pCallback;
1112 break;
1113
1114 case HAL_DCMI_MSPDEINIT_CB_ID :
1115 hdcmi->MspDeInitCallback = pCallback;
1116 break;
1117
1118 default :
1119 /* Return error status */
1120 status = HAL_ERROR;
1121 break;
1122 }
1123 }
1124 else if(hdcmi->State == HAL_DCMI_STATE_RESET)
1125 {
1126 switch (CallbackID)
1127 {
1128 case HAL_DCMI_MSPINIT_CB_ID :
1129 hdcmi->MspInitCallback = pCallback;
1130 break;
1131
1132 case HAL_DCMI_MSPDEINIT_CB_ID :
1133 hdcmi->MspDeInitCallback = pCallback;
1134 break;
1135
1136 default :
1137 /* update the error code */
1138 hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
1139 /* update return status */
1140 status = HAL_ERROR;
1141 break;
1142 }
1143 }
1144 else
1145 {
1146 /* update the error code */
1147 hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
1148 /* update return status */
1149 status = HAL_ERROR;
1150 }
1151 }
1152
1153 return status;
1154 }
1155
1156 /**
1157 * @brief DCMI Callback Unregistering
1158 * @param hdcmi dcmi handle
1159 * @param CallbackID dcmi Callback ID
1160 * @retval status
1161 */
HAL_DCMI_UnRegisterCallback(DCMI_HandleTypeDef * hdcmi,HAL_DCMI_CallbackIDTypeDef CallbackID)1162 HAL_StatusTypeDef HAL_DCMI_UnRegisterCallback(DCMI_HandleTypeDef *hdcmi, HAL_DCMI_CallbackIDTypeDef CallbackID)
1163 {
1164 HAL_StatusTypeDef status = HAL_OK;
1165
1166 if(hdcmi->State == HAL_DCMI_STATE_READY)
1167 {
1168 switch (CallbackID)
1169 {
1170 case HAL_DCMI_FRAME_EVENT_CB_ID :
1171 hdcmi->FrameEventCallback = HAL_DCMI_FrameEventCallback; /* Legacy weak FrameEventCallback */
1172 break;
1173
1174 case HAL_DCMI_VSYNC_EVENT_CB_ID :
1175 hdcmi->VsyncEventCallback = HAL_DCMI_VsyncEventCallback; /* Legacy weak VsyncEventCallback */
1176 break;
1177
1178 case HAL_DCMI_LINE_EVENT_CB_ID :
1179 hdcmi->LineEventCallback = HAL_DCMI_LineEventCallback; /* Legacy weak LineEventCallback */
1180 break;
1181
1182 case HAL_DCMI_ERROR_CB_ID :
1183 hdcmi->ErrorCallback = HAL_DCMI_ErrorCallback; /* Legacy weak ErrorCallback */
1184 break;
1185
1186 case HAL_DCMI_MSPINIT_CB_ID :
1187 hdcmi->MspInitCallback = HAL_DCMI_MspInit;
1188 break;
1189
1190 case HAL_DCMI_MSPDEINIT_CB_ID :
1191 hdcmi->MspDeInitCallback = HAL_DCMI_MspDeInit;
1192 break;
1193
1194 default :
1195 /* update the error code */
1196 hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
1197 /* update return status */
1198 status = HAL_ERROR;
1199 break;
1200 }
1201 }
1202 else if(hdcmi->State == HAL_DCMI_STATE_RESET)
1203 {
1204 switch (CallbackID)
1205 {
1206 case HAL_DCMI_MSPINIT_CB_ID :
1207 hdcmi->MspInitCallback = HAL_DCMI_MspInit;
1208 break;
1209
1210 case HAL_DCMI_MSPDEINIT_CB_ID :
1211 hdcmi->MspDeInitCallback = HAL_DCMI_MspDeInit;
1212 break;
1213
1214 default :
1215 /* update the error code */
1216 hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
1217 /* update return status */
1218 status = HAL_ERROR;
1219 break;
1220 }
1221 }
1222 else
1223 {
1224 /* update the error code */
1225 hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
1226 /* update return status */
1227 status = HAL_ERROR;
1228 }
1229
1230 return status;
1231 }
1232 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
1233
1234 /**
1235 * @}
1236 */
1237
1238 /* Private functions ---------------------------------------------------------*/
1239 /** @defgroup DCMI_Private_Functions DCMI Private Functions
1240 * @{
1241 */
1242
1243 /**
1244 * @brief DMA conversion complete callback.
1245 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
1246 * the configuration information for the specified DMA module.
1247 * @note When the size of the frame being captured by the DCMI peripheral is
1248 * larger than 0xFFFF (DMA maximum transfer length), this API initiates
1249 * another DMA transfer to copy the second half of the work buffer
1250 * associated to the DCMI handle to the final destination buffer.
1251 * @retval None
1252 */
DCMI_DMAXferCplt(DMA_HandleTypeDef * hdma)1253 static void DCMI_DMAXferCplt(DMA_HandleTypeDef *hdma)
1254 {
1255 uint32_t loop_length; /* transfer length */
1256 uint32_t * tmpBuffer_Dest;
1257 uint32_t * tmpBuffer_Orig;
1258 uint32_t temp;
1259
1260 DCMI_HandleTypeDef* hdcmi = ( DCMI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
1261
1262
1263 if(hdcmi->XferCount != 0U)
1264 {
1265 if (hdcmi->XferCount == 0xBEBE)
1266 {
1267 hdcmi->XferCount = hdcmi->XferCount_0;
1268 hdcmi->XferSize = hdcmi->XferSize_0;
1269 hdcmi->pBuffPtr = hdcmi->pBuffPtr_0;
1270 }
1271 else
1272 {
1273 /* Manage second half buffer copy in case of big transfer */
1274
1275 /* Decrement half-copies counter */
1276 hdcmi->XferCount--;
1277
1278 /* Point at DCMI final destination */
1279 tmpBuffer_Dest = (uint32_t *)hdcmi->pBuffPtr;
1280
1281 /* Point at DCMI circular buffer mid-location */
1282 tmpBuffer_Orig = (uint32_t *)hdcmi->pCircularBuffer;
1283 temp = (uint32_t) (tmpBuffer_Orig);
1284 temp += hdcmi->HalfCopyLength * 4U;
1285 tmpBuffer_Orig = (uint32_t *) temp;
1286
1287 /* copy half the buffer size */
1288 loop_length = hdcmi->HalfCopyLength;
1289
1290 /* Save next entry to write at next half DMA transfer interruption */
1291 hdcmi->pBuffPtr += (uint32_t) loop_length*4U;
1292 hdcmi->XferSize -= hdcmi->HalfCopyLength;
1293
1294 if (hdcmi->XferCount == 0)
1295 {
1296 hdcmi->XferCount = 0xBEBE;
1297 }
1298
1299
1300 /* Data copy from work buffer to final destination buffer */
1301 /* Enable the DMA Channel */
1302 if (HAL_DMA_Start_IT(hdcmi->DMAM2M_Handle, (uint32_t) tmpBuffer_Orig, (uint32_t) tmpBuffer_Dest, loop_length) != HAL_OK)
1303 {
1304 /* Update error code */
1305 hdcmi->ErrorCode |= HAL_DCMI_ERROR_DMA;
1306
1307 /* Change DCMI state */
1308 hdcmi->State = HAL_DCMI_STATE_READY;
1309
1310 /* Process Unlocked */
1311 __HAL_UNLOCK(hdcmi);
1312
1313 /* DCMI error Callback */
1314 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
1315 /*Call registered DCMI error callback*/
1316 hdcmi->ErrorCallback(hdcmi);
1317 #else
1318 HAL_DCMI_ErrorCallback(hdcmi);
1319 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
1320 }
1321 }
1322 }
1323 else
1324 {
1325 /* if End of frame IT is disabled */
1326 if((hdcmi->Instance->IER & DCMI_IT_FRAME) == 0x0U)
1327 {
1328 /* If End of Frame flag is set */
1329 if(__HAL_DCMI_GET_FLAG(hdcmi, (uint32_t)DCMI_FLAG_FRAMERI) != 0x0UL)
1330 {
1331 /* Clear the End of Frame flag */
1332 __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_FRAMERI);
1333
1334 /* When snapshot mode, disable Vsync, Error and Overrun interrupts */
1335 if((hdcmi->Instance->CR & DCMI_CR_CM) == DCMI_MODE_SNAPSHOT)
1336 {
1337 /* Disable the Vsync, Error and Overrun interrupts */
1338 __HAL_DCMI_DISABLE_IT(hdcmi, DCMI_IT_LINE | DCMI_IT_VSYNC | DCMI_IT_ERR | DCMI_IT_OVR);
1339
1340 hdcmi->State = HAL_DCMI_STATE_READY;
1341
1342 /* Process Unlocked */
1343 __HAL_UNLOCK(hdcmi);
1344 }
1345
1346 /* Frame Event Callback */
1347 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
1348 /*Call registered DCMI frame event callback*/
1349 hdcmi->FrameEventCallback(hdcmi);
1350 #else
1351 HAL_DCMI_FrameEventCallback(hdcmi);
1352 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
1353 }
1354 }
1355 }
1356 }
1357
1358
1359 /**
1360 * @brief DMA Half Transfer complete callback.
1361 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
1362 * the configuration information for the specified DMA module.
1363 * @note When the size of the frame being captured by the DCMI peripheral is
1364 * larger than 0xFFFF (DMA maximum transfer length), this API initiates
1365 * another DMA transfer to copy the first half of the work buffer
1366 * associated to the DCMI handle to the final destination buffer.
1367 * @retval None
1368 */
DCMI_DMAHalfXferCplt(DMA_HandleTypeDef * hdma)1369 static void DCMI_DMAHalfXferCplt(DMA_HandleTypeDef *hdma)
1370 {
1371 uint32_t loop_length; /* transfer length */
1372 uint32_t * tmpBuffer_Dest;
1373 uint32_t * tmpBuffer_Orig;
1374
1375 DCMI_HandleTypeDef* hdcmi = ( DCMI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
1376
1377 if(hdcmi->XferCount != 0U)
1378 {
1379 if (hdcmi->XferCount != 0xBEBE)
1380 {
1381 /* Manage first half buffer copy in case of big transfer */
1382
1383 /* Decrement half-copies counter */
1384 hdcmi->XferCount--;
1385
1386 /* Point at DCMI final destination */
1387 tmpBuffer_Dest = (uint32_t *)hdcmi->pBuffPtr;
1388
1389 /* Point at DCMI circular buffer start */
1390 tmpBuffer_Orig = (uint32_t *)hdcmi->pCircularBuffer;
1391
1392 /* copy half the buffer size */
1393 loop_length = hdcmi->HalfCopyLength;
1394
1395 /* Save next entry to write at next DMA transfer interruption */
1396 hdcmi->pBuffPtr += (uint32_t) loop_length*4U;
1397 hdcmi->XferSize -= hdcmi->HalfCopyLength;
1398
1399 /* Data copy from work buffer to final destination buffer */
1400 /* Enable the DMA Channel */
1401 if (HAL_DMA_Start_IT(hdcmi->DMAM2M_Handle, (uint32_t) tmpBuffer_Orig, (uint32_t) tmpBuffer_Dest, loop_length) != HAL_OK)
1402 {
1403 /* Update error code */
1404 hdcmi->ErrorCode |= HAL_DCMI_ERROR_DMA;
1405
1406 /* Change DCMI state */
1407 hdcmi->State = HAL_DCMI_STATE_READY;
1408
1409 /* Process Unlocked */
1410 __HAL_UNLOCK(hdcmi);
1411
1412 /* DCMI error Callback */
1413 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
1414 /*Call registered DCMI error callback*/
1415 hdcmi->ErrorCallback(hdcmi);
1416 #else
1417 HAL_DCMI_ErrorCallback(hdcmi);
1418 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
1419 }
1420 }
1421 }
1422 }
1423
1424 /**
1425 * @brief DMA error callback
1426 * @param hdma pointer to a DMA_HandleTypeDef structure that contains
1427 * the configuration information for the specified DMA module.
1428 * @retval None
1429 */
DCMI_DMAError(DMA_HandleTypeDef * hdma)1430 static void DCMI_DMAError(DMA_HandleTypeDef *hdma)
1431 {
1432 DCMI_HandleTypeDef* hdcmi = ( DCMI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
1433
1434 /* Update error code */
1435 hdcmi->ErrorCode |= HAL_DCMI_ERROR_DMA;
1436
1437 /* Change DCMI state */
1438 hdcmi->State = HAL_DCMI_STATE_READY;
1439
1440 /* DCMI error Callback */
1441 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
1442 /*Call registered DCMI error callback*/
1443 hdcmi->ErrorCallback(hdcmi);
1444 #else
1445 HAL_DCMI_ErrorCallback(hdcmi);
1446 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
1447 }
1448
1449 /**
1450 * @brief Sub-buffers transfer size computation.
1451 * @note In the case of a frame size larger than the maximum DMA transfer length (0xFFFF),
1452 * the transfer from DCMI DR register to the final output buffer is carried out by a sequence
1453 * of intermediate sub-copies to temporary buffers of size less than 0xFFFF.
1454 * To optimize the number of DMA transfers, the API computes the temporary buffer
1455 * size so that the latter is an even number less than 0xFFFF, that divides the final
1456 * buffer size and is as high as possible. The API implements a sub-optimum solution for
1457 * complexity's sake.
1458 * @note InputSize MUST be even.
1459 * @param InputSize full buffer size (in 32-bit words)
1460 * @retval Transfer size (in 32-bit words)
1461 */
DCMI_TransferSize(uint32_t InputSize)1462 static uint32_t DCMI_TransferSize(uint32_t InputSize)
1463 {
1464 uint32_t j = 1;
1465 uint32_t temp = InputSize;
1466 uint32_t aPrime[NPRIME] = {0};
1467 uint32_t output = 2; /* Want a result which is an even number */
1468 static const uint32_t PrimeArray[NPRIME] = { 1UL, 2UL, 3UL, 5UL,
1469 7UL, 11UL, 13UL, 17UL,
1470 19UL, 23UL, 29UL, 31UL,
1471 37UL, 41UL, 43UL, 47UL};
1472
1473
1474 /* Develop InputSize in product of prime numbers */
1475
1476 while (j < NPRIME)
1477 {
1478 if (temp < PrimeArray[j])
1479 {
1480 break;
1481 }
1482 while ((temp % PrimeArray[j]) == 0U)
1483 {
1484 aPrime[j]++;
1485 temp /= PrimeArray[j];
1486 }
1487 j++;
1488 }
1489
1490 /* Search for the biggest even divisor less or equal to 0xFFFE = 65534 */
1491 aPrime[1] -= 1U; /* output is initialized to 2, so don't count divider 2 twice */
1492
1493 /* The algorithm below yields a sub-optimal solution
1494 but in an acceptable time. */
1495 j = NPRIME-1U;
1496 while ((j > 0U) && (output <= 0xFFFEU))
1497 {
1498 while (aPrime[j] > 0U)
1499 {
1500 if ((output * PrimeArray[j]) > 0xFFFEU)
1501 {
1502 break;
1503 }
1504 else
1505 {
1506 output *= PrimeArray[j];
1507 aPrime[j]--;
1508 }
1509 }
1510 j--;
1511 }
1512
1513
1514
1515 return output;
1516 }
1517
1518
1519 /**
1520 * @}
1521 */
1522
1523 /**
1524 * @}
1525 */
1526
1527 /**
1528 * @}
1529 */
1530
1531 #endif /* DCMI */
1532 #endif /* HAL_DCMI_MODULE_ENABLED */
1533