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
12 *
13 ******************************************************************************
14 * @attention
15 *
16 * Copyright (c) 2017 STMicroelectronics.
17 * All rights reserved.
18 *
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.
22 *
23 ******************************************************************************
24 @verbatim
25 ================================================================================
26 ##### OPAMP Peripheral Features #####
27 ================================================================================
28
29 [..] The device integrates 2 operational amplifiers OPAMP1 & OPAMP2
30
31 (#) The OPAMP(s) provides several exclusive running modes.
32 (++) Standalone mode
33 (++) Programmable Gain Amplifier (PGA) modes
34 (++) Follower mode
35
36 (#) Each OPAMP(s) can be configured in normal and high speed mode.
37
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.
58
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.
63
64 (#) Running mode: Follower mode
65 (++) No Inverting Input is connected.
66
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 :
72
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.
78
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.
82
83 (#) The OPAMPs inverting input can be selected according to the Reference Manual
84 "OPAMP functional description" chapter.
85
86 (#) The OPAMPs non inverting input can be selected according to the Reference Manual
87 "OPAMP functional description" chapter.
88
89
90 ##### How to use this driver #####
91 ================================================================================
92 [..]
93
94 *** High speed / normal power mode ***
95 ============================================
96 [..] To run in high speed mode:
97
98 (#) Configure the OPAMP using HAL_OPAMP_Init() function:
99 (++) Select OPAMP_POWERMODE_HIGHSPEED
100 (++) Otherwise select OPAMP_POWERMODE_NORMAL
101
102 *** Calibration ***
103 ============================================
104 [..] To run the OPAMP calibration self calibration:
105
106 (#) Start calibration using HAL_OPAMP_SelfCalibrate.
107 Store the calibration results.
108
109 *** Running mode ***
110 ============================================
111
112 [..] To use the OPAMP, perform the following steps:
113
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.
118
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.
122
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.
129
130 (++) Use function HAL_OPAMP_UnRegisterCallback() to reset a callback to the default
131 weak (surcharged) 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).
143
144 (#) Enable the OPAMP using HAL_OPAMP_Start() function.
145
146 (#) Disable the OPAMP using HAL_OPAMP_Stop() function.
147
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)
151
152 (#) If needed, unlock the OPAMP using HAL_OPAMPEx_Unlock() function.
153
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
159
160 (#) Configure the OPAMP using HAL_OPAMP_Init() function:
161 (++) As in configure case, select first the parameters you wish to modify.
162
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.
167
168 @endverbatim
169 ******************************************************************************
170 Table 1. OPAMPs inverting/non-inverting inputs for the STM32H7 devices:
171
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 +------------------------------------------------------------------------|
191
192
193 [..] Table 2. OPAMPs outputs for the STM32H7 devices:
194
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 |-----------------|--------|-----------------------|---------------------|
204 */
205
206 /* Includes ------------------------------------------------------------------*/
207 #include "stm32h7xx_hal.h"
208
209 /** @addtogroup STM32H7xx_HAL_Driver
210 * @{
211 */
212
213 /** @defgroup OPAMP OPAMP
214 * @brief OPAMP module driver
215 * @{
216 */
217
218 #ifdef HAL_OPAMP_MODULE_ENABLED
219
220 /* Private types -------------------------------------------------------------*/
221 /* Private variables ---------------------------------------------------------*/
222 /* Private constants ---------------------------------------------------------*/
223 /** @addtogroup OPAMP_Private_Constants
224 * @{
225 */
226
227 /* CSR register reset value */
228 #define OPAMP_CSR_RESET_VALUE 0x00000000U
229
230 /* CSR Init masks */
231
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)
234
235
236 #define OPAMP_CSR_INIT_MASK_FOLLOWER (OPAMP_CSR_OPAHSM | OPAMP_CSR_VMSEL| OPAMP_CSR_VPSEL \
237 | OPAMP_CSR_USERTRIM)
238
239
240 #define OPAMP_CSR_INIT_MASK_STANDALONE (OPAMP_CSR_OPAHSM | OPAMP_CSR_VMSEL | OPAMP_CSR_VPSEL \
241 | OPAMP_CSR_VMSEL | OPAMP_CSR_USERTRIM)
242 /**
243 * @}
244 */
245
246 /* Private macros ------------------------------------------------------------*/
247 /* Private functions ---------------------------------------------------------*/
248 /* Exported functions --------------------------------------------------------*/
249
250 /** @defgroup OPAMP_Exported_Functions OPAMP Exported Functions
251 * @{
252 */
253
254 /** @defgroup OPAMP_Exported_Functions_Group1 Initialization and de-initialization functions
255 * @brief Initialization and Configuration functions
256 *
257 @verbatim
258 ==============================================================================
259 ##### Initialization and de-initialization functions #####
260 ==============================================================================
261
262 @endverbatim
263 * @{
264 */
265
266 /**
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
273 */
HAL_OPAMP_Init(OPAMP_HandleTypeDef * hopamp)274 HAL_StatusTypeDef HAL_OPAMP_Init(OPAMP_HandleTypeDef *hopamp)
275 {
276 HAL_StatusTypeDef status = HAL_OK;
277 uint32_t updateotrlpotr;
278
279 /* Check the OPAMP handle allocation and lock status */
280 /* Init not allowed if calibration is ongoing */
281 if(hopamp == NULL)
282 {
283 return HAL_ERROR;
284 }
285 else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
286 {
287 return HAL_ERROR;
288 }
289 else if(hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)
290 {
291 return HAL_ERROR;
292 }
293 else
294 {
295 /* Check the parameter */
296 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
297
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));
302
303 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
304 if(hopamp->State == HAL_OPAMP_STATE_RESET)
305 {
306 if(hopamp->MspInitCallback == NULL)
307 {
308 hopamp->MspInitCallback = HAL_OPAMP_MspInit;
309 }
310 }
311 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
312 if ((hopamp->Init.Mode) == OPAMP_STANDALONE_MODE)
313 {
314 assert_param(IS_OPAMP_INVERTING_INPUT_STANDALONE(hopamp->Init.InvertingInput));
315 }
316
317 if ((hopamp->Init.Mode) == OPAMP_PGA_MODE)
318 {
319 assert_param(IS_OPAMP_PGA_GAIN(hopamp->Init.PgaGain));
320 assert_param(IS_OPAMP_PGACONNECT(hopamp->Init.PgaConnect));
321 }
322
323
324 assert_param(IS_OPAMP_TRIMMING(hopamp->Init.UserTrimming));
325
326 if ((hopamp->Init.UserTrimming) == OPAMP_TRIMMING_USER)
327 {
328 if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
329 {
330 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueP));
331 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueN));
332 }
333 else
334 {
335 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValuePHighSpeed));
336 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueNHighSpeed));
337 }
338 }
339
340 if(hopamp->State == HAL_OPAMP_STATE_RESET)
341 {
342 /* Allocate lock resource and initialize it */
343 hopamp->Lock = HAL_UNLOCKED;
344 }
345
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 */
352
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)
357 {
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);
365 }
366
367 if (hopamp->Init.Mode == OPAMP_FOLLOWER_MODE)
368 {
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);
375 }
376
377 if (hopamp->Init.Mode == OPAMP_STANDALONE_MODE)
378 {
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);
385 }
386
387 if (hopamp->Init.UserTrimming == OPAMP_TRIMMING_USER)
388 {
389 /* Set power mode and associated calibration parameters */
390 if (hopamp->Init.PowerMode != OPAMP_POWERMODE_HIGHSPEED)
391 {
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);
399 }
400 else
401 {
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);
408 }
409 }
410
411 /* Update the OPAMP state*/
412 if (hopamp->State == HAL_OPAMP_STATE_RESET)
413 {
414 /* From RESET state to READY State */
415 hopamp->State = HAL_OPAMP_STATE_READY;
416 }
417 /* else: remain in READY or BUSY state (no update) */
418 return status;
419 }
420 }
421
422 /**
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
428 */
HAL_OPAMP_DeInit(OPAMP_HandleTypeDef * hopamp)429 HAL_StatusTypeDef HAL_OPAMP_DeInit(OPAMP_HandleTypeDef *hopamp)
430 {
431 HAL_StatusTypeDef status = HAL_OK;
432
433 /* Check the OPAMP handle allocation */
434 /* DeInit not allowed if calibration is on going */
435 if(hopamp == NULL)
436 {
437 status = HAL_ERROR;
438 }
439 else if(hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)
440 {
441 status = HAL_ERROR;
442 }
443 else
444 {
445 /* Check the parameter */
446 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
447
448 /* Set OPAMP_CSR register to reset value */
449 WRITE_REG(hopamp->Instance->CSR, OPAMP_CSR_RESET_VALUE);
450
451 /* DeInit the low level hardware */
452 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
453 if(hopamp->MspDeInitCallback == NULL)
454 {
455 hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit;
456 }
457 /* DeInit the low level hardware */
458 hopamp->MspDeInitCallback(hopamp);
459 #else
460 HAL_OPAMP_MspDeInit(hopamp);
461 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
462
463 /* Update the OPAMP state*/
464 hopamp->State = HAL_OPAMP_STATE_RESET;
465 /* Process unlocked */
466 __HAL_UNLOCK(hopamp);
467
468 }
469
470 return status;
471 }
472
473
474 /**
475 * @brief Initialize the OPAMP MSP.
476 * @param hopamp OPAMP handle
477 * @retval None
478 */
HAL_OPAMP_MspInit(OPAMP_HandleTypeDef * hopamp)479 __weak void HAL_OPAMP_MspInit(OPAMP_HandleTypeDef *hopamp)
480 {
481 /* Prevent unused argument(s) compilation warning */
482 UNUSED(hopamp);
483
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.
486 */
487 }
488
489 /**
490 * @brief DeInitialize OPAMP MSP.
491 * @param hopamp OPAMP handle
492 * @retval None
493 */
HAL_OPAMP_MspDeInit(OPAMP_HandleTypeDef * hopamp)494 __weak void HAL_OPAMP_MspDeInit(OPAMP_HandleTypeDef *hopamp)
495 {
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.
500 */
501 }
502
503 /**
504 * @}
505 */
506
507
508 /** @defgroup OPAMP_Exported_Functions_Group2 IO operation functions
509 * @brief IO operation functions
510 *
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.
518
519 @endverbatim
520 * @{
521 */
522
523 /**
524 * @brief Start the OPAMP.
525 * @param hopamp OPAMP handle
526 * @retval HAL status
527 */
HAL_OPAMP_Start(OPAMP_HandleTypeDef * hopamp)528 HAL_StatusTypeDef HAL_OPAMP_Start(OPAMP_HandleTypeDef *hopamp)
529 {
530 HAL_StatusTypeDef status = HAL_OK;
531
532 /* Check the OPAMP handle allocation */
533 /* Check if OPAMP locked */
534 if(hopamp == NULL)
535 {
536 status = HAL_ERROR;
537 }
538 else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
539 {
540 status = HAL_ERROR;
541 }
542 else
543 {
544 /* Check the parameter */
545 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
546
547 if(hopamp->State == HAL_OPAMP_STATE_READY)
548 {
549 /* Enable the selected opamp */
550 SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
551
552 /* Update the OPAMP state*/
553 /* From HAL_OPAMP_STATE_READY to HAL_OPAMP_STATE_BUSY */
554 hopamp->State = HAL_OPAMP_STATE_BUSY;
555 }
556 else
557 {
558 status = HAL_ERROR;
559 }
560
561 }
562 return status;
563 }
564
565 /**
566 * @brief Stop the OPAMP.
567 * @param hopamp OPAMP handle
568 * @retval HAL status
569 */
HAL_OPAMP_Stop(OPAMP_HandleTypeDef * hopamp)570 HAL_StatusTypeDef HAL_OPAMP_Stop(OPAMP_HandleTypeDef *hopamp)
571 {
572 HAL_StatusTypeDef status = HAL_OK;
573
574 /* Check the OPAMP handle allocation */
575 /* Check if OPAMP locked */
576 /* Check if OPAMP calibration ongoing */
577 if(hopamp == NULL)
578 {
579 status = HAL_ERROR;
580 }
581 else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
582 {
583 status = HAL_ERROR;
584 }
585 else if(hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)
586 {
587 status = HAL_ERROR;
588 }
589 else
590 {
591 /* Check the parameter */
592 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
593
594 if(hopamp->State == HAL_OPAMP_STATE_BUSY)
595 {
596 /* Disable the selected opamp */
597 CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
598
599 /* Update the OPAMP state*/
600 /* From HAL_OPAMP_STATE_BUSY to HAL_OPAMP_STATE_READY*/
601 hopamp->State = HAL_OPAMP_STATE_READY;
602 }
603 else
604 {
605 status = HAL_ERROR;
606 }
607 }
608 return status;
609 }
610
611 /**
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
620 */
HAL_OPAMP_SelfCalibrate(OPAMP_HandleTypeDef * hopamp)621 HAL_StatusTypeDef HAL_OPAMP_SelfCalibrate(OPAMP_HandleTypeDef *hopamp)
622 {
623
624 HAL_StatusTypeDef status = HAL_OK;
625
626 uint32_t trimmingvaluen;
627 uint32_t trimmingvaluep;
628 uint32_t delta;
629 uint32_t opampmode;
630
631 __IO uint32_t* tmp_opamp_reg_trimming; /* Selection of register of trimming depending on power mode: OTR or HSOTR */
632
633 /* Check the OPAMP handle allocation */
634 /* Check if OPAMP locked */
635 if(hopamp == NULL)
636 {
637 status = HAL_ERROR;
638 }
639 else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
640 {
641 status = HAL_ERROR;
642 }
643 else
644 {
645
646 /* Check if OPAMP in calibration mode and calibration not yet enable */
647 if(hopamp->State == HAL_OPAMP_STATE_READY)
648 {
649 /* Check the parameter */
650 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
651 assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode));
652
653 opampmode = READ_BIT(hopamp->Instance->CSR,OPAMP_CSR_VMSEL);
654
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);
659
660 /* Select trimming settings depending on power mode */
661 if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
662 {
663 tmp_opamp_reg_trimming = &hopamp->Instance->OTR;
664
665 }
666 else
667 {
668 /* high speed Mode */
669 tmp_opamp_reg_trimming = &hopamp->Instance->HSOTR;
670 }
671
672
673 /* Enable calibration */
674 SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_CALON);
675
676 /* Force internal reference on VP */
677 SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_FORCEVP);
678
679 /* 1st calibration - N */
680 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_90VDDA);
681
682 /* Enable the selected opamp */
683 SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
684
685 /* Init trimming counter */
686 /* Medium value */
687 trimmingvaluen = 16U;
688 delta = 8U;
689
690 while (delta != 0U)
691 {
692 /* Set candidate trimming */
693 /* OPAMP_POWERMODE_NORMAL */
694 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen);
695
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);
700
701 if (READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT) != 0U)
702 {
703 /* OPAMP_CSR_CALOUT is HIGH try higher trimming */
704 trimmingvaluen += delta;
705 }
706 else
707 {
708 /* OPAMP_CSR_CALOUT is LOW try lower trimming */
709 trimmingvaluen -= delta;
710 }
711 /* Divide range by 2 to continue dichotomy sweep */
712 delta >>= 1;
713 }
714
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 */
717
718 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen);
719
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);
724
725 if ((READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT)) != 0U)
726 {
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);
731 }
732
733 /* 2nd calibration - P */
734 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_10VDDA);
735
736 /* Init trimming counter */
737 /* Medium value */
738 trimmingvaluep = 16U;
739 delta = 8U;
740
741 while (delta != 0U)
742 {
743 /* Set candidate trimming */
744 /* OPAMP_POWERMODE_NORMAL */
745 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep<<OPAMP_INPUT_NONINVERTING));
746
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);
751
752 if (READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT)!= 0U)
753 {
754 /* OPAMP_CSR_CALOUT is HIGH try higher trimming */
755 trimmingvaluep += delta;
756 }
757 else
758 {
759 /* OPAMP_CSR_CALOUT is LOW try lower trimming */
760 trimmingvaluep -= delta;
761 }
762
763 /* Divide range by 2 to continue dichotomy sweep */
764 delta >>= 1U;
765 }
766
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));
771
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);
776
777 if (READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT) != 0U)
778 {
779 /* Trimming value is actually one value more */
780 trimmingvaluep++;
781 MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep<<OPAMP_INPUT_NONINVERTING));
782 }
783
784 /* Disable calibration & set normal mode (operating mode) */
785 CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_CALON);
786
787 /* Disable the OPAMP */
788 CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
789
790 /* Set operating mode back */
791 CLEAR_BIT(hopamp->Instance->CSR, OPAMP_CSR_FORCEVP);
792
793 /* Self calibration is successful */
794 /* Store calibration(user trimming) results in init structure. */
795
796 /* Set user trimming mode */
797 hopamp->Init.UserTrimming = OPAMP_TRIMMING_USER;
798
799 /* Affect calibration parameters depending on mode normal/high speed */
800 if (hopamp->Init.PowerMode != OPAMP_POWERMODE_HIGHSPEED)
801 {
802 /* Write calibration result N */
803 hopamp->Init.TrimmingValueN = trimmingvaluen;
804 /* Write calibration result P */
805 hopamp->Init.TrimmingValueP = trimmingvaluep;
806 }
807 else
808 {
809 /* Write calibration result N */
810 hopamp->Init.TrimmingValueNHighSpeed = trimmingvaluen;
811 /* Write calibration result P */
812 hopamp->Init.TrimmingValuePHighSpeed = trimmingvaluep;
813 }
814 /* Restore OPAMP mode after calibration */
815 MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_VMSEL, opampmode);
816 }
817
818 else
819 {
820 /* OPAMP can not be calibrated from this mode */
821 status = HAL_ERROR;
822 }
823 }
824 return status;
825 }
826
827 /**
828 * @}
829 */
830
831 /** @defgroup OPAMP_Exported_Functions_Group3 Peripheral Control functions
832 * @brief Peripheral Control functions
833 *
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.
841
842
843
844 @endverbatim
845 * @{
846 */
847
848 /**
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
855 */
HAL_OPAMP_Lock(OPAMP_HandleTypeDef * hopamp)856 HAL_StatusTypeDef HAL_OPAMP_Lock(OPAMP_HandleTypeDef *hopamp)
857 {
858 HAL_StatusTypeDef status = HAL_OK;
859
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)
865 {
866 status = HAL_ERROR;
867 }
868
869 else if(hopamp->State != HAL_OPAMP_STATE_BUSY)
870 {
871 status = HAL_ERROR;
872 }
873 else
874 {
875 /* Check the parameter */
876 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
877
878 /* OPAMP state changed to locked */
879 hopamp->State = HAL_OPAMP_STATE_BUSYLOCKED;
880 }
881 return status;
882 }
883
884 /**
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
903 *
904 */
HAL_OPAMP_GetTrimOffset(OPAMP_HandleTypeDef * hopamp,uint32_t trimmingoffset)905 HAL_OPAMP_TrimmingValueTypeDef HAL_OPAMP_GetTrimOffset (OPAMP_HandleTypeDef *hopamp, uint32_t trimmingoffset)
906 {
907 HAL_OPAMP_TrimmingValueTypeDef trimmingvalue;
908 __IO uint32_t* tmp_opamp_reg_trimming; /* Selection of register of trimming depending on power mode: OTR or LPOTR */
909
910 /* Check the OPAMP handle allocation */
911 /* Value can be retrieved in HAL_OPAMP_STATE_READY state */
912 if(hopamp == NULL)
913 {
914 return OPAMP_FACTORYTRIMMING_DUMMY;
915 }
916
917 if(hopamp->State == HAL_OPAMP_STATE_READY)
918 {
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));
923
924 /* Check the trimming mode */
925 if (READ_BIT(hopamp->Instance->CSR,OPAMP_CSR_USERTRIM)!= 0U)
926 {
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;
933 }
934 else
935 {
936 /* Select trimming settings depending on power mode */
937 if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
938 {
939 tmp_opamp_reg_trimming = &hopamp->Instance->OTR;
940 }
941 else
942 {
943 tmp_opamp_reg_trimming = &hopamp->Instance->HSOTR;
944 }
945
946 /* Get factory trimming */
947 if (trimmingoffset == OPAMP_FACTORYTRIMMING_P)
948 {
949 /* OPAMP_FACTORYTRIMMING_P */
950 trimmingvalue = ((*tmp_opamp_reg_trimming) & OPAMP_OTR_TRIMOFFSETP) >> OPAMP_INPUT_NONINVERTING;
951 }
952 else
953 {
954 /* OPAMP_FACTORYTRIMMING_N */
955 trimmingvalue = (*tmp_opamp_reg_trimming) & OPAMP_OTR_TRIMOFFSETN;
956 }
957 }
958 }
959 else
960 {
961 return OPAMP_FACTORYTRIMMING_DUMMY;
962 }
963
964 return trimmingvalue;
965 }
966
967 #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
968 /**
969 * @brief Register a User OPAMP Callback
970 * To be used instead of the weak (surcharged) 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
978 */
HAL_OPAMP_RegisterCallback(OPAMP_HandleTypeDef * hopamp,HAL_OPAMP_CallbackIDTypeDef CallbackId,pOPAMP_CallbackTypeDef pCallback)979 HAL_StatusTypeDef HAL_OPAMP_RegisterCallback (OPAMP_HandleTypeDef *hopamp, HAL_OPAMP_CallbackIDTypeDef CallbackId, pOPAMP_CallbackTypeDef pCallback)
980 {
981 HAL_StatusTypeDef status = HAL_OK;
982
983 if(pCallback == NULL)
984 {
985 return HAL_ERROR;
986 }
987
988 /* Process locked */
989 __HAL_LOCK(hopamp);
990
991 if(hopamp->State == HAL_OPAMP_STATE_READY)
992 {
993 switch (CallbackId)
994 {
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;
1005 }
1006 }
1007 else if (hopamp->State == HAL_OPAMP_STATE_RESET)
1008 {
1009 switch (CallbackId)
1010 {
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;
1021 }
1022 }
1023 else
1024 {
1025 /* update return status */
1026 status = HAL_ERROR;
1027 }
1028
1029 /* Release Lock */
1030 __HAL_UNLOCK(hopamp);
1031 return status;
1032 }
1033
1034 /**
1035 * @brief Unregister a User OPAMP Callback
1036 * OPAMP Callback is redirected to the weak (surcharged) 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
1044 */
HAL_OPAMP_UnRegisterCallback(OPAMP_HandleTypeDef * hopamp,HAL_OPAMP_CallbackIDTypeDef CallbackId)1045 HAL_StatusTypeDef HAL_OPAMP_UnRegisterCallback (OPAMP_HandleTypeDef *hopamp, HAL_OPAMP_CallbackIDTypeDef CallbackId)
1046 {
1047 HAL_StatusTypeDef status = HAL_OK;
1048
1049 /* Process locked */
1050 __HAL_LOCK(hopamp);
1051
1052 if(hopamp->State == HAL_OPAMP_STATE_READY)
1053 {
1054 switch (CallbackId)
1055 {
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;
1070 }
1071 }
1072 else if (hopamp->State == HAL_OPAMP_STATE_RESET)
1073 {
1074 switch (CallbackId)
1075 {
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;
1086 }
1087 }
1088 else
1089 {
1090 /* update return status */
1091 status = HAL_ERROR;
1092 }
1093
1094 /* Release Lock */
1095 __HAL_UNLOCK(hopamp);
1096 return status;
1097 }
1098
1099 #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
1100
1101 /**
1102 * @}
1103 */
1104
1105
1106 /** @defgroup OPAMP_Exported_Functions_Group4 Peripheral State functions
1107 * @brief Peripheral State functions
1108 *
1109 @verbatim
1110 ===============================================================================
1111 ##### Peripheral State functions #####
1112 ===============================================================================
1113 [..]
1114 This subsection permits to get in run-time the status of the peripheral.
1115
1116 @endverbatim
1117 * @{
1118 */
1119
1120 /**
1121 * @brief Return the OPAMP handle state.
1122 * @param hopamp OPAMP handle
1123 * @retval HAL state
1124 */
HAL_OPAMP_GetState(OPAMP_HandleTypeDef * hopamp)1125 HAL_OPAMP_StateTypeDef HAL_OPAMP_GetState(OPAMP_HandleTypeDef *hopamp)
1126 {
1127 /* Check the OPAMP handle allocation */
1128 if(hopamp == NULL)
1129 {
1130 return HAL_OPAMP_STATE_RESET;
1131 }
1132
1133 /* Check the parameter */
1134 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
1135
1136 /* Return OPAMP handle state */
1137 return hopamp->State;
1138 }
1139
1140 /**
1141 * @}
1142 */
1143
1144 /**
1145 * @}
1146 */
1147 #endif /* HAL_OPAMP_MODULE_ENABLED */
1148 /**
1149 * @}
1150 */
1151
1152 /**
1153 * @}
1154 */
1155
1156