]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F3/stm32f3xx_hal_opamp.c
Merge commit '1fe4406f374291ab2e86e95a97341fd9c475fcb8'
[qmk_firmware.git] / tmk_core / tool / mbed / mbed-sdk / libraries / mbed / targets / cmsis / TARGET_STM / TARGET_STM32F3 / stm32f3xx_hal_opamp.c
1 /**
2   ******************************************************************************
3   * @file    stm32f3xx_hal_opamp.c
4   * @author  MCD Application Team
5   * @version V1.1.0
6   * @date    12-Sept-2014
7   * @brief   OPAMP HAL module driver.
8   *    
9   *          This file provides firmware functions to manage the following 
10   *          functionalities of the operational amplifiers (OPAMP1,...OPAMP4) 
11   *          peripheral: 
12   *           + OPAMP Configuration
13   *           + OPAMP calibration
14   *
15   *          Thanks to
16   *           + Initialization/de-initialization functions
17   *           + I/O operation functions
18   *           + Peripheral Control functions
19   *           + Peripheral State functions
20   *         
21   @verbatim
22 ================================================================================
23           ##### OPAMP Peripheral Features #####
24 ================================================================================
25            
26   [..] The device integrates up to 4 operational amplifiers OPAMP1, OPAMP2,
27        OPAMP3 and OPAMP4:
28        
29        (#) The OPAMP(s) provides several exclusive running modes.
30        (+) Standalone mode
31        (+) Programmable Gain Amplifier (PGA) mode (Resistor feedback output)
32        (+) Follower mode
33
34        (#) The OPAMP(s) provide(s) calibration capabilities.  
35        (+) Calibration aims at correcting some offset for running mode.
36        (+) The OPAMP uses either factory calibration settings OR user defined 
37            calibration (trimming) settings (i.e. trimming mode).
38        (+) The user defined settings can be figured out using self calibration 
39            handled by HAL_OPAMP_SelfCalibrate, HAL_OPAMPEx_SelfCalibrateAll
40        (+) HAL_OPAMP_SelfCalibrate:
41        (++) Runs automatically the calibration in 2 steps. 
42             (90% of VDDA for NMOS transistors, 10% of VDDA for PMOS transistors).
43             (As OPAMP is Rail-to-rail input/output, these 2 steps calibration is 
44             appropriate and enough in most cases).
45        (++) Enables the user trimming mode
46        (++) Updates the init structure with trimming values with fresh calibration 
47             results. 
48             The user may store the calibration results for larger 
49             (ex monitoring the trimming as a function of temperature 
50             for instance)
51        (++) for STM32F3 devices having 2 or 4 OPAMPs
52             HAL_OPAMPEx_SelfCalibrateAll
53             runs calibration of 2 or 4 OPAMPs in parallel. 
54        
55        (#) For any running mode, an additional Timer-controlled Mux (multiplexer) 
56            mode can be set on top.
57        (+) Timer-controlled Mux mode allows Automatic switching between inverting
58            and non-inverting input. 
59        (+) Hence on top of defaults (primary) inverting and non-inverting inputs,
60            the user shall select secondary inverting and non inverting inputs.
61        (+) TIM1 CC6 provides the alternate switching tempo between defaults 
62            (primary) and secondary inputs. 
63              
64        (#) Running mode: Standalone mode 
65        (+) Gain is set externally (gain depends on external loads).
66        (+) Follower mode also possible externally by connecting the inverting input to
67            the output.
68        
69        (#) Running mode: Follower mode
70        (+) No Inverting Input is connected.
71        
72        (#) Running mode: Programmable Gain Amplifier (PGA) mode 
73            (Resistor feedback output)
74        (+) The OPAMP(s) output(s) can be internally connected to resistor feedback
75            output.
76        (+) OPAMP gain is either 2, 4, 8 or 16.
77         
78        (#) The OPAMPs non inverting input (both default and secondary) can be 
79            selected among the list shown by table below.
80        
81        (#) The OPAMPs non inverting input (both default and secondary) can be 
82            selected among the list shown by table below.
83        
84    [..] Table 1.  OPAMPs inverting/non-inverting inputs for the STM32F3 devices:
85      
86     +--------------------------------------------------------------+     
87     |                 |        | OPAMP1 | OPAMP2 | OPAMP3 | OPAMP4 |
88     |-----------------|--------|--------|--------|--------|--------|
89     |                 | No conn|   X    |   X    |   X    |   X    |
90     | Inverting Input | VM0    |  PC5   |  PC5   |  PB10  |  PB10  |
91     | (1)             | VM1    |  PA3   |  PA5   |  PB2   |  PD8   |
92     |-----------------|--------|--------|--------|--------|--------|
93     |                 | VP0    |  PA1   |  PA7   |  PB0   |  PB13  |
94     |  Non Inverting  | VP1    |  PA7   |  PD14  |  PB13  |  PD11  |
95     |    Input        | VP2    |  PA3   |  PB0   |  PA1   |  PA4   |
96     |                 | VP3    |  PA5   |  PB14  |  PA5   |  PB11  |
97     +--------------------------------------------------------------+  
98     (1): NA in follower mode.
99            
100    [..] Table 2.  OPAMPs outputs for the STM32F3 devices:
101
102     +--------------------------------------------------------------+     
103     |                 |        | OPAMP1 | OPAMP2 | OPAMP3 | OPAMP4 |
104     |-----------------|--------|--------|--------|--------|--------|
105     | Output          |        |  PA2   |  PA6   |  PB1   |  PB12  |
106     |-----------------|--------|--------|--------|--------|--------|
107
108       
109             ##### How to use this driver #####
110 ================================================================================
111   [..] 
112      
113     *** Calibration ***
114     ============================================
115       To run the opamp calibration self calibration:
116
117       (#) Start calibration using HAL_OPAMP_SelfCalibrate. 
118            Store the calibration results.
119
120     *** Running mode ***
121     ============================================
122       
123       To use the opamp, perform the following steps:
124             
125       (#) Fill in the HAL_OPAMP_MspInit() to
126       (+) Configure the opamp input AND output in analog mode using 
127           HAL_GPIO_Init() to map the opamp output to the GPIO pin.
128   
129       (#) Configure the opamp using HAL_OPAMP_Init() function:
130       (+) Select the mode
131       (+) Select the inverting input
132       (+) Select the non-inverting input 
133       (+) Select if the Timer controlled Mux mode is enabled/disabled
134       (+) If the Timer controlled Mux mode is enabled, select the secondary inverting input
135       (+) If the Timer controlled Mux mode is enabled, Select the secondary non-inverting input 
136       (+) If PGA mode is enabled, Select if inverting input is connected.
137       (+) Select either factory or user defined trimming mode.
138       (+) If the user defined trimming mode is enabled, select PMOS & NMOS trimming values
139           (typ. settings returned by HAL_OPAMP_SelfCalibrate function).
140       
141       (#) Enable the opamp using HAL_OPAMP_Start() function.
142            
143       (#) Disable the opamp using HAL_OPAMP_Stop() function.
144       
145       (#) Lock the opamp in running mode using HAL_OPAMP_Lock() function. From then The configuration 
146           can only be modified after HW reset.
147
148     *** Running mode: change of configuration while OPAMP ON  ***
149     ============================================
150     To Re-configure OPAMP when OPAMP is ON (change on the fly)
151       (#) If needed, Fill in the HAL_OPAMP_MspInit()
152       (+) This is the case for instance if you wish to use new OPAMP I/O
153
154       (#) Configure the opamp using HAL_OPAMP_Init() function:
155       (+) As in configure case, selects first the parameters you wish to modify.
156       
157   @endverbatim
158   ******************************************************************************
159   * @attention
160   *
161   * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
162   *
163   * Redistribution and use in source and binary forms, with or without modification,
164   * are permitted provided that the following conditions are met:
165   *   1. Redistributions of source code must retain the above copyright notice,
166   *      this list of conditions and the following disclaimer.
167   *   2. Redistributions in binary form must reproduce the above copyright notice,
168   *      this list of conditions and the following disclaimer in the documentation
169   *      and/or other materials provided with the distribution.
170   *   3. Neither the name of STMicroelectronics nor the names of its contributors
171   *      may be used to endorse or promote products derived from this software
172   *      without specific prior written permission.
173   *
174   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
175   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
176   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
177   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
178   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
179   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
180   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
181   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
182   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
183   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
184   *
185   ******************************************************************************  
186   */
187
188 /* Includes ------------------------------------------------------------------*/
189 #include "stm32f3xx_hal.h"
190     
191 /** @addtogroup STM32F3xx_HAL_Driver
192   * @{
193   */
194
195 /** @defgroup OPAMP OPAMP HAL module driver
196   * @brief OPAMP HAL module driver
197   * @{
198   */
199
200 #ifdef HAL_OPAMP_MODULE_ENABLED
201
202 #if defined(STM32F302xE) || defined(STM32F303xE) || defined(STM32F398xx) || \
203     defined(STM32F302xC) || defined(STM32F303xC) || defined(STM32F358xx) || \
204     defined(STM32F303x8) || defined(STM32F334x8) || defined(STM32F328xx) || \
205     defined(STM32F301x8) || defined(STM32F302x8) || defined(STM32F318xx)
206
207 /* Private typedef -----------------------------------------------------------*/
208 /* Private define ------------------------------------------------------------*/
209 /** @defgroup OPAMP_Private_Define OPAMP Private Define
210  * @{
211  */
212 /* CSR register reset value */ 
213 #define OPAMP_CSR_RESET_VALUE             ((uint32_t)0x00000000)
214 /**
215   * @}
216   */
217
218 /* Private macro -------------------------------------------------------------*/
219 /* Private variables ---------------------------------------------------------*/
220 /* Private function prototypes -----------------------------------------------*/
221 /* Exported functions ---------------------------------------------------------*/
222
223 /** @defgroup OPAMP_Exported_Functions OPAMP Exported Functions
224   * @{
225   */
226
227 /** @defgroup OPAMP_Exported_Functions_Group1 Initialization and de-initialization functions
228  *  @brief    Initialization and Configuration functions 
229  *
230 @verbatim    
231  ===============================================================================
232               ##### Initialization/de-initialization  functions #####
233  ===============================================================================
234     [..]  This section provides functions allowing to:
235  
236 @endverbatim
237   * @{
238   */
239
240 /**
241   * @brief  Initializes the OPAMP according to the specified
242   *         parameters in the OPAMP_InitTypeDef and create the associated handle.
243   * @note   If the selected opamp is locked, initialization can't be performed.
244   *         To unlock the configuration, perform a system reset.
245   * @param  hopamp: OPAMP handle
246   * @retval HAL status
247   */
248 HAL_StatusTypeDef HAL_OPAMP_Init(OPAMP_HandleTypeDef *hopamp)
249
250
251   HAL_StatusTypeDef status = HAL_OK;
252
253   /* Check the OPAMP handle allocation and lock status */
254   /* Init not allowed if calibration is ongoing */
255   if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED) \
256                       || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY))
257   {
258     return HAL_ERROR;
259   }
260   else
261   {
262       
263     /* Check the parameter */
264     assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
265        
266     /* Set OPAMP parameters */
267     assert_param(IS_OPAMP_FUNCTIONAL_NORMALMODE(hopamp->Init.Mode));
268     assert_param(IS_OPAMP_NONINVERTING_INPUT(hopamp->Init.NonInvertingInput));
269     if ((hopamp->Init.Mode) == OPAMP_STANDALONE_MODE)
270     {
271       assert_param(IS_OPAMP_INVERTING_INPUT(hopamp->Init.InvertingInput));
272     }
273   
274     assert_param(IS_OPAMP_TIMERCONTROLLED_MUXMODE(hopamp->Init.TimerControlledMuxmode));
275
276     if ((hopamp->Init.TimerControlledMuxmode) == OPAMP_TIMERCONTROLLEDMUXMODE_ENABLE)
277     {
278       assert_param(IS_OPAMP_SEC_NONINVERTINGINPUT(hopamp->Init.NonInvertingInputSecondary));
279       if ((hopamp->Init.Mode) == OPAMP_STANDALONE_MODE)
280       {
281         assert_param(IS_OPAMP_SEC_INVERTINGINPUT(hopamp->Init.InvertingInputSecondary));
282       }
283     }
284     
285     if ((hopamp->Init.Mode) == OPAMP_PGA_MODE)
286     {
287       assert_param(IS_OPAMP_PGACONNECT(hopamp->Init.PgaConnect));
288       assert_param(IS_OPAMP_PGA_GAIN(hopamp->Init.PgaGain));
289     }
290     
291     assert_param(IS_OPAMP_TRIMMING(hopamp->Init.UserTrimming)); 
292     if ((hopamp->Init.UserTrimming) == OPAMP_TRIMMING_USER)
293     {
294       assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueP));
295       assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueN));
296     }
297  
298     /* Init SYSCFG and the low level hardware to access opamp */
299     __SYSCFG_CLK_ENABLE();
300     
301     /* Call MSP init function */
302     HAL_OPAMP_MspInit(hopamp);
303                                           
304     /* Set OPAMP parameters */
305     /*     Set  bits according to hopamp->hopamp->Init.Mode value                                 */
306     /*     Set  bits according to hopamp->hopamp->Init.InvertingInput value                       */
307     /*     Set  bits according to hopamp->hopamp->Init.NonInvertingInput value                    */
308     /*     Set  bits according to hopamp->hopamp->Init.TimerControlledMuxmode value               */
309     /*     Set  bits according to hopamp->hopamp->Init.InvertingInputSecondary  value             */
310     /*     Set  bits according to hopamp->hopamp->Init.NonInvertingInputSecondary value           */
311     /*     Set  bits according to hopamp->hopamp->Init.PgaConnect value                           */
312     /*     Set  bits according to hopamp->hopamp->Init.PgaGain value                              */
313     /*     Set  bits according to hopamp->hopamp->Init.UserTrimming value                         */
314     /*     Set  bits according to hopamp->hopamp->Init.TrimmingValueP value                       */
315     /*     Set  bits according to hopamp->hopamp->Init.TrimmingValueN value                       */
316     
317     
318     /* check if OPAMP_PGA_MODE & in Follower mode */
319     /*   - InvertingInput                         */
320     /*   - InvertingInputSecondary                */
321     /* are Not Applicable                         */
322     
323     if ((hopamp->Init.Mode == OPAMP_PGA_MODE) || (hopamp->Init.Mode == OPAMP_FOLLOWER_MODE))
324     {
325       MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_UPDATE_PARAMETERS_INIT_MASK, \
326                                         hopamp->Init.Mode | \
327                                         hopamp->Init.NonInvertingInput | \
328                                         hopamp->Init.TimerControlledMuxmode | \
329                                         hopamp->Init.NonInvertingInputSecondary  | \
330                                         hopamp->Init.PgaConnect | \
331                                         hopamp->Init.PgaGain | \
332                                         hopamp->Init.UserTrimming | \
333                                         (hopamp->Init.TrimmingValueP << OPAMP_INPUT_NONINVERTING) | \
334                                         (hopamp->Init.TrimmingValueN << OPAMP_INPUT_INVERTING));  
335     }    
336     else /* OPAMP_STANDALONE_MODE */
337     {
338       MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_UPDATE_PARAMETERS_INIT_MASK, \
339                                         hopamp->Init.Mode | \
340                                         hopamp->Init.InvertingInput    | \
341                                         hopamp->Init.NonInvertingInput | \
342                                         hopamp->Init.TimerControlledMuxmode | \
343                                         hopamp->Init.InvertingInputSecondary  | \
344                                         hopamp->Init.NonInvertingInputSecondary  | \
345                                         hopamp->Init.PgaConnect | \
346                                         hopamp->Init.PgaGain | \
347                                         hopamp->Init.UserTrimming | \
348                                         (hopamp->Init.TrimmingValueP << OPAMP_INPUT_NONINVERTING) | \
349                                         (hopamp->Init.TrimmingValueN << OPAMP_INPUT_INVERTING));     
350     } 
351     
352     /* Update the OPAMP state*/
353     if (hopamp->State == HAL_OPAMP_STATE_RESET)
354     {
355       /* From RESET state to READY State */
356     hopamp->State = HAL_OPAMP_STATE_READY;
357     }
358     /* else: remain in READY or BUSY state (no update) */
359   
360     return status;
361     }
362 }
363
364
365 /**
366   * @brief  DeInitializes the OPAMP peripheral 
367   * @note   Deinitialization can't be performed if the OPAMP configuration is locked.
368   *         To unlock the configuration, perform a system reset.
369   * @param  hopamp: OPAMP handle
370   * @retval HAL status
371   */
372 HAL_StatusTypeDef HAL_OPAMP_DeInit(OPAMP_HandleTypeDef *hopamp)
373 {
374   HAL_StatusTypeDef status = HAL_OK;
375
376   /* Check the OPAMP handle allocation */
377   /* Check if OPAMP locked */
378   /* DeInit not allowed if calibration is ongoing */
379   if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED) \
380                       || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY))
381   {
382     status = HAL_ERROR;
383   }
384   else
385   {
386     /* Check the parameter */
387     assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
388
389     /* Set OPAMP_CSR register to reset value */
390     WRITE_REG(hopamp->Instance->CSR, OPAMP_CSR_RESET_VALUE);
391
392     /* DeInit the low level hardware: GPIO, CLOCK and NVIC */
393     HAL_OPAMP_MspDeInit(hopamp);
394
395     /* Update the OPAMP state*/
396     hopamp->State = HAL_OPAMP_STATE_RESET;
397   }
398   return status;
399 }
400
401 /**
402   * @brief  Initializes the OPAMP MSP.
403   * @param  hopamp: OPAMP handle
404   * @retval None
405   */
406 __weak void HAL_OPAMP_MspInit(OPAMP_HandleTypeDef *hopamp)
407 {
408   /* NOTE : This function should not be modified, when the callback is needed,
409             the HAL_OPAMP_MspInit could be implemented in the user file
410    */
411
412    /* Example */ 
413 }
414
415 /**
416   * @brief  DeInitializes OPAMP MSP.
417   * @param  hopamp: OPAMP handle
418   * @retval None
419   */
420 __weak void HAL_OPAMP_MspDeInit(OPAMP_HandleTypeDef *hopamp)
421 {
422   /* NOTE : This function should not be modified, when the callback is needed,
423             the HAL_OPAMP_MspDeInit could be implemented in the user file
424    */
425
426 }
427
428 /**
429   * @}
430   */
431
432
433 /** @defgroup OPAMP_Exported_Functions_Group2 Input and Output operation functions 
434  *  @brief   Data transfers functions 
435  *
436 @verbatim   
437  ===============================================================================
438                       ##### IO operation  functions #####
439  ===============================================================================  
440     [..]
441     This subsection provides a set of functions allowing to manage the OPAMP data 
442     transfers.
443
444 @endverbatim
445   * @{
446   */
447
448 /**
449   * @brief  Start the opamp
450   * @param  hopamp: OPAMP handle
451   * @retval HAL status
452   */
453
454 HAL_StatusTypeDef HAL_OPAMP_Start(OPAMP_HandleTypeDef *hopamp)
455
456   HAL_StatusTypeDef status = HAL_OK;
457   
458   /* Check the OPAMP handle allocation */
459   /* Check if OPAMP locked */
460   if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED))
461                       
462   {
463     status = HAL_ERROR;
464   }
465   else
466   {
467     /* Check the parameter */
468     assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
469     
470     if(hopamp->State == HAL_OPAMP_STATE_READY)
471     {
472       /* Enable the selected opamp */
473       SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
474
475       /* Update the OPAMP state*/     
476       /* From HAL_OPAMP_STATE_READY to HAL_OPAMP_STATE_BUSY */
477       hopamp->State = HAL_OPAMP_STATE_BUSY;   
478     }
479     else
480     {
481       status = HAL_ERROR;
482     }
483     
484     
485    }
486   return status;
487 }
488
489 /**
490   * @brief  Stop the opamp 
491   * @param  hopamp: OPAMP handle
492   * @retval HAL status
493   */
494 HAL_StatusTypeDef HAL_OPAMP_Stop(OPAMP_HandleTypeDef *hopamp)
495
496   HAL_StatusTypeDef status = HAL_OK;
497     
498   /* Check the OPAMP handle allocation */
499   /* Check if OPAMP locked */
500   /* Check if OPAMP calibration ongoing */
501   if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED) \
502                       || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY))  
503   {
504     status = HAL_ERROR;
505   }
506   else
507   {
508     /* Check the parameter */
509     assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
510
511     if(hopamp->State == HAL_OPAMP_STATE_BUSY)
512     {
513       /* Disable the selected opamp */
514       CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN); 
515     
516       /* Update the OPAMP state*/     
517       /* From  HAL_OPAMP_STATE_BUSY to HAL_OPAMP_STATE_READY*/
518       hopamp->State = HAL_OPAMP_STATE_READY;
519     }
520     else
521     {
522       status = HAL_ERROR;
523     }
524   }
525   return status;
526 }
527
528 /**
529   * @brief  Run the self calibration of one OPAMP
530   * @param  hopamp handle
531   * @retval Updated offset trimming values (PMOS & NMOS), user trimming is enabled
532   * @retval HAL status
533   * @note   Calibration runs about 25 ms.
534   */
535
536 HAL_StatusTypeDef HAL_OPAMP_SelfCalibrate(OPAMP_HandleTypeDef *hopamp)
537
538
539   HAL_StatusTypeDef status = HAL_OK;
540   
541   uint32_t trimmingvaluen = 0;
542   uint32_t trimmingvaluep = 0;
543   uint32_t delta;
544   
545   /* Check the OPAMP handle allocation */
546   /* Check if OPAMP locked */
547   if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED))
548   {
549     status = HAL_ERROR;
550   }
551   else
552   {
553   
554     /* Check if OPAMP in calibration mode and calibration not yet enable */
555     if(hopamp->State ==  HAL_OPAMP_STATE_READY)
556     {
557       /* Check the parameter */
558       assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
559
560       /* Set Calibration mode */
561       /* Non-inverting input connected to calibration reference voltage. */
562       SET_BIT(hopamp->Instance->CSR, OPAMP_CSR_FORCEVP);
563
564       /*  user trimming values are used for offset calibration */
565       SET_BIT(hopamp->Instance->CSR, OPAMP_CSR_USERTRIM);
566       
567       /* Enable calibration */
568       SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_CALON);
569   
570       /* 1st calibration - N */
571       /* Select 90% VREF */
572       MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_90VDDA);
573       
574       /* Enable the selected opamp */
575       SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
576       
577       /* Init trimming counter */    
578       /* Medium value */
579       trimmingvaluen = 16; 
580       delta = 8;
581       
582       while (delta != 0)
583       {
584         /* Set candidate trimming */
585         MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen<<OPAMP_INPUT_INVERTING);
586               
587         /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */ 
588         /* Offset trim time: during calibration, minimum time needed between */
589         /* two steps to have 1 mV accuracy */
590         HAL_Delay(2);
591
592         if ((hopamp->Instance->CSR & OPAMP_CSR_OUTCAL) != RESET)
593         { 
594           /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */
595           trimmingvaluen += delta;
596         }
597         else
598         {
599           /* OPAMP_CSR_OUTCAL is LOW try lower trimming */
600           trimmingvaluen -= delta;
601         }
602                       
603         delta >>= 1;
604       }
605
606       /* Still need to check if righ calibration is current value or un step below */
607       /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0  */
608       MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen<<OPAMP_INPUT_INVERTING);
609       
610        /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */ 
611        /* Offset trim time: during calibration, minimum time needed between */
612        /* two steps to have 1 mV accuracy */
613        HAL_Delay(2);
614       
615       if ((hopamp->Instance->CSR & OPAMP_CSR_OUTCAL) != RESET) 
616       { 
617         /* OPAMP_CSR_OUTCAL is actually one value more */
618         trimmingvaluen++;
619         /* Set right trimming */
620         MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen<<OPAMP_INPUT_INVERTING);
621       }
622        
623       /* 2nd calibration - P */
624       /* Select 10% VREF */
625       MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_10VDDA);
626       
627       /* Init trimming counter */    
628       /* Medium value */
629       trimmingvaluep = 16; 
630       delta = 8;
631       
632       while (delta != 0)
633       {
634         /* Set candidate trimming */
635         MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep<<OPAMP_INPUT_NONINVERTING);
636                
637         /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */ 
638         /* Offset trim time: during calibration, minimum time needed between */
639         /* two steps to have 1 mV accuracy */
640         HAL_Delay(2);
641
642         if ((hopamp->Instance->CSR & OPAMP_CSR_OUTCAL) != RESET) 
643         { 
644           /* OPAMP_CSR_OUTCAL is HIGH try higher trimming */
645           trimmingvaluep += delta;
646         }
647         else
648         {
649           trimmingvaluep -= delta;
650         }
651                       
652         delta >>= 1;
653       }
654       
655       /* Still need to check if righ calibration is current value or un step below */
656       /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */
657       /* Set candidate trimming */
658       MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep<<OPAMP_INPUT_NONINVERTING);
659
660        /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */ 
661        /* Offset trim time: during calibration, minimum time needed between */
662        /* two steps to have 1 mV accuracy */
663        HAL_Delay(2);
664       
665       if ((hopamp->Instance->CSR & OPAMP_CSR_OUTCAL) != RESET)
666       { 
667         /* OPAMP_CSR_OUTCAL is actually one value more */
668         trimmingvaluep++;
669         /* Set right trimming */
670         MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep<<OPAMP_INPUT_NONINVERTING);
671       }
672            
673       /* Disable calibration */
674       CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_CALON);
675
676       /* Disable the OPAMP */
677       CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
678       
679       /* Set normale operating mode  */
680       /* Non-inverting input connected to calibration reference voltage. */
681       CLEAR_BIT(hopamp->Instance->CSR, OPAMP_CSR_FORCEVP);
682             
683       /* Self calibration is successful  */
684       /* Store calibration(user timming) results in init structure. */
685
686       /* Write calibration result N */
687       hopamp->Init.TrimmingValueN = trimmingvaluen;
688      
689       /* Write calibration result P */
690       hopamp->Init.TrimmingValueP = trimmingvaluep;
691
692       /* Select user timming mode */      
693       /* And updated with calibrated settings */
694       hopamp->Init.UserTrimming = OPAMP_TRIMMING_USER;
695       MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, trimmingvaluep<<OPAMP_INPUT_NONINVERTING);
696       MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, trimmingvaluen<<OPAMP_INPUT_INVERTING);
697     }
698
699     else
700     {
701       /* OPAMP can not be calibrated from this mode */ 
702       status = HAL_ERROR;
703     }   
704   }
705   return status;
706 }
707
708 /**
709   * @}
710   */
711
712 /** @defgroup OPAMP_Exported_Functions_Group3 Peripheral Control functions 
713  *  @brief   management functions 
714  *
715 @verbatim   
716  ===============================================================================
717                       ##### Peripheral Control functions #####
718  ===============================================================================  
719     [..]
720     This subsection provides a set of functions allowing to control the OPAMP data 
721     transfers.
722
723
724
725 @endverbatim
726   * @{
727   */
728
729 /**
730   * @brief  Lock the selected opamp configuration. 
731   * @param  hopamp: OPAMP handle
732   * @retval HAL status
733   */
734 HAL_StatusTypeDef HAL_OPAMP_Lock(OPAMP_HandleTypeDef *hopamp)
735 {
736   HAL_StatusTypeDef status = HAL_OK;
737
738   /* Check the OPAMP handle allocation */
739   /* Check if OPAMP locked */
740   /* OPAMP can be locked when enabled and running in normal mode */ 
741   /*   It is meaningless otherwise */
742   if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_RESET) \
743                       || (hopamp->State == HAL_OPAMP_STATE_READY) \
744                       || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)\
745                       || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED))
746   
747   {
748     status = HAL_ERROR;
749   }
750   
751   else
752   {
753     /* Check the parameter */
754     assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
755     
756    /* Lock OPAMP */
757     SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_LOCK);
758   
759    /* OPAMP state changed to locked */
760     hopamp->State = HAL_OPAMP_STATE_BUSYLOCKED;
761   }
762   return status; 
763 }
764
765 /**
766   * @}
767   */
768
769 /** @defgroup OPAMP_Exported_Functions_Group4 Peripheral State functions 
770  *  @brief   Peripheral State functions 
771  *
772 @verbatim   
773  ===============================================================================
774                       ##### Peripheral State functions #####
775  ===============================================================================  
776     [..]
777     This subsection permit to get in run-time the status of the peripheral 
778     and the data flow.
779
780 @endverbatim
781   * @{
782   */
783
784 /**
785   * @brief  Return the OPAMP state
786   * @param  hopamp : OPAMP handle
787   * @retval HAL state
788   */
789 HAL_OPAMP_StateTypeDef HAL_OPAMP_GetState(OPAMP_HandleTypeDef *hopamp)
790 {
791   /* Check the OPAMP handle allocation */
792   if(hopamp == HAL_NULL)
793   {
794     return HAL_OPAMP_STATE_RESET;
795   }
796
797   /* Check the parameter */
798   assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
799
800   return hopamp->State;
801 }
802
803 /**
804   * @brief  Return the OPAMP factory trimming value
805   * @param  hopamp : OPAMP handle
806   * @param  trimmingoffset : Trimming offset (P or N)
807   * @retval Trimming value (P or N): range: 0->31
808   *         or OPAMP_FACTORYTRIMMING_DUMMY if trimming value is not available
809  */
810
811 OPAMP_TrimmingValueTypeDef HAL_OPAMP_GetTrimOffset (OPAMP_HandleTypeDef *hopamp, uint32_t trimmingoffset)
812 {
813   uint32_t oldusertrimming = 0;
814   OPAMP_TrimmingValueTypeDef  oldtrimmingvaluep = 0, oldtrimmingvaluen = 0, trimmingvalue = 0;
815   
816   /* Check the OPAMP handle allocation */
817   /* Value can be retrieved in HAL_OPAMP_STATE_READY state */
818   if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_RESET) \
819                       || (hopamp->State == HAL_OPAMP_STATE_BUSY) \
820                       || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)\
821                       || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED))
822   {
823     return OPAMP_FACTORYTRIMMING_DUMMY;
824   }
825   else
826   {
827     /* Check the parameter */
828     assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
829     assert_param(IS_OPAMP_FACTORYTRIMMING(trimmingoffset));
830     
831     /* Check the trimming mode */
832     if ((READ_BIT(hopamp->Instance->CSR,OPAMP_CSR_USERTRIM)) != RESET) 
833     {
834       /* User trimming is used */
835       oldusertrimming = OPAMP_TRIMMING_USER;
836       /* Store the TrimmingValueP & TrimmingValueN */
837       oldtrimmingvaluep = (hopamp->Instance->CSR & OPAMP_CSR_TRIMOFFSETP) >> OPAMP_INPUT_NONINVERTING;
838       oldtrimmingvaluen = (hopamp->Instance->CSR & OPAMP_CSR_TRIMOFFSETN) >> OPAMP_INPUT_INVERTING;
839     }
840     
841     /* Set factory timming mode */
842     CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_USERTRIM);
843     
844     /* Get factory trimming  */
845     if (trimmingoffset == OPAMP_FACTORYTRIMMING_P)
846     {
847       /* Return TrimOffsetP */
848      trimmingvalue = ((hopamp->Instance->CSR & OPAMP_CSR_TRIMOFFSETP) >> OPAMP_INPUT_NONINVERTING);
849     }
850     else 
851     {
852       /* Return TrimOffsetN */
853       trimmingvalue = ((hopamp->Instance->CSR & OPAMP_CSR_TRIMOFFSETN) >> OPAMP_INPUT_INVERTING);
854     }
855     
856     /* Restore user trimming configuration if it was formerly set */
857     /* Check if user trimming was used */
858     if (oldusertrimming == OPAMP_TRIMMING_USER) 
859     {
860       /* Restore user trimming */
861       SET_BIT(hopamp->Instance->CSR,OPAMP_CSR_USERTRIM);
862       MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETP, oldtrimmingvaluep<<OPAMP_INPUT_NONINVERTING);
863       MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_TRIMOFFSETN, oldtrimmingvaluen<<OPAMP_INPUT_INVERTING);
864     }
865   }  
866   return trimmingvalue;
867 }
868 /**
869   * @}
870   */
871
872 /**
873   * @}
874   */
875 #endif /* STM32F302xE || STM32F303xE || STM32F398xx || */
876        /* STM32F302xC || STM32F303xC || STM32F358xx || */
877        /* STM32F303x8 || STM32F334x8 || STM32F328xx || */
878        /* STM32F301x8 || STM32F302x8 || STM32F318xx    */
879
880 #endif /* HAL_OPAMP_MODULE_ENABLED */
881 /**
882   * @}
883   */
884
885 /**
886   * @}
887   */
888
889 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/