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