]> git.donarmstrong.com Git - qmk_firmware.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
[qmk_firmware.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****/