Merge maintenance-8.x.x fixes into master
[inav.git] / lib / main / STM32H7 / Drivers / STM32H7xx_HAL_Driver / Src / stm32h7xx_hal_opamp.c
blob5bb8080317f6ab6fe1f802f407f8e037f2bb05ae
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 * + Initialization and de-initialization functions
9 * + IO operation functions
10 * + Peripheral Control functions
11 * + Peripheral State functions
13 ******************************************************************************
14 * @attention
16 * Copyright (c) 2017 STMicroelectronics.
17 * All rights reserved.
19 * This software is licensed under terms that can be found in the LICENSE file
20 * in the root directory of this software component.
21 * If no LICENSE file comes with this software, it is provided AS-IS.
23 ******************************************************************************
24 @verbatim
25 ================================================================================
26 ##### OPAMP Peripheral Features #####
27 ================================================================================
29 [..] The device integrates 2 operational amplifiers OPAMP1 & OPAMP2
31 (#) The OPAMP(s) provides several exclusive running modes.
32 (++) Standalone mode
33 (++) Programmable Gain Amplifier (PGA) modes
34 (++) Follower mode
36 (#) Each OPAMP(s) can be configured in normal and high speed mode.
38 (#) The OPAMP(s) provide(s) calibration capabilities.
39 (++) Calibration aims at correcting some offset for running mode.
40 (++) The OPAMP uses either factory calibration settings OR user defined
41 calibration (trimming) settings (i.e. trimming mode).
42 (++) The user defined settings can be figured out using self calibration
43 handled by HAL_OPAMP_SelfCalibrate, HAL_OPAMPEx_SelfCalibrateAll
44 (++) HAL_OPAMP_SelfCalibrate:
45 (+++) Runs automatically the calibration in 2 steps.
46 (90% of VDDA for NMOS transistors, 10% of VDDA for PMOS transistors).
47 (As OPAMP is Rail-to-rail input/output, these 2 steps calibration is
48 appropriate and enough in most cases).
49 (+++) Runs automatically the calibration.
50 (+++) Enables the user trimming mode
51 (+++) Updates the init structure with trimming values with fresh calibration
52 results.
53 The user may store the calibration results for larger
54 (ex monitoring the trimming as a function of temperature
55 for instance)
56 (+++) HAL_OPAMPEx_SelfCalibrateAll
57 runs calibration of all OPAMPs in parallel to save search time.
59 (#) Running mode: Standalone mode
60 (++) Gain is set externally (gain depends on external loads).
61 (++) Follower mode also possible externally by connecting the inverting input to
62 the output.
64 (#) Running mode: Follower mode
65 (++) No Inverting Input is connected.
67 (#) Running mode: Programmable Gain Amplifier (PGA) mode
68 (Resistor feedback output)
69 (#) The OPAMP(s) output(s) can be internally connected to resistor feedback
70 output.
71 (#) OPAMP gain can be selected as :
73 (##) Gain of x2, x4, x8 or x16 for non inverting mode with:
74 (+++) VREF- referenced.
75 (+++) Filtering on VINM0, VREF- referenced.
76 (+++) VINM0 node for bias voltage and VINP0 for input signal.
77 (+++) VINM0 node for bias voltage and VINP0 for input signal, VINM1 node for filtering.
79 (##) Gain of x-1, x-3, x-7 or x-15 for inverting mode with:
80 (+++) VINM0 node for input signal and VINP0 for bias.
81 (+++) VINM0 node for input signal and VINP0 for bias voltage, VINM1 node for filtering.
83 (#) The OPAMPs inverting input can be selected according to the Reference Manual
84 "OPAMP functional description" chapter.
86 (#) The OPAMPs non inverting input can be selected according to the Reference Manual
87 "OPAMP functional description" chapter.
90 ##### How to use this driver #####
91 ================================================================================
92 [..]
94 *** High speed / normal power mode ***
95 ============================================
96 [..] To run in high speed mode:
98 (#) Configure the OPAMP using HAL_OPAMP_Init() function:
99 (++) Select OPAMP_POWERMODE_HIGHSPEED
100 (++) Otherwise select OPAMP_POWERMODE_NORMAL
102 *** Calibration ***
103 ============================================
104 [..] To run the OPAMP calibration self calibration:
106 (#) Start calibration using HAL_OPAMP_SelfCalibrate.
107 Store the calibration results.
109 *** Running mode ***
110 ============================================
112 [..] To use the OPAMP, perform the following steps:
114 (#) Fill in the HAL_OPAMP_MspInit() to
115 (++) Enable the OPAMP Peripheral clock using macro __HAL_RCC_OPAMP_CLK_ENABLE()
116 (++) Configure the OPAMP input AND output in analog mode using
117 HAL_GPIO_Init() to map the OPAMP output to the GPIO pin.
119 (#) Registrate Callbacks
120 (++) The compilation define USE_HAL_OPAMP_REGISTER_CALLBACKS when set to 1
121 allows the user to configure dynamically the driver callbacks.
123 (++) Use Functions HAL_OPAMP_RegisterCallback() to register a user callback,
124 it allows to register following callbacks:
125 (+++) MspInitCallback : OPAMP MspInit.
126 (+++) MspDeInitCallback : OPAMP MspDeInit.
127 This function takes as parameters the HAL peripheral handle, the Callback ID
128 and a pointer to the user callback function.
130 (++) Use function HAL_OPAMP_UnRegisterCallback() to reset a callback to the default
131 weak (overridden) function. It allows to reset following callbacks:
132 (+++) MspInitCallback : OPAMP MspInit.
133 (+++) MspDeInitCallback : OPAMP MspDeInit.
134 (+++) All Callbacks
135 (#) Configure the OPAMP using HAL_OPAMP_Init() function:
136 (++) Select the mode
137 (++) Select the inverting input
138 (++) Select the non-inverting input
139 (++) If PGA mode is enabled, Select if inverting input is connected.
140 (++) Select either factory or user defined trimming mode.
141 (++) If the user-defined trimming mode is enabled, select PMOS & NMOS trimming values
142 (typically values set by HAL_OPAMP_SelfCalibrate function).
144 (#) Enable the OPAMP using HAL_OPAMP_Start() function.
146 (#) Disable the OPAMP using HAL_OPAMP_Stop() function.
148 (#) Lock the OPAMP in running mode using HAL_OPAMP_Lock() function.
149 Caution: On STM32H7, HAL OPAMP lock is software lock only (not
150 hardware lock as on some other STM32 devices)
152 (#) If needed, unlock the OPAMP using HAL_OPAMPEx_Unlock() function.
154 *** Running mode: change of configuration while OPAMP ON ***
155 ============================================
156 [..] To Re-configure OPAMP when OPAMP is ON (change on the fly)
157 (#) If needed, fill in the HAL_OPAMP_MspInit()
158 (++) This is the case for instance if you wish to use new OPAMP I/O
160 (#) Configure the OPAMP using HAL_OPAMP_Init() function:
161 (++) As in configure case, select first the parameters you wish to modify.
163 (#) Change from high speed mode to normal power mode (& vice versa) requires
164 first HAL_OPAMP_DeInit() (force OPAMP OFF) and then HAL_OPAMP_Init().
165 In other words, of OPAMP is ON, HAL_OPAMP_Init can NOT change power mode
166 alone.
168 @endverbatim
169 ******************************************************************************
170 Table 1. OPAMPs inverting/non-inverting inputs for the STM32H7 devices:
172 +------------------------------------------------------------------------|
173 | | | OPAMP1 | OPAMP2 |
174 |-----------------|---------|----------------------|---------------------|
175 | Inverting Input | VM_SEL | VINM0-> PC5 | VINM0-> PE8 |
176 | | | VINM1-> PA7 | VINM1-> PG1 |
177 | | | Internal: | Internal: |
178 | | | ADC1_IN9 | OPAMP2_OUT |
179 | | | ADC2_IN9 | PGA mode |
180 | | | OPAMP1_OUT | |
181 | | | PGA mode | |
182 |-----------------|---------|----------------------|---------------------|
183 | Non Inverting | VP_SEL | | |
184 | | | VP0 -> PB0 (GPIO) | VP0 -> PE9 (GPIO) |
185 | | | Internal: | Internal: |
186 | Input | | DAC1_CH1_int | DAC1_CH2_int |
187 | | | ADC1_IN8 | DAC2_CH1_int |
188 | | | ADC2_IN8 | COMP2_INP |
189 | | | COMP1_INP | |
190 +------------------------------------------------------------------------|
193 [..] Table 2. OPAMPs outputs for the STM32H7 devices:
195 +-------------------------------------------------------------------------
196 | | | OPAMP1 | OPAMP2 |
197 |-----------------|--------|-----------------------|---------------------|
198 | Output | VOUT | PC4 | PE7 |
199 | | | & ADC1_IN4| | & COMP2_INN7 if |
200 | | | ADC2_IN4 |connected internally |
201 | | | COMP1_INN7 if | |
202 | | | connected internally | |
203 |-----------------|--------|-----------------------|---------------------|
206 /* Includes ------------------------------------------------------------------*/
207 #include "stm32h7xx_hal.h"
209 /** @addtogroup STM32H7xx_HAL_Driver
210 * @{
213 /** @defgroup OPAMP OPAMP
214 * @brief OPAMP module driver
215 * @{
218 #ifdef HAL_OPAMP_MODULE_ENABLED
220 /* Private types -------------------------------------------------------------*/
221 /* Private variables ---------------------------------------------------------*/
222 /* Private constants ---------------------------------------------------------*/
223 /** @addtogroup OPAMP_Private_Constants
224 * @{
227 /* CSR register reset value */
228 #define OPAMP_CSR_RESET_VALUE 0x00000000U
230 /* CSR Init masks */
232 #define OPAMP_CSR_INIT_MASK_PGA (OPAMP_CSR_OPAHSM | OPAMP_CSR_VMSEL | OPAMP_CSR_PGGAIN | OPAMP_CSR_PGGAIN \
233 | OPAMP_CSR_VPSEL | OPAMP_CSR_USERTRIM)
236 #define OPAMP_CSR_INIT_MASK_FOLLOWER (OPAMP_CSR_OPAHSM | OPAMP_CSR_VMSEL| OPAMP_CSR_VPSEL \
237 | OPAMP_CSR_USERTRIM)
240 #define OPAMP_CSR_INIT_MASK_STANDALONE (OPAMP_CSR_OPAHSM | OPAMP_CSR_VMSEL | OPAMP_CSR_VPSEL \
241 | OPAMP_CSR_VMSEL | OPAMP_CSR_USERTRIM)
243 * @}
246 /* Private macros ------------------------------------------------------------*/
247 /* Private functions ---------------------------------------------------------*/
248 /* Exported functions --------------------------------------------------------*/
250 /** @defgroup OPAMP_Exported_Functions OPAMP Exported Functions
251 * @{
254 /** @defgroup OPAMP_Exported_Functions_Group1 Initialization and de-initialization functions
255 * @brief Initialization and Configuration functions
257 @verbatim
258 ==============================================================================
259 ##### Initialization and de-initialization functions #####
260 ==============================================================================
262 @endverbatim
263 * @{
267 * @brief Initialize the OPAMP according to the specified
268 * parameters in the OPAMP_InitTypeDef and initialize the associated handle.
269 * @note If the selected opamp is locked, initialization can't be performed.
270 * To unlock the configuration, perform a system reset.
271 * @param hopamp OPAMP handle
272 * @retval HAL status
274 HAL_StatusTypeDef HAL_OPAMP_Init(OPAMP_HandleTypeDef *hopamp)
276 HAL_StatusTypeDef status = HAL_OK;
277 uint32_t updateotrlpotr;
279 /* Check the OPAMP handle allocation and lock status */
280 /* Init not allowed if calibration is ongoing */
281 if(hopamp == NULL)
283 return HAL_ERROR;
285 else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
287 return HAL_ERROR;
289 else if(hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)
291 return HAL_ERROR;
293 else
295 /* Check the parameter */
296 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
298 /* Set OPAMP parameters */
299 assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode));
300 assert_param(IS_OPAMP_FUNCTIONAL_NORMALMODE(hopamp->Init.Mode));
301 assert_param(IS_OPAMP_NONINVERTING_INPUT(hopamp->Init.NonInvertingInput));
303 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
304 if(hopamp->State == HAL_OPAMP_STATE_RESET)
306 if(hopamp->MspInitCallback == NULL)
308 hopamp->MspInitCallback = HAL_OPAMP_MspInit;
311 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
312 if ((hopamp->Init.Mode) == OPAMP_STANDALONE_MODE)
314 assert_param(IS_OPAMP_INVERTING_INPUT_STANDALONE(hopamp->Init.InvertingInput));
317 if ((hopamp->Init.Mode) == OPAMP_PGA_MODE)
319 assert_param(IS_OPAMP_PGA_GAIN(hopamp->Init.PgaGain));
320 assert_param(IS_OPAMP_PGACONNECT(hopamp->Init.PgaConnect));
324 assert_param(IS_OPAMP_TRIMMING(hopamp->Init.UserTrimming));
326 if ((hopamp->Init.UserTrimming) == OPAMP_TRIMMING_USER)
328 if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
330 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueP));
331 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueN));
333 else
335 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValuePHighSpeed));
336 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueNHighSpeed));
340 if(hopamp->State == HAL_OPAMP_STATE_RESET)
342 /* Allocate lock resource and initialize it */
343 hopamp->Lock = HAL_UNLOCKED;
346 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
347 hopamp->MspInitCallback(hopamp);
348 #else
349 /* Call MSP init function */
350 HAL_OPAMP_MspInit(hopamp);
351 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
353 /* Set operating mode */
354 CLEAR_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALON);
355 /* In PGA mode InvertingInput is Not Applicable */
356 if (hopamp->Init.Mode == OPAMP_PGA_MODE)
358 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_INIT_MASK_PGA, \
359 hopamp->Init.PowerMode | \
360 hopamp->Init.Mode | \
361 hopamp->Init.PgaGain | \
362 hopamp->Init.PgaConnect | \
363 hopamp->Init.NonInvertingInput | \
364 hopamp->Init.UserTrimming);
367 if (hopamp->Init.Mode == OPAMP_FOLLOWER_MODE)
369 /* In Follower mode InvertingInput is Not Applicable */
370 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_INIT_MASK_FOLLOWER, \
371 hopamp->Init.PowerMode | \
372 hopamp->Init.Mode | \
373 hopamp->Init.NonInvertingInput | \
374 hopamp->Init.UserTrimming);
377 if (hopamp->Init.Mode == OPAMP_STANDALONE_MODE)
379 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_INIT_MASK_STANDALONE, \
380 hopamp->Init.PowerMode | \
381 hopamp->Init.Mode | \
382 hopamp->Init.InvertingInput | \
383 hopamp->Init.NonInvertingInput | \
384 hopamp->Init.UserTrimming);
387 if (hopamp->Init.UserTrimming == OPAMP_TRIMMING_USER)
389 /* Set power mode and associated calibration parameters */
390 if (hopamp->Init.PowerMode != OPAMP_POWERMODE_HIGHSPEED)
392 /* OPAMP_POWERMODE_NORMAL */
393 /* Set calibration mode (factory or user) and values for */
394 /* transistors differential pair high (PMOS) and low (NMOS) for */
395 /* normal mode. */
396 updateotrlpotr = (((hopamp->Init.TrimmingValueP) << (OPAMP_INPUT_NONINVERTING)) \
397 | (hopamp->Init.TrimmingValueN));
398 MODIFY_REG(hopamp->Instance->OTR, OPAMP_OTR_TRIMOFFSETN | OPAMP_OTR_TRIMOFFSETP, updateotrlpotr);
400 else
402 /* OPAMP_POWERMODE_HIGHSPEED*/
403 /* transistors differential pair high (PMOS) and low (NMOS) for */
404 /* high speed mode. */
405 updateotrlpotr = (((hopamp->Init.TrimmingValuePHighSpeed) << (OPAMP_INPUT_NONINVERTING)) \
406 | (hopamp->Init.TrimmingValueNHighSpeed));
407 MODIFY_REG(hopamp->Instance->HSOTR, OPAMP_OTR_TRIMOFFSETN | OPAMP_OTR_TRIMOFFSETP, updateotrlpotr);
411 /* Update the OPAMP state*/
412 if (hopamp->State == HAL_OPAMP_STATE_RESET)
414 /* From RESET state to READY State */
415 hopamp->State = HAL_OPAMP_STATE_READY;
417 /* else: remain in READY or BUSY state (no update) */
418 return status;
423 * @brief DeInitialize the OPAMP peripheral
424 * @note Deinitialization can be performed if the OPAMP configuration is locked.
425 * (the lock is SW in H7)
426 * @param hopamp OPAMP handle
427 * @retval HAL status
429 HAL_StatusTypeDef HAL_OPAMP_DeInit(OPAMP_HandleTypeDef *hopamp)
431 HAL_StatusTypeDef status = HAL_OK;
433 /* Check the OPAMP handle allocation */
434 /* DeInit not allowed if calibration is on going */
435 if(hopamp == NULL)
437 status = HAL_ERROR;
439 else if(hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)
441 status = HAL_ERROR;
443 else
445 /* Check the parameter */
446 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
448 /* Set OPAMP_CSR register to reset value */
449 WRITE_REG(hopamp->Instance->CSR, OPAMP_CSR_RESET_VALUE);
451 /* DeInit the low level hardware */
452 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
453 if(hopamp->MspDeInitCallback == NULL)
455 hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit;
457 /* DeInit the low level hardware */
458 hopamp->MspDeInitCallback(hopamp);
459 #else
460 HAL_OPAMP_MspDeInit(hopamp);
461 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
463 /* Update the OPAMP state*/
464 hopamp->State = HAL_OPAMP_STATE_RESET;
465 /* Process unlocked */
466 __HAL_UNLOCK(hopamp);
470 return status;
475 * @brief Initialize the OPAMP MSP.
476 * @param hopamp OPAMP handle
477 * @retval None
479 __weak void HAL_OPAMP_MspInit(OPAMP_HandleTypeDef *hopamp)
481 /* Prevent unused argument(s) compilation warning */
482 UNUSED(hopamp);
484 /* NOTE : This function should not be modified, when the callback is needed,
485 the function "HAL_OPAMP_MspInit()" must be implemented in the user file.
490 * @brief DeInitialize OPAMP MSP.
491 * @param hopamp OPAMP handle
492 * @retval None
494 __weak void HAL_OPAMP_MspDeInit(OPAMP_HandleTypeDef *hopamp)
496 /* Prevent unused argument(s) compilation warning */
497 UNUSED(hopamp);
498 /* NOTE : This function should not be modified, when the callback is needed,
499 the function "HAL_OPAMP_MspDeInit()" must be implemented in the user file.
504 * @}
508 /** @defgroup OPAMP_Exported_Functions_Group2 IO operation functions
509 * @brief IO operation functions
511 @verbatim
512 ===============================================================================
513 ##### IO operation functions #####
514 ===============================================================================
515 [..]
516 This subsection provides a set of functions allowing to manage the OPAMP
517 start, stop and calibration actions.
519 @endverbatim
520 * @{
524 * @brief Start the OPAMP.
525 * @param hopamp OPAMP handle
526 * @retval HAL status
528 HAL_StatusTypeDef HAL_OPAMP_Start(OPAMP_HandleTypeDef *hopamp)
530 HAL_StatusTypeDef status = HAL_OK;
532 /* Check the OPAMP handle allocation */
533 /* Check if OPAMP locked */
534 if(hopamp == NULL)
536 status = HAL_ERROR;
538 else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
540 status = HAL_ERROR;
542 else
544 /* Check the parameter */
545 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
547 if(hopamp->State == HAL_OPAMP_STATE_READY)
549 /* Enable the selected opamp */
550 SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
552 /* Update the OPAMP state*/
553 /* From HAL_OPAMP_STATE_READY to HAL_OPAMP_STATE_BUSY */
554 hopamp->State = HAL_OPAMP_STATE_BUSY;
556 else
558 status = HAL_ERROR;
562 return status;
566 * @brief Stop the OPAMP.
567 * @param hopamp OPAMP handle
568 * @retval HAL status
570 HAL_StatusTypeDef HAL_OPAMP_Stop(OPAMP_HandleTypeDef *hopamp)
572 HAL_StatusTypeDef status = HAL_OK;
574 /* Check the OPAMP handle allocation */
575 /* Check if OPAMP locked */
576 /* Check if OPAMP calibration ongoing */
577 if(hopamp == NULL)
579 status = HAL_ERROR;
581 else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
583 status = HAL_ERROR;
585 else if(hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)
587 status = HAL_ERROR;
589 else
591 /* Check the parameter */
592 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
594 if(hopamp->State == HAL_OPAMP_STATE_BUSY)
596 /* Disable the selected opamp */
597 CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
599 /* Update the OPAMP state*/
600 /* From HAL_OPAMP_STATE_BUSY to HAL_OPAMP_STATE_READY*/
601 hopamp->State = HAL_OPAMP_STATE_READY;
603 else
605 status = HAL_ERROR;
608 return status;
612 * @brief Run the self calibration of one OPAMP.
613 * @note Calibration is performed in the mode specified in OPAMP init
614 * structure (mode normal or high-speed). To perform calibration for
615 * both modes, repeat this function twice after OPAMP init structure
616 * accordingly updated.
617 * @param hopamp handle
618 * @retval Updated offset trimming values (PMOS & NMOS), user trimming is enabled
619 * @retval HAL status
621 HAL_StatusTypeDef HAL_OPAMP_SelfCalibrate(OPAMP_HandleTypeDef *hopamp)
624 HAL_StatusTypeDef status = HAL_OK;
626 uint32_t trimmingvaluen;
627 uint32_t trimmingvaluep;
628 uint32_t delta;
629 uint32_t opampmode;
631 __IO uint32_t* tmp_opamp_reg_trimming; /* Selection of register of trimming depending on power mode: OTR or HSOTR */
633 /* Check the OPAMP handle allocation */
634 /* Check if OPAMP locked */
635 if(hopamp == NULL)
637 status = HAL_ERROR;
639 else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
641 status = HAL_ERROR;
643 else
646 /* Check if OPAMP in calibration mode and calibration not yet enable */
647 if(hopamp->State == HAL_OPAMP_STATE_READY)
649 /* Check the parameter */
650 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
651 assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode));
653 opampmode = READ_BIT(hopamp->Instance->CSR,OPAMP_CSR_VMSEL);
655 /* Use of standalone mode */
656 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_VMSEL, OPAMP_STANDALONE_MODE);
657 /* user trimming values are used for offset calibration */
658 SET_BIT(hopamp->Instance->CSR, OPAMP_CSR_USERTRIM);
660 /* Select trimming settings depending on power mode */
661 if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
663 tmp_opamp_reg_trimming = &hopamp->Instance->OTR;
666 else
668 /* high speed Mode */
669 tmp_opamp_reg_trimming = &hopamp->Instance->HSOTR;
673 /* Enable calibration */
674 SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_CALON);
676 /* Force internal reference on VP */
677 SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_FORCEVP);
679 /* 1st calibration - N */
680 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_90VDDA);
682 /* Enable the selected opamp */
683 SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
685 /* Init trimming counter */
686 /* Medium value */
687 trimmingvaluen = 16U;
688 delta = 8U;
690 while (delta != 0U)
692 /* Set candidate trimming */
693 /* OPAMP_POWERMODE_NORMAL */
694 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen);
696 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
697 /* Offset trim time: during calibration, minimum time needed between */
698 /* two steps to have 1 mV accuracy */
699 HAL_Delay(OPAMP_TRIMMING_DELAY);
701 if (READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT) != 0U)
703 /* OPAMP_CSR_CALOUT is HIGH try higher trimming */
704 trimmingvaluen += delta;
706 else
708 /* OPAMP_CSR_CALOUT is LOW try lower trimming */
709 trimmingvaluen -= delta;
711 /* Divide range by 2 to continue dichotomy sweep */
712 delta >>= 1;
715 /* Still need to check if right calibration is current value or one step below */
716 /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */
718 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen);
720 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
721 /* Offset trim time: during calibration, minimum time needed between */
722 /* two steps to have 1 mV accuracy */
723 HAL_Delay(OPAMP_TRIMMING_DELAY);
725 if ((READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT)) != 0U)
727 /* Trimming value is actually one value more */
728 trimmingvaluen++;
729 /* Set right trimming */
730 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen);
733 /* 2nd calibration - P */
734 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_10VDDA);
736 /* Init trimming counter */
737 /* Medium value */
738 trimmingvaluep = 16U;
739 delta = 8U;
741 while (delta != 0U)
743 /* Set candidate trimming */
744 /* OPAMP_POWERMODE_NORMAL */
745 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep<<OPAMP_INPUT_NONINVERTING));
747 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
748 /* Offset trim time: during calibration, minimum time needed between */
749 /* two steps to have 1 mV accuracy */
750 HAL_Delay(OPAMP_TRIMMING_DELAY);
752 if (READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT)!= 0U)
754 /* OPAMP_CSR_CALOUT is HIGH try higher trimming */
755 trimmingvaluep += delta;
757 else
759 /* OPAMP_CSR_CALOUT is LOW try lower trimming */
760 trimmingvaluep -= delta;
763 /* Divide range by 2 to continue dichotomy sweep */
764 delta >>= 1U;
767 /* Still need to check if right calibration is current value or one step below */
768 /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */
769 /* Set candidate trimming */
770 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep<<OPAMP_INPUT_NONINVERTING));
772 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
773 /* Offset trim time: during calibration, minimum time needed between */
774 /* two steps to have 1 mV accuracy */
775 HAL_Delay(OPAMP_TRIMMING_DELAY);
777 if (READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT) != 0U)
779 /* Trimming value is actually one value more */
780 trimmingvaluep++;
781 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep<<OPAMP_INPUT_NONINVERTING));
784 /* Disable calibration & set normal mode (operating mode) */
785 CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_CALON);
787 /* Disable the OPAMP */
788 CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
790 /* Set operating mode back */
791 CLEAR_BIT(hopamp->Instance->CSR, OPAMP_CSR_FORCEVP);
793 /* Self calibration is successful */
794 /* Store calibration(user trimming) results in init structure. */
796 /* Set user trimming mode */
797 hopamp->Init.UserTrimming = OPAMP_TRIMMING_USER;
799 /* Affect calibration parameters depending on mode normal/high speed */
800 if (hopamp->Init.PowerMode != OPAMP_POWERMODE_HIGHSPEED)
802 /* Write calibration result N */
803 hopamp->Init.TrimmingValueN = trimmingvaluen;
804 /* Write calibration result P */
805 hopamp->Init.TrimmingValueP = trimmingvaluep;
807 else
809 /* Write calibration result N */
810 hopamp->Init.TrimmingValueNHighSpeed = trimmingvaluen;
811 /* Write calibration result P */
812 hopamp->Init.TrimmingValuePHighSpeed = trimmingvaluep;
814 /* Restore OPAMP mode after calibration */
815 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_VMSEL, opampmode);
818 else
820 /* OPAMP can not be calibrated from this mode */
821 status = HAL_ERROR;
824 return status;
828 * @}
831 /** @defgroup OPAMP_Exported_Functions_Group3 Peripheral Control functions
832 * @brief Peripheral Control functions
834 @verbatim
835 ===============================================================================
836 ##### Peripheral Control functions #####
837 ===============================================================================
838 [..]
839 This subsection provides a set of functions allowing to control the OPAMP data
840 transfers.
844 @endverbatim
845 * @{
849 * @brief Lock the selected OPAMP configuration.
850 * @note On STM32H7, HAL OPAMP lock is software lock only (in
851 * contrast of hardware lock available on some other STM32
852 * devices)
853 * @param hopamp OPAMP handle
854 * @retval HAL status
856 HAL_StatusTypeDef HAL_OPAMP_Lock(OPAMP_HandleTypeDef *hopamp)
858 HAL_StatusTypeDef status = HAL_OK;
860 /* Check the OPAMP handle allocation */
861 /* Check if OPAMP locked */
862 /* OPAMP can be locked when enabled and running in normal mode */
863 /* It is meaningless otherwise */
864 if(hopamp == NULL)
866 status = HAL_ERROR;
869 else if(hopamp->State != HAL_OPAMP_STATE_BUSY)
871 status = HAL_ERROR;
873 else
875 /* Check the parameter */
876 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
878 /* OPAMP state changed to locked */
879 hopamp->State = HAL_OPAMP_STATE_BUSYLOCKED;
881 return status;
885 * @brief Return the OPAMP factory trimming value.
886 * @note On STM32H7 OPAMP, user can retrieve factory trimming if
887 * OPAMP has never been set to user trimming before.
888 * Therefore, this function must be called when OPAMP init
889 * parameter "UserTrimming" is set to trimming factory,
890 * and before OPAMP calibration (function
891 * "HAL_OPAMP_SelfCalibrate()").
892 * Otherwise, factory trimming value cannot be retrieved and
893 * error status is returned.
894 * @param hopamp OPAMP handle
895 * @param trimmingoffset Trimming offset (P or N)
896 * This parameter must be a value of @ref OPAMP_FactoryTrimming
897 * @note Calibration parameter retrieved is corresponding to the mode
898 * specified in OPAMP init structure (mode normal or high-speed).
899 * To retrieve calibration parameters for both modes, repeat this
900 * function after OPAMP init structure accordingly updated.
901 * @retval Trimming value (P or N): range: 0->31
902 * or OPAMP_FACTORYTRIMMING_DUMMY if trimming value is not available
905 HAL_OPAMP_TrimmingValueTypeDef HAL_OPAMP_GetTrimOffset (const OPAMP_HandleTypeDef *hopamp, uint32_t trimmingoffset)
907 HAL_OPAMP_TrimmingValueTypeDef trimmingvalue;
908 __IO const uint32_t* tmp_opamp_reg_trimming; /* Selection of register of trimming depending on power mode: OTR or LPOTR */
910 /* Check the OPAMP handle allocation */
911 /* Value can be retrieved in HAL_OPAMP_STATE_READY state */
912 if(hopamp == NULL)
914 return OPAMP_FACTORYTRIMMING_DUMMY;
917 if(hopamp->State == HAL_OPAMP_STATE_READY)
919 /* Check the parameter */
920 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
921 assert_param(IS_OPAMP_FACTORYTRIMMING(trimmingoffset));
922 assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode));
924 /* Check the trimming mode */
925 if (READ_BIT(hopamp->Instance->CSR,OPAMP_CSR_USERTRIM)!= 0U)
927 /* This function must called when OPAMP init parameter "UserTrimming" */
928 /* is set to trimming factory, and before OPAMP calibration (function */
929 /* "HAL_OPAMP_SelfCalibrate()"). */
930 /* Otherwise, factory trimming value cannot be retrieved and error */
931 /* status is returned. */
932 trimmingvalue = OPAMP_FACTORYTRIMMING_DUMMY;
934 else
936 /* Select trimming settings depending on power mode */
937 if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
939 tmp_opamp_reg_trimming = &hopamp->Instance->OTR;
941 else
943 tmp_opamp_reg_trimming = &hopamp->Instance->HSOTR;
946 /* Get factory trimming */
947 if (trimmingoffset == OPAMP_FACTORYTRIMMING_P)
949 /* OPAMP_FACTORYTRIMMING_P */
950 trimmingvalue = ((*tmp_opamp_reg_trimming) & OPAMP_OTR_TRIMOFFSETP) >> OPAMP_INPUT_NONINVERTING;
952 else
954 /* OPAMP_FACTORYTRIMMING_N */
955 trimmingvalue = (*tmp_opamp_reg_trimming) & OPAMP_OTR_TRIMOFFSETN;
959 else
961 return OPAMP_FACTORYTRIMMING_DUMMY;
964 return trimmingvalue;
967 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
969 * @brief Register a User OPAMP Callback
970 * To be used instead of the weak (overridden) predefined callback
971 * @param hopamp OPAMP handle
972 * @param CallbackId ID of the callback to be registered
973 * This parameter can be one of the following values:
974 * @arg @ref HAL_OPAMP_MSPINIT_CB_ID OPAMP MspInit callback ID
975 * @arg @ref HAL_OPAMP_MSPDEINIT_CB_ID OPAMP MspDeInit callback ID
976 * @param pCallback pointer to the Callback function
977 * @retval status
979 HAL_StatusTypeDef HAL_OPAMP_RegisterCallback (OPAMP_HandleTypeDef *hopamp, HAL_OPAMP_CallbackIDTypeDef CallbackId, pOPAMP_CallbackTypeDef pCallback)
981 HAL_StatusTypeDef status = HAL_OK;
983 if(pCallback == NULL)
985 return HAL_ERROR;
988 /* Process locked */
989 __HAL_LOCK(hopamp);
991 if(hopamp->State == HAL_OPAMP_STATE_READY)
993 switch (CallbackId)
995 case HAL_OPAMP_MSPINIT_CB_ID :
996 hopamp->MspInitCallback = pCallback;
997 break;
998 case HAL_OPAMP_MSPDEINIT_CB_ID :
999 hopamp->MspDeInitCallback = pCallback;
1000 break;
1001 default :
1002 /* update return status */
1003 status = HAL_ERROR;
1004 break;
1007 else if (hopamp->State == HAL_OPAMP_STATE_RESET)
1009 switch (CallbackId)
1011 case HAL_OPAMP_MSPINIT_CB_ID :
1012 hopamp->MspInitCallback = pCallback;
1013 break;
1014 case HAL_OPAMP_MSPDEINIT_CB_ID :
1015 hopamp->MspDeInitCallback = pCallback;
1016 break;
1017 default :
1018 /* update return status */
1019 status = HAL_ERROR;
1020 break;
1023 else
1025 /* update return status */
1026 status = HAL_ERROR;
1029 /* Release Lock */
1030 __HAL_UNLOCK(hopamp);
1031 return status;
1035 * @brief Unregister a User OPAMP Callback
1036 * OPAMP Callback is redirected to the weak (overridden) predefined callback
1037 * @param hopamp OPAMP handle
1038 * @param CallbackId ID of the callback to be unregistered
1039 * This parameter can be one of the following values:
1040 * @arg @ref HAL_OPAMP_MSPINIT_CB_ID OPAMP MSP Init Callback ID
1041 * @arg @ref HAL_OPAMP_MSPDEINIT_CB_ID OPAMP MSP DeInit Callback ID
1042 * @arg @ref HAL_OPAMP_ALL_CB_ID OPAMP All Callbacks
1043 * @retval status
1045 HAL_StatusTypeDef HAL_OPAMP_UnRegisterCallback (OPAMP_HandleTypeDef *hopamp, HAL_OPAMP_CallbackIDTypeDef CallbackId)
1047 HAL_StatusTypeDef status = HAL_OK;
1049 /* Process locked */
1050 __HAL_LOCK(hopamp);
1052 if(hopamp->State == HAL_OPAMP_STATE_READY)
1054 switch (CallbackId)
1056 case HAL_OPAMP_MSPINIT_CB_ID :
1057 hopamp->MspInitCallback = HAL_OPAMP_MspInit;
1058 break;
1059 case HAL_OPAMP_MSPDEINIT_CB_ID :
1060 hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit;
1061 break;
1062 case HAL_OPAMP_ALL_CB_ID :
1063 hopamp->MspInitCallback = HAL_OPAMP_MspInit;
1064 hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit;
1065 break;
1066 default :
1067 /* update return status */
1068 status = HAL_ERROR;
1069 break;
1072 else if (hopamp->State == HAL_OPAMP_STATE_RESET)
1074 switch (CallbackId)
1076 case HAL_OPAMP_MSPINIT_CB_ID :
1077 hopamp->MspInitCallback = HAL_OPAMP_MspInit;
1078 break;
1079 case HAL_OPAMP_MSPDEINIT_CB_ID :
1080 hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit;
1081 break;
1082 default :
1083 /* update return status */
1084 status = HAL_ERROR;
1085 break;
1088 else
1090 /* update return status */
1091 status = HAL_ERROR;
1094 /* Release Lock */
1095 __HAL_UNLOCK(hopamp);
1096 return status;
1099 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
1102 * @}
1106 /** @defgroup OPAMP_Exported_Functions_Group4 Peripheral State functions
1107 * @brief Peripheral State functions
1109 @verbatim
1110 ===============================================================================
1111 ##### Peripheral State functions #####
1112 ===============================================================================
1113 [..]
1114 This subsection permits to get in run-time the status of the peripheral.
1116 @endverbatim
1117 * @{
1121 * @brief Return the OPAMP handle state.
1122 * @param hopamp OPAMP handle
1123 * @retval HAL state
1125 HAL_OPAMP_StateTypeDef HAL_OPAMP_GetState(const OPAMP_HandleTypeDef *hopamp)
1127 /* Check the OPAMP handle allocation */
1128 if(hopamp == NULL)
1130 return HAL_OPAMP_STATE_RESET;
1133 /* Check the parameter */
1134 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
1136 /* Return OPAMP handle state */
1137 return hopamp->State;
1141 * @}
1145 * @}
1147 #endif /* HAL_OPAMP_MODULE_ENABLED */
1149 * @}
1153 * @}