1 /**
2   ******************************************************************************
3   * @file    stm32u5xx_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) 2021 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 image
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 to configure and enable
33       the DCMI to capture images.
34 
35     (#) Program the required configuration through following parameters:
36         horizontal and vertical polarity, pixel clock polarity, Capture Rate,
37         Synchronization Mode, code of the frame delimiter and data width
38         using HAL_DCMI_Init() function.
39 
40     (#) Configure the selected DMA stream to transfer Data from DCMI DR
41         register to the destination memory buffer.
42 
43     (#) Program the required configuration through following parameters:
44         DCMI mode, destination memory Buffer address and the data length
45         and enable capture using HAL_DCMI_Start_DMA() function.
46 
47     (#) Optionally, configure and Enable the CROP feature to select a rectangular
48         window from the received image using HAL_DCMI_ConfigCrop()
49         and HAL_DCMI_EnableCrop() functions
50 
51     (#) The capture can be stopped using HAL_DCMI_Stop() function.
52 
53     (#) To control DCMI state you can use the function HAL_DCMI_GetState().
54 
55      *** DCMI HAL driver macros list ***
56      =============================================
57      [..]
58        Below the list of most used macros in DCMI HAL driver.
59 
60       (+) __HAL_DCMI_ENABLE: Enable the DCMI peripheral.
61       (+) __HAL_DCMI_DISABLE: Disable the DCMI peripheral.
62       (+) __HAL_DCMI_GET_FLAG: Get the DCMI pending flags.
63       (+) __HAL_DCMI_CLEAR_FLAG: Clear the DCMI pending flags.
64       (+) __HAL_DCMI_ENABLE_IT: Enable the specified DCMI interrupts.
65       (+) __HAL_DCMI_DISABLE_IT: Disable the specified DCMI interrupts.
66       (+) __HAL_DCMI_GET_IT_SOURCE: Check whether the specified DCMI interrupt has occurred or not.
67 
68      [..]
69        (@) You can refer to the DCMI HAL driver header file for more useful macros
70 
71     *** Callback registration ***
72     =============================
73 
74     The compilation define USE_HAL_DCMI_REGISTER_CALLBACKS when set to 1
75     allows the user to configure dynamically the driver callbacks.
76     Use functions HAL_DCMI_RegisterCallback() to register a user callback.
77 
78     Function HAL_DCMI_RegisterCallback() allows to register following callbacks:
79       (+) FrameEventCallback : callback for DCMI Frame Event.
80       (+) VsyncEventCallback : callback for DCMI Vsync Event.
81       (+) LineEventCallback  : callback for DCMI Line Event.
82       (+) ErrorCallback      : callback for DCMI error detection.
83       (+) MspInitCallback    : callback for DCMI MspInit.
84       (+) MspDeInitCallback  : callback for DCMI MspDeInit.
85     This function takes as parameters the HAL peripheral handle, the Callback ID
86     and a pointer to the user callback function.
87 
88     Use function HAL_DCMI_UnRegisterCallback() to reset a callback to the default
89     weak (surcharged) function.
90     HAL_DCMI_UnRegisterCallback() takes as parameters the HAL peripheral handle,
91     and the callback ID.
92     This function allows to reset following callbacks:
93       (+) FrameEventCallback : callback for DCMI Frame Event.
94       (+) VsyncEventCallback : callback for DCMI Vsync Event.
95       (+) LineEventCallback  : callback for DCMI Line Event.
96       (+) ErrorCallback      : callback for DCMI error.
97       (+) MspInitCallback    : callback for DCMI MspInit.
98       (+) MspDeInitCallback  : callback for DCMI MspDeInit.
99 
100     By default, after the HAL_DCMI_Init and if the state is HAL_DCMI_STATE_RESET
101     all callbacks are reset to the corresponding legacy weak (surcharged) functions:
102     examples FrameEventCallback(), HAL_DCMI_ErrorCallback().
103     Exception done for MspInit and MspDeInit callbacks that are respectively
104     reset to the legacy weak (surcharged) functions in the HAL_DCMI_Init
105     and HAL_DCMI_DeInit only when these callbacks are null (not registered beforehand).
106     If not, MspInit or MspDeInit are not null, the HAL_DCMI_Init and HAL_DCMI_DeInit
107     keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
108 
109     Callbacks can be registered/unregistered in READY state only.
110     Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
111     in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
112     during the Init/DeInit.
113     In that case first register the MspInit/MspDeInit user callbacks
114     using HAL_DCMI_RegisterCallback before calling HAL_DCMI_DeInit
115     or HAL_DCMI_Init function.
116 
117     When the compilation define USE_HAL_DCMI_REGISTER_CALLBACKS is set to 0 or
118     not defined, the callback registering feature is not available
119     and weak (surcharged) callbacks are used.
120 
121   @endverbatim
122   ******************************************************************************
123   */
124 
125 /* Includes ------------------------------------------------------------------*/
126 #include "stm32u5xx_hal.h"
127 #ifdef HAL_DCMI_MODULE_ENABLED
128 #if defined (DCMI)
129 
130 /** @addtogroup STM32U5xx_HAL_Driver
131   * @{
132   */
133 /** @defgroup DCMI DCMI
134   * @brief DCMI HAL module driver
135   * @{
136   */
137 
138 /* Private typedef -----------------------------------------------------------*/
139 /* Private define ------------------------------------------------------------*/
140 /** @defgroup DCMI_Private_Constants DCMI Private Constants
141   * @{
142   */
143 
144 /** @defgroup DCMI_Stop_TimeOut DCMI Stop Time Out
145   * @{
146   */
147 #define HAL_TIMEOUT_DCMI_STOP    ((uint32_t)1000) /* Set timeout to 1s  */
148 /**
149   * @}
150   */
151 
152 /**
153   * @}
154   */
155 /* Private macro -------------------------------------------------------------*/
156 /* Private variables ---------------------------------------------------------*/
157 /* Private function prototypes -----------------------------------------------*/
158 /** @addtogroup DCMI_Private_Functions DCMI Private Functions
159   * @{
160   */
161 static void       DCMI_DMAXferCplt(DMA_HandleTypeDef *hdma);
162 static void       DCMI_DMAError(DMA_HandleTypeDef *hdma);
163 
164 /**
165   * @}
166   */
167 /* Exported functions --------------------------------------------------------*/
168 
169 /** @defgroup DCMI_Exported_Functions DCMI Exported Functions
170   * @{
171   */
172 
173 /** @defgroup DCMI_Exported_Functions_Group1 Initialization and Configuration functions
174   *  @brief   Initialization and Configuration functions
175   *
176 @verbatim
177  ===============================================================================
178                 ##### Initialization and Configuration functions #####
179  ===============================================================================
180     [..]  This section provides functions allowing to:
181       (+) Initialize and configure the DCMI
182       (+) De-initialize the DCMI
183 
184 @endverbatim
185   * @{
186   */
187 
188 /**
189   * @brief  Initializes the DCMI according to the specified
190   *         parameters in the DCMI_InitTypeDef and create the associated handle.
191   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
192   *                the configuration information for DCMI.
193   * @retval HAL status
194   */
HAL_DCMI_Init(DCMI_HandleTypeDef * hdcmi)195 HAL_StatusTypeDef HAL_DCMI_Init(DCMI_HandleTypeDef *hdcmi)
196 {
197   /* Check the DCMI peripheral state */
198   if (hdcmi == NULL)
199   {
200     return HAL_ERROR;
201   }
202 
203   /* Check function parameters */
204   assert_param(IS_DCMI_ALL_INSTANCE(hdcmi->Instance));
205   assert_param(IS_DCMI_PCKPOLARITY(hdcmi->Init.PCKPolarity));
206   assert_param(IS_DCMI_VSPOLARITY(hdcmi->Init.VSPolarity));
207   assert_param(IS_DCMI_HSPOLARITY(hdcmi->Init.HSPolarity));
208   assert_param(IS_DCMI_SYNCHRO(hdcmi->Init.SynchroMode));
209   assert_param(IS_DCMI_CAPTURE_RATE(hdcmi->Init.CaptureRate));
210   assert_param(IS_DCMI_EXTENDED_DATA(hdcmi->Init.ExtendedDataMode));
211   assert_param(IS_DCMI_MODE_JPEG(hdcmi->Init.JPEGMode));
212 
213   assert_param(IS_DCMI_BYTE_SELECT_MODE(hdcmi->Init.ByteSelectMode));
214   assert_param(IS_DCMI_BYTE_SELECT_START(hdcmi->Init.ByteSelectStart));
215   assert_param(IS_DCMI_LINE_SELECT_MODE(hdcmi->Init.LineSelectMode));
216   assert_param(IS_DCMI_LINE_SELECT_START(hdcmi->Init.LineSelectStart));
217 
218   if (hdcmi->State == HAL_DCMI_STATE_RESET)
219   {
220     /* Init the DCMI Callback settings */
221 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
222     /* Reset callback pointers to the weak predefined callbacks */
223     hdcmi->FrameEventCallback = HAL_DCMI_FrameEventCallback; /* Legacy weak FrameEventCallback  */
224     hdcmi->VsyncEventCallback = HAL_DCMI_VsyncEventCallback; /* Legacy weak VsyncEventCallback  */
225     hdcmi->LineEventCallback  = HAL_DCMI_LineEventCallback;  /* Legacy weak LineEventCallback   */
226     hdcmi->ErrorCallback      = HAL_DCMI_ErrorCallback;      /* Legacy weak ErrorCallback       */
227 
228     if (hdcmi->MspInitCallback == NULL)
229     {
230       /* Legacy weak MspInit Callback        */
231       hdcmi->MspInitCallback = HAL_DCMI_MspInit;
232     }
233     /* Initialize the low level hardware (MSP) */
234     hdcmi->MspInitCallback(hdcmi);
235 #else
236     /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
237     HAL_DCMI_MspInit(hdcmi);
238 #endif /* (USE_HAL_DCMI_REGISTER_CALLBACKS) */
239   }
240 
241   /* Change the DCMI state */
242   hdcmi->State = HAL_DCMI_STATE_BUSY;
243 
244   if (hdcmi->Init.ExtendedDataMode != DCMI_EXTEND_DATA_8B)
245   {
246     /* Byte select mode must be programmed to the reset value if the extended mode
247     is not set to 8-bit data capture on every pixel clock */
248     hdcmi->Init.ByteSelectMode = DCMI_BSM_ALL;
249   }
250   /* Configures the HS, VS, DE and PC polarity */
251   hdcmi->Instance->CR &= ~(DCMI_CR_PCKPOL | DCMI_CR_HSPOL  | DCMI_CR_VSPOL  | DCMI_CR_EDM_0 | \
252                            DCMI_CR_EDM_1  | DCMI_CR_FCRC_0 | DCMI_CR_FCRC_1 | DCMI_CR_JPEG  | \
253                            DCMI_CR_ESS | DCMI_CR_BSM_0 | DCMI_CR_BSM_1 | DCMI_CR_OEBS | \
254                            DCMI_CR_LSM | DCMI_CR_OELS);
255 
256   hdcmi->Instance->CR |= (uint32_t)(hdcmi->Init.SynchroMode | hdcmi->Init.CaptureRate | \
257                                     hdcmi->Init.VSPolarity  | hdcmi->Init.HSPolarity  | \
258                                     hdcmi->Init.PCKPolarity | hdcmi->Init.ExtendedDataMode | \
259                                     hdcmi->Init.JPEGMode | hdcmi->Init.ByteSelectMode | \
260                                     hdcmi->Init.ByteSelectStart | hdcmi->Init.LineSelectMode | \
261                                     hdcmi->Init.LineSelectStart);
262 
263   if (hdcmi->Init.SynchroMode == DCMI_SYNCHRO_EMBEDDED)
264   {
265     hdcmi->Instance->ESCR = (((uint32_t)hdcmi->Init.SyncroCode.FrameStartCode)    | \
266                              ((uint32_t)hdcmi->Init.SyncroCode.LineStartCode << DCMI_ESCR_LSC_Pos) | \
267                              ((uint32_t)hdcmi->Init.SyncroCode.LineEndCode << DCMI_ESCR_LEC_Pos) | \
268                              ((uint32_t)hdcmi->Init.SyncroCode.FrameEndCode << DCMI_ESCR_FEC_Pos));
269 
270   }
271 
272   /* Enable the Line, Vsync, Error and Overrun interrupts */
273   __HAL_DCMI_ENABLE_IT(hdcmi, DCMI_IT_LINE | DCMI_IT_VSYNC | DCMI_IT_ERR | DCMI_IT_OVR);
274 
275   /* Update error code */
276   hdcmi->ErrorCode = HAL_DCMI_ERROR_NONE;
277 
278   /* Initialize the DCMI state*/
279   hdcmi->State  = HAL_DCMI_STATE_READY;
280 
281   return HAL_OK;
282 }
283 
284 /**
285   * @brief  Deinitializes the DCMI peripheral registers to their default reset
286   *         values.
287   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
288   *                the configuration information for DCMI.
289   * @retval HAL status
290   */
291 
HAL_DCMI_DeInit(DCMI_HandleTypeDef * hdcmi)292 HAL_StatusTypeDef HAL_DCMI_DeInit(DCMI_HandleTypeDef *hdcmi)
293 {
294 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
295   if (hdcmi->MspDeInitCallback == NULL)
296   {
297     hdcmi->MspDeInitCallback = HAL_DCMI_MspDeInit;
298   }
299   /* De-Initialize the low level hardware (MSP) */
300   hdcmi->MspDeInitCallback(hdcmi);
301 #else
302   /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
303   HAL_DCMI_MspDeInit(hdcmi);
304 #endif /* (USE_HAL_DCMI_REGISTER_CALLBACKS) */
305 
306   /* Update error code */
307   hdcmi->ErrorCode = HAL_DCMI_ERROR_NONE;
308 
309   /* Initialize the DCMI state*/
310   hdcmi->State = HAL_DCMI_STATE_RESET;
311 
312   /* Release Lock */
313   __HAL_UNLOCK(hdcmi);
314 
315   return HAL_OK;
316 }
317 
318 /**
319   * @brief  Initializes the DCMI MSP.
320   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
321   *                the configuration information for DCMI.
322   * @retval None
323   */
HAL_DCMI_MspInit(DCMI_HandleTypeDef * hdcmi)324 __weak void HAL_DCMI_MspInit(DCMI_HandleTypeDef *hdcmi)
325 {
326   /* Prevent unused argument(s) compilation warning */
327   UNUSED(hdcmi);
328 
329   /* NOTE : This function Should not be modified, when the callback is needed,
330             the HAL_DCMI_MspInit could be implemented in the user file
331    */
332 }
333 
334 /**
335   * @brief  DeInitializes the DCMI MSP.
336   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
337   *                the configuration information for DCMI.
338   * @retval None
339   */
HAL_DCMI_MspDeInit(DCMI_HandleTypeDef * hdcmi)340 __weak void HAL_DCMI_MspDeInit(DCMI_HandleTypeDef *hdcmi)
341 {
342   /* Prevent unused argument(s) compilation warning */
343   UNUSED(hdcmi);
344 
345   /* NOTE : This function Should not be modified, when the callback is needed,
346             the HAL_DCMI_MspDeInit could be implemented in the user file
347    */
348 }
349 
350 /**
351   * @}
352   */
353 /** @defgroup DCMI_Exported_Functions_Group2 IO operation functions
354   *  @brief   IO operation functions
355   *
356 @verbatim
357  ===============================================================================
358                       #####  IO operation functions  #####
359  ===============================================================================
360     [..]  This section provides functions allowing to:
361       (+) Configure destination address and data length and
362           Enables DCMI DMA request and enables DCMI capture
363       (+) Stop the DCMI capture.
364       (+) Handles DCMI interrupt request.
365 
366 @endverbatim
367   * @{
368   */
369 
370 /**
371   * @brief  Enables DCMI DMA request and enables DCMI capture
372   * @param  hdcmi     pointer to a DCMI_HandleTypeDef structure that contains
373   *                    the configuration information for DCMI.
374   * @param  DCMI_Mode DCMI capture mode snapshot or continuous grab.
375   * @param  pData     The destination memory Buffer address (LCD Frame buffer).
376   * @param  Length    The length of capture to be transferred.
377   * @retval HAL status
378   */
HAL_DCMI_Start_DMA(DCMI_HandleTypeDef * hdcmi,uint32_t DCMI_Mode,uint32_t pData,uint32_t Length)379 HAL_StatusTypeDef HAL_DCMI_Start_DMA(DCMI_HandleTypeDef *hdcmi, uint32_t DCMI_Mode, uint32_t pData, uint32_t Length)
380 {
381   uint32_t tmp_length = Length;
382   HAL_StatusTypeDef status = HAL_OK;
383   uint32_t cllr_offset;
384   uint32_t tmp1;
385   uint32_t tmp2;
386 
387   /* Check function parameters */
388   assert_param(IS_DCMI_CAPTURE_MODE(DCMI_Mode));
389 
390   /* Process Locked */
391   __HAL_LOCK(hdcmi);
392 
393   /* Lock the DCMI peripheral state */
394   hdcmi->State = HAL_DCMI_STATE_BUSY;
395 
396   /* Enable DCMI by setting DCMIEN bit */
397   __HAL_DCMI_ENABLE(hdcmi);
398 
399   /* Configure the DCMI Mode */
400   hdcmi->Instance->CR &= ~(DCMI_CR_CM);
401   hdcmi->Instance->CR |= (uint32_t)(DCMI_Mode);
402 
403   /* Set the DMA memory0 conversion complete callback */
404   hdcmi->DMA_Handle->XferCpltCallback = DCMI_DMAXferCplt;
405 
406   /* Set the DMA error callback */
407   hdcmi->DMA_Handle->XferErrorCallback = DCMI_DMAError;
408 
409   /* Set the dma abort callback */
410   hdcmi->DMA_Handle->XferAbortCallback = NULL;
411 
412   /* Reset transfer counters value */
413   hdcmi->XferCount = 0;
414   hdcmi->XferTransferNumber = 0;
415   hdcmi->XferSize = 0;
416   hdcmi->pBuffPtr = 0;
417 
418   /* Length should be converted to number of bytes */
419   tmp_length = tmp_length * 4U;
420 
421   if (tmp_length <= 0xFFFFU)
422   {
423     /* Continuoues Mode */
424     /* Enable the DMA Stream */
425     if ((hdcmi->DMA_Handle->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
426     {
427       if ((hdcmi->DMA_Handle->LinkedListQueue != 0U) && (hdcmi->DMA_Handle->LinkedListQueue->Head != 0U))
428       {
429         /* Set Source , Destination , Length for DMA Xfer */
430 
431         /* Set DMA data size           */
432         hdcmi->DMA_Handle->LinkedListQueue->Head->LinkRegisters[NODE_CBR1_DEFAULT_OFFSET] = tmp_length;
433         /* Set DMA source address      */
434         hdcmi->DMA_Handle->LinkedListQueue->Head->LinkRegisters[NODE_CSAR_DEFAULT_OFFSET] = \
435             (uint32_t)&hdcmi->Instance->DR;
436         /* Set DMA destination address */
437         hdcmi->DMA_Handle->LinkedListQueue->Head->LinkRegisters[NODE_CDAR_DEFAULT_OFFSET] = (uint32_t)pData;
438 
439         status = HAL_DMAEx_List_Start_IT(hdcmi->DMA_Handle);
440       }
441       else
442       {
443         /* Set Error Code */
444         hdcmi->ErrorCode = HAL_DCMI_ERROR_DMA;
445         /* Change DCMI state */
446         hdcmi->State = HAL_DCMI_STATE_READY;
447         /* Release Lock */
448         __HAL_UNLOCK(hdcmi);
449         /* Return function status */
450         status = HAL_ERROR;
451       }
452     }
453     else
454     {
455       status = HAL_DMA_Start_IT(hdcmi->DMA_Handle, (uint32_t)&hdcmi->Instance->DR, (uint32_t)pData, tmp_length);
456     }
457   }
458   else /* DCMI_DOUBLE_BUFFER Mode */
459   {
460     /* Double buffering is used through 2 Nodes
461        Calculate the elementary size to be transferred by each node */
462 
463     /* Initialize transfer parameters */
464     hdcmi->XferCount = 1;
465     hdcmi->XferSize = tmp_length;
466     hdcmi->pBuffPtr = pData;
467 
468     /* Get the number of buffer */
469     while (hdcmi->XferSize > 0xFFFFU)
470     {
471       hdcmi->XferSize = (hdcmi->XferSize / 2U);
472       hdcmi->XferCount = hdcmi->XferCount * 2U;
473     }
474 
475     /* Update DCMI counter  and transfer number*/
476     hdcmi->XferCount = (hdcmi->XferCount - 1U);
477     hdcmi->XferTransferNumber = hdcmi->XferCount;
478 
479     if ((hdcmi->DMA_Handle->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
480     {
481       if ((hdcmi->DMA_Handle->LinkedListQueue != 0U) && (hdcmi->DMA_Handle->LinkedListQueue->Head != 0U))
482       {
483         /* Update first node */
484 
485         /* Set DMA Data size */
486         hdcmi->DMA_Handle->LinkedListQueue->Head->LinkRegisters[NODE_CBR1_DEFAULT_OFFSET] = hdcmi->XferSize ;
487 
488         /* Set DMA Source address */
489         hdcmi->DMA_Handle->LinkedListQueue->Head->LinkRegisters[NODE_CSAR_DEFAULT_OFFSET] = \
490             (uint32_t)&hdcmi->Instance->DR;
491 
492         /* Set DMA Destination address */
493         hdcmi->DMA_Handle->LinkedListQueue->Head->LinkRegisters[NODE_CDAR_DEFAULT_OFFSET] = (uint32_t)pData;
494 
495         /* Get CLLR offset */
496         cllr_offset = (hdcmi->DMA_Handle->LinkedListQueue->Head->NodeInfo & NODE_CLLR_IDX) >> 8U;
497 
498         /* Update second node */
499         if (hdcmi->DMA_Handle->LinkedListQueue->Head->LinkRegisters[cllr_offset] != 0U)
500         {
501           tmp1 = (uint32_t)hdcmi->DMA_Handle->LinkedListQueue->Head ;
502           tmp2 = hdcmi->DMA_Handle->LinkedListQueue->Head->LinkRegisters[cllr_offset];
503           /* Update second node */
504 
505           /* Set DMA Data size */
506           ((DMA_NodeTypeDef *)((tmp1 & DMA_CLBAR_LBA) + \
507                                (tmp2 & DMA_CLLR_LA)))->LinkRegisters[NODE_CBR1_DEFAULT_OFFSET] = hdcmi->XferSize;
508 
509           /* Set DMA Source address */
510           ((DMA_NodeTypeDef *)((tmp1 & DMA_CLBAR_LBA) + \
511                                (tmp2 & DMA_CLLR_LA)))->LinkRegisters[NODE_CSAR_DEFAULT_OFFSET] = \
512                                    (uint32_t)&hdcmi->Instance->DR;
513 
514           /* Set DMA Destination address */
515           ((DMA_NodeTypeDef *)((tmp1 & DMA_CLBAR_LBA) + \
516                                (tmp2 & DMA_CLLR_LA)))->LinkRegisters[NODE_CDAR_DEFAULT_OFFSET] = \
517                                    (uint32_t)pData + hdcmi->XferSize;
518 
519           if (HAL_DMAEx_List_Start_IT(hdcmi->DMA_Handle) != HAL_OK)
520           {
521             /* Set Error Code */
522             hdcmi->ErrorCode = HAL_DCMI_ERROR_DMA;
523             /* Change DCMI state */
524             hdcmi->State = HAL_DCMI_STATE_READY;
525             /* Release Lock */
526             __HAL_UNLOCK(hdcmi);
527             /* Return function status */
528             status = HAL_ERROR;
529           }
530         }
531         else
532         {
533           /* Set Error Code */
534           hdcmi->ErrorCode = HAL_DCMI_ERROR_DMA;
535           /* Change DCMI state */
536           hdcmi->State = HAL_DCMI_STATE_READY;
537           /* Release Lock */
538           __HAL_UNLOCK(hdcmi);
539           /* Return function status */
540           status = HAL_ERROR;
541         }
542       }
543       else
544       {
545         /* Set Error Code */
546         hdcmi->ErrorCode = HAL_DCMI_ERROR_DMA;
547         /* Change DCMI state */
548         hdcmi->State = HAL_DCMI_STATE_READY;
549         /* Release Lock */
550         __HAL_UNLOCK(hdcmi);
551         /* Return function status */
552         status = HAL_ERROR;
553       }
554     }
555     else
556     {
557       /* Set Error Code */
558       hdcmi->ErrorCode = HAL_DCMI_ERROR_DMA;
559       /* Change DCMI state */
560       hdcmi->State = HAL_DCMI_STATE_READY;
561       /* Release Lock */
562       __HAL_UNLOCK(hdcmi);
563       /* Return function status */
564       status = HAL_ERROR;
565     }
566   }
567   if (status == HAL_OK)
568   {
569     /* Enable Capture */
570     hdcmi->Instance->CR |= DCMI_CR_CAPTURE;
571 
572     /* Release Lock */
573     __HAL_UNLOCK(hdcmi);
574   }
575   else
576   {
577     /* Set Error Code */
578     hdcmi->ErrorCode = HAL_DCMI_ERROR_DMA;
579     /* Change DCMI state */
580     hdcmi->State = HAL_DCMI_STATE_READY;
581     /* Release Lock */
582     __HAL_UNLOCK(hdcmi);
583     /* Return function status */
584     status = HAL_ERROR;
585   }
586 
587   /* Return function status */
588   return status;
589 }
590 
591 /**
592   * @brief  Disable DCMI DMA request and Disable DCMI capture
593   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
594   *                the configuration information for DCMI.
595   * @retval HAL status
596   */
HAL_DCMI_Stop(DCMI_HandleTypeDef * hdcmi)597 HAL_StatusTypeDef HAL_DCMI_Stop(DCMI_HandleTypeDef *hdcmi)
598 {
599   uint32_t count = HAL_TIMEOUT_DCMI_STOP * (SystemCoreClock / 8U / 1000U);
600   HAL_StatusTypeDef status = HAL_OK;
601 
602   /* Process locked */
603   __HAL_LOCK(hdcmi);
604 
605   /* Lock the DCMI peripheral state */
606   hdcmi->State = HAL_DCMI_STATE_BUSY;
607 
608   /* Disable Capture */
609   hdcmi->Instance->CR &= ~(DCMI_CR_CAPTURE);
610 
611   /* Check if the DCMI capture effectively disabled */
612   do
613   {
614     count-- ;
615     if (count == 0U)
616     {
617       /* Update error code */
618       hdcmi->ErrorCode |= HAL_DCMI_ERROR_TIMEOUT;
619 
620       status = HAL_TIMEOUT;
621       break;
622     }
623   } while ((hdcmi->Instance->CR & DCMI_CR_CAPTURE) != 0U);
624 
625   /* Disable the DCMI */
626   __HAL_DCMI_DISABLE(hdcmi);
627 
628   /* Disable the DMA */
629   (void)HAL_DMA_Abort(hdcmi->DMA_Handle);
630 
631   /* Update error code */
632   hdcmi->ErrorCode |= HAL_DCMI_ERROR_NONE;
633 
634   /* Change DCMI state */
635   hdcmi->State = HAL_DCMI_STATE_READY;
636 
637   /* Process Unlocked */
638   __HAL_UNLOCK(hdcmi);
639 
640   /* Return function status */
641   return status;
642 }
643 
644 /**
645   * @brief  Suspend DCMI capture
646   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
647   *                the configuration information for DCMI.
648   * @retval HAL status
649   */
HAL_DCMI_Suspend(DCMI_HandleTypeDef * hdcmi)650 HAL_StatusTypeDef HAL_DCMI_Suspend(DCMI_HandleTypeDef *hdcmi)
651 {
652   uint32_t count = HAL_TIMEOUT_DCMI_STOP * (SystemCoreClock / 8U / 1000U);
653   HAL_StatusTypeDef status = HAL_OK;
654 
655   /* Process locked */
656   __HAL_LOCK(hdcmi);
657 
658   if (hdcmi->State == HAL_DCMI_STATE_BUSY)
659   {
660     /* Change DCMI state */
661     hdcmi->State = HAL_DCMI_STATE_SUSPENDED;
662 
663     /* Disable Capture */
664     hdcmi->Instance->CR &= ~(DCMI_CR_CAPTURE);
665 
666     /* Check if the DCMI capture effectively disabled */
667     do
668     {
669       count-- ;
670       if (count == 0U)
671       {
672         /* Update error code */
673         hdcmi->ErrorCode |= HAL_DCMI_ERROR_TIMEOUT;
674 
675         /* Change DCMI state */
676         hdcmi->State = HAL_DCMI_STATE_READY;
677 
678         status = HAL_TIMEOUT;
679         break;
680       }
681     } while ((hdcmi->Instance->CR & DCMI_CR_CAPTURE) != 0U);
682   }
683   /* Process Unlocked */
684   __HAL_UNLOCK(hdcmi);
685 
686   /* Return function status */
687   return status;
688 }
689 
690 /**
691   * @brief  Resume DCMI capture
692   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
693   *                the configuration information for DCMI.
694   * @retval HAL status
695   */
HAL_DCMI_Resume(DCMI_HandleTypeDef * hdcmi)696 HAL_StatusTypeDef HAL_DCMI_Resume(DCMI_HandleTypeDef *hdcmi)
697 {
698   /* Process locked */
699   __HAL_LOCK(hdcmi);
700 
701   if (hdcmi->State == HAL_DCMI_STATE_SUSPENDED)
702   {
703     /* Change DCMI state */
704     hdcmi->State = HAL_DCMI_STATE_BUSY;
705 
706     /* Enable Capture */
707     hdcmi->Instance->CR |= DCMI_CR_CAPTURE;
708   }
709   /* Process Unlocked */
710   __HAL_UNLOCK(hdcmi);
711 
712   /* Return function status */
713   return HAL_OK;
714 }
715 
716 /**
717   * @brief  Handles DCMI interrupt request.
718   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
719   *                the configuration information for the DCMI.
720   * @retval None
721   */
HAL_DCMI_IRQHandler(DCMI_HandleTypeDef * hdcmi)722 void HAL_DCMI_IRQHandler(DCMI_HandleTypeDef *hdcmi)
723 {
724   uint32_t isr_value = READ_REG(hdcmi->Instance->MISR);
725 
726   /* Synchronization error interrupt management *******************************/
727   if ((isr_value & DCMI_FLAG_ERRRI) == DCMI_FLAG_ERRRI)
728   {
729     /* Clear the Synchronization error flag */
730     __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_ERRRI);
731 
732     /* Update error code */
733     hdcmi->ErrorCode |= HAL_DCMI_ERROR_SYNC;
734 
735     /* Change DCMI state */
736     hdcmi->State = HAL_DCMI_STATE_ERROR;
737 
738     /* Set the synchronization error callback */
739     hdcmi->DMA_Handle->XferAbortCallback = DCMI_DMAError;
740 
741     /* Abort the DMA Transfer */
742     if (HAL_DMA_Abort_IT(hdcmi->DMA_Handle) != HAL_OK)
743     {
744       DCMI_DMAError(hdcmi->DMA_Handle);
745     }
746   }
747   /* Overflow interrupt management ********************************************/
748   if ((isr_value & DCMI_FLAG_OVRRI) == DCMI_FLAG_OVRRI)
749   {
750     /* Clear the Overflow flag */
751     __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_OVRRI);
752 
753     /* Update error code */
754     hdcmi->ErrorCode |= HAL_DCMI_ERROR_OVR;
755 
756     /* Change DCMI state */
757     hdcmi->State = HAL_DCMI_STATE_ERROR;
758 
759     /* Set the overflow callback */
760     hdcmi->DMA_Handle->XferAbortCallback = DCMI_DMAError;
761 
762     /* Abort the DMA Transfer */
763     if (HAL_DMA_Abort_IT(hdcmi->DMA_Handle) != HAL_OK)
764     {
765       DCMI_DMAError(hdcmi->DMA_Handle);
766     }
767   }
768   /* Line Interrupt management ************************************************/
769   if ((isr_value & DCMI_FLAG_LINERI) == DCMI_FLAG_LINERI)
770   {
771     /* Clear the Line interrupt flag */
772     __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_LINERI);
773 
774     /* Line interrupt Callback */
775 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
776     /*Call registered DCMI line event callback*/
777     hdcmi->LineEventCallback(hdcmi);
778 #else
779     HAL_DCMI_LineEventCallback(hdcmi);
780 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
781   }
782   /* VSYNC interrupt management ***********************************************/
783   if ((isr_value & DCMI_FLAG_VSYNCRI) == DCMI_FLAG_VSYNCRI)
784   {
785     /* Clear the VSYNC flag */
786     __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_VSYNCRI);
787 
788     /* VSYNC Callback */
789 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
790     /*Call registered DCMI vsync event callback*/
791     hdcmi->VsyncEventCallback(hdcmi);
792 #else
793     HAL_DCMI_VsyncEventCallback(hdcmi);
794 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
795   }
796   /* FRAME interrupt management ***********************************************/
797   if ((isr_value & DCMI_FLAG_FRAMERI) == DCMI_FLAG_FRAMERI)
798   {
799     /* When snapshot mode, disable Vsync, Error and Overrun interrupts */
800     if ((hdcmi->Instance->CR & DCMI_CR_CM) == DCMI_MODE_SNAPSHOT)
801     {
802       /* Disable the Line, Vsync, Error and Overrun interrupts */
803       __HAL_DCMI_DISABLE_IT(hdcmi, DCMI_IT_LINE | DCMI_IT_VSYNC | DCMI_IT_ERR | DCMI_IT_OVR);
804     }
805 
806     /* Disable the Frame interrupt */
807     __HAL_DCMI_DISABLE_IT(hdcmi, DCMI_IT_FRAME);
808 
809     /* Clear the End of Frame flag */
810     __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_FRAMERI);
811 
812     /* Frame Callback */
813 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
814     /*Call registered DCMI frame event callback*/
815     hdcmi->FrameEventCallback(hdcmi);
816 #else
817     HAL_DCMI_FrameEventCallback(hdcmi);
818 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
819   }
820 }
821 
822 /**
823   * @brief  Error DCMI callback.
824   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
825   *                the configuration information for DCMI.
826   * @retval None
827   */
HAL_DCMI_ErrorCallback(DCMI_HandleTypeDef * hdcmi)828 __weak void HAL_DCMI_ErrorCallback(DCMI_HandleTypeDef *hdcmi)
829 {
830   /* Prevent unused argument(s) compilation warning */
831   UNUSED(hdcmi);
832 
833   /* NOTE : This function Should not be modified, when the callback is needed,
834             the HAL_DCMI_ErrorCallback could be implemented in the user file
835    */
836 }
837 
838 /**
839   * @brief  Line Event callback.
840   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
841   *                the configuration information for DCMI.
842   * @retval None
843   */
HAL_DCMI_LineEventCallback(DCMI_HandleTypeDef * hdcmi)844 __weak void HAL_DCMI_LineEventCallback(DCMI_HandleTypeDef *hdcmi)
845 {
846   /* Prevent unused argument(s) compilation warning */
847   UNUSED(hdcmi);
848   /* NOTE : This function Should not be modified, when the callback is needed,
849             the HAL_DCMI_LineEventCallback could be implemented in the user file
850    */
851 }
852 
853 /**
854   * @brief  VSYNC Event callback.
855   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
856   *                the configuration information for DCMI.
857   * @retval None
858   */
HAL_DCMI_VsyncEventCallback(DCMI_HandleTypeDef * hdcmi)859 __weak void HAL_DCMI_VsyncEventCallback(DCMI_HandleTypeDef *hdcmi)
860 {
861   /* Prevent unused argument(s) compilation warning */
862   UNUSED(hdcmi);
863 
864   /* NOTE : This function Should not be modified, when the callback is needed,
865             the HAL_DCMI_VsyncEventCallback could be implemented in the user file
866    */
867 }
868 
869 /**
870   * @brief  Frame Event callback.
871   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
872   *                the configuration information for DCMI.
873   * @retval None
874   */
HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef * hdcmi)875 __weak void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi)
876 {
877   /* Prevent unused argument(s) compilation warning */
878   UNUSED(hdcmi);
879 
880   /* NOTE : This function Should not be modified, when the callback is needed,
881             the HAL_DCMI_FrameEventCallback could be implemented in the user file
882    */
883 }
884 
885 /**
886   * @}
887   */
888 
889 /** @defgroup DCMI_Exported_Functions_Group3 Peripheral Control functions
890   *  @brief    Peripheral Control functions
891   *
892 @verbatim
893  ===============================================================================
894                     ##### Peripheral Control functions #####
895  ===============================================================================
896 [..]  This section provides functions allowing to:
897       (+) Configure the CROP feature.
898       (+) Enable/Disable the CROP feature.
899       (+) Set embedded synchronization delimiters unmasks.
900 
901 @endverbatim
902   * @{
903   */
904 
905 /**
906   * @brief  Configure the DCMI CROP coordinate.
907   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
908   *                the configuration information for DCMI.
909   * @param  YSize DCMI Line number
910   * @param  XSize DCMI Pixel per line
911   * @param  X0    DCMI window X offset
912   * @param  Y0    DCMI window Y offset
913   * @retval HAL status
914   */
HAL_DCMI_ConfigCrop(DCMI_HandleTypeDef * hdcmi,uint32_t X0,uint32_t Y0,uint32_t XSize,uint32_t YSize)915 HAL_StatusTypeDef HAL_DCMI_ConfigCrop(DCMI_HandleTypeDef *hdcmi, uint32_t X0, uint32_t Y0, uint32_t XSize,
916                                       uint32_t 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   /* Check the parameters */
925   assert_param(IS_DCMI_WINDOW_COORDINATE(X0));
926   assert_param(IS_DCMI_WINDOW_HEIGHT(Y0));
927   assert_param(IS_DCMI_WINDOW_COORDINATE(XSize));
928   assert_param(IS_DCMI_WINDOW_COORDINATE(YSize));
929 
930   /* Configure CROP */
931   hdcmi->Instance->CWSIZER = (XSize | (YSize << DCMI_CWSIZE_VLINE_Pos));
932   hdcmi->Instance->CWSTRTR = (X0 | (Y0 << DCMI_CWSTRT_VST_Pos));
933 
934   /* Initialize the DCMI state*/
935   hdcmi->State  = HAL_DCMI_STATE_READY;
936 
937   /* Process Unlocked */
938   __HAL_UNLOCK(hdcmi);
939 
940   return HAL_OK;
941 }
942 
943 /**
944   * @brief  Disable the Crop feature.
945   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
946   *                the configuration information for DCMI.
947   * @retval HAL status
948   */
HAL_DCMI_DisableCrop(DCMI_HandleTypeDef * hdcmi)949 HAL_StatusTypeDef HAL_DCMI_DisableCrop(DCMI_HandleTypeDef *hdcmi)
950 {
951   /* Process Locked */
952   __HAL_LOCK(hdcmi);
953 
954   /* Lock the DCMI peripheral state */
955   hdcmi->State = HAL_DCMI_STATE_BUSY;
956 
957   /* Disable DCMI Crop feature */
958   hdcmi->Instance->CR &= ~(uint32_t)DCMI_CR_CROP;
959 
960   /* Change the DCMI state*/
961   hdcmi->State = HAL_DCMI_STATE_READY;
962 
963   /* Process Unlocked */
964   __HAL_UNLOCK(hdcmi);
965 
966   return HAL_OK;
967 }
968 
969 /**
970   * @brief  Enable the Crop feature.
971   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
972   *                the configuration information for DCMI.
973   * @retval HAL status
974   */
HAL_DCMI_EnableCrop(DCMI_HandleTypeDef * hdcmi)975 HAL_StatusTypeDef HAL_DCMI_EnableCrop(DCMI_HandleTypeDef *hdcmi)
976 {
977   /* Process Locked */
978   __HAL_LOCK(hdcmi);
979 
980   /* Lock the DCMI peripheral state */
981   hdcmi->State = HAL_DCMI_STATE_BUSY;
982 
983   /* Enable DCMI Crop feature */
984   hdcmi->Instance->CR |= (uint32_t)DCMI_CR_CROP;
985 
986   /* Change the DCMI state*/
987   hdcmi->State = HAL_DCMI_STATE_READY;
988 
989   /* Process Unlocked */
990   __HAL_UNLOCK(hdcmi);
991 
992   return HAL_OK;
993 }
994 
995 /**
996   * @brief  Set embedded synchronization delimiters unmasks.
997   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
998   *               the configuration information for DCMI.
999   * @param  SyncUnmask pointer to a DCMI_SyncUnmaskTypeDef structure that contains
1000   *                    the embedded synchronization delimiters unmasks.
1001   * @retval HAL status
1002   */
HAL_DCMI_ConfigSyncUnmask(DCMI_HandleTypeDef * hdcmi,DCMI_SyncUnmaskTypeDef * SyncUnmask)1003 HAL_StatusTypeDef  HAL_DCMI_ConfigSyncUnmask(DCMI_HandleTypeDef *hdcmi, DCMI_SyncUnmaskTypeDef *SyncUnmask)
1004 {
1005   /* Process Locked */
1006   __HAL_LOCK(hdcmi);
1007 
1008   /* Lock the DCMI peripheral state */
1009   hdcmi->State = HAL_DCMI_STATE_BUSY;
1010 
1011   /* Write DCMI embedded synchronization unmask register */
1012   hdcmi->Instance->ESUR = (((uint32_t)SyncUnmask->FrameStartUnmask) | \
1013                            ((uint32_t)SyncUnmask->LineStartUnmask << DCMI_ESUR_LSU_Pos) | \
1014                            ((uint32_t)SyncUnmask->LineEndUnmask << DCMI_ESUR_LEU_Pos) | \
1015                            ((uint32_t)SyncUnmask->FrameEndUnmask << DCMI_ESUR_FEU_Pos));
1016 
1017   /* Change the DCMI state*/
1018   hdcmi->State = HAL_DCMI_STATE_READY;
1019 
1020   /* Process Unlocked */
1021   __HAL_UNLOCK(hdcmi);
1022 
1023   return HAL_OK;
1024 }
1025 
1026 /**
1027   * @}
1028   */
1029 
1030 /** @defgroup DCMI_Exported_Functions_Group4 Peripheral State functions
1031   *  @brief    Peripheral State functions
1032   *
1033 @verbatim
1034  ===============================================================================
1035                ##### Peripheral State and Errors functions #####
1036  ===============================================================================
1037     [..]
1038     This subsection provides functions allowing to
1039       (+) Check the DCMI state.
1040       (+) Get the specific DCMI error flag.
1041 
1042 @endverbatim
1043   * @{
1044   */
1045 
1046 /**
1047   * @brief  Return the DCMI state
1048   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
1049   *                the configuration information for DCMI.
1050   * @retval HAL state
1051   */
HAL_DCMI_GetState(const DCMI_HandleTypeDef * hdcmi)1052 HAL_DCMI_StateTypeDef HAL_DCMI_GetState(const DCMI_HandleTypeDef *hdcmi)
1053 {
1054   return hdcmi->State;
1055 }
1056 
1057 /**
1058   * @brief  Return the DCMI error code
1059   * @param  hdcmi  pointer to a DCMI_HandleTypeDef structure that contains
1060   *               the configuration information for DCMI.
1061   * @retval DCMI Error Code
1062   */
HAL_DCMI_GetError(const DCMI_HandleTypeDef * hdcmi)1063 uint32_t HAL_DCMI_GetError(const DCMI_HandleTypeDef *hdcmi)
1064 {
1065   return hdcmi->ErrorCode;
1066 }
1067 
1068 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
1069 /**
1070   * @brief  Register a User DCMI Callback
1071   *         To be used instead of the weak predefined callback
1072   * @param  hdcmi DCMI handle
1073   * @param  CallbackID ID of the callback to be registered
1074   *         This parameter can be one of the following values:
1075   *          @arg @ref HAL_DCMI_LINE_EVENT_CB_ID Line Event callback ID
1076   *          @arg @ref HAL_DCMI_FRAME_EVENT_CB_ID Frame Event callback ID
1077   *          @arg @ref HAL_DCMI_VSYNC_EVENT_CB_ID Vsync Event callback ID
1078   *          @arg @ref HAL_DCMI_ERROR_CB_ID Error callback ID
1079   *          @arg @ref HAL_DCMI_MSPINIT_CB_ID MspInit callback ID
1080   *          @arg @ref HAL_DCMI_MSPDEINIT_CB_ID MspDeInit callback ID
1081   * @param  pCallback pointer to the Callback function
1082   * @retval HAL status
1083   */
HAL_DCMI_RegisterCallback(DCMI_HandleTypeDef * hdcmi,HAL_DCMI_CallbackIDTypeDef CallbackID,pDCMI_CallbackTypeDef pCallback)1084 HAL_StatusTypeDef HAL_DCMI_RegisterCallback(DCMI_HandleTypeDef *hdcmi, HAL_DCMI_CallbackIDTypeDef CallbackID,
1085                                             pDCMI_CallbackTypeDef pCallback)
1086 {
1087   HAL_StatusTypeDef status = HAL_OK;
1088 
1089   if (pCallback == NULL)
1090   {
1091     /* update the error code */
1092     hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
1093     /* update return status */
1094     status = HAL_ERROR;
1095   }
1096   else
1097   {
1098     if (hdcmi->State == HAL_DCMI_STATE_READY)
1099     {
1100       switch (CallbackID)
1101       {
1102         case HAL_DCMI_FRAME_EVENT_CB_ID :
1103           hdcmi->FrameEventCallback = pCallback;
1104           break;
1105 
1106         case HAL_DCMI_VSYNC_EVENT_CB_ID :
1107           hdcmi->VsyncEventCallback = pCallback;
1108           break;
1109 
1110         case HAL_DCMI_LINE_EVENT_CB_ID :
1111           hdcmi->LineEventCallback = pCallback;
1112           break;
1113 
1114         case HAL_DCMI_ERROR_CB_ID :
1115           hdcmi->ErrorCallback = pCallback;
1116           break;
1117 
1118         case HAL_DCMI_MSPINIT_CB_ID :
1119           hdcmi->MspInitCallback = pCallback;
1120           break;
1121 
1122         case HAL_DCMI_MSPDEINIT_CB_ID :
1123           hdcmi->MspDeInitCallback = pCallback;
1124           break;
1125 
1126         default :
1127           /* Return error status */
1128           status =  HAL_ERROR;
1129           break;
1130       }
1131     }
1132     else if (hdcmi->State == HAL_DCMI_STATE_RESET)
1133     {
1134       switch (CallbackID)
1135       {
1136         case HAL_DCMI_MSPINIT_CB_ID :
1137           hdcmi->MspInitCallback = pCallback;
1138           break;
1139 
1140         case HAL_DCMI_MSPDEINIT_CB_ID :
1141           hdcmi->MspDeInitCallback = pCallback;
1142           break;
1143 
1144         default :
1145           /* update the error code */
1146           hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
1147           /* update return status */
1148           status = HAL_ERROR;
1149           break;
1150       }
1151     }
1152     else
1153     {
1154       /* update the error code */
1155       hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
1156       /* update return status */
1157       status = HAL_ERROR;
1158     }
1159   }
1160 
1161   return status;
1162 }
1163 
1164 /**
1165   * @brief  Unregister a DCMI Callback
1166   *         DCMI callback is redirected to the weak predefined callback
1167   * @param  hdcmi DCMI handle
1168   * @param  CallbackID ID of the callback to be registered
1169   *         This parameter can be one of the following values:
1170   *          @arg @ref HAL_DCMI_LINE_EVENT_CB_ID Line Event callback ID
1171   *          @arg @ref HAL_DCMI_FRAME_EVENT_CB_ID Frame Event callback ID
1172   *          @arg @ref HAL_DCMI_VSYNC_EVENT_CB_ID Vsync Event callback ID
1173   *          @arg @ref HAL_DCMI_ERROR_CB_ID Error callback ID
1174   *          @arg @ref HAL_DCMI_MSPINIT_CB_ID MspInit callback ID
1175   *          @arg @ref HAL_DCMI_MSPDEINIT_CB_ID MspDeInit callback ID
1176   * @retval HAL status
1177   */
HAL_DCMI_UnRegisterCallback(DCMI_HandleTypeDef * hdcmi,HAL_DCMI_CallbackIDTypeDef CallbackID)1178 HAL_StatusTypeDef HAL_DCMI_UnRegisterCallback(DCMI_HandleTypeDef *hdcmi, HAL_DCMI_CallbackIDTypeDef CallbackID)
1179 {
1180   HAL_StatusTypeDef status = HAL_OK;
1181 
1182   if (hdcmi->State == HAL_DCMI_STATE_READY)
1183   {
1184     switch (CallbackID)
1185     {
1186       case HAL_DCMI_FRAME_EVENT_CB_ID :
1187         hdcmi->FrameEventCallback = HAL_DCMI_FrameEventCallback;  /* Legacy weak  FrameEventCallback  */
1188         break;
1189 
1190       case HAL_DCMI_VSYNC_EVENT_CB_ID :
1191         hdcmi->VsyncEventCallback = HAL_DCMI_VsyncEventCallback;  /* Legacy weak VsyncEventCallback   */
1192         break;
1193 
1194       case HAL_DCMI_LINE_EVENT_CB_ID :
1195         hdcmi->LineEventCallback = HAL_DCMI_LineEventCallback;    /* Legacy weak LineEventCallback    */
1196         break;
1197 
1198       case HAL_DCMI_ERROR_CB_ID :
1199         hdcmi->ErrorCallback = HAL_DCMI_ErrorCallback;           /* Legacy weak ErrorCallback         */
1200         break;
1201 
1202       case HAL_DCMI_MSPINIT_CB_ID :
1203         hdcmi->MspInitCallback = HAL_DCMI_MspInit;
1204         break;
1205 
1206       case HAL_DCMI_MSPDEINIT_CB_ID :
1207         hdcmi->MspDeInitCallback = HAL_DCMI_MspDeInit;
1208         break;
1209 
1210       default :
1211         /* update the error code */
1212         hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
1213         /* update return status */
1214         status = HAL_ERROR;
1215         break;
1216     }
1217   }
1218   else if (hdcmi->State == HAL_DCMI_STATE_RESET)
1219   {
1220     switch (CallbackID)
1221     {
1222       case HAL_DCMI_MSPINIT_CB_ID :
1223         hdcmi->MspInitCallback = HAL_DCMI_MspInit;
1224         break;
1225 
1226       case HAL_DCMI_MSPDEINIT_CB_ID :
1227         hdcmi->MspDeInitCallback = HAL_DCMI_MspDeInit;
1228         break;
1229 
1230       default :
1231         /* update the error code */
1232         hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
1233         /* update return status */
1234         status = HAL_ERROR;
1235         break;
1236     }
1237   }
1238   else
1239   {
1240     /* update the error code */
1241     hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
1242     /* update return status */
1243     status = HAL_ERROR;
1244   }
1245 
1246   return status;
1247 }
1248 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
1249 
1250 /**
1251   * @}
1252   */
1253 
1254 /**
1255   * @}
1256   */
1257 
1258 /* Private functions ---------------------------------------------------------*/
1259 /** @defgroup DCMI_Private_Functions DCMI Private Functions
1260   * @{
1261   */
1262 /**
1263   * @brief  DMA conversion complete callback.
1264   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
1265   *                the configuration information for the specified DMA module.
1266   * @retval None
1267   */
DCMI_DMAXferCplt(DMA_HandleTypeDef * hdma)1268 static void DCMI_DMAXferCplt(DMA_HandleTypeDef *hdma)
1269 {
1270 
1271   DCMI_HandleTypeDef *hdcmi = (DCMI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
1272   uint32_t tmp1;
1273   uint32_t tmp2;
1274   DMA_NodeTypeDef *pnode;
1275   uint32_t pbuff;
1276   uint32_t transfernumber;
1277   uint32_t transfercount;
1278   uint32_t transfersize ;
1279 
1280   /* Update Nodes destinations */
1281   if (hdcmi->XferSize != 0U)
1282   {
1283     pbuff          = hdcmi->pBuffPtr;
1284     transfernumber = hdcmi->XferTransferNumber;
1285     transfercount  = hdcmi->XferCount;
1286     transfersize   = hdcmi->XferSize;
1287 
1288     tmp1 = hdcmi->DMA_Handle->Instance->CLLR & DMA_CLLR_LA;
1289     tmp2 = hdcmi->DMA_Handle->Instance->CLBAR & DMA_CLBAR_LBA;
1290     pnode = (DMA_NodeTypeDef *)(uint32_t)(tmp1 | tmp2);
1291 
1292     if (hdcmi->XferCount > 1U)
1293     {
1294       pnode->LinkRegisters[NODE_CDAR_DEFAULT_OFFSET] = pbuff + ((transfernumber - transfercount + 2U) * transfersize);
1295       hdcmi->XferCount--;
1296     }
1297 
1298     else if (hdcmi->XferCount == 1U)
1299     {
1300       pnode->LinkRegisters[NODE_CDAR_DEFAULT_OFFSET] = hdcmi->pBuffPtr;
1301       hdcmi->XferCount--;
1302     }
1303     else
1304     {
1305       pnode->LinkRegisters[NODE_CDAR_DEFAULT_OFFSET] = hdcmi->pBuffPtr + hdcmi->XferSize;
1306 
1307       /* When Continuous mode, re-set dcmi XferCount */
1308       if ((hdcmi->Instance->CR & DCMI_CR_CM) == DCMI_MODE_CONTINUOUS)
1309       {
1310         hdcmi->XferCount = hdcmi->XferTransferNumber ;
1311       }
1312       /* When snapshot mode, set dcmi state to ready */
1313       else
1314       {
1315         hdcmi->State = HAL_DCMI_STATE_READY;
1316       }
1317 
1318       __HAL_DCMI_ENABLE_IT(hdcmi, DCMI_IT_FRAME);
1319     }
1320   }
1321   else  /* Snapshot Mode */
1322   {
1323     /* Enable the Frame interrupt */
1324     __HAL_DCMI_ENABLE_IT(hdcmi, DCMI_IT_FRAME);
1325 
1326     /* When snapshot mode, set dcmi state to ready */
1327     if ((hdcmi->Instance->CR & DCMI_CR_CM) == DCMI_MODE_SNAPSHOT)
1328     {
1329       hdcmi->State = HAL_DCMI_STATE_READY;
1330     }
1331   }
1332 }
1333 
1334 /**
1335   * @brief  DMA error callback
1336   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
1337   *                the configuration information for the specified DMA module.
1338   * @retval None
1339   */
DCMI_DMAError(DMA_HandleTypeDef * hdma)1340 static void DCMI_DMAError(DMA_HandleTypeDef *hdma)
1341 {
1342   DCMI_HandleTypeDef *hdcmi = (DCMI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
1343 
1344   if (hdcmi->DMA_Handle->ErrorCode != HAL_DMA_ERROR_ULE)
1345   {
1346     /* Initialize the DCMI state*/
1347     hdcmi->State = HAL_DCMI_STATE_READY;
1348 
1349     /* Set DCMI Error Code */
1350     hdcmi->ErrorCode |= HAL_DCMI_ERROR_DMA;
1351   }
1352 
1353   /* DCMI error Callback */
1354 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
1355   /*Call registered DCMI error callback*/
1356   hdcmi->ErrorCallback(hdcmi);
1357 #else
1358   HAL_DCMI_ErrorCallback(hdcmi);
1359 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
1360 
1361 }
1362 
1363 /**
1364   * @}
1365   */
1366 #endif /* DCMI */
1367 #endif /* HAL_DCMI_MODULE_ENABLED */
1368 /**
1369   * @}
1370   */
1371 
1372 /**
1373   * @}
1374   */
1375