FIX: Flash page size check is STM (or clone) specific (#14130)
[betaflight.git] / lib / main / STM32H7 / Drivers / STM32H7xx_HAL_Driver / Src / stm32h7xx_hal_opamp.c
blob5ebf16ea3bae91a4176d52430bf0066b83e999a5
1 /**
2 ******************************************************************************
3 * @file stm32h7xx_hal_opamp.c
4 * @author MCD Application Team
5 * @brief OPAMP HAL module driver.
6 * This file provides firmware functions to manage the following
7 * functionalities of the operational amplifier(s) peripheral:
8 * + OPAMP configuration
9 * + OPAMP calibration
10 * Thanks to
11 * + Initialization and de-initialization functions
12 * + IO operation functions
13 * + Peripheral Control functions
14 * + Peripheral State functions
16 @verbatim
17 ================================================================================
18 ##### OPAMP Peripheral Features #####
19 ================================================================================
21 [..] The device integrates 2 operational amplifiers OPAMP1 & OPAMP2
23 (#) The OPAMP(s) provides several exclusive running modes.
24 (++) Standalone mode
25 (++) Programmable Gain Amplifier (PGA) modes
26 (++) Follower mode
28 (#) Each OPAMP(s) can be configured in normal and high speed mode.
30 (#) The OPAMP(s) provide(s) calibration capabilities.
31 (++) Calibration aims at correcting some offset for running mode.
32 (++) The OPAMP uses either factory calibration settings OR user defined
33 calibration (trimming) settings (i.e. trimming mode).
34 (++) The user defined settings can be figured out using self calibration
35 handled by HAL_OPAMP_SelfCalibrate, HAL_OPAMPEx_SelfCalibrateAll
36 (++) HAL_OPAMP_SelfCalibrate:
37 (+++) Runs automatically the calibration in 2 steps.
38 (90% of VDDA for NMOS transistors, 10% of VDDA for PMOS transistors).
39 (As OPAMP is Rail-to-rail input/output, these 2 steps calibration is
40 appropriate and enough in most cases).
41 (+++) Runs automatically the calibration.
42 (+++) Enables the user trimming mode
43 (+++) Updates the init structure with trimming values with fresh calibration
44 results.
45 The user may store the calibration results for larger
46 (ex monitoring the trimming as a function of temperature
47 for instance)
48 (+++) HAL_OPAMPEx_SelfCalibrateAll
49 runs calibration of all OPAMPs in parallel to save search time.
51 (#) Running mode: Standalone mode
52 (++) Gain is set externally (gain depends on external loads).
53 (++) Follower mode also possible externally by connecting the inverting input to
54 the output.
56 (#) Running mode: Follower mode
57 (++) No Inverting Input is connected.
59 (#) Running mode: Programmable Gain Amplifier (PGA) mode
60 (Resistor feedback output)
61 (#) The OPAMP(s) output(s) can be internally connected to resistor feedback
62 output.
63 (#) OPAMP gain can be selected as :
65 (##) Gain of x2, x4, x8 or x16 for non inverting mode with:
66 (+++) VREF- referenced.
67 (+++) Filtering on VINM0, VREF- referenced.
68 (+++) VINM0 node for bias voltage and VINP0 for input signal.
69 (+++) VINM0 node for bias voltage and VINP0 for input signal, VINM1 node for filtering.
71 (##) Gain of x-1, x-3, x-7 or x-15 for inverting mode with:
72 (+++) VINM0 node for input signal and VINP0 for bias.
73 (+++) VINM0 node for input signal and VINP0 for bias voltage, VINM1 node for filtering.
75 (#) The OPAMPs inverting input can be selected according to the Reference Manual
76 "OPAMP functional description" chapter.
78 (#) The OPAMPs non inverting input can be selected according to the Reference Manual
79 "OPAMP functional description" chapter.
82 ##### How to use this driver #####
83 ================================================================================
84 [..]
86 *** High speed / normal power mode ***
87 ============================================
88 [..] To run in high speed mode:
90 (#) Configure the OPAMP using HAL_OPAMP_Init() function:
91 (++) Select OPAMP_POWERMODE_HIGHSPEED
92 (++) Otherwise select OPAMP_POWERMODE_NORMAL
94 *** Calibration ***
95 ============================================
96 [..] To run the OPAMP calibration self calibration:
98 (#) Start calibration using HAL_OPAMP_SelfCalibrate.
99 Store the calibration results.
101 *** Running mode ***
102 ============================================
104 [..] To use the OPAMP, perform the following steps:
106 (#) Fill in the HAL_OPAMP_MspInit() to
107 (++) Enable the OPAMP Peripheral clock using macro __HAL_RCC_OPAMP_CLK_ENABLE()
108 (++) Configure the OPAMP input AND output in analog mode using
109 HAL_GPIO_Init() to map the OPAMP output to the GPIO pin.
111 (#) Registrate Callbacks
112 (++) The compilation define USE_HAL_OPAMP_REGISTER_CALLBACKS when set to 1
113 allows the user to configure dynamically the driver callbacks.
115 (++) Use Functions @ref HAL_OPAMP_RegisterCallback() to register a user callback,
116 it allows to register following callbacks:
117 (+++) MspInitCallback : OPAMP MspInit.
118 (+++) MspDeInitCallback : OPAMP MspDeInit.
119 This function takes as parameters the HAL peripheral handle, the Callback ID
120 and a pointer to the user callback function.
122 (++) Use function @ref HAL_OPAMP_UnRegisterCallback() to reset a callback to the default
123 weak (surcharged) function. It allows to reset following callbacks:
124 (+++) MspInitCallback : OPAMP MspInit.
125 (+++) MspDeInitCallback : OPAMP MspDeInit.
126 (+++) All Callbacks
127 (#) Configure the OPAMP using HAL_OPAMP_Init() function:
128 (++) Select the mode
129 (++) Select the inverting input
130 (++) Select the non-inverting input
131 (++) If PGA mode is enabled, Select if inverting input is connected.
132 (++) Select either factory or user defined trimming mode.
133 (++) If the user-defined trimming mode is enabled, select PMOS & NMOS trimming values
134 (typically values set by HAL_OPAMP_SelfCalibrate function).
136 (#) Enable the OPAMP using HAL_OPAMP_Start() function.
138 (#) Disable the OPAMP using HAL_OPAMP_Stop() function.
140 (#) Lock the OPAMP in running mode using HAL_OPAMP_Lock() function.
141 Caution: On STM32H7, HAL OPAMP lock is software lock only (not
142 hardware lock as on some other STM32 devices)
144 (#) If needed, unlock the OPAMP using HAL_OPAMPEx_Unlock() function.
146 *** Running mode: change of configuration while OPAMP ON ***
147 ============================================
148 [..] To Re-configure OPAMP when OPAMP is ON (change on the fly)
149 (#) If needed, fill in the HAL_OPAMP_MspInit()
150 (++) This is the case for instance if you wish to use new OPAMP I/O
152 (#) Configure the OPAMP using HAL_OPAMP_Init() function:
153 (++) As in configure case, select first the parameters you wish to modify.
155 (#) Change from high speed mode to normal power mode (& vice versa) requires
156 first HAL_OPAMP_DeInit() (force OPAMP OFF) and then HAL_OPAMP_Init().
157 In other words, of OPAMP is ON, HAL_OPAMP_Init can NOT change power mode
158 alone.
160 @endverbatim
161 ******************************************************************************
162 Table 1. OPAMPs inverting/non-inverting inputs for the STM32H7 devices:
164 +------------------------------------------------------------------------|
165 | | | OPAMP1 | OPAMP2 |
166 |-----------------|---------|----------------------|---------------------|
167 | Inverting Input | VM_SEL | VINM0-> PC5 | VINM0-> PE8 |
168 | | | VINM1-> PA7 | VINM1-> PG1 |
169 | | | Internal: | Internal: |
170 | | | ADC1_IN9 | OPAMP2_OUT |
171 | | | ADC2_IN9 | PGA mode |
172 | | | OPAMP1_OUT | |
173 | | | PGA mode | |
174 |-----------------|---------|----------------------|---------------------|
175 | Non Inverting | VP_SEL | | |
176 | | | VP0 -> PB0 (GPIO) | VP0 -> PE9 (GPIO) |
177 | | | Internal: | Internal: |
178 | Input | | DAC1_CH1_int | DAC1_CH2_int |
179 | | | ADC1_IN8 | DAC2_CH1_int |
180 | | | ADC2_IN8 | COMP2_INP |
181 | | | COMP1_INP | |
182 +------------------------------------------------------------------------|
185 [..] Table 2. OPAMPs outputs for the STM32H7 devices:
187 +-------------------------------------------------------------------------
188 | | | OPAMP1 | OPAMP2 |
189 |-----------------|--------|-----------------------|---------------------|
190 | Output | VOUT | PC4 | PE7 |
191 | | | & ADC1_IN4| | & COMP2_INN7 if |
192 | | | ADC2_IN4 |connected internally |
193 | | | COMP1_INN7 if | |
194 | | | connected internally | |
195 |-----------------|--------|-----------------------|---------------------|
196 ******************************************************************************
197 * @attention
199 * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
200 * All rights reserved.</center></h2>
202 * This software component is licensed by ST under BSD 3-Clause license,
203 * the "License"; You may not use this file except in compliance with the
204 * License. You may obtain a copy of the License at:
205 * opensource.org/licenses/BSD-3-Clause
207 ******************************************************************************
210 /* Includes ------------------------------------------------------------------*/
211 #include "stm32h7xx_hal.h"
213 /** @addtogroup STM32H7xx_HAL_Driver
214 * @{
217 /** @defgroup OPAMP OPAMP
218 * @brief OPAMP module driver
219 * @{
222 #ifdef HAL_OPAMP_MODULE_ENABLED
224 /* Private types -------------------------------------------------------------*/
225 /* Private variables ---------------------------------------------------------*/
226 /* Private constants ---------------------------------------------------------*/
227 /** @addtogroup OPAMP_Private_Constants
228 * @{
231 /* CSR register reset value */
232 #define OPAMP_CSR_RESET_VALUE 0x00000000U
234 /* CSR Init masks */
236 #define OPAMP_CSR_INIT_MASK_PGA (OPAMP_CSR_OPAHSM | OPAMP_CSR_VMSEL | OPAMP_CSR_PGGAIN | OPAMP_CSR_PGGAIN \
237 | OPAMP_CSR_VPSEL | OPAMP_CSR_USERTRIM)
240 #define OPAMP_CSR_INIT_MASK_FOLLOWER (OPAMP_CSR_OPAHSM | OPAMP_CSR_VMSEL| OPAMP_CSR_VPSEL \
241 | OPAMP_CSR_USERTRIM)
244 #define OPAMP_CSR_INIT_MASK_STANDALONE (OPAMP_CSR_OPAHSM | OPAMP_CSR_VMSEL | OPAMP_CSR_VPSEL \
245 | OPAMP_CSR_VMSEL | OPAMP_CSR_USERTRIM)
247 * @}
250 /* Private macros ------------------------------------------------------------*/
251 /* Private functions ---------------------------------------------------------*/
252 /* Exported functions --------------------------------------------------------*/
254 /** @defgroup OPAMP_Exported_Functions OPAMP Exported Functions
255 * @{
258 /** @defgroup OPAMP_Exported_Functions_Group1 Initialization and de-initialization functions
259 * @brief Initialization and Configuration functions
261 @verbatim
262 ==============================================================================
263 ##### Initialization and de-initialization functions #####
264 ==============================================================================
266 @endverbatim
267 * @{
271 * @brief Initialize the OPAMP according to the specified
272 * parameters in the OPAMP_InitTypeDef and initialize the associated handle.
273 * @note If the selected opamp is locked, initialization can't be performed.
274 * To unlock the configuration, perform a system reset.
275 * @param hopamp OPAMP handle
276 * @retval HAL status
278 HAL_StatusTypeDef HAL_OPAMP_Init(OPAMP_HandleTypeDef *hopamp)
280 HAL_StatusTypeDef status = HAL_OK;
281 uint32_t updateotrlpotr;
283 /* Check the OPAMP handle allocation and lock status */
284 /* Init not allowed if calibration is ongoing */
285 if(hopamp == NULL)
287 return HAL_ERROR;
289 else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
291 return HAL_ERROR;
293 else if(hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)
295 return HAL_ERROR;
297 else
299 /* Check the parameter */
300 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
302 /* Set OPAMP parameters */
303 assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode));
304 assert_param(IS_OPAMP_FUNCTIONAL_NORMALMODE(hopamp->Init.Mode));
305 assert_param(IS_OPAMP_NONINVERTING_INPUT(hopamp->Init.NonInvertingInput));
307 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
308 if(hopamp->State == HAL_OPAMP_STATE_RESET)
310 if(hopamp->MspInitCallback == NULL)
312 hopamp->MspInitCallback = HAL_OPAMP_MspInit;
315 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
316 if ((hopamp->Init.Mode) == OPAMP_STANDALONE_MODE)
318 assert_param(IS_OPAMP_INVERTING_INPUT_STANDALONE(hopamp->Init.InvertingInput));
321 if ((hopamp->Init.Mode) == OPAMP_PGA_MODE)
323 assert_param(IS_OPAMP_PGA_GAIN(hopamp->Init.PgaGain));
324 assert_param(IS_OPAMP_PGACONNECT(hopamp->Init.PgaConnect));
328 assert_param(IS_OPAMP_TRIMMING(hopamp->Init.UserTrimming));
330 if ((hopamp->Init.UserTrimming) == OPAMP_TRIMMING_USER)
332 if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
334 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueP));
335 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueN));
337 else
339 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValuePHighSpeed));
340 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueNHighSpeed));
344 if(hopamp->State == HAL_OPAMP_STATE_RESET)
346 /* Allocate lock resource and initialize it */
347 hopamp->Lock = HAL_UNLOCKED;
350 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
351 hopamp->MspInitCallback(hopamp);
352 #else
353 /* Call MSP init function */
354 HAL_OPAMP_MspInit(hopamp);
355 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
357 /* Set operating mode */
358 CLEAR_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALON);
359 /* In PGA mode InvertingInput is Not Applicable */
360 if (hopamp->Init.Mode == OPAMP_PGA_MODE)
362 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_INIT_MASK_PGA, \
363 hopamp->Init.PowerMode | \
364 hopamp->Init.Mode | \
365 hopamp->Init.PgaGain | \
366 hopamp->Init.PgaConnect | \
367 hopamp->Init.NonInvertingInput | \
368 hopamp->Init.UserTrimming);
371 if (hopamp->Init.Mode == OPAMP_FOLLOWER_MODE)
373 /* In Follower mode InvertingInput is Not Applicable */
374 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_INIT_MASK_FOLLOWER, \
375 hopamp->Init.PowerMode | \
376 hopamp->Init.Mode | \
377 hopamp->Init.NonInvertingInput | \
378 hopamp->Init.UserTrimming);
381 if (hopamp->Init.Mode == OPAMP_STANDALONE_MODE)
383 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_INIT_MASK_STANDALONE, \
384 hopamp->Init.PowerMode | \
385 hopamp->Init.Mode | \
386 hopamp->Init.InvertingInput | \
387 hopamp->Init.NonInvertingInput | \
388 hopamp->Init.UserTrimming);
391 if (hopamp->Init.UserTrimming == OPAMP_TRIMMING_USER)
393 /* Set power mode and associated calibration parameters */
394 if (hopamp->Init.PowerMode != OPAMP_POWERMODE_HIGHSPEED)
396 /* OPAMP_POWERMODE_NORMAL */
397 /* Set calibration mode (factory or user) and values for */
398 /* transistors differential pair high (PMOS) and low (NMOS) for */
399 /* normal mode. */
400 updateotrlpotr = (((hopamp->Init.TrimmingValueP) << (OPAMP_INPUT_NONINVERTING)) \
401 | (hopamp->Init.TrimmingValueN));
402 MODIFY_REG(hopamp->Instance->OTR, OPAMP_OTR_TRIMOFFSETN | OPAMP_OTR_TRIMOFFSETP, updateotrlpotr);
404 else
406 /* OPAMP_POWERMODE_HIGHSPEED*/
407 /* transistors differential pair high (PMOS) and low (NMOS) for */
408 /* high speed mode. */
409 updateotrlpotr = (((hopamp->Init.TrimmingValuePHighSpeed) << (OPAMP_INPUT_NONINVERTING)) \
410 | (hopamp->Init.TrimmingValueNHighSpeed));
411 MODIFY_REG(hopamp->Instance->HSOTR, OPAMP_OTR_TRIMOFFSETN | OPAMP_OTR_TRIMOFFSETP, updateotrlpotr);
415 /* Update the OPAMP state*/
416 if (hopamp->State == HAL_OPAMP_STATE_RESET)
418 /* From RESET state to READY State */
419 hopamp->State = HAL_OPAMP_STATE_READY;
421 /* else: remain in READY or BUSY state (no update) */
422 return status;
427 * @brief DeInitialize the OPAMP peripheral
428 * @note Deinitialization can be performed if the OPAMP configuration is locked.
429 * (the lock is SW in H7)
430 * @param hopamp OPAMP handle
431 * @retval HAL status
433 HAL_StatusTypeDef HAL_OPAMP_DeInit(OPAMP_HandleTypeDef *hopamp)
435 HAL_StatusTypeDef status = HAL_OK;
437 /* Check the OPAMP handle allocation */
438 /* DeInit not allowed if calibration is on going */
439 if(hopamp == NULL)
441 status = HAL_ERROR;
443 else if(hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)
445 status = HAL_ERROR;
447 else
449 /* Check the parameter */
450 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
452 /* Set OPAMP_CSR register to reset value */
453 WRITE_REG(hopamp->Instance->CSR, OPAMP_CSR_RESET_VALUE);
455 /* DeInit the low level hardware */
456 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
457 if(hopamp->MspDeInitCallback == NULL)
459 hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit;
461 /* DeInit the low level hardware */
462 hopamp->MspDeInitCallback(hopamp);
463 #else
464 HAL_OPAMP_MspDeInit(hopamp);
465 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
467 /* Update the OPAMP state*/
468 hopamp->State = HAL_OPAMP_STATE_RESET;
469 /* Process unlocked */
470 __HAL_UNLOCK(hopamp);
474 return status;
479 * @brief Initialize the OPAMP MSP.
480 * @param hopamp OPAMP handle
481 * @retval None
483 __weak void HAL_OPAMP_MspInit(OPAMP_HandleTypeDef *hopamp)
485 /* Prevent unused argument(s) compilation warning */
486 UNUSED(hopamp);
488 /* NOTE : This function should not be modified, when the callback is needed,
489 the function "HAL_OPAMP_MspInit()" must be implemented in the user file.
494 * @brief DeInitialize OPAMP MSP.
495 * @param hopamp OPAMP handle
496 * @retval None
498 __weak void HAL_OPAMP_MspDeInit(OPAMP_HandleTypeDef *hopamp)
500 /* Prevent unused argument(s) compilation warning */
501 UNUSED(hopamp);
502 /* NOTE : This function should not be modified, when the callback is needed,
503 the function "HAL_OPAMP_MspDeInit()" must be implemented in the user file.
508 * @}
512 /** @defgroup OPAMP_Exported_Functions_Group2 IO operation functions
513 * @brief IO operation functions
515 @verbatim
516 ===============================================================================
517 ##### IO operation functions #####
518 ===============================================================================
519 [..]
520 This subsection provides a set of functions allowing to manage the OPAMP
521 start, stop and calibration actions.
523 @endverbatim
524 * @{
528 * @brief Start the OPAMP.
529 * @param hopamp OPAMP handle
530 * @retval HAL status
532 HAL_StatusTypeDef HAL_OPAMP_Start(OPAMP_HandleTypeDef *hopamp)
534 HAL_StatusTypeDef status = HAL_OK;
536 /* Check the OPAMP handle allocation */
537 /* Check if OPAMP locked */
538 if(hopamp == NULL)
540 status = HAL_ERROR;
542 else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
544 status = HAL_ERROR;
546 else
548 /* Check the parameter */
549 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
551 if(hopamp->State == HAL_OPAMP_STATE_READY)
553 /* Enable the selected opamp */
554 SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
556 /* Update the OPAMP state*/
557 /* From HAL_OPAMP_STATE_READY to HAL_OPAMP_STATE_BUSY */
558 hopamp->State = HAL_OPAMP_STATE_BUSY;
560 else
562 status = HAL_ERROR;
566 return status;
570 * @brief Stop the OPAMP.
571 * @param hopamp OPAMP handle
572 * @retval HAL status
574 HAL_StatusTypeDef HAL_OPAMP_Stop(OPAMP_HandleTypeDef *hopamp)
576 HAL_StatusTypeDef status = HAL_OK;
578 /* Check the OPAMP handle allocation */
579 /* Check if OPAMP locked */
580 /* Check if OPAMP calibration ongoing */
581 if(hopamp == NULL)
583 status = HAL_ERROR;
585 else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
587 status = HAL_ERROR;
589 else if(hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)
591 status = HAL_ERROR;
593 else
595 /* Check the parameter */
596 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
598 if(hopamp->State == HAL_OPAMP_STATE_BUSY)
600 /* Disable the selected opamp */
601 CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
603 /* Update the OPAMP state*/
604 /* From HAL_OPAMP_STATE_BUSY to HAL_OPAMP_STATE_READY*/
605 hopamp->State = HAL_OPAMP_STATE_READY;
607 else
609 status = HAL_ERROR;
612 return status;
616 * @brief Run the self calibration of one OPAMP.
617 * @note Calibration is performed in the mode specified in OPAMP init
618 * structure (mode normal or high-speed). To perform calibration for
619 * both modes, repeat this function twice after OPAMP init structure
620 * accordingly updated.
621 * @param hopamp handle
622 * @retval Updated offset trimming values (PMOS & NMOS), user trimming is enabled
623 * @retval HAL status
625 HAL_StatusTypeDef HAL_OPAMP_SelfCalibrate(OPAMP_HandleTypeDef *hopamp)
628 HAL_StatusTypeDef status = HAL_OK;
630 uint32_t trimmingvaluen;
631 uint32_t trimmingvaluep;
632 uint32_t delta;
633 uint32_t opampmode;
635 __IO uint32_t* tmp_opamp_reg_trimming; /* Selection of register of trimming depending on power mode: OTR or HSOTR */
637 /* Check the OPAMP handle allocation */
638 /* Check if OPAMP locked */
639 if(hopamp == NULL)
641 status = HAL_ERROR;
643 else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
645 status = HAL_ERROR;
647 else
650 /* Check if OPAMP in calibration mode and calibration not yet enable */
651 if(hopamp->State == HAL_OPAMP_STATE_READY)
653 /* Check the parameter */
654 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
655 assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode));
657 opampmode = READ_BIT(hopamp->Instance->CSR,OPAMP_CSR_VMSEL);
659 /* Use of standalone mode */
660 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_VMSEL, OPAMP_STANDALONE_MODE);
661 /* user trimming values are used for offset calibration */
662 SET_BIT(hopamp->Instance->CSR, OPAMP_CSR_USERTRIM);
664 /* Select trimming settings depending on power mode */
665 if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
667 tmp_opamp_reg_trimming = &hopamp->Instance->OTR;
670 else
672 /* high speed Mode */
673 tmp_opamp_reg_trimming = &hopamp->Instance->HSOTR;
677 /* Enable calibration */
678 SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_CALON);
680 /* Force internal reference on VP */
681 SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_FORCEVP);
683 /* 1st calibration - N */
684 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_90VDDA);
686 /* Enable the selected opamp */
687 SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
689 /* Init trimming counter */
690 /* Medium value */
691 trimmingvaluen = 16U;
692 delta = 8U;
694 while (delta != 0U)
696 /* Set candidate trimming */
697 /* OPAMP_POWERMODE_NORMAL */
698 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen);
700 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
701 /* Offset trim time: during calibration, minimum time needed between */
702 /* two steps to have 1 mV accuracy */
703 HAL_Delay(OPAMP_TRIMMING_DELAY);
705 if (READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT) != 0U)
707 /* OPAMP_CSR_CALOUT is HIGH try higher trimming */
708 trimmingvaluen += delta;
710 else
712 /* OPAMP_CSR_CALOUT is LOW try lower trimming */
713 trimmingvaluen -= delta;
715 /* Divide range by 2 to continue dichotomy sweep */
716 delta >>= 1;
719 /* Still need to check if right calibration is current value or one step below */
720 /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */
722 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen);
724 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
725 /* Offset trim time: during calibration, minimum time needed between */
726 /* two steps to have 1 mV accuracy */
727 HAL_Delay(OPAMP_TRIMMING_DELAY);
729 if ((READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT)) != 0U)
731 /* Trimming value is actually one value more */
732 trimmingvaluen++;
733 /* Set right trimming */
734 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen);
737 /* 2nd calibration - P */
738 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_10VDDA);
740 /* Init trimming counter */
741 /* Medium value */
742 trimmingvaluep = 16U;
743 delta = 8U;
745 while (delta != 0U)
747 /* Set candidate trimming */
748 /* OPAMP_POWERMODE_NORMAL */
749 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep<<OPAMP_INPUT_NONINVERTING));
751 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
752 /* Offset trim time: during calibration, minimum time needed between */
753 /* two steps to have 1 mV accuracy */
754 HAL_Delay(OPAMP_TRIMMING_DELAY);
756 if (READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT)!= 0U)
758 /* OPAMP_CSR_CALOUT is HIGH try higher trimming */
759 trimmingvaluep += delta;
761 else
763 /* OPAMP_CSR_CALOUT is LOW try lower trimming */
764 trimmingvaluep -= delta;
767 /* Divide range by 2 to continue dichotomy sweep */
768 delta >>= 1U;
771 /* Still need to check if right calibration is current value or one step below */
772 /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */
773 /* Set candidate trimming */
774 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep<<OPAMP_INPUT_NONINVERTING));
776 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
777 /* Offset trim time: during calibration, minimum time needed between */
778 /* two steps to have 1 mV accuracy */
779 HAL_Delay(OPAMP_TRIMMING_DELAY);
781 if (READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT) != 0U)
783 /* Trimming value is actually one value more */
784 trimmingvaluep++;
785 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep<<OPAMP_INPUT_NONINVERTING));
788 /* Disable calibration & set normal mode (operating mode) */
789 CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_CALON);
791 /* Disable the OPAMP */
792 CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
794 /* Set operating mode back */
795 CLEAR_BIT(hopamp->Instance->CSR, OPAMP_CSR_FORCEVP);
797 /* Self calibration is successful */
798 /* Store calibration(user trimming) results in init structure. */
800 /* Set user trimming mode */
801 hopamp->Init.UserTrimming = OPAMP_TRIMMING_USER;
803 /* Affect calibration parameters depending on mode normal/high speed */
804 if (hopamp->Init.PowerMode != OPAMP_POWERMODE_HIGHSPEED)
806 /* Write calibration result N */
807 hopamp->Init.TrimmingValueN = trimmingvaluen;
808 /* Write calibration result P */
809 hopamp->Init.TrimmingValueP = trimmingvaluep;
811 else
813 /* Write calibration result N */
814 hopamp->Init.TrimmingValueNHighSpeed = trimmingvaluen;
815 /* Write calibration result P */
816 hopamp->Init.TrimmingValuePHighSpeed = trimmingvaluep;
818 /* Restore OPAMP mode after calibration */
819 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_VMSEL, opampmode);
822 else
824 /* OPAMP can not be calibrated from this mode */
825 status = HAL_ERROR;
828 return status;
832 * @}
835 /** @defgroup OPAMP_Exported_Functions_Group3 Peripheral Control functions
836 * @brief Peripheral Control functions
838 @verbatim
839 ===============================================================================
840 ##### Peripheral Control functions #####
841 ===============================================================================
842 [..]
843 This subsection provides a set of functions allowing to control the OPAMP data
844 transfers.
848 @endverbatim
849 * @{
853 * @brief Lock the selected OPAMP configuration.
854 * @note On STM32H7, HAL OPAMP lock is software lock only (in
855 * contrast of hardware lock available on some other STM32
856 * devices)
857 * @param hopamp OPAMP handle
858 * @retval HAL status
860 HAL_StatusTypeDef HAL_OPAMP_Lock(OPAMP_HandleTypeDef *hopamp)
862 HAL_StatusTypeDef status = HAL_OK;
864 /* Check the OPAMP handle allocation */
865 /* Check if OPAMP locked */
866 /* OPAMP can be locked when enabled and running in normal mode */
867 /* It is meaningless otherwise */
868 if(hopamp == NULL)
870 status = HAL_ERROR;
873 else if(hopamp->State != HAL_OPAMP_STATE_BUSY)
875 status = HAL_ERROR;
877 else
879 /* Check the parameter */
880 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
882 /* OPAMP state changed to locked */
883 hopamp->State = HAL_OPAMP_STATE_BUSYLOCKED;
885 return status;
889 * @brief Return the OPAMP factory trimming value.
890 * @note On STM32H7 OPAMP, user can retrieve factory trimming if
891 * OPAMP has never been set to user trimming before.
892 * Therefore, this function must be called when OPAMP init
893 * parameter "UserTrimming" is set to trimming factory,
894 * and before OPAMP calibration (function
895 * "HAL_OPAMP_SelfCalibrate()").
896 * Otherwise, factory trimming value cannot be retrieved and
897 * error status is returned.
898 * @param hopamp OPAMP handle
899 * @param trimmingoffset Trimming offset (P or N)
900 * This parameter must be a value of @ref OPAMP_FactoryTrimming
901 * @note Calibration parameter retrieved is corresponding to the mode
902 * specified in OPAMP init structure (mode normal or high-speed).
903 * To retrieve calibration parameters for both modes, repeat this
904 * function after OPAMP init structure accordingly updated.
905 * @retval Trimming value (P or N): range: 0->31
906 * or OPAMP_FACTORYTRIMMING_DUMMY if trimming value is not available
909 HAL_OPAMP_TrimmingValueTypeDef HAL_OPAMP_GetTrimOffset (OPAMP_HandleTypeDef *hopamp, uint32_t trimmingoffset)
911 HAL_OPAMP_TrimmingValueTypeDef trimmingvalue;
912 __IO uint32_t* tmp_opamp_reg_trimming; /* Selection of register of trimming depending on power mode: OTR or LPOTR */
914 /* Check the OPAMP handle allocation */
915 /* Value can be retrieved in HAL_OPAMP_STATE_READY state */
916 if(hopamp == NULL)
918 return OPAMP_FACTORYTRIMMING_DUMMY;
921 if(hopamp->State == HAL_OPAMP_STATE_READY)
923 /* Check the parameter */
924 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
925 assert_param(IS_OPAMP_FACTORYTRIMMING(trimmingoffset));
926 assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode));
928 /* Check the trimming mode */
929 if (READ_BIT(hopamp->Instance->CSR,OPAMP_CSR_USERTRIM)!= 0U)
931 /* This function must called when OPAMP init parameter "UserTrimming" */
932 /* is set to trimming factory, and before OPAMP calibration (function */
933 /* "HAL_OPAMP_SelfCalibrate()"). */
934 /* Otherwise, factory trimming value cannot be retrieved and error */
935 /* status is returned. */
936 trimmingvalue = OPAMP_FACTORYTRIMMING_DUMMY;
938 else
940 /* Select trimming settings depending on power mode */
941 if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
943 tmp_opamp_reg_trimming = &hopamp->Instance->OTR;
945 else
947 tmp_opamp_reg_trimming = &hopamp->Instance->HSOTR;
950 /* Get factory trimming */
951 if (trimmingoffset == OPAMP_FACTORYTRIMMING_P)
953 /* OPAMP_FACTORYTRIMMING_P */
954 trimmingvalue = ((*tmp_opamp_reg_trimming) & OPAMP_OTR_TRIMOFFSETP) >> OPAMP_INPUT_NONINVERTING;
956 else
958 /* OPAMP_FACTORYTRIMMING_N */
959 trimmingvalue = (*tmp_opamp_reg_trimming) & OPAMP_OTR_TRIMOFFSETN;
963 else
965 return OPAMP_FACTORYTRIMMING_DUMMY;
968 return trimmingvalue;
972 * @}
976 /** @defgroup OPAMP_Exported_Functions_Group4 Peripheral State functions
977 * @brief Peripheral State functions
979 @verbatim
980 ===============================================================================
981 ##### Peripheral State functions #####
982 ===============================================================================
983 [..]
984 This subsection permits to get in run-time the status of the peripheral.
986 @endverbatim
987 * @{
991 * @brief Return the OPAMP handle state.
992 * @param hopamp OPAMP handle
993 * @retval HAL state
995 HAL_OPAMP_StateTypeDef HAL_OPAMP_GetState(OPAMP_HandleTypeDef *hopamp)
997 /* Check the OPAMP handle allocation */
998 if(hopamp == NULL)
1000 return HAL_OPAMP_STATE_RESET;
1003 /* Check the parameter */
1004 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
1006 /* Return OPAMP handle state */
1007 return hopamp->State;
1011 * @}
1014 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
1016 * @brief Register a User OPAMP Callback
1017 * To be used instead of the weak (surcharged) predefined callback
1018 * @param hopamp OPAMP handle
1019 * @param CallbackId ID of the callback to be registered
1020 * This parameter can be one of the following values:
1021 * @arg @ref HAL_OPAMP_MSPINIT_CB_ID OPAMP MspInit callback ID
1022 * @arg @ref HAL_OPAMP_MSPDEINIT_CB_ID OPAMP MspDeInit callback ID
1023 * @param pCallback pointer to the Callback function
1024 * @retval status
1026 HAL_StatusTypeDef HAL_OPAMP_RegisterCallback (OPAMP_HandleTypeDef *hopamp, HAL_OPAMP_CallbackIDTypeDef CallbackId, pOPAMP_CallbackTypeDef pCallback)
1028 HAL_StatusTypeDef status = HAL_OK;
1030 if(pCallback == NULL)
1032 return HAL_ERROR;
1035 /* Process locked */
1036 __HAL_LOCK(hopamp);
1038 if(hopamp->State == HAL_OPAMP_STATE_READY)
1040 switch (CallbackId)
1042 case HAL_OPAMP_MSPINIT_CB_ID :
1043 hopamp->MspInitCallback = pCallback;
1044 break;
1045 case HAL_OPAMP_MSPDEINIT_CB_ID :
1046 hopamp->MspDeInitCallback = pCallback;
1047 break;
1048 default :
1049 /* update return status */
1050 status = HAL_ERROR;
1051 break;
1054 else if (hopamp->State == HAL_OPAMP_STATE_RESET)
1056 switch (CallbackId)
1058 case HAL_OPAMP_MSPINIT_CB_ID :
1059 hopamp->MspInitCallback = pCallback;
1060 break;
1061 case HAL_OPAMP_MSPDEINIT_CB_ID :
1062 hopamp->MspDeInitCallback = pCallback;
1063 break;
1064 default :
1065 /* update return status */
1066 status = HAL_ERROR;
1067 break;
1070 else
1072 /* update return status */
1073 status = HAL_ERROR;
1076 /* Release Lock */
1077 __HAL_UNLOCK(hopamp);
1078 return status;
1082 * @brief Unregister a User OPAMP Callback
1083 * OPAMP Callback is redirected to the weak (surcharged) predefined callback
1084 * @param hopamp OPAMP handle
1085 * @param CallbackId ID of the callback to be unregistered
1086 * This parameter can be one of the following values:
1087 * @arg @ref HAL_OPAMP_MSPINIT_CB_ID OPAMP MSP Init Callback ID
1088 * @arg @ref HAL_OPAMP_MSPDEINIT_CB_ID OPAMP MSP DeInit Callback ID
1089 * @arg @ref HAL_OPAMP_ALL_CB_ID OPAMP All Callbacks
1090 * @retval status
1092 HAL_StatusTypeDef HAL_OPAMP_UnRegisterCallback (OPAMP_HandleTypeDef *hopamp, HAL_OPAMP_CallbackIDTypeDef CallbackId)
1094 HAL_StatusTypeDef status = HAL_OK;
1096 /* Process locked */
1097 __HAL_LOCK(hopamp);
1099 if(hopamp->State == HAL_OPAMP_STATE_READY)
1101 switch (CallbackId)
1103 case HAL_OPAMP_MSPINIT_CB_ID :
1104 hopamp->MspInitCallback = HAL_OPAMP_MspInit;
1105 break;
1106 case HAL_OPAMP_MSPDEINIT_CB_ID :
1107 hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit;
1108 break;
1109 case HAL_OPAMP_ALL_CB_ID :
1110 hopamp->MspInitCallback = HAL_OPAMP_MspInit;
1111 hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit;
1112 break;
1113 default :
1114 /* update return status */
1115 status = HAL_ERROR;
1116 break;
1119 else if (hopamp->State == HAL_OPAMP_STATE_RESET)
1121 switch (CallbackId)
1123 case HAL_OPAMP_MSPINIT_CB_ID :
1124 hopamp->MspInitCallback = HAL_OPAMP_MspInit;
1125 break;
1126 case HAL_OPAMP_MSPDEINIT_CB_ID :
1127 hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit;
1128 break;
1129 default :
1130 /* update return status */
1131 status = HAL_ERROR;
1132 break;
1135 else
1137 /* update return status */
1138 status = HAL_ERROR;
1141 /* Release Lock */
1142 __HAL_UNLOCK(hopamp);
1143 return status;
1146 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
1148 * @}
1152 * @}
1154 #endif /* HAL_OPAMP_MODULE_ENABLED */
1156 * @}
1160 * @}
1163 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/