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