]> git.donarmstrong.com Git - qmk_firmware.git/blob - tool/mbed/mbed-sdk/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32L1/stm32l1xx_hal_opamp.c
Squashed 'tmk_core/' changes from 7967731..b9e0ea0
[qmk_firmware.git] / tool / mbed / mbed-sdk / libraries / mbed / targets / cmsis / TARGET_STM / TARGET_STM32L1 / stm32l1xx_hal_opamp.c
1 /**
2   ******************************************************************************
3   * @file    stm32l1xx_hal_opamp.c
4   * @author  MCD Application Team
5   * @version V1.0.0
6   * @date    5-September-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 ,... ,OPAMP3) 
11   *          peripheral: 
12   *           + OPAMP configuration
13   *           + OPAMP calibration
14   *
15   *          Thanks to
16   *           + Initialization and de-initialization functions
17   *           + IO 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 3 operational amplifiers OPAMP1, OPAMP2,
27        OPAMP3 (OPAMP3 availability depends on device category)
28        
29        (#) The OPAMP(s) provides several exclusive running modes.
30        (+) Standalone mode
31        (+) Follower mode
32
33        (#) The OPAMP(s) provide(s) calibration capabilities.  
34        (+) Calibration aims at correcting some offset for running mode.
35        (+) The OPAMP uses either factory calibration settings OR user defined 
36            calibration (trimming) settings (i.e. trimming mode).
37        (+) The user defined settings can be figured out using self calibration 
38            handled by HAL_OPAMP_SelfCalibrate, HAL_OPAMPEx_SelfCalibrateAll
39        (+) HAL_OPAMP_SelfCalibrate:
40        (++) Runs automatically the calibration in 2 steps: for transistors 
41             differential pair high (PMOS) or low (NMOS)
42        (++) Enables the user trimming mode
43        (++) Updates the init structure with trimming values with fresh calibration 
44             results.
45             The user may store the calibration results for larger 
46             (ex monitoring the trimming as a function of temperature 
47             for instance)
48        (++) for devices having several OPAMPs, HAL_OPAMPEx_SelfCalibrateAll
49             runs calibration of all OPAMPs in parallel to save trimming search
50             wait time.
51              
52        (#) Running mode: Standalone mode 
53        (+) Gain is set externally (gain depends on external loads).
54        (+) Follower mode also possible externally by connecting the inverting input to
55            the output.
56        
57        (#) Running mode: Follower mode
58        (+) No Inverting Input is connected.
59        (+) The OPAMP(s) output(s) are internally connected to inverting input
60         
61        (#) The OPAMPs inverting input can be selected among the list shown
62            in table below.
63        
64        (#) The OPAMPs non inverting input can be selected among the list shown
65            in table below.
66        
67    [..] Table 1.  OPAMPs inverting/non-inverting inputs for STM32L1 devices:
68      
69     +--------------------------------------------------------------------------+
70     |                | HAL param  |    OPAMP1    |    OPAMP2    |   OPAMP3(4)  |
71     |                |   name     |              |              |              |
72     |----------------|------------|--------------|--------------|--------------|
73     |   Inverting    |    VM0     |     PA2      |     PA7      |     PC2      |
74     |    input (1)   |    VM1     | VINM pin (2) | VINM pin (2) | VINM pin (2) |
75     |----------------|------------|--------------|--------------|--------------|
76     |  Non Inverting |    VP0     |     PA1      |     PA6      |     PC1      |
77     |    input       | DAC_CH1 (3)|   DAC_CH1    |   DAC_CH1    |     ---      |
78     |                | DAC_CH2 (3)|     ---      |   DAC_CH2    |   DAC_CH2    |
79     +--------------------------------------------------------------------------+
80     (1): NA in follower mode.
81     (2): OPAMP input OPAMPx_VINM are dedicated OPAMP pins, their availability
82          depends on device package.
83     (3): DAC channels 1 and 2 are connected internally to OPAMP. Nevertheless,
84          I/O pins connected to DAC can still be used as DAC output (pins PA4 
85          and PA5).
86     (4): OPAMP3 availability depends on device category.
87
88
89    [..] Table 2.  OPAMPs outputs for STM32L1 devices:
90
91     +--------------------------------------------------------+
92     |                 |   OPAMP1   |   OPAMP2   |  OPAMP3(4) | 
93     |-----------------|------------|------------|------------|
94     | Output          |    PA3     |    PB0     |    PC3     |
95     +--------------------------------------------------------+
96     (4) : OPAMP3 availability depends on device category
97
98
99             ##### How to use this driver #####
100 ================================================================================
101   [..] 
102      
103     *** Calibration ***
104     ============================================
105       To run the opamp calibration self calibration:
106
107       (#) Start calibration using HAL_OPAMP_SelfCalibrate. 
108            Store the calibration results.
109
110     *** Running mode ***
111     ============================================
112       
113       To use the opamp, perform the following steps:
114             
115       (#) Fill in the HAL_OPAMP_MspInit() to
116       (+) Enable the OPAMP Peripheral clock using macro "__OPAMP_CLK_ENABLE()"
117       (++) Configure the opamp input AND output in analog mode using 
118            HAL_GPIO_Init() to map the opamp output to the GPIO pin.
119   
120       (#) Configure the opamp using HAL_OPAMP_Init() function:
121       (+) Select the mode
122       (+) Select the inverting input
123       (+) Select the non-inverting input 
124       (+) Select either factory or user defined trimming mode.
125       (+) If the user defined trimming mode is enabled, select PMOS & NMOS trimming values
126           (typ. settings returned by HAL_OPAMP_SelfCalibrate function).
127       
128       (#) Enable the opamp using HAL_OPAMP_Start() function.
129            
130       (#) Disable the opamp using HAL_OPAMP_Stop() function.
131       
132       (#) Lock the opamp in running mode using HAL_OPAMP_Lock() function.
133           Caution: On STM32L1, HAL OPAMP lock is software lock only (not 
134           hardware lock as on some other STM32 devices)
135
136       (#) If needed, unlock the opamp using HAL_OPAMPEx_Unlock() function.
137
138     *** Running mode: change of configuration while OPAMP ON  ***
139     ============================================
140     To Re-configure OPAMP when OPAMP is ON (change on the fly)
141       (#) If needed, Fill in the HAL_OPAMP_MspInit()
142       (+) This is the case for instance if you wish to use new OPAMP I/O
143
144       (#) Configure the opamp using HAL_OPAMP_Init() function:
145       (+) As in configure case, selects first the parameters you wish to modify.
146       
147   @endverbatim
148   ******************************************************************************
149   * @attention
150   *
151   * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
152   *
153   * Redistribution and use in source and binary forms, with or without modification,
154   * are permitted provided that the following conditions are met:
155   *   1. Redistributions of source code must retain the above copyright notice,
156   *      this list of conditions and the following disclaimer.
157   *   2. Redistributions in binary form must reproduce the above copyright notice,
158   *      this list of conditions and the following disclaimer in the documentation
159   *      and/or other materials provided with the distribution.
160   *   3. Neither the name of STMicroelectronics nor the names of its contributors
161   *      may be used to endorse or promote products derived from this software
162   *      without specific prior written permission.
163   *
164   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
165   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
166   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
167   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
168   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
169   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
170   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
171   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
172   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
173   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
174   *
175   ******************************************************************************  
176   */
177
178 /* Includes ------------------------------------------------------------------*/
179 #include "stm32l1xx_hal.h"
180     
181 /** @addtogroup STM32L1xx_HAL_Driver
182   * @{
183   */
184
185 /** @defgroup OPAMP OPAMP
186   * @brief OPAMP HAL module driver
187   * @{
188   */
189
190 #ifdef HAL_OPAMP_MODULE_ENABLED
191
192 #if defined (STM32L151xCA) || defined (STM32L151xD) || defined (STM32L152xCA) || defined (STM32L152xD) || defined (STM32L162xCA) || defined (STM32L162xD) || defined (STM32L151xE) || defined (STM32L152xE) || defined (STM32L162xE) || defined (STM32L162xC) || defined (STM32L152xC) || defined (STM32L151xC)
193
194 /* Private typedef -----------------------------------------------------------*/
195 /* Private define ------------------------------------------------------------*/
196 /* Private macro -------------------------------------------------------------*/
197 /* Private variables ---------------------------------------------------------*/
198 /* Private function prototypes -----------------------------------------------*/
199 /* Private functions ---------------------------------------------------------*/
200
201 /** @defgroup OPAMP_Exported_Functions OPAMP Exported Functions
202   * @{
203   */
204
205 /** @defgroup OPAMP_Exported_Functions_Group1 Initialization and de-initialization functions 
206  *  @brief    Initialization and Configuration functions 
207  *
208 @verbatim    
209  ===============================================================================
210               ##### Initialization and de-initialization functions #####
211  ===============================================================================
212     [..]  This section provides functions allowing to:
213  
214 @endverbatim
215   * @{
216   */
217
218 /**
219   * @brief  Initializes the OPAMP according to the specified
220   *         parameters in the OPAMP_InitTypeDef and create the associated handle.
221   * @note   If the selected opamp is locked, initialization can't be performed.
222   *         To unlock the configuration, perform a system reset.
223   * @param  hopamp: OPAMP handle
224   * @retval HAL status
225   */
226 HAL_StatusTypeDef HAL_OPAMP_Init(OPAMP_HandleTypeDef* hopamp)
227
228   HAL_StatusTypeDef status = HAL_OK;
229   uint32_t tmp_csr = 0;       /* Temporary variable to update register CSR, except bits ANAWSSELx, S7SEL2, OPA_RANGE, OPAxCALOUT */
230   
231   /* Check the OPAMP handle allocation and lock status */
232   /* Init not allowed if calibration is ongoing */
233   if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
234                       || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY) )
235   {
236     status = HAL_ERROR;
237   }
238   else
239   {
240     /* Check the parameter */
241     assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
242        
243     /* Set OPAMP parameters */
244     assert_param(IS_OPAMP_FUNCTIONAL_NORMALMODE(hopamp->Init.Mode));
245     assert_param(IS_OPAMP_NONINVERTING_INPUT(hopamp->Init.NonInvertingInput));       
246     assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode));
247     assert_param(IS_OPAMP_POWER_SUPPLY_RANGE(hopamp->Init.PowerSupplyRange));
248     assert_param(IS_OPAMP_TRIMMING(hopamp->Init.UserTrimming));
249     
250     if (hopamp->Init.Mode != OPAMP_FOLLOWER_MODE)
251     {
252       assert_param(IS_OPAMP_INVERTING_INPUT(hopamp->Init.InvertingInput));
253     }
254     
255     if (hopamp->Init.UserTrimming == OPAMP_TRIMMING_USER)
256     {
257       if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
258       {
259         assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueP));
260         assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueN));
261       }
262       else
263       {
264         assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValuePLowPower));
265         assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueNLowPower));
266       }
267     }
268     
269     /* Call MSP init function */
270     HAL_OPAMP_MspInit(hopamp);
271     
272     
273     /* Set OPAMP parameters                                                   */
274     /* - Set internal switches in function of:                                */
275     /*   - OPAMP selected mode: standalone or follower.                       */
276     /*   - Non-inverting input connection                                     */
277     /*   - Inverting input connection                                         */
278     /* - Set power supply range                                               */
279     /* - Set power mode and associated calibration parameters                 */
280     
281     /* Get OPAMP CSR register into temporary variable */
282     tmp_csr = OPAMP->CSR;
283     
284     /* Open all switches on non-inverting input, inverting input and output   */
285     /* feedback.                                                              */
286     CLEAR_BIT(tmp_csr, __OPAMP_CSR_ALL_SWITCHES(hopamp));
287     
288     /* Set internal switches in function of OPAMP mode selected: standalone   */
289     /* or follower.                                                           */
290     /* If follower mode is selected, feedback switch S3 is closed and         */
291     /* inverting inputs switches are let opened.                              */
292     /* If standalone mode is selected, feedback switch S3 is let opened and   */
293     /* the selected inverting inputs switch is closed.                        */
294     if (hopamp->Init.Mode == OPAMP_FOLLOWER_MODE)
295     {
296       /* Follower mode: Close switches S3 and SanB */
297       SET_BIT(tmp_csr, __OPAMP_CSR_S3SELX(hopamp));
298     }
299     else
300     {
301       /* Set internal switches in function of inverting input selected:       */
302       /* Close switch to connect comparator inverting input to the selected   */
303       /* input: dedicated IO pin or alternative IO pin available on some      */
304       /* device packages.                                                     */
305       if (hopamp->Init.InvertingInput == OPAMP_INVERTINGINPUT_VM0)
306       {
307         /* Close switch to connect comparator non-inverting input to          */
308         /* dedicated IO pin low-leakage.                                      */
309         SET_BIT(tmp_csr, __OPAMP_CSR_S4SELX(hopamp));
310       }
311       else
312       {
313         /* Close switch to connect comparator inverting input to alternative  */
314         /* IO pin available on some device packages.                          */
315         SET_BIT(tmp_csr, __OPAMP_CSR_ANAWSELX(hopamp));
316       }
317     }
318     
319     /* Set internal switches in function of non-inverting input selected:     */
320     /* Close switch to connect comparator non-inverting input to the selected */
321     /* input: dedicated IO pin or DAC channel.                                */
322     if (hopamp->Init.NonInvertingInput == OPAMP_NONINVERTINGINPUT_VP0)
323     {
324       /* Close switch to connect comparator non-inverting input to            */
325       /* dedicated IO pin low-leakage.                                        */
326       SET_BIT(tmp_csr, __OPAMP_CSR_S5SELX(hopamp));
327     }
328     else if (hopamp->Init.NonInvertingInput == OPAMP_NONINVERTINGINPUT_DAC_CH1)
329     {
330       
331       /* Particular case for connection to DAC channel 1:                     */
332       /* OPAMP_NONINVERTINGINPUT_DAC_CH1 available on OPAMP1 and OPAMP2 only  */
333       /* (OPAMP3 availability depends on device category).                    */
334       if ((hopamp->Instance == OPAMP1) || (hopamp->Instance == OPAMP2))
335       {
336         /* Close switch to connect comparator non-inverting input to          */
337         /* DAC channel 1.                                                     */
338         SET_BIT(tmp_csr, __OPAMP_CSR_S6SELX(hopamp));
339       }
340       else
341       {
342         /* Set HAL status to error if another OPAMP instance as OPAMP1 or     */
343         /* OPAMP2 is intended to be connected to DAC channel 2.               */
344         status = HAL_ERROR;
345       }
346     }
347     else /* if (hopamp->Init.NonInvertingInput ==                             */
348          /*     OPAMP_NONINVERTINGINPUT_DAC_CH2  )                            */
349     {
350       /* Particular case for connection to DAC channel 2:                     */
351       /* OPAMP_NONINVERTINGINPUT_DAC_CH2 available on OPAMP2 and OPAMP3 only  */
352       /* (OPAMP3 availability depends on device category).                    */
353       if (hopamp->Instance == OPAMP2)
354       {
355         /* Close switch to connect comparator non-inverting input to          */
356         /* DAC channel 2.                                                     */
357         SET_BIT(tmp_csr, OPAMP_CSR_S7SEL2);
358       }
359       /* If OPAMP3 is selected (if available) */
360       else if (hopamp->Instance != OPAMP1)
361       {
362         /* Close switch to connect comparator non-inverting input to          */
363         /* DAC channel 2.                                                     */
364         SET_BIT(tmp_csr, __OPAMP_CSR_S6SELX(hopamp));
365       }
366       else
367       {
368         /* Set HAL status to error if another OPAMP instance as OPAMP2 or     */
369         /* OPAMP3 (if available) is intended to be connected to DAC channel 2.*/
370         status = HAL_ERROR;
371       }
372     }
373     
374     /* Continue OPAMP configuration if settings of switches are correct */
375     if (status != HAL_ERROR)
376     {
377       /* Set power mode and associated calibration parameters */
378       if (hopamp->Init.PowerMode != OPAMP_POWERMODE_LOWPOWER)
379       {
380         /* Set normal mode */
381         CLEAR_BIT(tmp_csr, __OPAMP_CSR_OPAXLPM(hopamp));
382         
383         if (hopamp->Init.UserTrimming == OPAMP_TRIMMING_USER)
384         {
385           /* Set calibration mode (factory or user) and values for            */
386           /* transistors differential pair high (PMOS) and low (NMOS) for     */
387           /* normal mode.                                                     */
388           MODIFY_REG(OPAMP->OTR, OPAMP_OTR_OT_USER                                                                     |
389                                  __OPAMP_OFFSET_TRIM_SET(hopamp, OPAMP_FACTORYTRIMMING_N, OPAMP_TRIM_VALUE_MASK)       |
390                                  __OPAMP_OFFSET_TRIM_SET(hopamp, OPAMP_FACTORYTRIMMING_P, OPAMP_TRIM_VALUE_MASK)        ,
391                                  hopamp->Init.UserTrimming                                                             |
392                                  __OPAMP_OFFSET_TRIM_SET(hopamp, OPAMP_FACTORYTRIMMING_N, hopamp->Init.TrimmingValueN) |
393                                  __OPAMP_OFFSET_TRIM_SET(hopamp, OPAMP_FACTORYTRIMMING_P, hopamp->Init.TrimmingValueP)  );
394         }
395         else
396         {
397           /* Set calibration mode to factory */
398           CLEAR_BIT(OPAMP->OTR, OPAMP_OTR_OT_USER);
399         }
400         
401       }
402       else
403       {
404         /* Set low power mode */
405         SET_BIT(tmp_csr, __OPAMP_CSR_OPAXLPM(hopamp));
406         
407         if (hopamp->Init.UserTrimming == OPAMP_TRIMMING_USER)
408         {
409           /* Set calibration mode to user trimming */
410           SET_BIT(OPAMP->OTR, OPAMP_OTR_OT_USER);
411           
412           /* Set values for transistors differential pair high (PMOS) and low */
413           /* (NMOS) for low power mode.                                       */
414           MODIFY_REG(OPAMP->LPOTR, __OPAMP_OFFSET_TRIM_SET(hopamp, OPAMP_FACTORYTRIMMING_N, OPAMP_TRIM_VALUE_MASK)               |
415                                    __OPAMP_OFFSET_TRIM_SET(hopamp, OPAMP_FACTORYTRIMMING_P, OPAMP_TRIM_VALUE_MASK)                ,
416                                    __OPAMP_OFFSET_TRIM_SET(hopamp, OPAMP_FACTORYTRIMMING_N, hopamp->Init.TrimmingValueNLowPower) |
417                                    __OPAMP_OFFSET_TRIM_SET(hopamp, OPAMP_FACTORYTRIMMING_P, hopamp->Init.TrimmingValuePLowPower)  );
418         }
419         else
420         {
421           /* Set calibration mode to factory trimming */
422           CLEAR_BIT(OPAMP->OTR, OPAMP_OTR_OT_USER);
423         }
424         
425       }
426       
427       
428       /* Configure the power supply range */
429       MODIFY_REG(tmp_csr, OPAMP_CSR_AOP_RANGE,
430                           hopamp->Init.PowerSupplyRange);
431       
432       /* Set OPAMP CSR register from temporary variable */
433       /* This allows to apply all changes on one time, in case of update on   */
434       /* the fly with OPAMP previously set and running:                       */
435       /*  - to avoid hazardous transient switches settings (risk of short     */
436       /*    circuit)                                                          */
437       /*  - to avoid interruption of input signal                             */
438       OPAMP->CSR = tmp_csr;
439
440                 
441       /* Update the OPAMP state */
442       /* If coming from state reset: Update from state RESET to state READY */
443       /* else: remain in state READY or BUSY (no update) */
444       if (hopamp->State == HAL_OPAMP_STATE_RESET)
445       {
446         hopamp->State = HAL_OPAMP_STATE_READY;
447       }
448     }
449   }
450   
451   return status;
452 }
453
454
455 /**
456   * @brief  DeInitializes the OPAMP peripheral 
457   * @note   Deinitialization can't be performed if the OPAMP configuration is locked.
458   *         To unlock the configuration, perform a system reset.
459   * @param  hopamp: OPAMP handle
460   * @retval HAL status
461   */
462 HAL_StatusTypeDef HAL_OPAMP_DeInit(OPAMP_HandleTypeDef* hopamp)
463 {
464   HAL_StatusTypeDef status = HAL_OK;
465   
466   /* Check the OPAMP handle allocation */
467   /* Check if OPAMP locked */
468   /* DeInit not allowed if calibration is ongoing */
469   if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED) \
470                       || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY))
471   {
472     status = HAL_ERROR;
473   }
474   else
475   {
476
477     /* Check the parameter */
478     assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
479     
480     /* Open all switches on non-inverting input, inverting input and output   */
481     /* feedback.                                                              */
482     CLEAR_BIT(OPAMP->CSR, __OPAMP_CSR_ALL_SWITCHES(hopamp));
483
484     /* DeInit the low level hardware */
485     HAL_OPAMP_MspDeInit(hopamp);
486
487   /* Update the OPAMP state*/
488     hopamp->State = HAL_OPAMP_STATE_RESET;
489   }
490   
491   /* Process unlocked */
492   __HAL_UNLOCK(hopamp);
493   
494   return status;
495 }
496
497
498 /**
499   * @brief  Initializes the OPAMP MSP.
500   * @param  hopamp: OPAMP handle
501   * @retval None
502   */
503 __weak void HAL_OPAMP_MspInit(OPAMP_HandleTypeDef* hopamp)
504 {
505   /* NOTE : This function Should not be modified, when the callback is needed,
506             the function "HAL_OPAMP_MspInit()" must be implemented in the user file.
507   */
508 }
509
510 /**
511   * @brief  DeInitializes OPAMP MSP.
512   * @param  hopamp: OPAMP handle
513   * @retval None
514   */
515 __weak void HAL_OPAMP_MspDeInit(OPAMP_HandleTypeDef* hopamp)
516 {
517   /* NOTE : This function Should not be modified, when the callback is needed,
518             the function "HAL_OPAMP_MspDeInit()" must be implemented in the user file.
519   */
520 }
521
522 /**
523   * @}
524   */
525
526
527 /** @defgroup OPAMP_Exported_Functions_Group2 IO operation functions 
528   * @brief   IO operation functions 
529   *
530 @verbatim   
531  ===============================================================================
532                       ##### IO operation functions #####
533  ===============================================================================  
534     [..]
535     This subsection provides a set of functions allowing to manage the OPAMP
536     start, stop and calibration actions.
537
538 @endverbatim
539   * @{
540   */
541
542 /**
543   * @brief  Start the opamp
544   * @param  hopamp: OPAMP handle
545   * @retval HAL status
546   */
547
548 HAL_StatusTypeDef HAL_OPAMP_Start(OPAMP_HandleTypeDef* hopamp)
549
550   HAL_StatusTypeDef status = HAL_OK;
551   
552   /* Check the OPAMP handle allocation */
553   /* Check if OPAMP locked */
554   if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED))
555   {
556     status = HAL_ERROR;
557   }
558   else
559   {
560     /* Check the parameter */
561     assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
562     
563     if(hopamp->State == HAL_OPAMP_STATE_READY)
564     {
565       /* Enable the selected opamp */
566       CLEAR_BIT (OPAMP->CSR, __OPAMP_CSR_OPAXPD(hopamp));
567       
568       /* Update the OPAMP state */
569       /* From HAL_OPAMP_STATE_READY to HAL_OPAMP_STATE_BUSY */
570       hopamp->State = HAL_OPAMP_STATE_BUSY;   
571     }
572     else
573     {
574       status = HAL_ERROR;
575     }
576     
577    }
578   return status;
579 }
580
581 /**
582   * @brief  Stop the opamp 
583   * @param  hopamp: OPAMP handle
584   * @retval HAL status
585   */
586 HAL_StatusTypeDef HAL_OPAMP_Stop(OPAMP_HandleTypeDef* hopamp)
587
588   HAL_StatusTypeDef status = HAL_OK;
589     
590   /* Check the OPAMP handle allocation */
591   /* Check if OPAMP locked */
592   /* Check if OPAMP calibration ongoing */
593   if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED) \
594                       || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY))  
595   {
596     status = HAL_ERROR;
597   }
598   else
599   {
600     /* Check the parameter */
601     assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
602
603     if(hopamp->State == HAL_OPAMP_STATE_BUSY)
604     {
605       /* Disable the selected opamp */
606       SET_BIT (OPAMP->CSR, __OPAMP_CSR_OPAXPD(hopamp)); 
607       
608       /* Update the OPAMP state*/     
609       /* From  HAL_OPAMP_STATE_BUSY to HAL_OPAMP_STATE_READY*/
610       hopamp->State = HAL_OPAMP_STATE_READY;
611     }
612     else
613     {
614       status = HAL_ERROR;
615     }
616   }
617   return status;
618 }
619
620 /**
621   * @brief  Run the self calibration of one OPAMP
622   * @note   Trimming values (PMOS & NMOS) are updated and user trimming is 
623   *         enabled is calibration is succesful.
624   * @note   Calibration is performed in the mode specified in OPAMP init
625   *         structure (mode normal or low-power). To perform calibration for
626   *         both modes, repeat this function twice after OPAMP init structure
627   *         accordingly updated.
628   * @note   Calibration runs about 10 ms (5 dichotmy steps, repeated for P  
629   *         and N transistors: 10 steps with 1 ms for each step).
630   * @param  hopamp: handle
631   * @retval Updated offset trimming values (PMOS & NMOS), user trimming is enabled
632   * @retval HAL status
633   */
634 HAL_StatusTypeDef HAL_OPAMP_SelfCalibrate(OPAMP_HandleTypeDef* hopamp)
635
636   HAL_StatusTypeDef status = HAL_OK;
637   
638   uint32_t* opamp_trimmingvalue = 0;
639   uint32_t opamp_trimmingvaluen = 0;
640   uint32_t opamp_trimmingvaluep = 0;
641   
642   uint32_t trimming_diff_pair = 0;           /* Selection of differential transistors pair high or low */
643
644   __IO uint32_t* tmp_opamp_reg_trimming;     /* Selection of register of trimming depending on power mode: OTR or LPOTR */
645   uint32_t tmp_opamp_otr_otuser = 0;         /* Selection of bit OPAMP_OTR_OT_USER depending on trimming register pointed: OTR or LPOTR */
646
647   uint32_t tmp_Opaxcalout_DefaultSate = 0;   /* Bit OPAMP_CSR_OPAXCALOUT default state when trimming value is 00000b. Used to detect the bit toggling */
648
649   uint32_t tmp_OpaxSwitchesContextBackup = 0;
650   
651   uint8_t trimming_diff_pair_iteration_count = 0;
652   uint8_t delta = 0;
653
654   
655   /* Check the OPAMP handle allocation */
656   /* Check if OPAMP locked */
657   if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED))
658   {
659     status = HAL_ERROR;
660   }
661   else
662   {
663   
664     /* Check if OPAMP in calibration mode and calibration not yet enable */
665     if(hopamp->State == HAL_OPAMP_STATE_READY)
666     {
667       /* Check the parameter */
668       assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
669       assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode));
670       
671       /* Update OPAMP state */
672       hopamp->State = HAL_OPAMP_STATE_CALIBBUSY;
673       
674       /* Backup of switches configuration to restore it at the end of the     */
675       /* calibration.                                                         */
676       tmp_OpaxSwitchesContextBackup = READ_BIT(OPAMP->CSR, __OPAMP_CSR_ALL_SWITCHES(hopamp));
677   
678       /* Open all switches on non-inverting input, inverting input and output */
679       /* feedback.                                                            */
680       CLEAR_BIT(OPAMP->CSR, __OPAMP_CSR_ALL_SWITCHES(hopamp));
681
682       /* Set calibration mode to user programmed trimming values */
683       SET_BIT(OPAMP->OTR, OPAMP_OTR_OT_USER);
684
685       
686       /* Select trimming settings depending on power mode */
687       if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
688       {
689         tmp_opamp_otr_otuser = OPAMP_OTR_OT_USER;
690         tmp_opamp_reg_trimming = &OPAMP->OTR;
691       }
692       else
693       {
694         tmp_opamp_otr_otuser = 0x00000000;
695         tmp_opamp_reg_trimming = &OPAMP->LPOTR;
696       }
697
698       
699       /* Enable the selected opamp */
700       CLEAR_BIT (OPAMP->CSR, __OPAMP_CSR_OPAXPD(hopamp));
701
702       /* Perform trimming for both differential transistors pair high and low */
703       for (trimming_diff_pair_iteration_count = 0; trimming_diff_pair_iteration_count <=1; trimming_diff_pair_iteration_count++)
704       {
705         if (trimming_diff_pair_iteration_count == 0)
706         {
707           /* Calibration of transistors differential pair high (NMOS) */
708           trimming_diff_pair = OPAMP_FACTORYTRIMMING_N;
709           opamp_trimmingvalue = &opamp_trimmingvaluen;
710           
711           /* Set bit OPAMP_CSR_OPAXCALOUT default state when trimming value   */
712           /* is 00000b. Used to detect the bit toggling during trimming.      */
713           tmp_Opaxcalout_DefaultSate = RESET;
714
715           /* Enable calibration for N differential pair */
716           MODIFY_REG(OPAMP->CSR, __OPAMP_CSR_OPAXCAL_L(hopamp),
717                                  __OPAMP_CSR_OPAXCAL_H(hopamp) );
718         }
719         else /* (trimming_diff_pair_iteration_count == 1) */
720         {
721           /* Calibration of transistors differential pair low (PMOS) */
722           trimming_diff_pair = OPAMP_FACTORYTRIMMING_P;
723           opamp_trimmingvalue = &opamp_trimmingvaluep;
724           
725           /* Set bit OPAMP_CSR_OPAXCALOUT default state when trimming value   */
726           /* is 00000b. Used to detect the bit toggling during trimming.      */
727           tmp_Opaxcalout_DefaultSate = __OPAMP_CSR_OPAXCALOUT(hopamp);
728           
729           /* Enable calibration for P differential pair */
730           MODIFY_REG(OPAMP->CSR, __OPAMP_CSR_OPAXCAL_H(hopamp),
731                                  __OPAMP_CSR_OPAXCAL_L(hopamp) );
732         }
733         
734       
735         /* Perform calibration parameter search by dichotomy sweep */
736         /*  - Delta initial value 16: for 5 dichotomy steps: 16 for the       */
737         /*    initial range, then successive delta sweeps (8, 4, 2, 1).       */
738         /*    can extend the search range to +/- 15 units.                    */
739         /*  - Trimming initial value 15: search range will go from 0 to 30    */
740         /*    (Trimming value 31 is forbidden).                               */
741         *opamp_trimmingvalue = 15;
742         delta = 16;
743
744         while (delta != 0)
745         {
746           /* Set candidate trimming */               
747           MODIFY_REG(*tmp_opamp_reg_trimming, __OPAMP_OFFSET_TRIM_SET(hopamp, trimming_diff_pair, OPAMP_TRIM_VALUE_MASK) ,
748                                               __OPAMP_OFFSET_TRIM_SET(hopamp, trimming_diff_pair, *opamp_trimmingvalue) | tmp_opamp_otr_otuser);
749           
750           /* Offset trimming time: during calibration, minimum time needed    */
751           /* between two steps to have 1 mV accuracy.                         */
752           HAL_Delay(OPAMP_TRIMMING_DELAY);
753
754           /* Divide range by 2 to continue dichotomy sweep */
755           delta >>= 1;
756             
757           /* Set trimming values for next iteration in function of trimming   */
758           /* result toggle (versus initial state).                            */
759           if (READ_BIT(OPAMP->CSR, __OPAMP_CSR_OPAXCALOUT(hopamp)) != tmp_Opaxcalout_DefaultSate)
760           {
761             /* If calibration output is has toggled, try lower trimming */
762             *opamp_trimmingvalue -= delta;
763           }
764           else
765           {
766             /* If calibration output is has not toggled, try higher trimming */
767             *opamp_trimmingvalue += delta;
768           }
769         }
770         
771       }
772        
773       /* Disable calibration for P and N differential pairs */
774       /* Disable the selected opamp */
775       CLEAR_BIT (OPAMP->CSR, (__OPAMP_CSR_OPAXCAL_H(hopamp) | 
776                               __OPAMP_CSR_OPAXCAL_L(hopamp) |
777                               __OPAMP_CSR_OPAXPD(hopamp))    );
778
779       /* Backup of switches configuration to restore it at the end of the     */
780       /* calibration.                                                         */
781       SET_BIT(OPAMP->CSR, tmp_OpaxSwitchesContextBackup);
782       
783       /* Self calibration is successful */
784       /* Store calibration (user trimming) results in init structure. */
785       
786       /* Set user trimming mode */  
787       hopamp->Init.UserTrimming = OPAMP_TRIMMING_USER;
788       
789       /* Affect calibration parameters depending on mode normal/low power */
790       if (hopamp->Init.PowerMode != OPAMP_POWERMODE_LOWPOWER)
791       {
792         /* Write calibration result N */
793         hopamp->Init.TrimmingValueN = opamp_trimmingvaluen;
794         /* Write calibration result P */
795         hopamp->Init.TrimmingValueP = opamp_trimmingvaluep;
796       }
797       else
798       {
799         /* Write calibration result N */
800         hopamp->Init.TrimmingValueNLowPower = opamp_trimmingvaluen;
801         /* Write calibration result P */
802         hopamp->Init.TrimmingValuePLowPower = opamp_trimmingvaluep;
803       }
804       
805       /* Update OPAMP state */
806       hopamp->State = HAL_OPAMP_STATE_READY;
807
808     }
809     else
810     {
811       /* OPAMP can not be calibrated from this mode */ 
812       status = HAL_ERROR;
813     }
814   }
815
816   return status;
817 }
818
819 /**
820   * @brief  Return the OPAMP factory trimming value
821   *         Caution: On STM32L1 OPAMP, user can retrieve factory trimming if 
822   *                  OPAMP has never been set to user trimming before.
823   *                  Therefore, this fonction must be called when OPAMP init  
824   *                  parameter "UserTrimming" is set to trimming factory, 
825   *                  and before OPAMP  calibration (function 
826   *                  "HAL_OPAMP_SelfCalibrate()").
827   *                  Otherwise, factory triming value cannot be retrieved and 
828   *                  error status is returned.
829   * @param  hopamp : OPAMP handle
830   * @param  trimmingoffset : Trimming offset (P or N)
831   *         This parameter must be a value of @ref OPAMP_FactoryTrimming
832   * @note   Calibration parameter retrieved is corresponding to the mode 
833   *         specified in OPAMP init structure (mode normal or low-power). 
834   *         To retrieve calibration parameters for both modes, repeat this 
835   *         function after OPAMP init structure accordingly updated.
836   * @retval Trimming value (P or N): range: 0->31
837   *         or OPAMP_FACTORYTRIMMING_DUMMY if trimming value is not available
838   * @{
839   */
840 OPAMP_TrimmingValueTypeDef HAL_OPAMP_GetTrimOffset (OPAMP_HandleTypeDef *hopamp, uint32_t trimmingoffset)
841
842   OPAMP_TrimmingValueTypeDef trimmingvalue;
843   __IO uint32_t* tmp_opamp_reg_trimming;  /* Selection of register of trimming depending on power mode: OTR or LPOTR */
844   
845   /* Check the OPAMP handle allocation */
846   /* Value can be retrieved in HAL_OPAMP_STATE_READY state */
847   if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_RESET)
848                       || (hopamp->State == HAL_OPAMP_STATE_BUSY)
849                       || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)
850                       || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED))
851   {
852     trimmingvalue = OPAMP_FACTORYTRIMMING_DUMMY;
853   }
854   else
855   {
856     /* Check the parameter */
857     assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
858     assert_param(IS_OPAMP_FACTORYTRIMMING(trimmingoffset));
859     assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode));
860     
861     /* Check the trimming mode */
862     if (hopamp->Init.UserTrimming == OPAMP_TRIMMING_USER) 
863     {
864       /* This fonction must called when OPAMP init parameter "UserTrimming"   */
865       /* is set to trimming factory, and before OPAMP calibration (function   */
866       /* "HAL_OPAMP_SelfCalibrate()").                                        */
867       /* Otherwise, factory triming value cannot be retrieved and error       */
868       /* status is returned.                                                  */
869       trimmingvalue = OPAMP_FACTORYTRIMMING_DUMMY;
870     }
871     else
872     {
873       /* Select trimming settings depending on power mode */
874       if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
875       {
876         tmp_opamp_reg_trimming = &OPAMP->OTR;
877       }
878       else
879       {
880         tmp_opamp_reg_trimming = &OPAMP->LPOTR;
881       }
882         
883       /* Get factory trimming  */
884       trimmingvalue = ((*tmp_opamp_reg_trimming >> __OPAMP_OFFSET_TRIM_BITSPOSITION(hopamp, trimmingoffset)) & OPAMP_TRIM_VALUE_MASK);
885       }
886   }
887   
888   return trimmingvalue;
889 }
890
891 /**
892   * @}
893   */
894
895 /**
896   * @}
897   */
898       
899 /** @defgroup OPAMP_Exported_Functions_Group3 Peripheral Control functions 
900  *  @brief   Peripheral Control functions 
901  *
902 @verbatim   
903  ===============================================================================
904                       ##### Peripheral Control functions #####
905  ===============================================================================  
906     [..]
907
908 @endverbatim
909   * @{
910   */
911
912 /**
913   * @brief  Lock the selected opamp configuration.
914   *         Caution: On STM32L1, HAL OPAMP lock is software lock only (not 
915   *         hardware lock as on some other STM32 devices)
916   * @param  hopamp: OPAMP handle
917   * @retval HAL status
918   */
919 HAL_StatusTypeDef HAL_OPAMP_Lock(OPAMP_HandleTypeDef* hopamp)
920 {
921   HAL_StatusTypeDef status = HAL_OK;
922
923   /* Check the OPAMP handle allocation */
924   /* Check if OPAMP locked */
925   /* OPAMP can be locked when enabled and running in normal mode */ 
926   /*   It is meaningless otherwise */
927   if((hopamp == HAL_NULL) || (hopamp->State == HAL_OPAMP_STATE_RESET) \
928                       || (hopamp->State == HAL_OPAMP_STATE_READY) \
929                       || (hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)\
930                       || (hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED))
931   
932   {
933     status = HAL_ERROR;
934   }
935   
936   else
937   {
938     /* Check the parameter */
939     assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
940   
941    /* OPAMP state changed to locked */
942     hopamp->State = HAL_OPAMP_STATE_BUSYLOCKED;
943   }
944   return status; 
945 }
946
947 /**
948   * @}
949   */
950
951
952 /** @defgroup OPAMP_Exported_Functions_Group4 Peripheral State functions 
953  *  @brief   Peripheral State functions 
954  *
955 @verbatim   
956  ===============================================================================
957                       ##### Peripheral State functions #####
958  ===============================================================================  
959     [..]
960     This subsection permit to get in run-time the status of the peripheral.
961
962 @endverbatim
963   * @{
964   */
965
966 /**
967   * @brief  Return the OPAMP state
968   * @param  hopamp : OPAMP handle
969   * @retval HAL state
970   */
971 HAL_OPAMP_StateTypeDef HAL_OPAMP_GetState(OPAMP_HandleTypeDef* hopamp)
972 {
973   /* Check the OPAMP handle allocation */
974   if(hopamp == HAL_NULL)
975   {
976     return HAL_OPAMP_STATE_RESET;
977   }
978
979   /* Check the parameter */
980   assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
981
982   return hopamp->State;
983 }
984
985 /**
986   * @}
987   */
988
989 /**
990   * @}
991   */
992
993 #endif /* STM32L151xCA || STM32L151xD || STM32L152xCA || STM32L152xD || STM32L162xCA || STM32L162xD || STM32L151xE || STM32L152xE || STM32L162xE || STM32L162xC || STM32L152xC || STM32L151xC */
994
995 #endif /* HAL_OPAMP_MODULE_ENABLED */
996 /**
997   * @}
998   */
999
1000 /**
1001   * @}
1002   */
1003
1004 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/