]> git.gir.st - tmk_keyboard.git/blob - tool/mbed/mbed-sdk/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32L1/stm32l1xx_hal_opamp_ex.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_ex.c
1 /**
2 ******************************************************************************
3 * @file stm32l1xx_hal_opamp_ex.c
4 * @author MCD Application Team
5 * @version V1.0.0
6 * @date 5-September-2014
7 * @brief Extended OPAMP HAL module driver.
8 *
9 * This file provides firmware functions to manage the following
10 * functionalities of the Power Controller (OPAMP) peripheral:
11 * + Extended Initialization and de-initialization functions
12 * + Extended Peripheral Control functions
13 *
14 @verbatim
15 ******************************************************************************
16 * @attention
17 *
18 * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
19 *
20 * Redistribution and use in source and binary forms, with or without modification,
21 * are permitted provided that the following conditions are met:
22 * 1. Redistributions of source code must retain the above copyright notice,
23 * this list of conditions and the following disclaimer.
24 * 2. Redistributions in binary form must reproduce the above copyright notice,
25 * this list of conditions and the following disclaimer in the documentation
26 * and/or other materials provided with the distribution.
27 * 3. Neither the name of STMicroelectronics nor the names of its contributors
28 * may be used to endorse or promote products derived from this software
29 * without specific prior written permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
32 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
34 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
35 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
37 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
39 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
40 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 *
42 ******************************************************************************
43 */
44
45 /* Includes ------------------------------------------------------------------*/
46 #include "stm32l1xx_hal.h"
47
48 /** @addtogroup STM32L1xx_HAL_Driver
49 * @{
50 */
51
52 /** @defgroup OPAMPEx OPAMPEx
53 * @brief OPAMP Extended HAL module driver.
54 * @{
55 */
56
57 #ifdef HAL_OPAMP_MODULE_ENABLED
58
59 #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)
60
61 /* Private typedef -----------------------------------------------------------*/
62 /* Private define ------------------------------------------------------------*/
63 /* Private macro -------------------------------------------------------------*/
64 /* Private variables ---------------------------------------------------------*/
65 /* Private function prototypes -----------------------------------------------*/
66 /* Private functions ---------------------------------------------------------*/
67
68 /** @addtogroup OPAMPEx_Exported_Functions OPAMPEx Exported Functions
69 * @{
70 */
71
72 /** @addtogroup OPAMPEx_Exported_Functions_Group1
73 * @brief Extended operation functions
74 *
75 @verbatim
76 ===============================================================================
77 ##### Extended IO operation functions #####
78 ===============================================================================
79 [..]
80 (+) OPAMP Self calibration.
81
82 @endverbatim
83 * @{
84 */
85
86 #if defined (STM32L151xD) || defined (STM32L152xD) || defined (STM32L162xD)
87
88 /* 3 OPAMPS available */
89 /* 3 OPAMPS can be calibrated in parallel */
90
91 /**
92 * @brief Run the self calibration of the 3 OPAMPs in parallel.
93 * @note Trimming values (PMOS & NMOS) are updated and user trimming is
94 * enabled is calibration is succesful.
95 * @note Calibration is performed in the mode specified in OPAMP init
96 * structure (mode normal or low-power). To perform calibration for
97 * both modes, repeat this function twice after OPAMP init structure
98 * accordingly updated.
99 * @note Calibration runs about 10 ms (5 dichotmy steps, repeated for P
100 * and N transistors: 10 steps with 1 ms for each step).
101 * @param hopamp1 handle
102 * @param hopamp2 handle
103 * @param hopamp3 handle
104 * @retval HAL status
105 */
106 HAL_StatusTypeDef HAL_OPAMPEx_SelfCalibrateAll(OPAMP_HandleTypeDef *hopamp1, OPAMP_HandleTypeDef *hopamp2, OPAMP_HandleTypeDef *hopamp3)
107 {
108 HAL_StatusTypeDef status = HAL_OK;
109
110 uint32_t* opamp1_trimmingvalue = 0;
111 uint32_t opamp1_trimmingvaluen = 0;
112 uint32_t opamp1_trimmingvaluep = 0;
113
114 uint32_t* opamp2_trimmingvalue = 0;
115 uint32_t opamp2_trimmingvaluen = 0;
116 uint32_t opamp2_trimmingvaluep = 0;
117
118 uint32_t* opamp3_trimmingvalue = 0;
119 uint32_t opamp3_trimmingvaluen = 0;
120 uint32_t opamp3_trimmingvaluep = 0;
121
122 uint32_t trimming_diff_pair = 0; /* Selection of differential transistors pair high or low */
123
124 __IO uint32_t* tmp_opamp1_reg_trimming; /* Selection of register of trimming depending on power mode: OTR or LPOTR */
125 __IO uint32_t* tmp_opamp2_reg_trimming;
126 __IO uint32_t* tmp_opamp3_reg_trimming;
127 uint32_t tmp_opamp1_otr_otuser = 0; /* Selection of bit OPAMP_OTR_OT_USER depending on trimming register pointed: OTR or LPOTR */
128 uint32_t tmp_opamp2_otr_otuser = 0;
129 uint32_t tmp_opamp3_otr_otuser = 0;
130
131 uint32_t tmp_Opa1calout_DefaultSate = 0; /* Bit OPAMP_CSR_OPA1CALOUT default state when trimming value is 00000b. Used to detect the bit toggling */
132 uint32_t tmp_Opa2calout_DefaultSate = 0; /* Bit OPAMP_CSR_OPA2CALOUT default state when trimming value is 00000b. Used to detect the bit toggling */
133 uint32_t tmp_Opa3calout_DefaultSate = 0; /* Bit OPAMP_CSR_OPA3CALOUT default state when trimming value is 00000b. Used to detect the bit toggling */
134
135 uint32_t tmp_OpaxSwitchesContextBackup = 0;
136
137 uint8_t trimming_diff_pair_iteration_count = 0;
138 uint8_t delta = 0;
139
140
141 /* Check the OPAMP handle allocation */
142 /* Check if OPAMP locked */
143 if((hopamp1 == HAL_NULL) || (hopamp1->State == HAL_OPAMP_STATE_BUSYLOCKED) ||
144 (hopamp2 == HAL_NULL) || (hopamp2->State == HAL_OPAMP_STATE_BUSYLOCKED) ||
145 (hopamp3 == HAL_NULL) || (hopamp3->State == HAL_OPAMP_STATE_BUSYLOCKED) )
146 {
147 status = HAL_ERROR;
148 }
149 else
150 {
151
152 /* Check if OPAMP in calibration mode and calibration not yet enable */
153 if((hopamp1->State == HAL_OPAMP_STATE_READY) &&
154 (hopamp2->State == HAL_OPAMP_STATE_READY) &&
155 (hopamp3->State == HAL_OPAMP_STATE_READY) )
156 {
157 /* Check the parameter */
158 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp1->Instance));
159 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp2->Instance));
160 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp3->Instance));
161 assert_param(IS_OPAMP_POWERMODE(hopamp1->Init.PowerMode));
162 assert_param(IS_OPAMP_POWERMODE(hopamp2->Init.PowerMode));
163 assert_param(IS_OPAMP_POWERMODE(hopamp3->Init.PowerMode));
164
165 /* Update OPAMP state */
166 hopamp1->State = HAL_OPAMP_STATE_CALIBBUSY;
167 hopamp2->State = HAL_OPAMP_STATE_CALIBBUSY;
168 hopamp3->State = HAL_OPAMP_STATE_CALIBBUSY;
169
170 /* Backup of switches configuration to restore it at the end of the */
171 /* calibration. */
172 tmp_OpaxSwitchesContextBackup = READ_BIT(OPAMP->CSR, OPAMP_CSR_ALL_SWITCHES_ALL_OPAMPS);
173
174 /* Open all switches on non-inverting input, inverting input and output */
175 /* feedback. */
176 CLEAR_BIT(OPAMP->CSR, OPAMP_CSR_ALL_SWITCHES_ALL_OPAMPS);
177
178 /* Set calibration mode to user programmed trimming values */
179 SET_BIT(OPAMP->OTR, OPAMP_OTR_OT_USER);
180
181 /* Select trimming settings depending on power mode */
182 if (hopamp1->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
183 {
184 tmp_opamp1_otr_otuser = OPAMP_OTR_OT_USER;
185 tmp_opamp1_reg_trimming = &OPAMP->OTR;
186 }
187 else
188 {
189 tmp_opamp1_otr_otuser = 0x00000000;
190 tmp_opamp1_reg_trimming = &OPAMP->LPOTR;
191 }
192
193 if (hopamp2->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
194 {
195 tmp_opamp2_otr_otuser = OPAMP_OTR_OT_USER;
196 tmp_opamp2_reg_trimming = &OPAMP->OTR;
197 }
198 else
199 {
200 tmp_opamp2_otr_otuser = 0x00000000;
201 tmp_opamp2_reg_trimming = &OPAMP->LPOTR;
202 }
203
204 if (hopamp3->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
205 {
206 tmp_opamp3_otr_otuser = OPAMP_OTR_OT_USER;
207 tmp_opamp3_reg_trimming = &OPAMP->OTR;
208 }
209 else
210 {
211 tmp_opamp3_otr_otuser = 0x00000000;
212 tmp_opamp3_reg_trimming = &OPAMP->LPOTR;
213 }
214
215 /* Enable the selected opamp */
216 CLEAR_BIT (OPAMP->CSR, OPAMP_CSR_OPAXPD_ALL);
217
218 /* Perform trimming for both differential transistors pair high and low */
219 for (trimming_diff_pair_iteration_count = 0; trimming_diff_pair_iteration_count <=1; trimming_diff_pair_iteration_count++)
220 {
221 if (trimming_diff_pair_iteration_count == 0)
222 {
223 /* Calibration of transistors differential pair high (NMOS) */
224 trimming_diff_pair = OPAMP_FACTORYTRIMMING_N;
225 opamp1_trimmingvalue = &opamp1_trimmingvaluen;
226 opamp2_trimmingvalue = &opamp2_trimmingvaluen;
227 opamp3_trimmingvalue = &opamp3_trimmingvaluen;
228
229 /* Set bit OPAMP_CSR_OPAXCALOUT default state when trimming value */
230 /* is 00000b. Used to detect the bit toggling during trimming. */
231 tmp_Opa1calout_DefaultSate = RESET;
232 tmp_Opa2calout_DefaultSate = RESET;
233 tmp_Opa3calout_DefaultSate = RESET;
234
235 /* Enable calibration for N differential pair */
236 MODIFY_REG(OPAMP->CSR, OPAMP_CSR_OPAXCAL_L_ALL,
237 OPAMP_CSR_OPAXCAL_H_ALL);
238 }
239 else /* (trimming_diff_pair_iteration_count == 1) */
240 {
241 /* Calibration of transistors differential pair low (PMOS) */
242 trimming_diff_pair = OPAMP_FACTORYTRIMMING_P;
243 opamp1_trimmingvalue = &opamp1_trimmingvaluep;
244 opamp2_trimmingvalue = &opamp2_trimmingvaluep;
245 opamp3_trimmingvalue = &opamp3_trimmingvaluep;
246
247 /* Set bit OPAMP_CSR_OPAXCALOUT default state when trimming value */
248 /* is 00000b. Used to detect the bit toggling during trimming. */
249 tmp_Opa1calout_DefaultSate = __OPAMP_CSR_OPAXCALOUT(hopamp1);
250 tmp_Opa2calout_DefaultSate = __OPAMP_CSR_OPAXCALOUT(hopamp2);
251 tmp_Opa3calout_DefaultSate = __OPAMP_CSR_OPAXCALOUT(hopamp3);
252
253 /* Enable calibration for P differential pair */
254 MODIFY_REG(OPAMP->CSR, OPAMP_CSR_OPAXCAL_H_ALL,
255 OPAMP_CSR_OPAXCAL_L_ALL);
256 }
257
258
259 /* Perform calibration parameter search by dichotomy sweep */
260 /* - Delta initial value 16: for 5 dichotomy steps: 16 for the */
261 /* initial range, then successive delta sweeps (8, 4, 2, 1). */
262 /* can extend the search range to +/- 15 units. */
263 /* - Trimming initial value 15: search range will go from 0 to 30 */
264 /* (Trimming value 31 is forbidden). */
265 *opamp1_trimmingvalue = 15;
266 *opamp2_trimmingvalue = 15;
267 *opamp3_trimmingvalue = 15;
268 delta = 16;
269
270 while (delta != 0)
271 {
272 /* Set candidate trimming */
273
274 MODIFY_REG(*tmp_opamp1_reg_trimming, __OPAMP_OFFSET_TRIM_SET(hopamp1, trimming_diff_pair, OPAMP_TRIM_VALUE_MASK) ,
275 __OPAMP_OFFSET_TRIM_SET(hopamp1, trimming_diff_pair, *opamp1_trimmingvalue) | tmp_opamp1_otr_otuser);
276
277 MODIFY_REG(*tmp_opamp2_reg_trimming, __OPAMP_OFFSET_TRIM_SET(hopamp2, trimming_diff_pair, OPAMP_TRIM_VALUE_MASK) ,
278 __OPAMP_OFFSET_TRIM_SET(hopamp2, trimming_diff_pair, *opamp2_trimmingvalue) | tmp_opamp2_otr_otuser);
279
280 MODIFY_REG(*tmp_opamp3_reg_trimming, __OPAMP_OFFSET_TRIM_SET(hopamp3, trimming_diff_pair, OPAMP_TRIM_VALUE_MASK) ,
281 __OPAMP_OFFSET_TRIM_SET(hopamp3, trimming_diff_pair, *opamp3_trimmingvalue) | tmp_opamp3_otr_otuser);
282
283
284 /* Offset trimming time: during calibration, minimum time needed */
285 /* between two steps to have 1 mV accuracy. */
286 HAL_Delay(OPAMP_TRIMMING_DELAY);
287
288 /* Divide range by 2 to continue dichotomy sweep */
289 delta >>= 1;
290
291 /* Set trimming values for next iteration in function of trimming */
292 /* result toggle (versus initial state). */
293 /* Trimming values update with dichotomy delta of previous */
294 /* iteration. */
295 if (READ_BIT(OPAMP->CSR, __OPAMP_CSR_OPAXCALOUT(hopamp1)) != tmp_Opa1calout_DefaultSate)
296 {
297 /* If calibration output is has toggled, try lower trimming */
298 *opamp1_trimmingvalue -= delta;
299 }
300 else
301 {
302 /* If calibration output is has not toggled, try higher trimming */
303 *opamp1_trimmingvalue += delta;
304 }
305
306 /* Set trimming values for next iteration in function of trimming */
307 /* result toggle (versus initial state). */
308 /* Trimming values update with dichotomy delta of previous */
309 /* iteration. */
310 if (READ_BIT(OPAMP->CSR, __OPAMP_CSR_OPAXCALOUT(hopamp2)) != tmp_Opa2calout_DefaultSate)
311 {
312 /* If calibration output is has toggled, try lower trimming */
313 *opamp2_trimmingvalue -= delta;
314 }
315 else
316 {
317 /* If calibration output is has not toggled, try higher trimming */
318 *opamp2_trimmingvalue += delta;
319 }
320
321 /* Set trimming values for next iteration in function of trimming */
322 /* result toggle (versus initial state). */
323 /* Trimming values update with dichotomy delta of previous */
324 /* iteration. */
325 if (READ_BIT(OPAMP->CSR, __OPAMP_CSR_OPAXCALOUT(hopamp3)) != tmp_Opa3calout_DefaultSate)
326 {
327 /* If calibration output is has toggled, try lower trimming */
328 *opamp3_trimmingvalue -= delta;
329 }
330 else
331 {
332 /* If calibration output is has not toggled, try higher trimming */
333 *opamp3_trimmingvalue += delta;
334 }
335
336 }
337 }
338
339
340 /* Disable calibration for P and N differential pairs */
341 /* Disable the selected opamp */
342 CLEAR_BIT (OPAMP->CSR, (OPAMP_CSR_OPAXCAL_H_ALL |
343 OPAMP_CSR_OPAXCAL_L_ALL |
344 OPAMP_CSR_OPAXPD_ALL ));
345
346 /* Backup of switches configuration to restore it at the end of the */
347 /* calibration. */
348 SET_BIT(OPAMP->CSR, tmp_OpaxSwitchesContextBackup);
349
350 /* Self calibration is successful */
351 /* Store calibration (user trimming) results in init structure. */
352
353 /* Set user trimming mode */
354 hopamp1->Init.UserTrimming = OPAMP_TRIMMING_USER;
355 hopamp2->Init.UserTrimming = OPAMP_TRIMMING_USER;
356 hopamp3->Init.UserTrimming = OPAMP_TRIMMING_USER;
357
358 /* Affect calibration parameters depending on mode normal/low power */
359 if (hopamp1->Init.PowerMode != OPAMP_POWERMODE_LOWPOWER)
360 {
361 /* Write calibration result N */
362 hopamp1->Init.TrimmingValueN = opamp1_trimmingvaluen;
363 /* Write calibration result P */
364 hopamp1->Init.TrimmingValueP = opamp1_trimmingvaluep;
365 }
366 else
367 {
368 /* Write calibration result N */
369 hopamp1->Init.TrimmingValueNLowPower = opamp1_trimmingvaluen;
370 /* Write calibration result P */
371 hopamp1->Init.TrimmingValuePLowPower = opamp1_trimmingvaluep;
372 }
373
374 if (hopamp2->Init.PowerMode != OPAMP_POWERMODE_LOWPOWER)
375 {
376 /* Write calibration result N */
377 hopamp2->Init.TrimmingValueN = opamp2_trimmingvaluen;
378 /* Write calibration result P */
379 hopamp2->Init.TrimmingValueP = opamp2_trimmingvaluep;
380 }
381 else
382 {
383 /* Write calibration result N */
384 hopamp2->Init.TrimmingValueNLowPower = opamp2_trimmingvaluen;
385 /* Write calibration result P */
386 hopamp2->Init.TrimmingValuePLowPower = opamp2_trimmingvaluep;
387 }
388
389 if (hopamp3->Init.PowerMode != OPAMP_POWERMODE_LOWPOWER)
390 {
391 /* Write calibration result N */
392 hopamp3->Init.TrimmingValueN = opamp3_trimmingvaluen;
393 /* Write calibration result P */
394 hopamp3->Init.TrimmingValueP = opamp3_trimmingvaluep;
395 }
396 else
397 {
398 /* Write calibration result N */
399 hopamp3->Init.TrimmingValueNLowPower = opamp3_trimmingvaluen;
400 /* Write calibration result P */
401 hopamp3->Init.TrimmingValuePLowPower = opamp3_trimmingvaluep;
402 }
403
404 /* Update OPAMP state */
405 hopamp1->State = HAL_OPAMP_STATE_READY;
406 hopamp2->State = HAL_OPAMP_STATE_READY;
407 hopamp3->State = HAL_OPAMP_STATE_READY;
408
409 }
410 else
411 {
412 /* OPAMP can not be calibrated from this mode */
413 status = HAL_ERROR;
414 }
415 }
416
417 return status;
418 }
419
420 #else
421
422 /* 2 OPAMPS available */
423 /* 2 OPAMPS can be calibrated in parallel */
424
425 /**
426 * @brief Run the self calibration of the 2 OPAMPs in parallel.
427 * @note Trimming values (PMOS & NMOS) are updated and user trimming is
428 * enabled is calibration is succesful.
429 * @note Calibration is performed in the mode specified in OPAMP init
430 * structure (mode normal or low-power). To perform calibration for
431 * both modes, repeat this function twice after OPAMP init structure
432 * accordingly updated.
433 * @note Calibration runs about 10 ms (5 dichotmy steps, repeated for P
434 * and N transistors: 10 steps with 1 ms for each step).
435 * @param hopamp1 handle
436 * @param hopamp2 handle
437 * @retval HAL status
438 */
439 HAL_StatusTypeDef HAL_OPAMPEx_SelfCalibrateAll(OPAMP_HandleTypeDef *hopamp1, OPAMP_HandleTypeDef *hopamp2)
440 {
441 HAL_StatusTypeDef status = HAL_OK;
442
443 uint32_t* opamp1_trimmingvalue = 0;
444 uint32_t opamp1_trimmingvaluen = 0;
445 uint32_t opamp1_trimmingvaluep = 0;
446
447 uint32_t* opamp2_trimmingvalue = 0;
448 uint32_t opamp2_trimmingvaluen = 0;
449 uint32_t opamp2_trimmingvaluep = 0;
450
451 uint32_t trimming_diff_pair = 0; /* Selection of differential transistors pair high or low */
452
453 __IO uint32_t* tmp_opamp1_reg_trimming; /* Selection of register of trimming depending on power mode: OTR or LPOTR */
454 __IO uint32_t* tmp_opamp2_reg_trimming;
455 uint32_t tmp_opamp1_otr_otuser = 0; /* Selection of bit OPAMP_OTR_OT_USER depending on trimming register pointed: OTR or LPOTR */
456 uint32_t tmp_opamp2_otr_otuser = 0;
457
458 uint32_t tmp_Opa1calout_DefaultSate = 0; /* Bit OPAMP_CSR_OPA1CALOUT default state when trimming value is 00000b. Used to detect the bit toggling */
459 uint32_t tmp_Opa2calout_DefaultSate = 0; /* Bit OPAMP_CSR_OPA2CALOUT default state when trimming value is 00000b. Used to detect the bit toggling */
460
461 uint32_t tmp_OpaxSwitchesContextBackup = 0;
462
463 uint8_t trimming_diff_pair_iteration_count = 0;
464 uint8_t delta = 0;
465
466
467 /* Check the OPAMP handle allocation */
468 /* Check if OPAMP locked */
469 if((hopamp1 == HAL_NULL) || (hopamp1->State == HAL_OPAMP_STATE_BUSYLOCKED) ||
470 (hopamp2 == HAL_NULL) || (hopamp2->State == HAL_OPAMP_STATE_BUSYLOCKED) )
471 {
472 status = HAL_ERROR;
473 }
474 else
475 {
476
477 /* Check if OPAMP in calibration mode and calibration not yet enable */
478 if((hopamp1->State == HAL_OPAMP_STATE_READY) &&
479 (hopamp2->State == HAL_OPAMP_STATE_READY) )
480 {
481 /* Check the parameter */
482 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp1->Instance));
483 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp2->Instance));
484 assert_param(IS_OPAMP_POWERMODE(hopamp1->Init.PowerMode));
485 assert_param(IS_OPAMP_POWERMODE(hopamp2->Init.PowerMode));
486
487 /* Update OPAMP state */
488 hopamp1->State = HAL_OPAMP_STATE_CALIBBUSY;
489 hopamp2->State = HAL_OPAMP_STATE_CALIBBUSY;
490
491 /* Backup of switches configuration to restore it at the end of the */
492 /* calibration. */
493 tmp_OpaxSwitchesContextBackup = READ_BIT(OPAMP->CSR, OPAMP_CSR_ALL_SWITCHES_ALL_OPAMPS);
494
495 /* Open all switches on non-inverting input, inverting input and output */
496 /* feedback. */
497 CLEAR_BIT(OPAMP->CSR, OPAMP_CSR_ALL_SWITCHES_ALL_OPAMPS);
498
499 /* Set calibration mode to user programmed trimming values */
500 SET_BIT(OPAMP->OTR, OPAMP_OTR_OT_USER);
501
502 /* Select trimming settings depending on power mode */
503 if (hopamp1->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
504 {
505 tmp_opamp1_otr_otuser = OPAMP_OTR_OT_USER;
506 tmp_opamp1_reg_trimming = &OPAMP->OTR;
507 }
508 else
509 {
510 tmp_opamp1_otr_otuser = 0x00000000;
511 tmp_opamp1_reg_trimming = &OPAMP->LPOTR;
512 }
513
514 if (hopamp2->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
515 {
516 tmp_opamp2_otr_otuser = OPAMP_OTR_OT_USER;
517 tmp_opamp2_reg_trimming = &OPAMP->OTR;
518 }
519 else
520 {
521 tmp_opamp2_otr_otuser = 0x00000000;
522 tmp_opamp2_reg_trimming = &OPAMP->LPOTR;
523 }
524
525 /* Enable the selected opamp */
526 CLEAR_BIT (OPAMP->CSR, OPAMP_CSR_OPAXPD_ALL);
527
528 /* Perform trimming for both differential transistors pair high and low */
529 for (trimming_diff_pair_iteration_count = 0; trimming_diff_pair_iteration_count <=1; trimming_diff_pair_iteration_count++)
530 {
531 if (trimming_diff_pair_iteration_count == 0)
532 {
533 /* Calibration of transistors differential pair high (NMOS) */
534 trimming_diff_pair = OPAMP_FACTORYTRIMMING_N;
535 opamp1_trimmingvalue = &opamp1_trimmingvaluen;
536 opamp2_trimmingvalue = &opamp2_trimmingvaluen;
537
538 /* Set bit OPAMP_CSR_OPAXCALOUT default state when trimming value */
539 /* is 00000b. Used to detect the bit toggling during trimming. */
540 tmp_Opa1calout_DefaultSate = RESET;
541 tmp_Opa2calout_DefaultSate = RESET;
542
543 /* Enable calibration for N differential pair */
544 MODIFY_REG(OPAMP->CSR, OPAMP_CSR_OPAXCAL_L_ALL,
545 OPAMP_CSR_OPAXCAL_H_ALL);
546 }
547 else /* (trimming_diff_pair_iteration_count == 1) */
548 {
549 /* Calibration of transistors differential pair low (PMOS) */
550 trimming_diff_pair = OPAMP_FACTORYTRIMMING_P;
551 opamp1_trimmingvalue = &opamp1_trimmingvaluep;
552 opamp2_trimmingvalue = &opamp2_trimmingvaluep;
553
554 /* Set bit OPAMP_CSR_OPAXCALOUT default state when trimming value */
555 /* is 00000b. Used to detect the bit toggling during trimming. */
556 tmp_Opa1calout_DefaultSate = __OPAMP_CSR_OPAXCALOUT(hopamp1);
557 tmp_Opa2calout_DefaultSate = __OPAMP_CSR_OPAXCALOUT(hopamp2);
558
559 /* Enable calibration for P differential pair */
560 MODIFY_REG(OPAMP->CSR, OPAMP_CSR_OPAXCAL_H_ALL,
561 OPAMP_CSR_OPAXCAL_L_ALL);
562 }
563
564
565 /* Perform calibration parameter search by dichotomy sweep */
566 /* - Delta initial value 16: for 5 dichotomy steps: 16 for the */
567 /* initial range, then successive delta sweeps (8, 4, 2, 1). */
568 /* can extend the search range to +/- 15 units. */
569 /* - Trimming initial value 15: search range will go from 0 to 30 */
570 /* (Trimming value 31 is forbidden). */
571 *opamp1_trimmingvalue = 15;
572 *opamp2_trimmingvalue = 15;
573 delta = 16;
574
575 while (delta != 0)
576 {
577 /* Set candidate trimming */
578
579 MODIFY_REG(*tmp_opamp1_reg_trimming, __OPAMP_OFFSET_TRIM_SET(hopamp1, trimming_diff_pair, OPAMP_TRIM_VALUE_MASK) ,
580 __OPAMP_OFFSET_TRIM_SET(hopamp1, trimming_diff_pair, *opamp1_trimmingvalue) | tmp_opamp1_otr_otuser);
581
582 MODIFY_REG(*tmp_opamp2_reg_trimming, __OPAMP_OFFSET_TRIM_SET(hopamp2, trimming_diff_pair, OPAMP_TRIM_VALUE_MASK) ,
583 __OPAMP_OFFSET_TRIM_SET(hopamp2, trimming_diff_pair, *opamp2_trimmingvalue) | tmp_opamp2_otr_otuser);
584
585
586 /* Offset trimming time: during calibration, minimum time needed */
587 /* between two steps to have 1 mV accuracy. */
588 HAL_Delay(OPAMP_TRIMMING_DELAY);
589
590 /* Divide range by 2 to continue dichotomy sweep */
591 delta >>= 1;
592
593 /* Set trimming values for next iteration in function of trimming */
594 /* result toggle (versus initial state). */
595 if (READ_BIT(OPAMP->CSR, __OPAMP_CSR_OPAXCALOUT(hopamp1)) != tmp_Opa1calout_DefaultSate)
596 {
597 /* If calibration output is has toggled, try lower trimming */
598 *opamp1_trimmingvalue -= delta;
599 }
600 else
601 {
602 /* If calibration output is has not toggled, try higher trimming */
603 *opamp1_trimmingvalue += delta;
604 }
605
606 /* Set trimming values for next iteration in function of trimming */
607 /* result toggle (versus initial state). */
608 if (READ_BIT(OPAMP->CSR, __OPAMP_CSR_OPAXCALOUT(hopamp2)) != tmp_Opa2calout_DefaultSate)
609 {
610 /* If calibration output is has toggled, try lower trimming */
611 *opamp2_trimmingvalue -= delta;
612 }
613 else
614 {
615 /* If calibration output is has not toggled, try higher trimming */
616 *opamp2_trimmingvalue += delta;
617 }
618
619 }
620 }
621
622
623 /* Disable calibration for P and N differential pairs */
624 /* Disable the selected opamp */
625 CLEAR_BIT (OPAMP->CSR, (OPAMP_CSR_OPAXCAL_H_ALL |
626 OPAMP_CSR_OPAXCAL_L_ALL |
627 OPAMP_CSR_OPAXPD_ALL ));
628
629 /* Backup of switches configuration to restore it at the end of the */
630 /* calibration. */
631 SET_BIT(OPAMP->CSR, tmp_OpaxSwitchesContextBackup);
632
633 /* Self calibration is successful */
634 /* Store calibration (user trimming) results in init structure. */
635
636 /* Set user trimming mode */
637 hopamp1->Init.UserTrimming = OPAMP_TRIMMING_USER;
638 hopamp2->Init.UserTrimming = OPAMP_TRIMMING_USER;
639
640 /* Affect calibration parameters depending on mode normal/low power */
641 if (hopamp1->Init.PowerMode != OPAMP_POWERMODE_LOWPOWER)
642 {
643 /* Write calibration result N */
644 hopamp1->Init.TrimmingValueN = opamp1_trimmingvaluen;
645 /* Write calibration result P */
646 hopamp1->Init.TrimmingValueP = opamp1_trimmingvaluep;
647 }
648 else
649 {
650 /* Write calibration result N */
651 hopamp1->Init.TrimmingValueNLowPower = opamp1_trimmingvaluen;
652 /* Write calibration result P */
653 hopamp1->Init.TrimmingValuePLowPower = opamp1_trimmingvaluep;
654 }
655
656 if (hopamp2->Init.PowerMode != OPAMP_POWERMODE_LOWPOWER)
657 {
658 /* Write calibration result N */
659 hopamp2->Init.TrimmingValueN = opamp2_trimmingvaluen;
660 /* Write calibration result P */
661 hopamp2->Init.TrimmingValueP = opamp2_trimmingvaluep;
662 }
663 else
664 {
665 /* Write calibration result N */
666 hopamp2->Init.TrimmingValueNLowPower = opamp2_trimmingvaluen;
667 /* Write calibration result P */
668 hopamp2->Init.TrimmingValuePLowPower = opamp2_trimmingvaluep;
669 }
670
671 /* Update OPAMP state */
672 hopamp1->State = HAL_OPAMP_STATE_READY;
673 hopamp2->State = HAL_OPAMP_STATE_READY;
674
675 }
676 else
677 {
678 /* OPAMP can not be calibrated from this mode */
679 status = HAL_ERROR;
680 }
681 }
682
683 return status;
684 }
685
686 #endif /* STM32L151xD || STM32L152xD || STM32L162xD */
687
688 /**
689 * @}
690 */
691
692 /** @defgroup OPAMPEx_Exported_Functions_Group2 Extended Peripheral Control functions
693 * @brief Extended control functions
694 *
695 @verbatim
696 ===============================================================================
697 ##### Peripheral Control functions #####
698 ===============================================================================
699 [..]
700 (+) OPAMP unlock.
701
702 @endverbatim
703 * @{
704 */
705
706 /**
707 * @brief Unlock the selected opamp configuration.
708 * This function must be called only when OPAMP is in state "locked".
709 * @param hopamp: OPAMP handle
710 * @retval HAL status
711 */
712 HAL_StatusTypeDef HAL_OPAMPEx_Unlock(OPAMP_HandleTypeDef* hopamp)
713 {
714 HAL_StatusTypeDef status = HAL_OK;
715
716 /* Check the OPAMP handle allocation */
717 /* Check if OPAMP locked */
718 if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_RESET)
719 || (hopamp->State == HAL_OPAMP_STATE_READY)
720 || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)
721 || (hopamp->State == HAL_OPAMP_STATE_BUSY))
722
723 {
724 status = HAL_ERROR;
725 }
726 else
727 {
728 /* Check the parameter */
729 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
730
731 /* OPAMP state changed to locked */
732 hopamp->State = HAL_OPAMP_STATE_BUSY;
733 }
734 return status;
735 }
736
737 /**
738 * @}
739 */
740
741
742 /**
743 * @}
744 */
745
746 #endif /* STM32L151xCA || STM32L151xD || STM32L152xCA || STM32L152xD || STM32L162xCA || STM32L162xD || STM32L151xE || STM32L152xE || STM32L162xE || STM32L162xC || STM32L152xC || STM32L151xC */
747
748 #endif /* HAL_OPAMP_MODULE_ENABLED */
749 /**
750 * @}
751 */
752
753 /**
754 * @}
755 */
756
757 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Imprint / Impressum