]> git.gir.st - tmk_keyboard.git/blob - tool/mbed/mbed-sdk/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F3/stm32f3xx_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_STM32F3 / stm32f3xx_hal_opamp_ex.c
1 /**
2 ******************************************************************************
3 * @file stm32f3xx_hal_opamp_ex.c
4 * @author MCD Application Team
5 * @version V1.1.0
6 * @date 12-Sept-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 "stm32f3xx_hal.h"
47
48 /** @addtogroup STM32F3xx_HAL_Driver
49 * @{
50 */
51
52 /** @defgroup OPAMPEx OPAMP Extended HAL module driver
53 * @brief OPAMP Extended HAL module driver.
54 * @{
55 */
56
57 #ifdef HAL_OPAMP_MODULE_ENABLED
58
59 /* Private typedef -----------------------------------------------------------*/
60 /* Private define ------------------------------------------------------------*/
61 /* Private macro -------------------------------------------------------------*/
62 /* Private variables ---------------------------------------------------------*/
63 /* Private function prototypes -----------------------------------------------*/
64 /* Exported functions ---------------------------------------------------------*/
65
66 /** @defgroup OPAMPEx_Exported_Functions OPAMP Extended Exported Functions
67 * @{
68 */
69
70
71 /** @defgroup OPAMPEx_Exported_Functions_Group1 Extended Input and Output operation functions
72 * @brief Extended Self calibration functions
73 *
74 @verbatim
75 ===============================================================================
76 ##### Extended IO operation functions #####
77 ===============================================================================
78 [..]
79
80 @endverbatim
81 * @{
82 */
83
84 #if defined(STM32F302xE) || \
85 defined(STM32F302xC)
86 /* 2 OPAMPS available */
87 /* 2 OPAMPS can be calibrated in parallel */
88
89 /**
90 * @brief Run the self calibration of 2 OPAMPs in parallel.
91 * @param hopamp1 handle
92 * @param hopamp2 handle
93 * @retval HAL status
94 * @note Updated offset trimming values (PMOS & NMOS), user trimming is enabled
95 * @note Calibration runs about 25 ms.
96 */
97
98 HAL_StatusTypeDef HAL_OPAMPEx_SelfCalibrateAll(OPAMP_HandleTypeDef *hopamp1, OPAMP_HandleTypeDef *hopamp2)
99 {
100 HAL_StatusTypeDef status = HAL_OK;
101
102 uint32_t trimmingvaluen1 = 0;
103 uint32_t trimmingvaluep1 = 0;
104 uint32_t trimmingvaluen2 = 0;
105 uint32_t trimmingvaluep2 = 0;
106
107 uint32_t delta;
108
109 if((hopamp1 == HAL_NULL) || (hopamp1->State == HAL_OPAMP_STATE_BUSYLOCKED) || \
110 (hopamp2 == HAL_NULL) || (hopamp2->State == HAL_OPAMP_STATE_BUSYLOCKED))
111 {
112 status = HAL_ERROR;
113 }
114
115 if(status == HAL_OK)
116 {
117 /* Check if OPAMP in calibration mode and calibration not yet enable */
118 if((hopamp1->State == HAL_OPAMP_STATE_READY) && (hopamp2->State == HAL_OPAMP_STATE_READY))
119 {
120 /* Check the parameter */
121 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp1->Instance));
122 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp2->Instance));
123
124 /* Set Calibration mode */
125 /* Non-inverting input connected to calibration reference voltage. */
126 SET_BIT(hopamp1->Instance->CSR, OPAMP_CSR_FORCEVP);
127 SET_BIT(hopamp2->Instance->CSR, OPAMP_CSR_FORCEVP);
128
129 /* user trimming values are used for offset calibration */
130 SET_BIT(hopamp1->Instance->CSR, OPAMP_CSR_USERTRIM);
131 SET_BIT(hopamp2->Instance->CSR, OPAMP_CSR_USERTRIM);
132
133 /* Enable calibration */
134 SET_BIT (hopamp1->Instance->CSR, OPAMP_CSR_CALON);
135 SET_BIT (hopamp2->Instance->CSR, OPAMP_CSR_CALON);
136
137 /* 1st calibration - N */
138 /* Select 90% VREF */
139 MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_90VDDA);
140 MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_90VDDA);
141
142 /* Enable the opamps */
143 SET_BIT (hopamp1->Instance->CSR, OPAMP_CSR_OPAMPxEN);
144 SET_BIT (hopamp2->Instance->CSR, OPAMP_CSR_OPAMPxEN);
145
146 /* Init trimming counter */
147 /* Medium value */
148 trimmingvaluen1 = 16;
149 trimmingvaluen2 = 16;
150 delta = 8;
151
152 while (delta != 0)
153 {
154 // Set candidate trimming */
155 MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen1<<OPAMP_INPUT_INVERTING);
156 MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen2<<OPAMP_INPUT_INVERTING);
157
158 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
159 /* Offset trim time: during calibration, minimum time needed between */
160 /* two steps to have 1 mV accuracy */
161 HAL_Delay(2);
162
163 if (hopamp1->Instance->CSR & OPAMP_CSR_OUTCAL)
164 {
165 /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */
166 trimmingvaluen1 += delta;
167 }
168 else
169 {
170 /* OPAMP_CSR_OUTCAL is LOW try lower trimming */
171 trimmingvaluen1 -= delta;
172 }
173
174 if (hopamp2->Instance->CSR & OPAMP_CSR_OUTCAL)
175 {
176 /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */
177 trimmingvaluen2 += delta;
178 }
179 else
180 {
181 /* OPAMP_CSR_OUTCAL is LOW try lower trimming */
182 trimmingvaluen2 -= delta;
183 }
184
185 delta >>= 1;
186 }
187
188 // Still need to check if righ calibration is current value or un step below
189 // Indeed the first value that causes the OUTCAL bit to change from 1 to 0
190 MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen1<<OPAMP_INPUT_INVERTING);
191 MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen2<<OPAMP_INPUT_INVERTING);
192
193 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
194 /* Offset trim time: during calibration, minimum time needed between */
195 /* two steps to have 1 mV accuracy */
196 HAL_Delay(2);
197
198 if (hopamp1->Instance->CSR & OPAMP_CSR_OUTCAL)
199 {
200 /* OPAMP_CSR_OUTCAL is actually one value more */
201 trimmingvaluen1++;
202 /* Set right trimming */
203 MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen1<<OPAMP_INPUT_INVERTING);
204 }
205
206 if (hopamp2->Instance->CSR & OPAMP_CSR_OUTCAL)
207 {
208 /* OPAMP_CSR_OUTCAL is actually one value more */
209 trimmingvaluen2++;
210 /* Set right trimming */
211 MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen2<<OPAMP_INPUT_INVERTING);
212 }
213
214
215 /* 2nd calibration - P */
216 /* Select 10% VREF */
217 MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_10VDDA);
218 MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_10VDDA);
219
220 /* Init trimming counter */
221 /* Medium value */
222 trimmingvaluep1 = 16;
223 trimmingvaluep2 = 16;
224 delta = 8;
225
226 while (delta != 0)
227 {
228 // Set candidate trimming */
229 MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep1<<OPAMP_INPUT_NONINVERTING);
230 MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep2<<OPAMP_INPUT_NONINVERTING);
231
232 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
233 /* Offset trim time: during calibration, minimum time needed between */
234 /* two steps to have 1 mV accuracy */
235 HAL_Delay(2);
236
237 if (hopamp1->Instance->CSR & OPAMP_CSR_OUTCAL)
238 {
239 /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */
240 trimmingvaluep1 += delta;
241 }
242 else
243 {
244 trimmingvaluep1 -= delta;
245 }
246
247 if (hopamp2->Instance->CSR & OPAMP_CSR_OUTCAL)
248 {
249 /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */
250 trimmingvaluep2 += delta;
251 }
252 else
253 {
254 trimmingvaluep2 -= delta;
255 }
256
257 delta >>= 1;
258 }
259
260 // Still need to check if righ calibration is current value or un step below
261 // Indeed the first value that causes the OUTCAL bit to change from 1 to 0
262 // Set candidate trimming */
263 MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep1<<OPAMP_INPUT_NONINVERTING);
264 MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep2<<OPAMP_INPUT_NONINVERTING);
265
266 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
267 /* Offset trim time: during calibration, minimum time needed between */
268 /* two steps to have 1 mV accuracy */
269 HAL_Delay(2);
270
271 if (hopamp1->Instance->CSR & OPAMP_CSR_OUTCAL)
272 {
273 /* OPAMP_CSR_OUTCAL is actually one value more */
274 trimmingvaluep1++;
275 /* Set right trimming */
276 MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep1<<OPAMP_INPUT_NONINVERTING);
277 }
278
279 if (hopamp2->Instance->CSR & OPAMP_CSR_OUTCAL)
280 {
281 /* OPAMP_CSR_OUTCAL is actually one value more */
282 trimmingvaluep2++;
283 /* Set right trimming */
284 MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep2<<OPAMP_INPUT_NONINVERTING);
285 }
286
287 /* Disable calibration */
288 CLEAR_BIT (hopamp1->Instance->CSR, OPAMP_CSR_CALON);
289 CLEAR_BIT (hopamp2->Instance->CSR, OPAMP_CSR_CALON);
290
291 /* Disable the OPAMPs */
292 CLEAR_BIT (hopamp1->Instance->CSR, OPAMP_CSR_OPAMPxEN);
293 CLEAR_BIT (hopamp2->Instance->CSR, OPAMP_CSR_OPAMPxEN);
294
295 /* Set normale operating mode back */
296 CLEAR_BIT(hopamp1->Instance->CSR, OPAMP_CSR_FORCEVP);
297 CLEAR_BIT(hopamp2->Instance->CSR, OPAMP_CSR_FORCEVP);
298
299 /* Self calibration is successful */
300 /* Store calibration(user timming) results in init structure. */
301 /* Select user timming mode */
302
303 /* Write calibration result N */
304 hopamp1->Init.TrimmingValueN = trimmingvaluen1;
305 hopamp2->Init.TrimmingValueN = trimmingvaluen2;
306
307 /* Write calibration result P */
308 hopamp1->Init.TrimmingValueP = trimmingvaluep1;
309 hopamp2->Init.TrimmingValueP = trimmingvaluep2;
310
311 /* Calibration */
312 hopamp1->Init.UserTrimming = OPAMP_TRIMMING_USER;
313 hopamp2->Init.UserTrimming = OPAMP_TRIMMING_USER;
314
315 /* Select user timming mode */
316 /* And updated with calibrated settings */
317 hopamp1->Init.UserTrimming = OPAMP_TRIMMING_USER;
318 hopamp2->Init.UserTrimming = OPAMP_TRIMMING_USER;
319
320 MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen1<<OPAMP_INPUT_INVERTING);
321 MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen2<<OPAMP_INPUT_INVERTING);
322
323 MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep1<<OPAMP_INPUT_NONINVERTING);
324 MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep2<<OPAMP_INPUT_NONINVERTING);
325
326 }
327
328 else
329 {
330 /* At least one OPAMP can not be calibrated */
331 status = HAL_ERROR;
332 }
333 }
334
335 return status;
336 }
337 #endif /* STM32F302xE || */
338 /* STM32F302xC */
339
340 #if defined(STM32F303xE) || defined(STM32F398xx) || \
341 defined(STM32F303xC) || defined(STM32F358xx)
342 /* 4 OPAMPS available */
343 /* 4 OPAMPS can be calibrated in parallel */
344
345 /**
346 * @brief Run the self calibration of 4 OPAMPs in parallel.
347 * @param hopamp1 handle
348 * @param hopamp2 handle
349 * @param hopamp3 handle
350 * @param hopamp4 handle
351 * @retval HAL status
352 * @note Updated offset trimming values (PMOS & NMOS), user trimming is enabled
353 * @note Calibration runs about 25 ms.
354 */
355
356 HAL_StatusTypeDef HAL_OPAMPEx_SelfCalibrateAll(OPAMP_HandleTypeDef *hopamp1, OPAMP_HandleTypeDef *hopamp2, OPAMP_HandleTypeDef *hopamp3, OPAMP_HandleTypeDef *hopamp4)
357 {
358 HAL_StatusTypeDef status = HAL_OK;
359
360 uint32_t trimmingvaluen1 = 0;
361 uint32_t trimmingvaluep1 = 0;
362 uint32_t trimmingvaluen2 = 0;
363 uint32_t trimmingvaluep2 = 0;
364 uint32_t trimmingvaluen3 = 0;
365 uint32_t trimmingvaluep3 = 0;
366 uint32_t trimmingvaluen4 = 0;
367 uint32_t trimmingvaluep4 = 0;
368
369 uint32_t delta;
370
371 if((hopamp1 == HAL_NULL) || (hopamp1->State == HAL_OPAMP_STATE_BUSYLOCKED) || \
372 (hopamp2 == HAL_NULL) || (hopamp2->State == HAL_OPAMP_STATE_BUSYLOCKED) || \
373 (hopamp3 == HAL_NULL) || (hopamp3->State == HAL_OPAMP_STATE_BUSYLOCKED) || \
374 (hopamp4 == HAL_NULL) || (hopamp4->State == HAL_OPAMP_STATE_BUSYLOCKED))
375 {
376 status = HAL_ERROR;
377 }
378
379 if(status == HAL_OK)
380 {
381 /* Check if OPAMP in calibration mode and calibration not yet enable */
382 if((hopamp1->State == HAL_OPAMP_STATE_READY) && (hopamp2->State == HAL_OPAMP_STATE_READY) && \
383 (hopamp3->State == HAL_OPAMP_STATE_READY) && (hopamp4->State == HAL_OPAMP_STATE_READY))
384 {
385 /* Check the parameter */
386 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp1->Instance));
387 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp2->Instance));
388 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp3->Instance));
389 assert_param(IS_OPAMP_ALL_INSTANCE(hopamp4->Instance));
390
391 /* Set Calibration mode */
392 /* Non-inverting input connected to calibration reference voltage. */
393 SET_BIT(hopamp1->Instance->CSR, OPAMP_CSR_FORCEVP);
394 SET_BIT(hopamp2->Instance->CSR, OPAMP_CSR_FORCEVP);
395 SET_BIT(hopamp3->Instance->CSR, OPAMP_CSR_FORCEVP);
396 SET_BIT(hopamp4->Instance->CSR, OPAMP_CSR_FORCEVP);
397
398 /* user trimming values are used for offset calibration */
399 SET_BIT(hopamp1->Instance->CSR, OPAMP_CSR_USERTRIM);
400 SET_BIT(hopamp2->Instance->CSR, OPAMP_CSR_USERTRIM);
401 SET_BIT(hopamp3->Instance->CSR, OPAMP_CSR_USERTRIM);
402 SET_BIT(hopamp4->Instance->CSR, OPAMP_CSR_USERTRIM);
403
404 /* Enable calibration */
405 SET_BIT (hopamp1->Instance->CSR, OPAMP_CSR_CALON);
406 SET_BIT (hopamp2->Instance->CSR, OPAMP_CSR_CALON);
407 SET_BIT (hopamp3->Instance->CSR, OPAMP_CSR_CALON);
408 SET_BIT (hopamp4->Instance->CSR, OPAMP_CSR_CALON);
409
410 /* 1st calibration - N */
411 /* Select 90% VREF */
412 MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_90VDDA);
413 MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_90VDDA);
414 MODIFY_REG(hopamp3->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_90VDDA);
415 MODIFY_REG(hopamp4->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_90VDDA);
416
417 /* Enable the opamps */
418 SET_BIT (hopamp1->Instance->CSR, OPAMP_CSR_OPAMPxEN);
419 SET_BIT (hopamp2->Instance->CSR, OPAMP_CSR_OPAMPxEN);
420 SET_BIT (hopamp3->Instance->CSR, OPAMP_CSR_OPAMPxEN);
421 SET_BIT (hopamp4->Instance->CSR, OPAMP_CSR_OPAMPxEN);
422
423 /* Init trimming counter */
424 /* Medium value */
425 trimmingvaluen1 = 16;
426 trimmingvaluen2 = 16;
427 trimmingvaluen3 = 16;
428 trimmingvaluen4 = 16;
429 delta = 8;
430
431 while (delta != 0)
432 {
433 /* Set candidate trimming */
434 MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen1<<OPAMP_INPUT_INVERTING);
435 MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen2<<OPAMP_INPUT_INVERTING);
436 MODIFY_REG(hopamp3->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen3<<OPAMP_INPUT_INVERTING);
437 MODIFY_REG(hopamp4->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen4<<OPAMP_INPUT_INVERTING);
438
439 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
440 /* Offset trim time: during calibration, minimum time needed between */
441 /* two steps to have 1 mV accuracy */
442 HAL_Delay(2);
443
444 if ((hopamp1->Instance->CSR & OPAMP_CSR_OUTCAL) != RESET)
445 {
446 /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */
447 trimmingvaluen1 += delta;
448 }
449 else
450 {
451 /* OPAMP_CSR_OUTCAL is LOW try lower trimming */
452 trimmingvaluen1 -= delta;
453 }
454
455 if ((hopamp2->Instance->CSR & OPAMP_CSR_OUTCAL) != RESET)
456 {
457 /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */
458 trimmingvaluen2 += delta;
459 }
460 else
461 {
462 /* OPAMP_CSR_OUTCAL is LOW try lower trimming */
463 trimmingvaluen2 -= delta;
464 }
465
466 if ((hopamp3->Instance->CSR & OPAMP_CSR_OUTCAL) != RESET)
467 {
468 /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */
469 trimmingvaluen3 += delta;
470 }
471 else
472 {
473 /* OPAMP_CSR_OUTCAL is LOW try lower trimming */
474 trimmingvaluen3 -= delta;
475 }
476
477 if ((hopamp4->Instance->CSR & OPAMP_CSR_OUTCAL) != RESET)
478 {
479 /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */
480 trimmingvaluen4 += delta;
481 }
482 else
483 {
484 /* OPAMP_CSR_OUTCAL is LOW try lower trimming */
485 trimmingvaluen4 -= delta;
486 }
487
488 delta >>= 1;
489 }
490
491 /* Still need to check if righ calibration is current value or un step below */
492 /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */
493 MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen1<<OPAMP_INPUT_INVERTING);
494 MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen2<<OPAMP_INPUT_INVERTING);
495 MODIFY_REG(hopamp3->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen3<<OPAMP_INPUT_INVERTING);
496 MODIFY_REG(hopamp4->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen4<<OPAMP_INPUT_INVERTING);
497
498 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
499 /* Offset trim time: during calibration, minimum time needed between */
500 /* two steps to have 1 mV accuracy */
501 HAL_Delay(2);
502
503 if ((hopamp1->Instance->CSR & OPAMP_CSR_OUTCAL) != RESET)
504 {
505 /* OPAMP_CSR_OUTCAL is actually one value more */
506 trimmingvaluen1++;
507 /* Set right trimming */
508 MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen1<<OPAMP_INPUT_INVERTING);
509 }
510
511 if ((hopamp2->Instance->CSR & OPAMP_CSR_OUTCAL) != RESET)
512 {
513 /* OPAMP_CSR_OUTCAL is actually one value more */
514 trimmingvaluen2++;
515 /* Set right trimming */
516 MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen2<<OPAMP_INPUT_INVERTING);
517 }
518
519 if ((hopamp3->Instance->CSR & OPAMP_CSR_OUTCAL) != RESET)
520 {
521 /* OPAMP_CSR_OUTCAL is actually one value more */
522 trimmingvaluen3++;
523 /* Set right trimming */
524 MODIFY_REG(hopamp3->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen3<<OPAMP_INPUT_INVERTING);
525 }
526
527 if ((hopamp4->Instance->CSR & OPAMP_CSR_OUTCAL) != RESET)
528 {
529 /* OPAMP_CSR_OUTCAL is actually one value more */
530 trimmingvaluen4++;
531 /* Set right trimming */
532 MODIFY_REG(hopamp4->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen4<<OPAMP_INPUT_INVERTING);
533 }
534
535 /* 2nd calibration - P */
536 /* Select 10% VREF */
537 MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_10VDDA);
538 MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_10VDDA);
539 MODIFY_REG(hopamp3->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_10VDDA);
540 MODIFY_REG(hopamp4->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_10VDDA);
541
542 /* Init trimming counter */
543 /* Medium value */
544 trimmingvaluep1 = 16;
545 trimmingvaluep2 = 16;
546 trimmingvaluep3 = 16;
547 trimmingvaluep4 = 16;
548
549 delta = 8;
550
551 while (delta != 0)
552 {
553 /* Set candidate trimming */
554 MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep1<<OPAMP_INPUT_NONINVERTING);
555 MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep2<<OPAMP_INPUT_NONINVERTING);
556 MODIFY_REG(hopamp3->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep3<<OPAMP_INPUT_NONINVERTING);
557 MODIFY_REG(hopamp4->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep4<<OPAMP_INPUT_NONINVERTING);
558
559 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
560 /* Offset trim time: during calibration, minimum time needed between */
561 /* two steps to have 1 mV accuracy */
562 HAL_Delay(2);
563
564 if ((hopamp1->Instance->CSR & OPAMP_CSR_OUTCAL) != RESET)
565 {
566 /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */
567 trimmingvaluep1 += delta;
568 }
569 else
570 {
571 trimmingvaluep1 -= delta;
572 }
573
574 if ((hopamp2->Instance->CSR & OPAMP_CSR_OUTCAL) != RESET)
575 {
576 /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */
577 trimmingvaluep2 += delta;
578 }
579 else
580 {
581 trimmingvaluep2 -= delta;
582 }
583
584 if ((hopamp3->Instance->CSR & OPAMP_CSR_OUTCAL) != RESET)
585 {
586 /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */
587 trimmingvaluep3 += delta;
588 }
589 else
590 {
591 trimmingvaluep3 -= delta;
592 }
593
594 if ((hopamp4->Instance->CSR & OPAMP_CSR_OUTCAL) != RESET)
595 {
596 /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */
597 trimmingvaluep4 += delta;
598 }
599 else
600 {
601 trimmingvaluep4 -= delta;
602 }
603
604 delta >>= 1;
605 }
606
607 /* Still need to check if righ calibration is current value or un step below */
608 /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */
609 /* Set candidate trimming */
610 MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep1<<OPAMP_INPUT_NONINVERTING);
611 MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep2<<OPAMP_INPUT_NONINVERTING);
612 MODIFY_REG(hopamp3->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep3<<OPAMP_INPUT_NONINVERTING);
613 MODIFY_REG(hopamp4->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep4<<OPAMP_INPUT_NONINVERTING);
614
615 /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
616 /* Offset trim time: during calibration, minimum time needed between */
617 /* two steps to have 1 mV accuracy */
618 HAL_Delay(2);
619
620 if ((hopamp1->Instance->CSR & OPAMP_CSR_OUTCAL) != RESET)
621 {
622 /* OPAMP_CSR_OUTCAL is actually one value more */
623 trimmingvaluep1++;
624 /* Set right trimming */
625 MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep1<<OPAMP_INPUT_NONINVERTING);
626 }
627
628 if ((hopamp2->Instance->CSR & OPAMP_CSR_OUTCAL) != RESET)
629 {
630 /* OPAMP_CSR_OUTCAL is actually one value more */
631 trimmingvaluep2++;
632 /* Set right trimming */
633 MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep2<<OPAMP_INPUT_NONINVERTING);
634 }
635
636 if ((hopamp3->Instance->CSR & OPAMP_CSR_OUTCAL) != RESET)
637 {
638 /* OPAMP_CSR_OUTCAL is actually one value more */
639 trimmingvaluep3++;
640 /* Set right trimming */
641 MODIFY_REG(hopamp3->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep3<<OPAMP_INPUT_NONINVERTING);
642 }
643
644 if ((hopamp4->Instance->CSR & OPAMP_CSR_OUTCAL) != RESET)
645 {
646 /* OPAMP_CSR_OUTCAL is actually one value more */
647 trimmingvaluep4++;
648 /* Set right trimming */
649 MODIFY_REG(hopamp4->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep4<<OPAMP_INPUT_NONINVERTING);
650 }
651
652 /* Disable calibration */
653 CLEAR_BIT (hopamp1->Instance->CSR, OPAMP_CSR_CALON);
654 CLEAR_BIT (hopamp2->Instance->CSR, OPAMP_CSR_CALON);
655 CLEAR_BIT (hopamp3->Instance->CSR, OPAMP_CSR_CALON);
656 CLEAR_BIT (hopamp4->Instance->CSR, OPAMP_CSR_CALON);
657
658 /* Disable the OPAMPs */
659 CLEAR_BIT (hopamp1->Instance->CSR, OPAMP_CSR_OPAMPxEN);
660 CLEAR_BIT (hopamp2->Instance->CSR, OPAMP_CSR_OPAMPxEN);
661 CLEAR_BIT (hopamp3->Instance->CSR, OPAMP_CSR_OPAMPxEN);
662 CLEAR_BIT (hopamp4->Instance->CSR, OPAMP_CSR_OPAMPxEN);
663
664 /* Set normal operating mode back */
665 CLEAR_BIT(hopamp1->Instance->CSR, OPAMP_CSR_FORCEVP);
666 CLEAR_BIT(hopamp2->Instance->CSR, OPAMP_CSR_FORCEVP);
667 CLEAR_BIT(hopamp3->Instance->CSR, OPAMP_CSR_FORCEVP);
668 CLEAR_BIT(hopamp4->Instance->CSR, OPAMP_CSR_FORCEVP);
669
670 /* Self calibration is successful */
671 /* Store calibration(user timming) results in init structure. */
672 /* Select user timming mode */
673
674 /* Write calibration result N */
675 hopamp1->Init.TrimmingValueN = trimmingvaluen1;
676 hopamp2->Init.TrimmingValueN = trimmingvaluen2;
677 hopamp3->Init.TrimmingValueN = trimmingvaluen3;
678 hopamp4->Init.TrimmingValueN = trimmingvaluen4;
679
680 /* Write calibration result P */
681 hopamp1->Init.TrimmingValueP = trimmingvaluep1;
682 hopamp2->Init.TrimmingValueP = trimmingvaluep2;
683 hopamp3->Init.TrimmingValueP = trimmingvaluep3;
684 hopamp4->Init.TrimmingValueP = trimmingvaluep4;
685
686 /* Select user timming mode */
687 /* And updated with calibrated settings */
688 hopamp1->Init.UserTrimming = OPAMP_TRIMMING_USER;
689 hopamp2->Init.UserTrimming = OPAMP_TRIMMING_USER;
690 hopamp3->Init.UserTrimming = OPAMP_TRIMMING_USER;
691 hopamp4->Init.UserTrimming = OPAMP_TRIMMING_USER;
692
693 MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen1<<OPAMP_INPUT_INVERTING);
694 MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen2<<OPAMP_INPUT_INVERTING);
695 MODIFY_REG(hopamp3->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen3<<OPAMP_INPUT_INVERTING);
696 MODIFY_REG(hopamp4->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen4<<OPAMP_INPUT_INVERTING);
697
698 MODIFY_REG(hopamp1->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep1<<OPAMP_INPUT_NONINVERTING);
699 MODIFY_REG(hopamp2->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep2<<OPAMP_INPUT_NONINVERTING);
700 MODIFY_REG(hopamp3->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep3<<OPAMP_INPUT_NONINVERTING);
701 MODIFY_REG(hopamp4->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep4<<OPAMP_INPUT_NONINVERTING);
702
703 }
704
705 else
706 {
707 /* At least one OPAMP can not be calibrated */
708 status = HAL_ERROR;
709 }
710 }
711
712 return status;
713 }
714 #endif /* STM32F303xE || STM32F398xx || */
715 /* STM32F303xC || STM32F358xx */
716
717 /**
718 * @}
719 */
720
721 /**
722 * @}
723 */
724
725 #endif /* HAL_OPAMP_MODULE_ENABLED */
726 /**
727 * @}
728 */
729
730 /**
731 * @}
732 */
733
734 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Imprint / Impressum