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