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>© 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