]> git.gir.st - tmk_keyboard.git/blob - tool/mbed/mbed-sdk/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32L1/stm32l1xx_hal_opamp.c
Squashed 'tmk_core/' changes from 7967731..b9e0ea0
[tmk_keyboard.git] / tool / mbed / mbed-sdk / libraries / mbed / targets / cmsis / TARGET_STM / TARGET_STM32L1 / stm32l1xx_hal_opamp.c
1 /**
2 ******************************************************************************
3 * @file stm32l1xx_hal_opamp.c
4 * @author MCD Application Team
5 * @version V1.0.0
6 * @date 5-September-2014
7 * @brief OPAMP HAL module driver.
8 *
9 * This file provides firmware functions to manage the following
10 * functionalities of the operational amplifiers (OPAMP1 ,... ,OPAMP3)
11 * peripheral:
12 * + OPAMP configuration
13 * + OPAMP calibration
14 *
15 * Thanks to
16 * + Initialization and de-initialization functions
17 * + IO operation functions
18 * + Peripheral Control functions
19 * + Peripheral State functions
20 *
21 @verbatim
22 ================================================================================
23 ##### OPAMP Peripheral Features #####
24 ================================================================================
25
26 [..] The device integrates up to 3 operational amplifiers OPAMP1, OPAMP2,
27 OPAMP3 (OPAMP3 availability depends on device category)
28
29 (#) The OPAMP(s) provides several exclusive running modes.
30 (+) Standalone mode
31 (+) Follower mode
32
33 (#) The OPAMP(s) provide(s) calibration capabilities.
34 (+) Calibration aims at correcting some offset for running mode.
35 (+) The OPAMP uses either factory calibration settings OR user defined
36 calibration (trimming) settings (i.e. trimming mode).
37 (+) The user defined settings can be figured out using self calibration
38 handled by HAL_OPAMP_SelfCalibrate, HAL_OPAMPEx_SelfCalibrateAll
39 (+) HAL_OPAMP_SelfCalibrate:
40 (++) Runs automatically the calibration in 2 steps: for transistors
41 differential pair high (PMOS) or low (NMOS)
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 (++) for devices having several OPAMPs, HAL_OPAMPEx_SelfCalibrateAll
49 runs calibration of all OPAMPs in parallel to save trimming search
50 wait time.
51
52 (#) Running mode: Standalone mode
53 (+) Gain is set externally (gain depends on external loads).
54 (+) Follower mode also possible externally by connecting the inverting input to
55 the output.
56
57 (#) Running mode: Follower mode
58 (+) No Inverting Input is connected.
59 (+) The OPAMP(s) output(s) are internally connected to inverting input
60
61 (#) The OPAMPs inverting input can be selected among the list shown
62 in table below.
63
64 (#) The OPAMPs non inverting input can be selected among the list shown
65 in table below.
66
67 [..] Table 1. OPAMPs inverting/non-inverting inputs for STM32L1 devices:
68
69 +--------------------------------------------------------------------------+
70 | | HAL param | OPAMP1 | OPAMP2 | OPAMP3(4) |
71 | | name | | | |
72 |----------------|------------|--------------|--------------|--------------|
73 | Inverting | VM0 | PA2 | PA7 | PC2 |
74 | input (1) | VM1 | VINM pin (2) | VINM pin (2) | VINM pin (2) |
75 |----------------|------------|--------------|--------------|--------------|
76 | Non Inverting | VP0 | PA1 | PA6 | PC1 |
77 | input | DAC_CH1 (3)| DAC_CH1 | DAC_CH1 | --- |
78 | | DAC_CH2 (3)| --- | DAC_CH2 | DAC_CH2 |
79 +--------------------------------------------------------------------------+
80 (1): NA in follower mode.
81 (2): OPAMP input OPAMPx_VINM are dedicated OPAMP pins, their availability
82 depends on device package.
83 (3): DAC channels 1 and 2 are connected internally to OPAMP. Nevertheless,
84 I/O pins connected to DAC can still be used as DAC output (pins PA4
85 and PA5).
86 (4): OPAMP3 availability depends on device category.
87
88
89 [..] Table 2. OPAMPs outputs for STM32L1 devices:
90
91 +--------------------------------------------------------+
92 | | OPAMP1 | OPAMP2 | OPAMP3(4) |
93 |-----------------|------------|------------|------------|
94 | Output | PA3 | PB0 | PC3 |
95 +--------------------------------------------------------+
96 (4) : OPAMP3 availability depends on device category
97
98
99 ##### How to use this driver #####
100 ================================================================================
101 [..]
102
103 *** Calibration ***
104 ============================================
105 To run the opamp calibration self calibration:
106
107 (#) Start calibration using HAL_OPAMP_SelfCalibrate.
108 Store the calibration results.
109
110 *** Running mode ***
111 ============================================
112
113 To use the opamp, perform the following steps:
114
115 (#) Fill in the HAL_OPAMP_MspInit() to
116 (+) Enable the OPAMP Peripheral clock using macro "__OPAMP_CLK_ENABLE()"
117 (++) Configure the opamp input AND output in analog mode using
118 HAL_GPIO_Init() to map the opamp output to the GPIO pin.
119
120 (#) Configure the opamp using HAL_OPAMP_Init() function:
121 (+) Select the mode
122 (+) Select the inverting input
123 (+) Select the non-inverting input
124 (+) Select either factory or user defined trimming mode.
125 (+) If the user defined trimming mode is enabled, select PMOS & NMOS trimming values
126 (typ. settings returned by HAL_OPAMP_SelfCalibrate function).
127
128 (#) Enable the opamp using HAL_OPAMP_Start() function.
129
130 (#) Disable the opamp using HAL_OPAMP_Stop() function.
131
132 (#) Lock the opamp in running mode using HAL_OPAMP_Lock() function.
133 Caution: On STM32L1, HAL OPAMP lock is software lock only (not
134 hardware lock as on some other STM32 devices)
135
136 (#) If needed, unlock the opamp using HAL_OPAMPEx_Unlock() function.
137
138 *** Running mode: change of configuration while OPAMP ON ***
139 ============================================
140 To Re-configure OPAMP when OPAMP is ON (change on the fly)
141 (#) If needed, Fill in the HAL_OPAMP_MspInit()
142 (+) This is the case for instance if you wish to use new OPAMP I/O
143
144 (#) Configure the opamp using HAL_OPAMP_Init() function:
145 (+) As in configure case, selects first the parameters you wish to modify.
146
147 @endverbatim
148 ******************************************************************************
149 * @attention
150 *
151 * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
152 *
153 * Redistribution and use in source and binary forms, with or without modification,
154 * are permitted provided that the following conditions are met:
155 * 1. Redistributions of source code must retain the above copyright notice,
156 * this list of conditions and the following disclaimer.
157 * 2. Redistributions in binary form must reproduce the above copyright notice,
158 * this list of conditions and the following disclaimer in the documentation
159 * and/or other materials provided with the distribution.
160 * 3. Neither the name of STMicroelectronics nor the names of its contributors
161 * may be used to endorse or promote products derived from this software
162 * without specific prior written permission.
163 *
164 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
165 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
166 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
167 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
168 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
169 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
170 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
171 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
172 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
173 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
174 *
175 ******************************************************************************
176 */
177
178 /* Includes ------------------------------------------------------------------*/
179 #include "stm32l1xx_hal.h"
180
181 /** @addtogroup STM32L1xx_HAL_Driver
182 * @{
183 */
184
185 /** @defgroup OPAMP OPAMP
186 * @brief OPAMP HAL module driver
187 * @{
188 */
189
190 #ifdef HAL_OPAMP_MODULE_ENABLED
191
192 #if defined (STM32L151xCA) || defined (STM32L151xD) || defined (STM32L152xCA) || defined (STM32L152xD) || defined (STM32L162xCA) || defined (STM32L162xD) || defined (STM32L151xE) || defined (STM32L152xE) || defined (STM32L162xE) || defined (STM32L162xC) || defined (STM32L152xC) || defined (STM32L151xC)
193
194 /* Private typedef -----------------------------------------------------------*/
195 /* Private define ------------------------------------------------------------*/
196 /* Private macro -------------------------------------------------------------*/
197 /* Private variables ---------------------------------------------------------*/
198 /* Private function prototypes -----------------------------------------------*/
199 /* Private functions ---------------------------------------------------------*/
200
201 /** @defgroup OPAMP_Exported_Functions OPAMP Exported Functions
202 * @{
203 */
204
205 /** @defgroup OPAMP_Exported_Functions_Group1 Initialization and de-initialization functions
206 * @brief Initialization and Configuration functions
207 *
208 @verbatim
209 ===============================================================================
210 ##### Initialization and de-initialization functions #####
211 ===============================================================================
212 [..] This section provides functions allowing to:
213
214 @endverbatim
215 * @{
216 */
217
218 /**
219 * @brief Initializes the OPAMP according to the specified
220 * parameters in the OPAMP_InitTypeDef and create the associated handle.
221 * @note If the selected opamp is locked, initialization can't be performed.
222 * To unlock the configuration, perform a system reset.
223 * @param hopamp: OPAMP handle
224 * @retval HAL status
225 */
226 HAL_StatusTypeDef HAL_OPAMP_Init(OPAMP_HandleTypeDef* hopamp)
227 {
228 HAL_StatusTypeDef status = HAL_OK;
229 uint32_t tmp_csr = 0; /* Temporary variable to update register CSR, except bits ANAWSSELx, S7SEL2, OPA_RANGE, OPAxCALOUT */
230
231 /* Check the OPAMP handle allocation and lock status */
232 /* Init not allowed if calibration is ongoing */
233 if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
234 || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY) )
235 {
236 status = HAL_ERROR;
237 }
238 else
239 {
240 /* Check the parameter */
241 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
242
243 /* Set OPAMP parameters */
244 assert_param(IS_OPAMP_FUNCTIONAL_NORMALMODE(hopamp->Init.Mode));
245 assert_param(IS_OPAMP_NONINVERTING_INPUT(hopamp->Init.NonInvertingInput));
246 assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode));
247 assert_param(IS_OPAMP_POWER_SUPPLY_RANGE(hopamp->Init.PowerSupplyRange));
248 assert_param(IS_OPAMP_TRIMMING(hopamp->Init.UserTrimming));
249
250 if (hopamp->Init.Mode != OPAMP_FOLLOWER_MODE)
251 {
252 assert_param(IS_OPAMP_INVERTING_INPUT(hopamp->Init.InvertingInput));
253 }
254
255 if (hopamp->Init.UserTrimming == OPAMP_TRIMMING_USER)
256 {
257 if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
258 {
259 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueP));
260 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueN));
261 }
262 else
263 {
264 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValuePLowPower));
265 assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueNLowPower));
266 }
267 }
268
269 /* Call MSP init function */
270 HAL_OPAMP_MspInit(hopamp);
271
272
273 /* Set OPAMP parameters */
274 /* - Set internal switches in function of: */
275 /* - OPAMP selected mode: standalone or follower. */
276 /* - Non-inverting input connection */
277 /* - Inverting input connection */
278 /* - Set power supply range */
279 /* - Set power mode and associated calibration parameters */
280
281 /* Get OPAMP CSR register into temporary variable */
282 tmp_csr = OPAMP->CSR;
283
284 /* Open all switches on non-inverting input, inverting input and output */
285 /* feedback. */
286 CLEAR_BIT(tmp_csr, __OPAMP_CSR_ALL_SWITCHES(hopamp));
287
288 /* Set internal switches in function of OPAMP mode selected: standalone */
289 /* or follower. */
290 /* If follower mode is selected, feedback switch S3 is closed and */
291 /* inverting inputs switches are let opened. */
292 /* If standalone mode is selected, feedback switch S3 is let opened and */
293 /* the selected inverting inputs switch is closed. */
294 if (hopamp->Init.Mode == OPAMP_FOLLOWER_MODE)
295 {
296 /* Follower mode: Close switches S3 and SanB */
297 SET_BIT(tmp_csr, __OPAMP_CSR_S3SELX(hopamp));
298 }
299 else
300 {
301 /* Set internal switches in function of inverting input selected: */
302 /* Close switch to connect comparator inverting input to the selected */
303 /* input: dedicated IO pin or alternative IO pin available on some */
304 /* device packages. */
305 if (hopamp->Init.InvertingInput == OPAMP_INVERTINGINPUT_VM0)
306 {
307 /* Close switch to connect comparator non-inverting input to */
308 /* dedicated IO pin low-leakage. */
309 SET_BIT(tmp_csr, __OPAMP_CSR_S4SELX(hopamp));
310 }
311 else
312 {
313 /* Close switch to connect comparator inverting input to alternative */
314 /* IO pin available on some device packages. */
315 SET_BIT(tmp_csr, __OPAMP_CSR_ANAWSELX(hopamp));
316 }
317 }
318
319 /* Set internal switches in function of non-inverting input selected: */
320 /* Close switch to connect comparator non-inverting input to the selected */
321 /* input: dedicated IO pin or DAC channel. */
322 if (hopamp->Init.NonInvertingInput == OPAMP_NONINVERTINGINPUT_VP0)
323 {
324 /* Close switch to connect comparator non-inverting input to */
325 /* dedicated IO pin low-leakage. */
326 SET_BIT(tmp_csr, __OPAMP_CSR_S5SELX(hopamp));
327 }
328 else if (hopamp->Init.NonInvertingInput == OPAMP_NONINVERTINGINPUT_DAC_CH1)
329 {
330
331 /* Particular case for connection to DAC channel 1: */
332 /* OPAMP_NONINVERTINGINPUT_DAC_CH1 available on OPAMP1 and OPAMP2 only */
333 /* (OPAMP3 availability depends on device category). */
334 if ((hopamp->Instance == OPAMP1) || (hopamp->Instance == OPAMP2))
335 {
336 /* Close switch to connect comparator non-inverting input to */
337 /* DAC channel 1. */
338 SET_BIT(tmp_csr, __OPAMP_CSR_S6SELX(hopamp));
339 }
340 else
341 {
342 /* Set HAL status to error if another OPAMP instance as OPAMP1 or */
343 /* OPAMP2 is intended to be connected to DAC channel 2. */
344 status = HAL_ERROR;
345 }
346 }
347 else /* if (hopamp->Init.NonInvertingInput == */
348 /* OPAMP_NONINVERTINGINPUT_DAC_CH2 ) */
349 {
350 /* Particular case for connection to DAC channel 2: */
351 /* OPAMP_NONINVERTINGINPUT_DAC_CH2 available on OPAMP2 and OPAMP3 only */
352 /* (OPAMP3 availability depends on device category). */
353 if (hopamp->Instance == OPAMP2)
354 {
355 /* Close switch to connect comparator non-inverting input to */
356 /* DAC channel 2. */
357 SET_BIT(tmp_csr, OPAMP_CSR_S7SEL2);
358 }
359 /* If OPAMP3 is selected (if available) */
360 else if (hopamp->Instance != OPAMP1)
361 {
362 /* Close switch to connect comparator non-inverting input to */
363 /* DAC channel 2. */
364 SET_BIT(tmp_csr, __OPAMP_CSR_S6SELX(hopamp));
365 }
366 else
367 {
368 /* Set HAL status to error if another OPAMP instance as OPAMP2 or */
369 /* OPAMP3 (if available) is intended to be connected to DAC channel 2.*/
370 status = HAL_ERROR;
371 }
372 }
373
374 /* Continue OPAMP configuration if settings of switches are correct */
375 if (status != HAL_ERROR)
376 {
377 /* Set power mode and associated calibration parameters */
378 if (hopamp->Init.PowerMode != OPAMP_POWERMODE_LOWPOWER)
379 {
380 /* Set normal mode */
381 CLEAR_BIT(tmp_csr, __OPAMP_CSR_OPAXLPM(hopamp));
382
383 if (hopamp->Init.UserTrimming == OPAMP_TRIMMING_USER)
384 {
385 /* Set calibration mode (factory or user) and values for */
386 /* transistors differential pair high (PMOS) and low (NMOS) for */
387 /* normal mode. */
388 MODIFY_REG(OPAMP->OTR, OPAMP_OTR_OT_USER |
389 __OPAMP_OFFSET_TRIM_SET(hopamp, OPAMP_FACTORYTRIMMING_N, OPAMP_TRIM_VALUE_MASK) |
390 __OPAMP_OFFSET_TRIM_SET(hopamp, OPAMP_FACTORYTRIMMING_P, OPAMP_TRIM_VALUE_MASK) ,
391 hopamp->Init.UserTrimming |
392 __OPAMP_OFFSET_TRIM_SET(hopamp, OPAMP_FACTORYTRIMMING_N, hopamp->Init.TrimmingValueN) |
393 __OPAMP_OFFSET_TRIM_SET(hopamp, OPAMP_FACTORYTRIMMING_P, hopamp->Init.TrimmingValueP) );
394 }
395 else
396 {
397 /* Set calibration mode to factory */
398 CLEAR_BIT(OPAMP->OTR, OPAMP_OTR_OT_USER);
399 }
400
401 }
402 else
403 {
404 /* Set low power mode */
405 SET_BIT(tmp_csr, __OPAMP_CSR_OPAXLPM(hopamp));
406
407 if (hopamp->Init.UserTrimming == OPAMP_TRIMMING_USER)
408 {
409 /* Set calibration mode to user trimming */
410 SET_BIT(OPAMP->OTR, OPAMP_OTR_OT_USER);
411
412 /* Set values for transistors differential pair high (PMOS) and low */
413 /* (NMOS) for low power mode. */
414 MODIFY_REG(OPAMP->LPOTR, __OPAMP_OFFSET_TRIM_SET(hopamp, OPAMP_FACTORYTRIMMING_N, OPAMP_TRIM_VALUE_MASK) |
415 __OPAMP_OFFSET_TRIM_SET(hopamp, OPAMP_FACTORYTRIMMING_P, OPAMP_TRIM_VALUE_MASK) ,
416 __OPAMP_OFFSET_TRIM_SET(hopamp, OPAMP_FACTORYTRIMMING_N, hopamp->Init.TrimmingValueNLowPower) |
417 __OPAMP_OFFSET_TRIM_SET(hopamp, OPAMP_FACTORYTRIMMING_P, hopamp->Init.TrimmingValuePLowPower) );
418 }
419 else
420 {
421 /* Set calibration mode to factory trimming */
422 CLEAR_BIT(OPAMP->OTR, OPAMP_OTR_OT_USER);
423 }
424
425 }
426
427
428 /* Configure the power supply range */
429 MODIFY_REG(tmp_csr, OPAMP_CSR_AOP_RANGE,
430 hopamp->Init.PowerSupplyRange);
431
432 /* Set OPAMP CSR register from temporary variable */
433 /* This allows to apply all changes on one time, in case of update on */
434 /* the fly with OPAMP previously set and running: */
435 /* - to avoid hazardous transient switches settings (risk of short */
436 /* circuit) */
437 /* - to avoid interruption of input signal */
438 OPAMP->CSR = tmp_csr;
439
440
441 /* Update the OPAMP state */
442 /* If coming from state reset: Update from state RESET to state READY */
443 /* else: remain in state READY or BUSY (no update) */
444 if (hopamp->State == HAL_OPAMP_STATE_RESET)
445 {
446 hopamp->State = HAL_OPAMP_STATE_READY;
447 }
448 }
449 }
450
451 return status;
452 }
453
454
455 /**
456 * @brief DeInitializes the OPAMP peripheral
457 * @note Deinitialization can't be performed if the OPAMP configuration is locked.
458 * To unlock the configuration, perform a system reset.
459 * @param hopamp: OPAMP handle
460 * @retval HAL status
461 */
462 HAL_StatusTypeDef HAL_OPAMP_DeInit(OPAMP_HandleTypeDef* hopamp)
463 {
464 HAL_StatusTypeDef status = HAL_OK;
465
466 /* Check the OPAMP handle allocation */
467 /* Check if OPAMP locked */
468 /* DeInit not allowed if calibration is ongoing */
469 if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED) \
470 || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY))
471 {
472 status = HAL_ERROR;
473 }
474 else
475 {
476
477 /* Check the parameter */
478 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
479
480 /* Open all switches on non-inverting input, inverting input and output */
481 /* feedback. */
482 CLEAR_BIT(OPAMP->CSR, __OPAMP_CSR_ALL_SWITCHES(hopamp));
483
484 /* DeInit the low level hardware */
485 HAL_OPAMP_MspDeInit(hopamp);
486
487 /* Update the OPAMP state*/
488 hopamp->State = HAL_OPAMP_STATE_RESET;
489 }
490
491 /* Process unlocked */
492 __HAL_UNLOCK(hopamp);
493
494 return status;
495 }
496
497
498 /**
499 * @brief Initializes the OPAMP MSP.
500 * @param hopamp: OPAMP handle
501 * @retval None
502 */
503 __weak void HAL_OPAMP_MspInit(OPAMP_HandleTypeDef* hopamp)
504 {
505 /* NOTE : This function Should not be modified, when the callback is needed,
506 the function "HAL_OPAMP_MspInit()" must be implemented in the user file.
507 */
508 }
509
510 /**
511 * @brief DeInitializes OPAMP MSP.
512 * @param hopamp: OPAMP handle
513 * @retval None
514 */
515 __weak void HAL_OPAMP_MspDeInit(OPAMP_HandleTypeDef* hopamp)
516 {
517 /* NOTE : This function Should not be modified, when the callback is needed,
518 the function "HAL_OPAMP_MspDeInit()" must be implemented in the user file.
519 */
520 }
521
522 /**
523 * @}
524 */
525
526
527 /** @defgroup OPAMP_Exported_Functions_Group2 IO operation functions
528 * @brief IO operation functions
529 *
530 @verbatim
531 ===============================================================================
532 ##### IO operation functions #####
533 ===============================================================================
534 [..]
535 This subsection provides a set of functions allowing to manage the OPAMP
536 start, stop and calibration actions.
537
538 @endverbatim
539 * @{
540 */
541
542 /**
543 * @brief Start the opamp
544 * @param hopamp: OPAMP handle
545 * @retval HAL status
546 */
547
548 HAL_StatusTypeDef HAL_OPAMP_Start(OPAMP_HandleTypeDef* hopamp)
549 {
550 HAL_StatusTypeDef status = HAL_OK;
551
552 /* Check the OPAMP handle allocation */
553 /* Check if OPAMP locked */
554 if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED))
555 {
556 status = HAL_ERROR;
557 }
558 else
559 {
560 /* Check the parameter */
561 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
562
563 if(hopamp->State == HAL_OPAMP_STATE_READY)
564 {
565 /* Enable the selected opamp */
566 CLEAR_BIT (OPAMP->CSR, __OPAMP_CSR_OPAXPD(hopamp));
567
568 /* Update the OPAMP state */
569 /* From HAL_OPAMP_STATE_READY to HAL_OPAMP_STATE_BUSY */
570 hopamp->State = HAL_OPAMP_STATE_BUSY;
571 }
572 else
573 {
574 status = HAL_ERROR;
575 }
576
577 }
578 return status;
579 }
580
581 /**
582 * @brief Stop the opamp
583 * @param hopamp: OPAMP handle
584 * @retval HAL status
585 */
586 HAL_StatusTypeDef HAL_OPAMP_Stop(OPAMP_HandleTypeDef* hopamp)
587 {
588 HAL_StatusTypeDef status = HAL_OK;
589
590 /* Check the OPAMP handle allocation */
591 /* Check if OPAMP locked */
592 /* Check if OPAMP calibration ongoing */
593 if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED) \
594 || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY))
595 {
596 status = HAL_ERROR;
597 }
598 else
599 {
600 /* Check the parameter */
601 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
602
603 if(hopamp->State == HAL_OPAMP_STATE_BUSY)
604 {
605 /* Disable the selected opamp */
606 SET_BIT (OPAMP->CSR, __OPAMP_CSR_OPAXPD(hopamp));
607
608 /* Update the OPAMP state*/
609 /* From HAL_OPAMP_STATE_BUSY to HAL_OPAMP_STATE_READY*/
610 hopamp->State = HAL_OPAMP_STATE_READY;
611 }
612 else
613 {
614 status = HAL_ERROR;
615 }
616 }
617 return status;
618 }
619
620 /**
621 * @brief Run the self calibration of one OPAMP
622 * @note Trimming values (PMOS & NMOS) are updated and user trimming is
623 * enabled is calibration is succesful.
624 * @note Calibration is performed in the mode specified in OPAMP init
625 * structure (mode normal or low-power). To perform calibration for
626 * both modes, repeat this function twice after OPAMP init structure
627 * accordingly updated.
628 * @note Calibration runs about 10 ms (5 dichotmy steps, repeated for P
629 * and N transistors: 10 steps with 1 ms for each step).
630 * @param hopamp: handle
631 * @retval Updated offset trimming values (PMOS & NMOS), user trimming is enabled
632 * @retval HAL status
633 */
634 HAL_StatusTypeDef HAL_OPAMP_SelfCalibrate(OPAMP_HandleTypeDef* hopamp)
635 {
636 HAL_StatusTypeDef status = HAL_OK;
637
638 uint32_t* opamp_trimmingvalue = 0;
639 uint32_t opamp_trimmingvaluen = 0;
640 uint32_t opamp_trimmingvaluep = 0;
641
642 uint32_t trimming_diff_pair = 0; /* Selection of differential transistors pair high or low */
643
644 __IO uint32_t* tmp_opamp_reg_trimming; /* Selection of register of trimming depending on power mode: OTR or LPOTR */
645 uint32_t tmp_opamp_otr_otuser = 0; /* Selection of bit OPAMP_OTR_OT_USER depending on trimming register pointed: OTR or LPOTR */
646
647 uint32_t tmp_Opaxcalout_DefaultSate = 0; /* Bit OPAMP_CSR_OPAXCALOUT default state when trimming value is 00000b. Used to detect the bit toggling */
648
649 uint32_t tmp_OpaxSwitchesContextBackup = 0;
650
651 uint8_t trimming_diff_pair_iteration_count = 0;
652 uint8_t delta = 0;
653
654
655 /* Check the OPAMP handle allocation */
656 /* Check if OPAMP locked */
657 if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED))
658 {
659 status = HAL_ERROR;
660 }
661 else
662 {
663
664 /* Check if OPAMP in calibration mode and calibration not yet enable */
665 if(hopamp->State == HAL_OPAMP_STATE_READY)
666 {
667 /* Check the parameter */
668 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
669 assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode));
670
671 /* Update OPAMP state */
672 hopamp->State = HAL_OPAMP_STATE_CALIBBUSY;
673
674 /* Backup of switches configuration to restore it at the end of the */
675 /* calibration. */
676 tmp_OpaxSwitchesContextBackup = READ_BIT(OPAMP->CSR, __OPAMP_CSR_ALL_SWITCHES(hopamp));
677
678 /* Open all switches on non-inverting input, inverting input and output */
679 /* feedback. */
680 CLEAR_BIT(OPAMP->CSR, __OPAMP_CSR_ALL_SWITCHES(hopamp));
681
682 /* Set calibration mode to user programmed trimming values */
683 SET_BIT(OPAMP->OTR, OPAMP_OTR_OT_USER);
684
685
686 /* Select trimming settings depending on power mode */
687 if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
688 {
689 tmp_opamp_otr_otuser = OPAMP_OTR_OT_USER;
690 tmp_opamp_reg_trimming = &OPAMP->OTR;
691 }
692 else
693 {
694 tmp_opamp_otr_otuser = 0x00000000;
695 tmp_opamp_reg_trimming = &OPAMP->LPOTR;
696 }
697
698
699 /* Enable the selected opamp */
700 CLEAR_BIT (OPAMP->CSR, __OPAMP_CSR_OPAXPD(hopamp));
701
702 /* Perform trimming for both differential transistors pair high and low */
703 for (trimming_diff_pair_iteration_count = 0; trimming_diff_pair_iteration_count <=1; trimming_diff_pair_iteration_count++)
704 {
705 if (trimming_diff_pair_iteration_count == 0)
706 {
707 /* Calibration of transistors differential pair high (NMOS) */
708 trimming_diff_pair = OPAMP_FACTORYTRIMMING_N;
709 opamp_trimmingvalue = &opamp_trimmingvaluen;
710
711 /* Set bit OPAMP_CSR_OPAXCALOUT default state when trimming value */
712 /* is 00000b. Used to detect the bit toggling during trimming. */
713 tmp_Opaxcalout_DefaultSate = RESET;
714
715 /* Enable calibration for N differential pair */
716 MODIFY_REG(OPAMP->CSR, __OPAMP_CSR_OPAXCAL_L(hopamp),
717 __OPAMP_CSR_OPAXCAL_H(hopamp) );
718 }
719 else /* (trimming_diff_pair_iteration_count == 1) */
720 {
721 /* Calibration of transistors differential pair low (PMOS) */
722 trimming_diff_pair = OPAMP_FACTORYTRIMMING_P;
723 opamp_trimmingvalue = &opamp_trimmingvaluep;
724
725 /* Set bit OPAMP_CSR_OPAXCALOUT default state when trimming value */
726 /* is 00000b. Used to detect the bit toggling during trimming. */
727 tmp_Opaxcalout_DefaultSate = __OPAMP_CSR_OPAXCALOUT(hopamp);
728
729 /* Enable calibration for P differential pair */
730 MODIFY_REG(OPAMP->CSR, __OPAMP_CSR_OPAXCAL_H(hopamp),
731 __OPAMP_CSR_OPAXCAL_L(hopamp) );
732 }
733
734
735 /* Perform calibration parameter search by dichotomy sweep */
736 /* - Delta initial value 16: for 5 dichotomy steps: 16 for the */
737 /* initial range, then successive delta sweeps (8, 4, 2, 1). */
738 /* can extend the search range to +/- 15 units. */
739 /* - Trimming initial value 15: search range will go from 0 to 30 */
740 /* (Trimming value 31 is forbidden). */
741 *opamp_trimmingvalue = 15;
742 delta = 16;
743
744 while (delta != 0)
745 {
746 /* Set candidate trimming */
747 MODIFY_REG(*tmp_opamp_reg_trimming, __OPAMP_OFFSET_TRIM_SET(hopamp, trimming_diff_pair, OPAMP_TRIM_VALUE_MASK) ,
748 __OPAMP_OFFSET_TRIM_SET(hopamp, trimming_diff_pair, *opamp_trimmingvalue) | tmp_opamp_otr_otuser);
749
750 /* Offset trimming time: during calibration, minimum time needed */
751 /* between two steps to have 1 mV accuracy. */
752 HAL_Delay(OPAMP_TRIMMING_DELAY);
753
754 /* Divide range by 2 to continue dichotomy sweep */
755 delta >>= 1;
756
757 /* Set trimming values for next iteration in function of trimming */
758 /* result toggle (versus initial state). */
759 if (READ_BIT(OPAMP->CSR, __OPAMP_CSR_OPAXCALOUT(hopamp)) != tmp_Opaxcalout_DefaultSate)
760 {
761 /* If calibration output is has toggled, try lower trimming */
762 *opamp_trimmingvalue -= delta;
763 }
764 else
765 {
766 /* If calibration output is has not toggled, try higher trimming */
767 *opamp_trimmingvalue += delta;
768 }
769 }
770
771 }
772
773 /* Disable calibration for P and N differential pairs */
774 /* Disable the selected opamp */
775 CLEAR_BIT (OPAMP->CSR, (__OPAMP_CSR_OPAXCAL_H(hopamp) |
776 __OPAMP_CSR_OPAXCAL_L(hopamp) |
777 __OPAMP_CSR_OPAXPD(hopamp)) );
778
779 /* Backup of switches configuration to restore it at the end of the */
780 /* calibration. */
781 SET_BIT(OPAMP->CSR, tmp_OpaxSwitchesContextBackup);
782
783 /* Self calibration is successful */
784 /* Store calibration (user trimming) results in init structure. */
785
786 /* Set user trimming mode */
787 hopamp->Init.UserTrimming = OPAMP_TRIMMING_USER;
788
789 /* Affect calibration parameters depending on mode normal/low power */
790 if (hopamp->Init.PowerMode != OPAMP_POWERMODE_LOWPOWER)
791 {
792 /* Write calibration result N */
793 hopamp->Init.TrimmingValueN = opamp_trimmingvaluen;
794 /* Write calibration result P */
795 hopamp->Init.TrimmingValueP = opamp_trimmingvaluep;
796 }
797 else
798 {
799 /* Write calibration result N */
800 hopamp->Init.TrimmingValueNLowPower = opamp_trimmingvaluen;
801 /* Write calibration result P */
802 hopamp->Init.TrimmingValuePLowPower = opamp_trimmingvaluep;
803 }
804
805 /* Update OPAMP state */
806 hopamp->State = HAL_OPAMP_STATE_READY;
807
808 }
809 else
810 {
811 /* OPAMP can not be calibrated from this mode */
812 status = HAL_ERROR;
813 }
814 }
815
816 return status;
817 }
818
819 /**
820 * @brief Return the OPAMP factory trimming value
821 * Caution: On STM32L1 OPAMP, user can retrieve factory trimming if
822 * OPAMP has never been set to user trimming before.
823 * Therefore, this fonction must be called when OPAMP init
824 * parameter "UserTrimming" is set to trimming factory,
825 * and before OPAMP calibration (function
826 * "HAL_OPAMP_SelfCalibrate()").
827 * Otherwise, factory triming value cannot be retrieved and
828 * error status is returned.
829 * @param hopamp : OPAMP handle
830 * @param trimmingoffset : Trimming offset (P or N)
831 * This parameter must be a value of @ref OPAMP_FactoryTrimming
832 * @note Calibration parameter retrieved is corresponding to the mode
833 * specified in OPAMP init structure (mode normal or low-power).
834 * To retrieve calibration parameters for both modes, repeat this
835 * function after OPAMP init structure accordingly updated.
836 * @retval Trimming value (P or N): range: 0->31
837 * or OPAMP_FACTORYTRIMMING_DUMMY if trimming value is not available
838 * @{
839 */
840 OPAMP_TrimmingValueTypeDef HAL_OPAMP_GetTrimOffset (OPAMP_HandleTypeDef *hopamp, uint32_t trimmingoffset)
841 {
842 OPAMP_TrimmingValueTypeDef trimmingvalue;
843 __IO uint32_t* tmp_opamp_reg_trimming; /* Selection of register of trimming depending on power mode: OTR or LPOTR */
844
845 /* Check the OPAMP handle allocation */
846 /* Value can be retrieved in HAL_OPAMP_STATE_READY state */
847 if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_RESET)
848 || (hopamp->State == HAL_OPAMP_STATE_BUSY)
849 || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)
850 || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED))
851 {
852 trimmingvalue = OPAMP_FACTORYTRIMMING_DUMMY;
853 }
854 else
855 {
856 /* Check the parameter */
857 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
858 assert_param(IS_OPAMP_FACTORYTRIMMING(trimmingoffset));
859 assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode));
860
861 /* Check the trimming mode */
862 if (hopamp->Init.UserTrimming == OPAMP_TRIMMING_USER)
863 {
864 /* This fonction must called when OPAMP init parameter "UserTrimming" */
865 /* is set to trimming factory, and before OPAMP calibration (function */
866 /* "HAL_OPAMP_SelfCalibrate()"). */
867 /* Otherwise, factory triming value cannot be retrieved and error */
868 /* status is returned. */
869 trimmingvalue = OPAMP_FACTORYTRIMMING_DUMMY;
870 }
871 else
872 {
873 /* Select trimming settings depending on power mode */
874 if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
875 {
876 tmp_opamp_reg_trimming = &OPAMP->OTR;
877 }
878 else
879 {
880 tmp_opamp_reg_trimming = &OPAMP->LPOTR;
881 }
882
883 /* Get factory trimming */
884 trimmingvalue = ((*tmp_opamp_reg_trimming >> __OPAMP_OFFSET_TRIM_BITSPOSITION(hopamp, trimmingoffset)) & OPAMP_TRIM_VALUE_MASK);
885 }
886 }
887
888 return trimmingvalue;
889 }
890
891 /**
892 * @}
893 */
894
895 /**
896 * @}
897 */
898
899 /** @defgroup OPAMP_Exported_Functions_Group3 Peripheral Control functions
900 * @brief Peripheral Control functions
901 *
902 @verbatim
903 ===============================================================================
904 ##### Peripheral Control functions #####
905 ===============================================================================
906 [..]
907
908 @endverbatim
909 * @{
910 */
911
912 /**
913 * @brief Lock the selected opamp configuration.
914 * Caution: On STM32L1, HAL OPAMP lock is software lock only (not
915 * hardware lock as on some other STM32 devices)
916 * @param hopamp: OPAMP handle
917 * @retval HAL status
918 */
919 HAL_StatusTypeDef HAL_OPAMP_Lock(OPAMP_HandleTypeDef* hopamp)
920 {
921 HAL_StatusTypeDef status = HAL_OK;
922
923 /* Check the OPAMP handle allocation */
924 /* Check if OPAMP locked */
925 /* OPAMP can be locked when enabled and running in normal mode */
926 /* It is meaningless otherwise */
927 if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_RESET) \
928 || (hopamp->State == HAL_OPAMP_STATE_READY) \
929 || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)\
930 || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED))
931
932 {
933 status = HAL_ERROR;
934 }
935
936 else
937 {
938 /* Check the parameter */
939 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
940
941 /* OPAMP state changed to locked */
942 hopamp->State = HAL_OPAMP_STATE_BUSYLOCKED;
943 }
944 return status;
945 }
946
947 /**
948 * @}
949 */
950
951
952 /** @defgroup OPAMP_Exported_Functions_Group4 Peripheral State functions
953 * @brief Peripheral State functions
954 *
955 @verbatim
956 ===============================================================================
957 ##### Peripheral State functions #####
958 ===============================================================================
959 [..]
960 This subsection permit to get in run-time the status of the peripheral.
961
962 @endverbatim
963 * @{
964 */
965
966 /**
967 * @brief Return the OPAMP state
968 * @param hopamp : OPAMP handle
969 * @retval HAL state
970 */
971 HAL_OPAMP_StateTypeDef HAL_OPAMP_GetState(OPAMP_HandleTypeDef* hopamp)
972 {
973 /* Check the OPAMP handle allocation */
974 if(hopamp == HAL_NULL)
975 {
976 return HAL_OPAMP_STATE_RESET;
977 }
978
979 /* Check the parameter */
980 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
981
982 return hopamp->State;
983 }
984
985 /**
986 * @}
987 */
988
989 /**
990 * @}
991 */
992
993 #endif /* STM32L151xCA || STM32L151xD || STM32L152xCA || STM32L152xD || STM32L162xCA || STM32L162xD || STM32L151xE || STM32L152xE || STM32L162xE || STM32L162xC || STM32L152xC || STM32L151xC */
994
995 #endif /* HAL_OPAMP_MODULE_ENABLED */
996 /**
997 * @}
998 */
999
1000 /**
1001 * @}
1002 */
1003
1004 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Imprint / Impressum