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