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