STM32L486xx HAL User Manual
stm32l4xx_hal_dcmi.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32l4xx_hal_dcmi.c
00004   * @author  MCD Application Team
00005   * @brief   DCMI HAL module driver
00006   *          This file provides firmware functions to manage the following
00007   *          functionalities of the Digital Camera Interface (DCMI) peripheral:
00008   *           + Initialization and de-initialization functions
00009   *           + IO operation functions
00010   *           + Peripheral Control functions
00011   *           + Peripheral State and Error functions
00012   *
00013   @verbatim
00014   ==============================================================================
00015                         ##### How to use this driver #####
00016   ==============================================================================
00017   [..]
00018       The sequence below describes how to use this driver to capture images
00019       from a camera module connected to the DCMI Interface.
00020       This sequence does not take into account the configuration of the
00021       camera module, which should be made before configuring and enabling
00022       the DCMI to capture images.
00023 
00024     (#) Program the required configuration through the following parameters:
00025         horizontal and vertical polarity, pixel clock polarity, capture rate,
00026         synchronization mode, frame delimiter codes, data width, byte and line
00027         selection using HAL_DCMI_Init() function.
00028 
00029     (#) Optionally select JPEG mode; in that case, only the polarity
00030         and the capture mode parameters need to be set.
00031 
00032     (#) Capture mode can be either snapshot or continuous mode.
00033 
00034     (#) Configure the DMA_Handle to transfer data from DCMI DR
00035         register to the destination memory buffer.
00036 
00037     -@- In snapshot mode, the interface transfers a single frame through DMA. In
00038        continuous mode, the DMA must be set in circular mode to ensure a continuous
00039        flow of images data samples.
00040 
00041     (#) Program the transfer configuration through the following parameters:
00042         DCMI mode, destination memory buffer address and data length then
00043         enable capture using HAL_DCMI_Start_DMA() function.
00044 
00045     (#) Whether in continuous or snapshot mode, data length parameter must be
00046         equal to the frame size.
00047 
00048     (#) When the frame size is unknown beforehand (e.g. JPEG case), data length must
00049         be large enough to ensure the capture of a frame.
00050 
00051     (#) If the frame size is larger than the maximum DMA transfer length (i.e. 65535),
00052         (++) the DMA must be configured in circular mode, either for snapshot or continuous
00053              capture mode,
00054         (++) during capture, the driver copies the image data samples from DCMI DR register
00055              at the end of the final destination buffer used as a work buffer,
00056         (++) at each DMA half (respectively complete) transfer interrupt, the first
00057              (resp. second) half of the work buffer is copied to the final destination thru
00058              a second DMA channel.
00059         (++) Parameters of this second DMA channel are contained in the memory to memory DMA
00060              handle "DMAM2M_Handle", itself field of the DCMI handle structure.
00061         (++) This memory to memory transfer has length half that of the work buffer and is
00062              carried out in normal mode (not in circular mode).
00063 
00064     (#) Optionally, configure and enable the CROP feature to select a
00065         rectangular window from the received image using HAL_DCMI_ConfigCrop()
00066         and HAL_DCMI_EnableCrop() functions. Use HAL_DCMI_DisableCrop() to
00067         disable this feature.
00068 
00069     (#) The capture can be stopped with HAL_DCMI_Stop() function.
00070 
00071     (#) To control the DCMI state, use the function HAL_DCMI_GetState().
00072 
00073     (#) To read the DCMI error code, use the function HAL_DCMI_GetError().
00074 
00075     [..]
00076     (@) When the frame size is less than the maximum DMA transfer length (i.e. 65535)
00077         and when in snapshot mode, user must make sure the FRAME interrupt is disabled.
00078         This allows to avoid corner cases where the FRAME interrupt might be triggered
00079         before the DMA transfer completion interrupt. In this specific configuration,
00080         the driver checks the FRAME capture flag after the DMA transfer end and calls
00081         HAL_DCMI_FrameEventCallback() if the flag is set.
00082 
00083      *** DCMI HAL driver macros list ***
00084      =============================================
00085      [..]
00086        Below the list of most used macros in DCMI HAL driver.
00087 
00088       (+) __HAL_DCMI_ENABLE: Enable the DCMI peripheral.
00089       (+) __HAL_DCMI_DISABLE: Disable the DCMI peripheral.
00090       (+) __HAL_DCMI_GET_FLAG: Get the DCMI pending flags.
00091       (+) __HAL_DCMI_CLEAR_FLAG: Clear the DCMI pending flags.
00092       (+) __HAL_DCMI_ENABLE_IT: Enable the specified DCMI interrupts.
00093       (+) __HAL_DCMI_DISABLE_IT: Disable the specified DCMI interrupts.
00094       (+) __HAL_DCMI_GET_IT_SOURCE: Check whether the specified DCMI interrupt has occurred or not.
00095 
00096     *** Callback registration ***
00097     =============================
00098 
00099     The compilation define USE_HAL_DCMI_REGISTER_CALLBACKS when set to 1
00100     allows the user to configure dynamically the driver callbacks.
00101     Use functions @ref HAL_DCMI_RegisterCallback() to register a user callback.
00102 
00103     Function @ref HAL_DCMI_RegisterCallback() allows to register following callbacks:
00104       (+) FrameEventCallback : DCMI Frame Event.
00105       (+) VsyncEventCallback : DCMI Vsync Event.
00106       (+) LineEventCallback  : DCMI Line Event.
00107       (+) ErrorCallback      : DCMI error.
00108       (+) MspInitCallback    : DCMI MspInit.
00109       (+) MspDeInitCallback  : DCMI MspDeInit.
00110     This function takes as parameters the HAL peripheral handle, the callback ID
00111     and a pointer to the user callback function.
00112 
00113     Use function @ref HAL_DCMI_UnRegisterCallback() to reset a callback to the default
00114     weak (surcharged) function.
00115     @ref HAL_DCMI_UnRegisterCallback() takes as parameters the HAL peripheral handle,
00116     and the callback ID.
00117     This function allows to reset following callbacks:
00118       (+) FrameEventCallback : DCMI Frame Event.
00119       (+) VsyncEventCallback : DCMI Vsync Event.
00120       (+) LineEventCallback  : DCMI Line Event.
00121       (+) ErrorCallback      : DCMI error.
00122       (+) MspInitCallback    : DCMI MspInit.
00123       (+) MspDeInitCallback  : DCMI MspDeInit.
00124 
00125     By default, after the @ref HAL_DCMI_Init and if the state is HAL_DCMI_STATE_RESET
00126     all callbacks are reset to the corresponding legacy weak (surcharged) functions:
00127     examples @ref FrameEventCallback(), @ref HAL_DCMI_ErrorCallback().
00128     Exception done for MspInit and MspDeInit callbacks that are respectively
00129     reset to the legacy weak (surcharged) functions in the @ref HAL_DCMI_Init
00130     and @ref  HAL_DCMI_DeInit only when these callbacks are null (not registered beforehand).
00131     If not, MspInit or MspDeInit are not null, the @ref HAL_DCMI_Init and @ref HAL_DCMI_DeInit
00132     keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
00133 
00134     Callbacks can be registered/unregistered in READY state only.
00135     Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
00136     in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
00137     during the Init/DeInit.
00138     In that case first register the MspInit/MspDeInit user callbacks
00139     using @ref HAL_DCMI_RegisterCallback before calling @ref HAL_DCMI_DeInit
00140     or @ref HAL_DCMI_Init function.
00141 
00142     When the compilation define USE_HAL_DCMI_REGISTER_CALLBACKS is set to 0 or
00143     not defined, the callback registering feature is not available
00144     and weak (surcharged) callbacks are used.
00145 
00146   @endverbatim
00147   ******************************************************************************
00148   * @attention
00149   *
00150   * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
00151   *
00152   * Redistribution and use in source and binary forms, with or without modification,
00153   * are permitted provided that the following conditions are met:
00154   *   1. Redistributions of source code must retain the above copyright notice,
00155   *      this list of conditions and the following disclaimer.
00156   *   2. Redistributions in binary form must reproduce the above copyright notice,
00157   *      this list of conditions and the following disclaimer in the documentation
00158   *      and/or other materials provided with the distribution.
00159   *   3. Neither the name of STMicroelectronics nor the names of its contributors
00160   *      may be used to endorse or promote products derived from this software
00161   *      without specific prior written permission.
00162   *
00163   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00164   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00165   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00166   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00167   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00168   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00169   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00170   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00171   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00172   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00173   *
00174   ******************************************************************************
00175   */
00176 
00177 /* Includes ------------------------------------------------------------------*/
00178 #include "stm32l4xx_hal.h"
00179 
00180 #ifdef HAL_DCMI_MODULE_ENABLED
00181 #if defined (DCMI)
00182 
00183 /** @addtogroup STM32L4xx_HAL_Driver
00184   * @{
00185   */
00186 /** @defgroup DCMI DCMI
00187   * @brief DCMI HAL module driver
00188   * @{
00189   */
00190 
00191 /* Private typedef -----------------------------------------------------------*/
00192 /* Private define ------------------------------------------------------------*/
00193 /** @defgroup DCMI_Private_Constants DCMI Private Constants
00194   * @{
00195   */
00196 
00197 /** @defgroup DCMI_Stop_TimeOut DCMI Stop TimeOut
00198   * @{
00199   */
00200 #define DCMI_TIMEOUT_STOP    ((uint32_t)1000U)  /*!< 1s  */
00201 /**
00202   * @}
00203   */
00204 
00205 #define NPRIME   16
00206 
00207 /**
00208   * @}
00209   */
00210 /* Private macro -------------------------------------------------------------*/
00211 /* Private variables ---------------------------------------------------------*/
00212 uint32_t PrimeArray[NPRIME] = { 1,  2,  3,  5,
00213                                 7, 11, 13, 17,
00214                                19, 23, 29, 31,
00215                                37, 41, 43, 47};
00216 /* Private function prototypes -----------------------------------------------*/
00217 /** @addtogroup DCMI_Private_Functions DCMI Private Functions
00218   * @{
00219   */
00220 static void       DCMI_DMAXferCplt(DMA_HandleTypeDef *hdma);
00221 static void       DCMI_DMAHalfXferCplt(DMA_HandleTypeDef *hdma);
00222 static void       DCMI_DMAError(DMA_HandleTypeDef *hdma);
00223 static uint32_t   DCMI_TransferSize(uint32_t InputSize);
00224 /**
00225   * @}
00226   */
00227 /* Exported functions --------------------------------------------------------*/
00228 
00229 /** @defgroup DCMI_Exported_Functions DCMI Exported Functions
00230   * @{
00231   */
00232 
00233 /** @defgroup DCMI_Exported_Functions_Group1 Initialization and Configuration functions
00234  *  @brief   Initialization and Configuration functions
00235  *
00236 @verbatim
00237  ===============================================================================
00238                 ##### Initialization and Configuration functions #####
00239  ===============================================================================
00240     [..]  This section provides functions allowing to:
00241       (+) Initialize and configure the DCMI
00242       (+) De-initialize the DCMI
00243 
00244 @endverbatim
00245   * @{
00246   */
00247 
00248 /**
00249   * @brief  Initialize the DCMI according to the specified
00250   *         parameters in the DCMI_InitTypeDef and create the associated handle.
00251   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
00252   *               the configuration information for DCMI.
00253   * @note   By default, all interruptions are enabled (line end, frame end, overrun,
00254   *         VSYNC and embedded synchronization error interrupts).
00255   * @retval HAL status
00256   */
00257 HAL_StatusTypeDef HAL_DCMI_Init(DCMI_HandleTypeDef *hdcmi)
00258 {
00259   /* Check the DCMI peripheral state */
00260   if(hdcmi == NULL)
00261   {
00262      return HAL_ERROR;
00263   }
00264 
00265   /* Check function parameters */
00266   assert_param(IS_DCMI_ALL_INSTANCE(hdcmi->Instance));
00267   assert_param(IS_DCMI_SYNCHRO(hdcmi->Init.SynchroMode));
00268   assert_param(IS_DCMI_PCKPOLARITY(hdcmi->Init.PCKPolarity));
00269   assert_param(IS_DCMI_VSPOLARITY(hdcmi->Init.VSPolarity));
00270   assert_param(IS_DCMI_HSPOLARITY(hdcmi->Init.HSPolarity));
00271   assert_param(IS_DCMI_CAPTURE_RATE(hdcmi->Init.CaptureRate));
00272   assert_param(IS_DCMI_EXTENDED_DATA(hdcmi->Init.ExtendedDataMode));
00273   assert_param(IS_DCMI_MODE_JPEG(hdcmi->Init.JPEGMode));
00274 
00275   assert_param(IS_DCMI_BYTE_SELECT_MODE(hdcmi->Init.ByteSelectMode));
00276   assert_param(IS_DCMI_BYTE_SELECT_START(hdcmi->Init.ByteSelectStart));
00277   assert_param(IS_DCMI_LINE_SELECT_MODE(hdcmi->Init.LineSelectMode));
00278   assert_param(IS_DCMI_LINE_SELECT_START(hdcmi->Init.LineSelectStart));
00279 
00280   if(hdcmi->State == HAL_DCMI_STATE_RESET)
00281   {
00282     /* Allocate lock resource and initialize it */
00283     hdcmi->Lock = HAL_UNLOCKED;
00284 
00285   /* Init the DCMI Callback settings */
00286 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
00287     hdcmi->FrameEventCallback = HAL_DCMI_FrameEventCallback; /* Legacy weak FrameEventCallback  */
00288     hdcmi->VsyncEventCallback = HAL_DCMI_VsyncEventCallback; /* Legacy weak VsyncEventCallback  */
00289     hdcmi->LineEventCallback  = HAL_DCMI_LineEventCallback;  /* Legacy weak LineEventCallback   */
00290     hdcmi->ErrorCallback      = HAL_DCMI_ErrorCallback;      /* Legacy weak ErrorCallback       */
00291 
00292     if(hdcmi->MspInitCallback == NULL)
00293     {
00294       /* Legacy weak MspInit Callback        */
00295       hdcmi->MspInitCallback = HAL_DCMI_MspInit;
00296     }
00297     /* Initialize the low level hardware (MSP) */
00298     hdcmi->MspInitCallback(hdcmi);
00299 #else
00300     /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
00301     HAL_DCMI_MspInit(hdcmi);
00302 #endif /* (USE_HAL_DCMI_REGISTER_CALLBACKS) */
00303   }
00304 
00305   /* Change the DCMI state */
00306   hdcmi->State = HAL_DCMI_STATE_BUSY;
00307 
00308   /* Disable DCMI IP before setting the configuration register */
00309   __HAL_DCMI_DISABLE(hdcmi);
00310 
00311   if (hdcmi->Init.ExtendedDataMode != DCMI_EXTEND_DATA_8B)
00312   {
00313     /* Byte select mode must be programmed to the reset value if the extended mode
00314       is not set to 8-bit data capture on every pixel clock */
00315     hdcmi->Init.ByteSelectMode = DCMI_BSM_ALL;
00316   }
00317 
00318   /* Set DCMI parameters */
00319   hdcmi->Instance->CR &= ~(DCMI_CR_PCKPOL | DCMI_CR_HSPOL  | DCMI_CR_VSPOL  | DCMI_CR_EDM_0 |\
00320                            DCMI_CR_EDM_1  | DCMI_CR_FCRC_0 | DCMI_CR_FCRC_1 | DCMI_CR_JPEG  |\
00321                            DCMI_CR_ESS | DCMI_CR_BSM_0 | DCMI_CR_BSM_1 | DCMI_CR_OEBS |\
00322                            DCMI_CR_LSM | DCMI_CR_OELS);
00323 
00324   hdcmi->Instance->CR |=  (uint32_t)(hdcmi->Init.SynchroMode | hdcmi->Init.CaptureRate |\
00325                                      hdcmi->Init.VSPolarity  | hdcmi->Init.HSPolarity  |\
00326                                      hdcmi->Init.PCKPolarity | hdcmi->Init.ExtendedDataMode |\
00327                                      hdcmi->Init.JPEGMode | hdcmi->Init.ByteSelectMode |\
00328                                      hdcmi->Init.ByteSelectStart | hdcmi->Init.LineSelectMode |\
00329                                      hdcmi->Init.LineSelectStart);
00330 
00331   if(hdcmi->Init.SynchroMode == DCMI_SYNCHRO_EMBEDDED)
00332   {
00333     hdcmi->Instance->ESCR = (((uint32_t)hdcmi->Init.SynchroCode.FrameStartCode)    |\
00334                              ((uint32_t)hdcmi->Init.SynchroCode.LineStartCode << DCMI_ESCR_LSC_Pos)|\
00335                              ((uint32_t)hdcmi->Init.SynchroCode.LineEndCode << DCMI_ESCR_LEC_Pos) |\
00336                              ((uint32_t)hdcmi->Init.SynchroCode.FrameEndCode << DCMI_ESCR_FEC_Pos));
00337   }
00338 
00339   /* By default, enable all interrupts. The user may disable the unwanted ones
00340      in resorting to __HAL_DCMI_DISABLE_IT() macro before invoking HAL_DCMI_Start_DMA().
00341      Enabled interruptions are
00342      - end of line
00343      - end of frame
00344      - data reception overrun
00345      - frame synchronization signal VSYNC
00346      - synchronization error */
00347   __HAL_DCMI_ENABLE_IT(hdcmi, DCMI_IT_FRAME|DCMI_IT_OVR|DCMI_IT_ERR|DCMI_IT_VSYNC|DCMI_IT_LINE);
00348 
00349   /* Update error code */
00350   hdcmi->ErrorCode = HAL_DCMI_ERROR_NONE;
00351 
00352   /* Initialize the DCMI state*/
00353   hdcmi->State  = HAL_DCMI_STATE_READY;
00354 
00355   return HAL_OK;
00356 }
00357 
00358 /**
00359   * @brief  De-initialize the DCMI peripheral, reset control registers to
00360   *         their default values.
00361   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
00362   *               the configuration information for DCMI.
00363   * @retval HAL status
00364   */
00365 HAL_StatusTypeDef HAL_DCMI_DeInit(DCMI_HandleTypeDef *hdcmi)
00366 {
00367   /* Before aborting any DCMI transfer, check
00368      first whether or not DCMI clock is enabled */
00369   if (__HAL_RCC_DCMI_IS_CLK_ENABLED())
00370   {
00371      if (HAL_DCMI_Stop(hdcmi) != HAL_OK)
00372      {
00373         /* Issue when stopping DCMI IP */
00374         return HAL_ERROR;
00375      }
00376   }
00377 
00378   /* Reset DCMI control register */
00379   hdcmi->Instance->CR = 0;
00380 
00381 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
00382   if(hdcmi->MspDeInitCallback == NULL)
00383   {
00384     hdcmi->MspDeInitCallback = HAL_DCMI_MspDeInit;
00385   }
00386   /* De-Initialize the low level hardware (MSP) */
00387   hdcmi->MspDeInitCallback(hdcmi);
00388 #else
00389   /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */
00390   HAL_DCMI_MspDeInit(hdcmi);
00391 #endif /* (USE_HAL_DCMI_REGISTER_CALLBACKS) */
00392 
00393   /* Update error code */
00394   hdcmi->ErrorCode = HAL_DCMI_ERROR_NONE;
00395 
00396   /* Initialize the DCMI state*/
00397   hdcmi->State = HAL_DCMI_STATE_RESET;
00398 
00399   /* Release Lock */
00400   __HAL_UNLOCK(hdcmi);
00401 
00402   return HAL_OK;
00403 }
00404 
00405 /**
00406   * @brief  Initialize the DCMI MSP.
00407   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
00408   *               the configuration information for DCMI.
00409   * @retval None
00410   */
00411 __weak void HAL_DCMI_MspInit(DCMI_HandleTypeDef* hdcmi)
00412 {
00413   /* Prevent unused argument(s) compilation warning */
00414   UNUSED(hdcmi);
00415 
00416   /* NOTE : This function should not be modified; when the callback is needed,
00417             the HAL_DCMI_MspInit() callback can be implemented in the user file
00418    */
00419 }
00420 
00421 /**
00422   * @brief  De-initialize the DCMI MSP.
00423   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
00424   *               the configuration information for DCMI.
00425   * @retval None
00426   */
00427 __weak void HAL_DCMI_MspDeInit(DCMI_HandleTypeDef* hdcmi)
00428 {
00429   /* Prevent unused argument(s) compilation warning */
00430   UNUSED(hdcmi);
00431 
00432   /* NOTE : This function should not be modified; when the callback is needed,
00433             the HAL_DCMI_MspDeInit() callback can be implemented in the user file
00434    */
00435 }
00436 
00437 /**
00438   * @}
00439   */
00440 
00441 /** @defgroup DCMI_Exported_Functions_Group2 IO operation functions
00442  *  @brief   IO operation functions
00443  *
00444 @verbatim
00445  ===============================================================================
00446                       #####  IO operation functions  #####
00447  ===============================================================================
00448     [..]  This section provides functions allowing to:
00449       (+) Configure destination address and data length,
00450           enable DCMI DMA request and DCMI capture.
00451       (+) Stop DCMI capture.
00452       (+) Handle DCMI interrupt request.
00453 
00454     [..]  A set of callbacks is provided:
00455         (+) HAL_DCMI_ErrorCallback()
00456         (+) HAL_DCMI_LineEventCallback()
00457         (+) HAL_DCMI_VsyncEventCallback()
00458         (+) HAL_DCMI_FrameEventCallback()
00459 
00460 
00461 @endverbatim
00462   * @{
00463   */
00464 
00465 /**
00466   * @brief  Enable DCMI capture in DMA mode.
00467   * @param  hdcmi     Pointer to a DCMI_HandleTypeDef structure that contains
00468   *                   the configuration information for DCMI.
00469   * @param  DCMI_Mode DCMI capture mode snapshot or continuous grab.
00470   * @param  pData     The destination memory buffer address.
00471   * @param  Length    The length of capture to be transferred (in 32-bit words).
00472   * @note  In case of length larger than 65535 (0xFFFF is the DMA maximum transfer length),
00473   *        the API uses the end of the destination buffer as a work area: HAL_DCMI_Start_DMA()
00474   *        initiates a circular DMA transfer from DCMI DR to the ad-hoc work buffer and each
00475   *        half and complete transfer interrupt triggers a copy from the work buffer to
00476   *        the final destination pData thru a second DMA channel.
00477   * @note  Following HAL_DCMI_Init() call, all interruptions are enabled (line end,
00478   *        frame end, overrun, VSYNC and embedded synchronization error interrupts).
00479   *        User can disable unwanted interrupts thru __HAL_DCMI_DISABLE_IT() macro
00480   *        before invoking HAL_DCMI_Start_DMA().
00481   * @note  For length less than 0xFFFF (DMA maximum transfer length) and in snapshot mode,
00482   *        frame interrupt is disabled before DMA transfer. FRAME capture flag is checked
00483   *        in DCMI_DMAXferCplt callback at the end of the DMA transfer. If flag is set,
00484   *        HAL_DCMI_FrameEventCallback() API is called.
00485   * @retval HAL status
00486   */
00487 HAL_StatusTypeDef HAL_DCMI_Start_DMA(DCMI_HandleTypeDef* hdcmi, uint32_t DCMI_Mode, uint32_t pData, uint32_t Length)
00488 {
00489   uint32_t circular_copy_length = 0;
00490 
00491   /* Check capture parameter */
00492   assert_param(IS_DCMI_CAPTURE_MODE(DCMI_Mode));
00493 
00494   /* Process Locked */
00495   __HAL_LOCK(hdcmi);
00496 
00497   /* Lock the DCMI peripheral state */
00498   hdcmi->State = HAL_DCMI_STATE_BUSY;
00499 
00500   /* Configure the DCMI Mode and enable the DCMI IP at the same time */
00501   MODIFY_REG(hdcmi->Instance->CR, (DCMI_CR_CM|DCMI_CR_ENABLE), (DCMI_Mode|DCMI_CR_ENABLE));
00502 
00503   /* Set the DMA conversion complete callback */
00504   hdcmi->DMA_Handle->XferCpltCallback = DCMI_DMAXferCplt;
00505 
00506   /* Set the DMA error callback */
00507   hdcmi->DMA_Handle->XferErrorCallback = DCMI_DMAError;
00508 
00509   /* Set the dma abort callback */
00510   hdcmi->DMA_Handle->XferAbortCallback = NULL;
00511 
00512   if(Length <= 0xFFFF)
00513   {
00514     hdcmi->XferCount = 0; /* Mark as direct transfer from DCMI_DR register to final destination buffer */
00515 
00516     /* Enable the DMA channel */
00517     if (HAL_DMA_Start_IT(hdcmi->DMA_Handle, (uint32_t)&hdcmi->Instance->DR, (uint32_t)pData, Length) != HAL_OK)
00518     {
00519       /* Update error code */
00520       hdcmi->ErrorCode |= HAL_DCMI_ERROR_DMA;
00521 
00522       /* Set state back to Ready */
00523       hdcmi->State = HAL_DCMI_STATE_READY;
00524 
00525       /* Process Unlocked */
00526       __HAL_UNLOCK(hdcmi);
00527 
00528        return HAL_ERROR;
00529     }
00530   }
00531   else /* Capture length is longer than DMA maximum transfer size */
00532   {
00533      /* Set DMA in circular mode */
00534     hdcmi->DMA_Handle->Init.Mode = DMA_CIRCULAR;
00535 
00536     /* Set the DMA half transfer complete callback */
00537     hdcmi->DMA_Handle->XferHalfCpltCallback = DCMI_DMAHalfXferCplt;
00538 
00539     /* Initialize transfer parameters */
00540     hdcmi->XferSize = Length;  /* Store the complete transfer length in DCMI handle */
00541     hdcmi->pBuffPtr = pData;   /* Final destination buffer pointer */
00542 
00543     circular_copy_length = DCMI_TransferSize(Length);
00544 
00545     /* Check if issue in intermediate length computation */
00546     if (circular_copy_length == 0)
00547     {
00548       /* Set state back to Ready */
00549       hdcmi->State = HAL_DCMI_STATE_READY;
00550 
00551       /* Process Unlocked */
00552       __HAL_UNLOCK(hdcmi);
00553 
00554        return HAL_ERROR;
00555     }
00556 
00557     /* Store the number of half - intermediate buffer copies needed */
00558     hdcmi->XferCount = 2 * ((Length / circular_copy_length) - 1);
00559     /* Store the half-buffer copy length */
00560     hdcmi->HalfCopyLength = circular_copy_length / 2;
00561 
00562     /* DCMI DR samples in circular mode will be copied
00563        at the end of the final buffer.
00564        Now compute the circular buffer start address. */
00565     /* Start by pointing at the final buffer */
00566     hdcmi->pCircularBuffer = pData;
00567     /* Update pCircularBuffer in "moving" at the end of the final
00568        buffer, don't forger to convert in bytes to compute exact address */
00569     hdcmi->pCircularBuffer +=  4 * (((Length / circular_copy_length) - 1) * circular_copy_length);
00570 
00571     /* Initiate the circular DMA transfer from DCMI IP to final buffer end */
00572     if ( HAL_DMA_Start_IT(hdcmi->DMA_Handle, (uint32_t)&hdcmi->Instance->DR, (uint32_t)hdcmi->pCircularBuffer, circular_copy_length) != HAL_OK)
00573     {
00574       /* Update error code */
00575       hdcmi->ErrorCode |= HAL_DCMI_ERROR_DMA;
00576 
00577       /* Set state back to Ready */
00578       hdcmi->State = HAL_DCMI_STATE_READY;
00579 
00580       /* Process Unlocked */
00581       __HAL_UNLOCK(hdcmi);
00582 
00583        return HAL_ERROR;
00584     }
00585   }
00586 
00587   /* Enable Capture */
00588   SET_BIT(hdcmi->Instance->CR, DCMI_CR_CAPTURE);
00589 
00590   /* Release Lock */
00591   __HAL_UNLOCK(hdcmi);
00592 
00593   /* Return function status */
00594   return HAL_OK;
00595 }
00596 
00597 /**
00598   * @brief  Disable DCMI capture in DMA mode.
00599   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
00600   *               the configuration information for DCMI.
00601   * @retval HAL status
00602   */
00603 HAL_StatusTypeDef HAL_DCMI_Stop(DCMI_HandleTypeDef* hdcmi)
00604 {
00605   uint32_t tickstart = 0;
00606   HAL_StatusTypeDef status = HAL_OK;
00607 
00608   /* Process locked */
00609   __HAL_LOCK(hdcmi);
00610 
00611   /* Lock the DCMI peripheral state */
00612   hdcmi->State = HAL_DCMI_STATE_BUSY;
00613 
00614   /* Disable Capture */
00615   CLEAR_BIT(hdcmi->Instance->CR, DCMI_CR_CAPTURE);
00616 
00617   /* Get tick */
00618   tickstart = HAL_GetTick();
00619 
00620   /* Check if the DCMI capture is effectively disabled */
00621   while((hdcmi->Instance->CR & DCMI_CR_CAPTURE) != 0)
00622   {
00623     if((HAL_GetTick() - tickstart ) > DCMI_TIMEOUT_STOP)
00624     {
00625       /* Update error code */
00626       hdcmi->ErrorCode |= HAL_DCMI_ERROR_TIMEOUT;
00627 
00628       status = HAL_TIMEOUT;
00629       break;
00630     }
00631   }
00632 
00633   /* Disable the DMA */
00634   HAL_DMA_Abort(hdcmi->DMA_Handle);
00635 
00636   /* Disable DCMI IP */
00637   __HAL_DCMI_DISABLE(hdcmi);
00638 
00639   /* Change DCMI state */
00640   hdcmi->State = HAL_DCMI_STATE_READY;
00641 
00642   /* Process Unlocked */
00643   __HAL_UNLOCK(hdcmi);
00644 
00645   /* Return function status */
00646   return status;
00647 }
00648 
00649 /**
00650   * @brief  Suspend DCMI capture.
00651   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
00652   *               the configuration information for DCMI.
00653   * @retval HAL status
00654   */
00655 HAL_StatusTypeDef HAL_DCMI_Suspend(DCMI_HandleTypeDef* hdcmi)
00656 {
00657   uint32_t tickstart = 0;
00658 
00659   /* Process locked */
00660   __HAL_LOCK(hdcmi);
00661 
00662   if(hdcmi->State == HAL_DCMI_STATE_BUSY)
00663   {
00664     /* Change DCMI state */
00665     hdcmi->State = HAL_DCMI_STATE_SUSPENDED;
00666 
00667     /* Disable Capture */
00668     CLEAR_BIT(hdcmi->Instance->CR, DCMI_CR_CAPTURE);
00669 
00670     /* Get tick */
00671     tickstart = HAL_GetTick();
00672 
00673     /* Check if the DCMI capture is effectively disabled */
00674     while((hdcmi->Instance->CR & DCMI_CR_CAPTURE) != 0)
00675     {
00676       if((HAL_GetTick() - tickstart ) > DCMI_TIMEOUT_STOP)
00677       {
00678         /* Update error code */
00679         hdcmi->ErrorCode |= HAL_DCMI_ERROR_TIMEOUT;
00680 
00681         /* Change DCMI state */
00682         hdcmi->State = HAL_DCMI_STATE_READY;
00683 
00684         /* Process Unlocked */
00685         __HAL_UNLOCK(hdcmi);
00686 
00687         return HAL_TIMEOUT;
00688       }
00689     }
00690   }
00691 
00692   /* Process Unlocked */
00693   __HAL_UNLOCK(hdcmi);
00694 
00695   /* Return function status */
00696   return HAL_OK;
00697 }
00698 
00699 /**
00700   * @brief  Resume DCMI capture.
00701   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
00702   *               the configuration information for DCMI.
00703   * @retval HAL status
00704   */
00705 HAL_StatusTypeDef HAL_DCMI_Resume(DCMI_HandleTypeDef* hdcmi)
00706 {
00707   /* Process locked */
00708   __HAL_LOCK(hdcmi);
00709 
00710   if(hdcmi->State == HAL_DCMI_STATE_SUSPENDED)
00711   {
00712     /* Change DCMI state */
00713     hdcmi->State = HAL_DCMI_STATE_BUSY;
00714 
00715     /* Enable Capture */
00716     SET_BIT(hdcmi->Instance->CR, DCMI_CR_CAPTURE);
00717   }
00718 
00719   /* Process Unlocked */
00720   __HAL_UNLOCK(hdcmi);
00721 
00722   return HAL_OK;
00723 }
00724 
00725 /**
00726   * @brief  Handle DCMI interrupt request.
00727   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
00728   *               the configuration information for the DCMI.
00729   * @retval None
00730   */
00731 void HAL_DCMI_IRQHandler(DCMI_HandleTypeDef *hdcmi)
00732 {
00733   uint32_t misflags = READ_REG(hdcmi->Instance->MISR);
00734 
00735   /* Synchronization error interrupt management *******************************/
00736   if ((misflags & DCMI_MIS_ERR_MIS) != RESET)
00737   {
00738     /* Clear the Synchronization error flag */
00739     __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_ERRRI);
00740 
00741     /* Update error code */
00742     hdcmi->ErrorCode |= HAL_DCMI_ERROR_SYNC;
00743   }
00744 
00745   /* Overflow interrupt management ********************************************/
00746   if ((misflags & DCMI_MIS_OVR_MIS) != RESET)
00747   {
00748     /* Clear the Overflow flag */
00749     __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_OVRRI);
00750 
00751     /* Update error code */
00752     hdcmi->ErrorCode |= HAL_DCMI_ERROR_OVR;
00753   }
00754 
00755   if (hdcmi->ErrorCode != HAL_DCMI_ERROR_NONE)
00756   {
00757     /* Change DCMI state */
00758     hdcmi->State = HAL_DCMI_STATE_READY;
00759 
00760     /* Set the overflow callback */
00761     hdcmi->DMA_Handle->XferAbortCallback = DCMI_DMAError;
00762 
00763     /* Abort the DMA Transfer */
00764     HAL_DMA_Abort_IT(hdcmi->DMA_Handle);
00765   }
00766 
00767   /* Line Interrupt management ************************************************/
00768   if ((misflags & DCMI_MIS_LINE_MIS) != RESET)
00769   {
00770     /* Clear the Line interrupt flag */
00771     __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_LINERI);
00772 
00773     /* Line interrupt Event Callback */
00774 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
00775     /*Call registered DCMI line event callback*/
00776     hdcmi->LineEventCallback(hdcmi);
00777 #else
00778     HAL_DCMI_LineEventCallback(hdcmi);
00779 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
00780   }
00781 
00782   /* VSYNC interrupt management ***********************************************/
00783   if ((misflags & DCMI_MIS_VSYNC_MIS) != RESET)
00784   {
00785     /* Clear the VSYNC flag */
00786     __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_VSYNCRI);
00787 
00788     /* VSYNC Event Callback */
00789 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
00790     /*Call registered DCMI vsync event callback*/
00791     hdcmi->VsyncEventCallback(hdcmi);
00792 #else
00793     HAL_DCMI_VsyncEventCallback(hdcmi);
00794 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
00795   }
00796 
00797   /* End of Frame interrupt management ****************************************/
00798   if ((misflags & DCMI_MIS_FRAME_MIS) != RESET)
00799   {
00800     /* Disable the Line interrupt when using snapshot mode */
00801     if ((hdcmi->Instance->CR & DCMI_CR_CM) == DCMI_MODE_SNAPSHOT)
00802     {
00803       __HAL_DCMI_DISABLE_IT(hdcmi, DCMI_IT_LINE|DCMI_IT_VSYNC|DCMI_IT_ERR|DCMI_IT_OVR);
00804       /* Change the DCMI state */
00805       hdcmi->State = HAL_DCMI_STATE_READY;
00806     }
00807 
00808     /* Clear the End of Frame flag */
00809     __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_FRAMERI);
00810 
00811     /* Frame Event Callback */
00812 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
00813     /*Call registered DCMI frame event callback*/
00814     hdcmi->FrameEventCallback(hdcmi);
00815 #else
00816     HAL_DCMI_FrameEventCallback(hdcmi);
00817 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
00818   }
00819 }
00820 
00821 /**
00822   * @brief  Error DCMI callback.
00823   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
00824   *               the configuration information for DCMI.
00825   * @retval None
00826   */
00827 __weak void HAL_DCMI_ErrorCallback(DCMI_HandleTypeDef *hdcmi)
00828 {
00829   /* Prevent unused argument(s) compilation warning */
00830   UNUSED(hdcmi);
00831 
00832   /* NOTE : This function should not be modified; when the callback is needed,
00833             the HAL_DCMI_ErrorCallback() callback can be implemented in the user file.
00834    */
00835 }
00836 
00837 /**
00838   * @brief  Line Event callback.
00839   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
00840   *               the configuration information for DCMI.
00841   * @retval None
00842   */
00843 __weak void HAL_DCMI_LineEventCallback(DCMI_HandleTypeDef *hdcmi)
00844 {
00845   /* Prevent unused argument(s) compilation warning */
00846   UNUSED(hdcmi);
00847 
00848   /* NOTE : This function should not be modified; when the callback is needed,
00849             the HAL_DCMI_LineEventCallback() callback can be implemented in the user file.
00850    */
00851 }
00852 
00853 /**
00854   * @brief  VSYNC Event callback.
00855   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
00856   *               the configuration information for DCMI.
00857   * @retval None
00858   */
00859 __weak void HAL_DCMI_VsyncEventCallback(DCMI_HandleTypeDef *hdcmi)
00860 {
00861   /* Prevent unused argument(s) compilation warning */
00862   UNUSED(hdcmi);
00863 
00864   /* NOTE : This function should not be modified; when the callback is needed,
00865             the HAL_DCMI_VsyncEventCallback() callback can be implemented in the user file.
00866    */
00867 }
00868 
00869 /**
00870   * @brief  Frame Event callback.
00871   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
00872   *               the configuration information for DCMI.
00873   * @retval None
00874   */
00875 __weak void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi)
00876 {
00877   /* Prevent unused argument(s) compilation warning */
00878   UNUSED(hdcmi);
00879 
00880   /* NOTE : This function should not be modified; when the callback is needed,
00881             the HAL_DCMI_FrameEventCallback() callback can be implemented in the user file.
00882    */
00883 }
00884 /**
00885   * @}
00886   */
00887 
00888 
00889 /** @defgroup DCMI_Exported_Functions_Group3 Peripheral Control functions
00890  *  @brief    Peripheral Control functions
00891  *
00892 @verbatim
00893  ===============================================================================
00894                     ##### Peripheral Control functions #####
00895  ===============================================================================
00896 [..]  This section provides functions allowing to:
00897       (+) Configure the crop feature.
00898       (+) Enable/Disable the crop feature.
00899       (+) Configure the synchronization delimiters unmasks.
00900       (+) Enable/Disable user-specified DCMI interrupts.
00901 
00902 @endverbatim
00903   * @{
00904   */
00905 
00906 /**
00907   * @brief  Configure the DCMI crop window coordinates.
00908   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
00909   *               the configuration information for DCMI.
00910   * @param  X0    DCMI window crop window X offset (number of pixels clocks to count before the capture).
00911   * @param  Y0    DCMI window crop window Y offset (image capture starts with this line number, previous
00912   *               line data are ignored).
00913   * @param  XSize DCMI crop window horizontal size (in number of pixels per line).
00914   * @param  YSize DCMI crop window vertical size (in lines count).
00915   * @note For all the parameters, the actual value is the input data + 1 (e.g. YSize = 0x0 means 1 line,
00916   *       YSize = 0x1 means 2 lines, ...)
00917   * @retval HAL status
00918   */
00919 HAL_StatusTypeDef HAL_DCMI_ConfigCrop(DCMI_HandleTypeDef *hdcmi, uint32_t X0, uint32_t Y0, uint32_t XSize, uint32_t YSize)
00920 {
00921   /* Check the parameters */
00922   assert_param(IS_DCMI_WINDOW_COORDINATE(X0));
00923   assert_param(IS_DCMI_WINDOW_HEIGHT(Y0));
00924   assert_param(IS_DCMI_WINDOW_COORDINATE(XSize));
00925   assert_param(IS_DCMI_WINDOW_COORDINATE(YSize));
00926 
00927   /* Process Locked */
00928   __HAL_LOCK(hdcmi);
00929 
00930   /* Lock the DCMI peripheral state */
00931   hdcmi->State = HAL_DCMI_STATE_BUSY;
00932 
00933   /* Configure CROP */
00934   MODIFY_REG(hdcmi->Instance->CWSIZER, (DCMI_CWSIZE_VLINE|DCMI_CWSIZE_CAPCNT), (XSize | (YSize << DCMI_CWSIZE_VLINE_Pos)));
00935   MODIFY_REG(hdcmi->Instance->CWSTRTR, (DCMI_CWSTRT_VST|DCMI_CWSTRT_HOFFCNT), (X0 | (Y0 << DCMI_CWSTRT_VST_Pos)));
00936 
00937   /* Initialize the DCMI state*/
00938   hdcmi->State  = HAL_DCMI_STATE_READY;
00939 
00940   /* Process Unlocked */
00941   __HAL_UNLOCK(hdcmi);
00942 
00943   return HAL_OK;
00944 }
00945 
00946 /**
00947   * @brief  Disable the crop feature.
00948   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
00949   *               the configuration information for DCMI.
00950   * @retval HAL status
00951   */
00952 HAL_StatusTypeDef HAL_DCMI_DisableCrop(DCMI_HandleTypeDef *hdcmi)
00953 {
00954   /* Process Locked */
00955   __HAL_LOCK(hdcmi);
00956 
00957   /* Lock the DCMI peripheral state */
00958   hdcmi->State = HAL_DCMI_STATE_BUSY;
00959 
00960   /* Disable DCMI Crop feature */
00961   CLEAR_BIT(hdcmi->Instance->CR, DCMI_CR_CROP);
00962 
00963   /* Change the DCMI state*/
00964   hdcmi->State = HAL_DCMI_STATE_READY;
00965 
00966   /* Process Unlocked */
00967   __HAL_UNLOCK(hdcmi);
00968 
00969   return HAL_OK;
00970 }
00971 
00972 /**
00973   * @brief  Enable the crop feature.
00974   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
00975   *               the configuration information for DCMI.
00976   * @retval HAL status
00977   */
00978 HAL_StatusTypeDef HAL_DCMI_EnableCrop(DCMI_HandleTypeDef *hdcmi)
00979 {
00980   /* Process Locked */
00981   __HAL_LOCK(hdcmi);
00982 
00983   /* Lock the DCMI peripheral state */
00984   hdcmi->State = HAL_DCMI_STATE_BUSY;
00985 
00986   /* Enable DCMI Crop feature */
00987   SET_BIT(hdcmi->Instance->CR, DCMI_CR_CROP);
00988 
00989   /* Change the DCMI state*/
00990   hdcmi->State = HAL_DCMI_STATE_READY;
00991 
00992   /* Process Unlocked */
00993   __HAL_UNLOCK(hdcmi);
00994 
00995   return HAL_OK;
00996 }
00997 
00998 /**
00999   * @brief  Set embedded synchronization delimiters unmasks.
01000   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
01001   *               the configuration information for DCMI.
01002   * @param  SyncUnmask pointer to a DCMI_SyncUnmaskTypeDef structure that contains
01003   *                    the embedded synchronization delimiters unmasks.
01004   * @retval HAL status
01005   */
01006 HAL_StatusTypeDef  HAL_DCMI_ConfigSyncUnmask(DCMI_HandleTypeDef *hdcmi, DCMI_SyncUnmaskTypeDef *SyncUnmask)
01007 {
01008   /* Process Locked */
01009   __HAL_LOCK(hdcmi);
01010 
01011   /* Lock the DCMI peripheral state */
01012   hdcmi->State = HAL_DCMI_STATE_BUSY;
01013 
01014   /* Write DCMI embedded synchronization unmask register */
01015     hdcmi->Instance->ESUR = (((uint32_t)SyncUnmask->FrameStartUnmask) |\
01016                              ((uint32_t)SyncUnmask->LineStartUnmask << DCMI_ESUR_LSU_Pos)|\
01017                              ((uint32_t)SyncUnmask->LineEndUnmask << DCMI_ESUR_LEU_Pos)|\
01018                              ((uint32_t)SyncUnmask->FrameEndUnmask << DCMI_ESUR_FEU_Pos));
01019 
01020   /* Change the DCMI state*/
01021   hdcmi->State = HAL_DCMI_STATE_READY;
01022 
01023   /* Process Unlocked */
01024   __HAL_UNLOCK(hdcmi);
01025 
01026   return HAL_OK;
01027 }
01028 
01029 
01030 
01031 
01032 /**
01033   * @}
01034   */
01035 
01036 /** @defgroup DCMI_Exported_Functions_Group4 Peripheral State functions
01037  *  @brief    Peripheral State functions
01038  *
01039 @verbatim
01040  ===============================================================================
01041                ##### Peripheral State and Errors functions #####
01042  ===============================================================================
01043     [..]
01044     This subsection provides functions allowing to
01045       (+) Check the DCMI state.
01046       (+) Get the specific DCMI error flag.
01047 
01048 @endverbatim
01049   * @{
01050   */
01051 
01052 /**
01053   * @brief  Return the DCMI state.
01054   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
01055   *               the configuration information for DCMI.
01056   * @retval HAL state
01057   */
01058 HAL_DCMI_StateTypeDef HAL_DCMI_GetState(DCMI_HandleTypeDef *hdcmi)
01059 {
01060   return hdcmi->State;
01061 }
01062 
01063 /**
01064   * @brief  Return the DCMI error code.
01065   * @param  hdcmi pointer to a DCMI_HandleTypeDef structure that contains
01066   *               the configuration information for DCMI.
01067   * @retval DCMI Error Code
01068   */
01069 uint32_t HAL_DCMI_GetError(DCMI_HandleTypeDef *hdcmi)
01070 {
01071   return hdcmi->ErrorCode;
01072 }
01073 
01074 /**
01075   * @}
01076   */
01077 
01078 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
01079 /**
01080   * @brief DCMI Callback registering
01081   * @param hdcmi        dcmi handle
01082   * @param CallbackID   dcmi Callback ID
01083   * @param hdcmi        pointer to dcmi Callback function
01084   * @retval status
01085   */
01086 HAL_StatusTypeDef HAL_DCMI_RegisterCallback(DCMI_HandleTypeDef *hdcmi, HAL_DCMI_CallbackIDTypeDef CallbackID, pDCMI_CallbackTypeDef pCallback)
01087 {
01088   HAL_StatusTypeDef status = HAL_OK;
01089 
01090   if(pCallback == NULL)
01091   {
01092     /* update the error code */
01093     hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
01094     /* update return status */
01095     status = HAL_ERROR;
01096   }
01097   else
01098   {
01099     if(hdcmi->State == HAL_DCMI_STATE_READY)
01100     {
01101       switch (CallbackID)
01102       {
01103       case HAL_DCMI_FRAME_EVENT_CB_ID :
01104         hdcmi->FrameEventCallback = pCallback;
01105         break;
01106 
01107       case HAL_DCMI_VSYNC_EVENT_CB_ID :
01108         hdcmi->VsyncEventCallback = pCallback;
01109         break;
01110 
01111       case HAL_DCMI_LINE_EVENT_CB_ID :
01112         hdcmi->LineEventCallback = pCallback;
01113         break;
01114 
01115       case HAL_DCMI_ERROR_CB_ID :
01116         hdcmi->ErrorCallback = pCallback;
01117         break;
01118 
01119       case HAL_DCMI_MSPINIT_CB_ID :
01120         hdcmi->MspInitCallback = pCallback;
01121         break;
01122 
01123       case HAL_DCMI_MSPDEINIT_CB_ID :
01124         hdcmi->MspDeInitCallback = pCallback;
01125         break;
01126 
01127       default :
01128         /* Return error status */
01129         status =  HAL_ERROR;
01130         break;
01131       }
01132     }
01133     else if(hdcmi->State == HAL_DCMI_STATE_RESET)
01134     {
01135       switch (CallbackID)
01136       {
01137       case HAL_DCMI_MSPINIT_CB_ID :
01138         hdcmi->MspInitCallback = pCallback;
01139         break;
01140 
01141       case HAL_DCMI_MSPDEINIT_CB_ID :
01142         hdcmi->MspDeInitCallback = pCallback;
01143         break;
01144 
01145       default :
01146         /* update the error code */
01147         hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
01148         /* update return status */
01149         status = HAL_ERROR;
01150         break;
01151       }
01152     }
01153     else
01154     {
01155       /* update the error code */
01156       hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
01157       /* update return status */
01158       status = HAL_ERROR;
01159     }
01160   }
01161 
01162   return status;
01163 }
01164 
01165 /**
01166   * @brief DCMI Callback Unregistering
01167   * @param hdcmi       dcmi handle
01168   * @param CallbackID  dcmi Callback ID
01169   * @retval status
01170   */
01171 HAL_StatusTypeDef HAL_DCMI_UnRegisterCallback(DCMI_HandleTypeDef *hdcmi, HAL_DCMI_CallbackIDTypeDef CallbackID)
01172 {
01173   HAL_StatusTypeDef status = HAL_OK;
01174 
01175   if(hdcmi->State == HAL_DCMI_STATE_READY)
01176   {
01177     switch (CallbackID)
01178     {
01179     case HAL_DCMI_FRAME_EVENT_CB_ID :
01180       hdcmi->FrameEventCallback = HAL_DCMI_FrameEventCallback;  /* Legacy weak  FrameEventCallback  */
01181       break;
01182 
01183     case HAL_DCMI_VSYNC_EVENT_CB_ID :
01184       hdcmi->VsyncEventCallback = HAL_DCMI_VsyncEventCallback;  /* Legacy weak VsyncEventCallback       */
01185       break;
01186 
01187     case HAL_DCMI_LINE_EVENT_CB_ID :
01188       hdcmi->LineEventCallback = HAL_DCMI_LineEventCallback;    /* Legacy weak LineEventCallback   */
01189       break;
01190 
01191     case HAL_DCMI_ERROR_CB_ID :
01192       hdcmi->ErrorCallback = HAL_DCMI_ErrorCallback;           /* Legacy weak ErrorCallback        */
01193       break;
01194 
01195     case HAL_DCMI_MSPINIT_CB_ID :
01196       hdcmi->MspInitCallback = HAL_DCMI_MspInit;
01197       break;
01198 
01199     case HAL_DCMI_MSPDEINIT_CB_ID :
01200       hdcmi->MspDeInitCallback = HAL_DCMI_MspDeInit;
01201       break;
01202 
01203     default :
01204       /* update the error code */
01205       hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
01206       /* update return status */
01207       status = HAL_ERROR;
01208       break;
01209     }
01210   }
01211   else if(hdcmi->State == HAL_DCMI_STATE_RESET)
01212   {
01213     switch (CallbackID)
01214     {
01215     case HAL_DCMI_MSPINIT_CB_ID :
01216       hdcmi->MspInitCallback = HAL_DCMI_MspInit;
01217       break;
01218 
01219     case HAL_DCMI_MSPDEINIT_CB_ID :
01220       hdcmi->MspDeInitCallback = HAL_DCMI_MspDeInit;
01221       break;
01222 
01223     default :
01224       /* update the error code */
01225       hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
01226       /* update return status */
01227       status = HAL_ERROR;
01228       break;
01229     }
01230   }
01231   else
01232   {
01233     /* update the error code */
01234     hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK;
01235     /* update return status */
01236     status = HAL_ERROR;
01237   }
01238 
01239   return status;
01240 }
01241 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
01242 
01243 /**
01244   * @}
01245   */
01246 
01247 /* Private functions ---------------------------------------------------------*/
01248 /** @defgroup DCMI_Private_Functions DCMI Private Functions
01249   * @{
01250   */
01251 
01252 /**
01253   * @brief  DMA conversion complete callback.
01254   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
01255   *              the configuration information for the specified DMA module.
01256   * @note When the size of the frame being captured by the DCMI peripheral is
01257   *       larger than 0xFFFF (DMA maximum transfer length), this API initiates
01258   *       another DMA transfer to copy the second half of the work buffer
01259   *       associated to the DCMI handle to the final destination buffer.
01260   * @retval None
01261   */
01262 static void DCMI_DMAXferCplt(DMA_HandleTypeDef *hdma)
01263 {
01264   uint32_t loop_length       = 0;     /* transfer length  */
01265   uint32_t * tmpBuffer_Dest  = NULL;
01266   uint32_t * tmpBuffer_Orig  = NULL;
01267 
01268   DCMI_HandleTypeDef* hdcmi = ( DCMI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
01269 
01270 
01271   if(hdcmi->XferCount != 0)
01272   {
01273     /* Manage second half buffer copy in case of big transfer */
01274 
01275     /* Decrement half-copies counter */
01276     hdcmi->XferCount--;
01277 
01278     /* Point at DCMI final destination */
01279     tmpBuffer_Dest = (uint32_t *)hdcmi->pBuffPtr;
01280 
01281     /* Point at DCMI circular buffer mid-location */
01282     tmpBuffer_Orig = (uint32_t *)hdcmi->pCircularBuffer;
01283     tmpBuffer_Orig +=  hdcmi->HalfCopyLength;
01284 
01285     /* copy half the buffer size */
01286     loop_length = hdcmi->HalfCopyLength;
01287 
01288     /* Save next entry to write at next half DMA transfer interruption */
01289     hdcmi->pBuffPtr += (uint32_t) loop_length*4;
01290     hdcmi->XferSize -= hdcmi->HalfCopyLength;
01291 
01292     /* Data copy from work buffer to final destination buffer */
01293     /* Enable the DMA Channel */
01294     if (HAL_DMA_Start_IT(hdcmi->DMAM2M_Handle, (uint32_t) tmpBuffer_Orig, (uint32_t) tmpBuffer_Dest, loop_length) != HAL_OK)
01295     {
01296       /* Update error code */
01297       hdcmi->ErrorCode |= HAL_DCMI_ERROR_DMA;
01298 
01299       /* Change DCMI state */
01300       hdcmi->State = HAL_DCMI_STATE_READY;
01301 
01302       /* Process Unlocked */
01303       __HAL_UNLOCK(hdcmi);
01304 
01305       /* DCMI error Callback */
01306 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
01307       /*Call registered DCMI error callback*/
01308       hdcmi->ErrorCallback(hdcmi);
01309 #else
01310       HAL_DCMI_ErrorCallback(hdcmi);
01311 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
01312     }
01313   }
01314   else
01315   {
01316     /* if End of frame IT is disabled */
01317     if((hdcmi->Instance->IER & DCMI_IT_FRAME) == RESET)
01318     {
01319       /* If End of Frame flag is set */
01320       if(__HAL_DCMI_GET_FLAG(hdcmi, DCMI_FLAG_FRAMERI) != RESET)
01321       {
01322         /* Clear the End of Frame flag */
01323         __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_FRAMERI);
01324 
01325         /* When snapshot mode, disable Vsync, Error and Overrun interrupts */
01326         if((hdcmi->Instance->CR & DCMI_CR_CM) == DCMI_MODE_SNAPSHOT)
01327         {
01328           /* Disable the Vsync, Error and Overrun interrupts */
01329           __HAL_DCMI_DISABLE_IT(hdcmi, DCMI_IT_LINE | DCMI_IT_VSYNC | DCMI_IT_ERR | DCMI_IT_OVR);
01330 
01331           hdcmi->State = HAL_DCMI_STATE_READY;
01332 
01333           /* Process Unlocked */
01334           __HAL_UNLOCK(hdcmi);
01335         }
01336 
01337         /* Frame Event Callback */
01338 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
01339         /*Call registered DCMI frame event callback*/
01340         hdcmi->FrameEventCallback(hdcmi);
01341 #else
01342         HAL_DCMI_FrameEventCallback(hdcmi);
01343 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
01344       }
01345     }
01346   }
01347 }
01348 
01349 
01350 /**
01351   * @brief  DMA Half Transfer complete callback.
01352   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
01353   *              the configuration information for the specified DMA module.
01354   * @note When the size of the frame being captured by the DCMI peripheral is
01355   *       larger than 0xFFFF (DMA maximum transfer length), this API initiates
01356   *       another DMA transfer to copy the first half of the work buffer
01357   *       associated to the DCMI handle to the final destination buffer.
01358   * @retval None
01359   */
01360 static void DCMI_DMAHalfXferCplt(DMA_HandleTypeDef *hdma)
01361 {
01362   uint32_t loop_length       = 0;     /* transfer length  */
01363   uint32_t * tmpBuffer_Dest  = NULL;
01364   uint32_t * tmpBuffer_Orig  = NULL;
01365 
01366   DCMI_HandleTypeDef* hdcmi = ( DCMI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
01367 
01368   if(hdcmi->XferCount != 0)
01369   {
01370     /* Manage first half buffer copy in case of big transfer */
01371 
01372     /* Decrement half-copies counter */
01373     hdcmi->XferCount--;
01374 
01375     /* Point at DCMI final destination */
01376     tmpBuffer_Dest = (uint32_t *)hdcmi->pBuffPtr;
01377 
01378     /* Point at DCMI circular buffer start */
01379     tmpBuffer_Orig = (uint32_t *)hdcmi->pCircularBuffer;
01380 
01381     /* copy half the buffer size */
01382     loop_length = hdcmi->HalfCopyLength;
01383 
01384     /* Save next entry to write at next DMA transfer interruption */
01385     hdcmi->pBuffPtr += (uint32_t) loop_length*4;
01386     hdcmi->XferSize -= hdcmi->HalfCopyLength;
01387 
01388     /* Data copy from work buffer to final destination buffer */
01389     /* Enable the DMA Channel */
01390     if (HAL_DMA_Start_IT(hdcmi->DMAM2M_Handle, (uint32_t) tmpBuffer_Orig, (uint32_t) tmpBuffer_Dest, loop_length) != HAL_OK)
01391     {
01392       /* Update error code */
01393       hdcmi->ErrorCode |= HAL_DCMI_ERROR_DMA;
01394 
01395       /* Change DCMI state */
01396       hdcmi->State = HAL_DCMI_STATE_READY;
01397 
01398       /* Process Unlocked */
01399       __HAL_UNLOCK(hdcmi);
01400 
01401       /* DCMI error Callback */
01402 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
01403       /*Call registered DCMI error callback*/
01404       hdcmi->ErrorCallback(hdcmi);
01405 #else
01406       HAL_DCMI_ErrorCallback(hdcmi);
01407 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
01408     }
01409   }
01410 }
01411 
01412 /**
01413   * @brief  DMA error callback
01414   * @param  hdma pointer to a DMA_HandleTypeDef structure that contains
01415   *              the configuration information for the specified DMA module.
01416   * @retval None
01417   */
01418 static void DCMI_DMAError(DMA_HandleTypeDef *hdma)
01419 {
01420   DCMI_HandleTypeDef* hdcmi = ( DCMI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
01421 
01422   /* Update error code */
01423   hdcmi->ErrorCode |= HAL_DCMI_ERROR_DMA;
01424 
01425   /* Change DCMI state */
01426   hdcmi->State = HAL_DCMI_STATE_READY;
01427 
01428   /* DCMI error Callback */
01429 #if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1)
01430   /*Call registered DCMI error callback*/
01431   hdcmi->ErrorCallback(hdcmi);
01432 #else
01433   HAL_DCMI_ErrorCallback(hdcmi);
01434 #endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */
01435 }
01436 
01437 /**
01438   * @brief Sub-buffers transfer size computation.
01439   * @note In the case of a frame size larger than the maximum DMA transfer length (0xFFFF),
01440   *       the tranfer from DCMI DR register to the final output buffer is carried out by a sequence
01441   *       of intermediate sub-copies to temporary buffers of size less than 0xFFFF.
01442   *       To optimize the number of DMA transfers, the API computes the temporary buffer
01443   *       size so that the latter is an even number less than 0xFFFF, that divides the final
01444   *       buffer size and is as high as possible. The API implements a sub-optimum solution for
01445   *       complexity's sake.
01446   * @note InputSize MUST be even.
01447   * @param  InputSize full buffer size (in 32-bit words)
01448   * @retval Transfer size (in 32-bit words)
01449   */
01450 static uint32_t DCMI_TransferSize(uint32_t InputSize)
01451 {
01452   uint32_t j = 1;
01453   uint32_t temp = InputSize;
01454   uint32_t aPrime[NPRIME] = {0};
01455   uint32_t output = 2; /* Want a result which is an even number */
01456 
01457 
01458   /* Develop InputSize in product of prime numbers */
01459 
01460   while (j < NPRIME)
01461   {
01462     if (temp < PrimeArray[j])
01463     {
01464       break;
01465     }
01466     while ((temp % PrimeArray[j]) == 0)
01467     {
01468       aPrime[j]++;
01469       temp /= PrimeArray[j];
01470     }
01471     j++;
01472   }
01473 
01474   /*  Search for the biggest even divisor less or equal to 0xFFFE = 65534 */
01475   aPrime[1] -= 1; /* output is initialized to 2, so don't count dividor 2 twice */
01476 
01477    /*  The algorithm below yields a sub-optimal solution
01478        but in an acceptable time.  */
01479     j =  NPRIME-1;
01480   while ((j > 0) &&  (output <= 0xFFFE))
01481   {
01482     while (aPrime[j] >0)
01483     {
01484       if (output * PrimeArray[j] > 0xFFFE)
01485       {
01486         break;
01487       }
01488       else
01489       {
01490         output *= PrimeArray[j];
01491         aPrime[j]--;
01492       }
01493     }
01494     j--;
01495   }
01496 
01497 
01498 
01499   return output;
01500 }
01501 
01502 
01503 /**
01504   * @}
01505   */
01506 
01507 /**
01508   * @}
01509   */
01510 
01511 /**
01512   * @}
01513   */
01514 
01515 #endif /* DCMI */
01516 #endif /* HAL_DCMI_MODULE_ENABLED */
01517 
01518 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/