You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

1164 lines
38 KiB

  1. /**
  2. ******************************************************************************
  3. * @file stm32h7xx_hal_opamp.c
  4. * @author MCD Application Team
  5. * @brief OPAMP HAL module driver.
  6. * This file provides firmware functions to manage the following
  7. * functionalities of the operational amplifier(s) peripheral:
  8. * + OPAMP configuration
  9. * + OPAMP calibration
  10. * Thanks to
  11. * + Initialization and de-initialization functions
  12. * + IO operation functions
  13. * + Peripheral Control functions
  14. * + Peripheral State functions
  15. *
  16. @verbatim
  17. ================================================================================
  18. ##### OPAMP Peripheral Features #####
  19. ================================================================================
  20. [..] The device integrates 2 operational amplifiers OPAMP1 & OPAMP2
  21. (#) The OPAMP(s) provides several exclusive running modes.
  22. (++) Standalone mode
  23. (++) Programmable Gain Amplifier (PGA) modes
  24. (++) Follower mode
  25. (#) Each OPAMP(s) can be configured in normal and high speed mode.
  26. (#) The OPAMP(s) provide(s) calibration capabilities.
  27. (++) Calibration aims at correcting some offset for running mode.
  28. (++) The OPAMP uses either factory calibration settings OR user defined
  29. calibration (trimming) settings (i.e. trimming mode).
  30. (++) The user defined settings can be figured out using self calibration
  31. handled by HAL_OPAMP_SelfCalibrate, HAL_OPAMPEx_SelfCalibrateAll
  32. (++) HAL_OPAMP_SelfCalibrate:
  33. (+++) Runs automatically the calibration in 2 steps.
  34. (90% of VDDA for NMOS transistors, 10% of VDDA for PMOS transistors).
  35. (As OPAMP is Rail-to-rail input/output, these 2 steps calibration is
  36. appropriate and enough in most cases).
  37. (+++) Runs automatically the calibration.
  38. (+++) Enables the user trimming mode
  39. (+++) Updates the init structure with trimming values with fresh calibration
  40. results.
  41. The user may store the calibration results for larger
  42. (ex monitoring the trimming as a function of temperature
  43. for instance)
  44. (+++) HAL_OPAMPEx_SelfCalibrateAll
  45. runs calibration of all OPAMPs in parallel to save search time.
  46. (#) Running mode: Standalone mode
  47. (++) Gain is set externally (gain depends on external loads).
  48. (++) Follower mode also possible externally by connecting the inverting input to
  49. the output.
  50. (#) Running mode: Follower mode
  51. (++) No Inverting Input is connected.
  52. (#) Running mode: Programmable Gain Amplifier (PGA) mode
  53. (Resistor feedback output)
  54. (#) The OPAMP(s) output(s) can be internally connected to resistor feedback
  55. output.
  56. (#) OPAMP gain can be selected as :
  57. (##) Gain of x2, x4, x8 or x16 for non inverting mode with:
  58. (+++) VREF- referenced.
  59. (+++) Filtering on VINM0, VREF- referenced.
  60. (+++) VINM0 node for bias voltage and VINP0 for input signal.
  61. (+++) VINM0 node for bias voltage and VINP0 for input signal, VINM1 node for filtering.
  62. (##) Gain of x-1, x-3, x-7 or x-15 for inverting mode with:
  63. (+++) VINM0 node for input signal and VINP0 for bias.
  64. (+++) VINM0 node for input signal and VINP0 for bias voltage, VINM1 node for filtering.
  65. (#) The OPAMPs inverting input can be selected according to the Reference Manual
  66. "OPAMP functional description" chapter.
  67. (#) The OPAMPs non inverting input can be selected according to the Reference Manual
  68. "OPAMP functional description" chapter.
  69. ##### How to use this driver #####
  70. ================================================================================
  71. [..]
  72. *** High speed / normal power mode ***
  73. ============================================
  74. [..] To run in high speed mode:
  75. (#) Configure the OPAMP using HAL_OPAMP_Init() function:
  76. (++) Select OPAMP_POWERMODE_HIGHSPEED
  77. (++) Otherwise select OPAMP_POWERMODE_NORMAL
  78. *** Calibration ***
  79. ============================================
  80. [..] To run the OPAMP calibration self calibration:
  81. (#) Start calibration using HAL_OPAMP_SelfCalibrate.
  82. Store the calibration results.
  83. *** Running mode ***
  84. ============================================
  85. [..] To use the OPAMP, perform the following steps:
  86. (#) Fill in the HAL_OPAMP_MspInit() to
  87. (++) Enable the OPAMP Peripheral clock using macro __HAL_RCC_OPAMP_CLK_ENABLE()
  88. (++) Configure the OPAMP input AND output in analog mode using
  89. HAL_GPIO_Init() to map the OPAMP output to the GPIO pin.
  90. (#) Registrate Callbacks
  91. (++) The compilation define USE_HAL_OPAMP_REGISTER_CALLBACKS when set to 1
  92. allows the user to configure dynamically the driver callbacks.
  93. (++) Use Functions @ref HAL_OPAMP_RegisterCallback() to register a user callback,
  94. it allows to register following callbacks:
  95. (+++) MspInitCallback : OPAMP MspInit.
  96. (+++) MspDeInitCallback : OPAMP MspDeInit.
  97. This function takes as parameters the HAL peripheral handle, the Callback ID
  98. and a pointer to the user callback function.
  99. (++) Use function @ref HAL_OPAMP_UnRegisterCallback() to reset a callback to the default
  100. weak (surcharged) function. It allows to reset following callbacks:
  101. (+++) MspInitCallback : OPAMP MspInit.
  102. (+++) MspDeInitCallback : OPAMP MspDeInit.
  103. (+++) All Callbacks
  104. (#) Configure the OPAMP using HAL_OPAMP_Init() function:
  105. (++) Select the mode
  106. (++) Select the inverting input
  107. (++) Select the non-inverting input
  108. (++) If PGA mode is enabled, Select if inverting input is connected.
  109. (++) Select either factory or user defined trimming mode.
  110. (++) If the user-defined trimming mode is enabled, select PMOS & NMOS trimming values
  111. (typically values set by HAL_OPAMP_SelfCalibrate function).
  112. (#) Enable the OPAMP using HAL_OPAMP_Start() function.
  113. (#) Disable the OPAMP using HAL_OPAMP_Stop() function.
  114. (#) Lock the OPAMP in running mode using HAL_OPAMP_Lock() function.
  115. Caution: On STM32H7, HAL OPAMP lock is software lock only (not
  116. hardware lock as on some other STM32 devices)
  117. (#) If needed, unlock the OPAMP using HAL_OPAMPEx_Unlock() function.
  118. *** Running mode: change of configuration while OPAMP ON ***
  119. ============================================
  120. [..] To Re-configure OPAMP when OPAMP is ON (change on the fly)
  121. (#) If needed, fill in the HAL_OPAMP_MspInit()
  122. (++) This is the case for instance if you wish to use new OPAMP I/O
  123. (#) Configure the OPAMP using HAL_OPAMP_Init() function:
  124. (++) As in configure case, select first the parameters you wish to modify.
  125. (#) Change from high speed mode to normal power mode (& vice versa) requires
  126. first HAL_OPAMP_DeInit() (force OPAMP OFF) and then HAL_OPAMP_Init().
  127. In other words, of OPAMP is ON, HAL_OPAMP_Init can NOT change power mode
  128. alone.
  129. @endverbatim
  130. ******************************************************************************
  131. Table 1. OPAMPs inverting/non-inverting inputs for the STM32H7 devices:
  132. +------------------------------------------------------------------------|
  133. | | | OPAMP1 | OPAMP2 |
  134. |-----------------|---------|----------------------|---------------------|
  135. | Inverting Input | VM_SEL | VINM0-> PC5 | VINM0-> PE8 |
  136. | | | VINM1-> PA7 | VINM1-> PG1 |
  137. | | | Internal: | Internal: |
  138. | | | ADC1_IN9 | OPAMP2_OUT |
  139. | | | ADC2_IN9 | PGA mode |
  140. | | | OPAMP1_OUT | |
  141. | | | PGA mode | |
  142. |-----------------|---------|----------------------|---------------------|
  143. | Non Inverting | VP_SEL | | |
  144. | | | VP0 -> PB0 (GPIO) | VP0 -> PE9 (GPIO) |
  145. | | | Internal: | Internal: |
  146. | Input | | DAC1_CH1_int | DAC1_CH2_int |
  147. | | | ADC1_IN8 | DAC2_CH1_int |
  148. | | | ADC2_IN8 | COMP2_INP |
  149. | | | COMP1_INP | |
  150. +------------------------------------------------------------------------|
  151. [..] Table 2. OPAMPs outputs for the STM32H7 devices:
  152. +-------------------------------------------------------------------------
  153. | | | OPAMP1 | OPAMP2 |
  154. |-----------------|--------|-----------------------|---------------------|
  155. | Output | VOUT | PC4 | PE7 |
  156. | | | & ADC1_IN4| | & COMP2_INN7 if |
  157. | | | ADC2_IN4 |connected internally |
  158. | | | COMP1_INN7 if | |
  159. | | | connected internally | |
  160. |-----------------|--------|-----------------------|---------------------|
  161. ******************************************************************************
  162. * @attention
  163. *
  164. * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
  165. * All rights reserved.</center></h2>
  166. *
  167. * This software component is licensed by ST under BSD 3-Clause license,
  168. * the "License"; You may not use this file except in compliance with the
  169. * License. You may obtain a copy of the License at:
  170. * opensource.org/licenses/BSD-3-Clause
  171. *
  172. ******************************************************************************
  173. */
  174. /* Includes ------------------------------------------------------------------*/
  175. #include "stm32h7xx_hal.h"
  176. /** @addtogroup STM32H7xx_HAL_Driver
  177. * @{
  178. */
  179. /** @defgroup OPAMP OPAMP
  180. * @brief OPAMP module driver
  181. * @{
  182. */
  183. #ifdef HAL_OPAMP_MODULE_ENABLED
  184. /* Private types -------------------------------------------------------------*/
  185. /* Private variables ---------------------------------------------------------*/
  186. /* Private constants ---------------------------------------------------------*/
  187. /** @addtogroup OPAMP_Private_Constants
  188. * @{
  189. */
  190. /* CSR register reset value */
  191. #define OPAMP_CSR_RESET_VALUE 0x00000000U
  192. /* CSR Init masks */
  193. #define OPAMP_CSR_INIT_MASK_PGA (OPAMP_CSR_OPAHSM | OPAMP_CSR_VMSEL | OPAMP_CSR_PGGAIN | OPAMP_CSR_PGGAIN \
  194. | OPAMP_CSR_VPSEL | OPAMP_CSR_USERTRIM)
  195. #define OPAMP_CSR_INIT_MASK_FOLLOWER (OPAMP_CSR_OPAHSM | OPAMP_CSR_VMSEL| OPAMP_CSR_VPSEL \
  196. | OPAMP_CSR_USERTRIM)
  197. #define OPAMP_CSR_INIT_MASK_STANDALONE (OPAMP_CSR_OPAHSM | OPAMP_CSR_VMSEL | OPAMP_CSR_VPSEL \
  198. | OPAMP_CSR_VMSEL | OPAMP_CSR_USERTRIM)
  199. /**
  200. * @}
  201. */
  202. /* Private macros ------------------------------------------------------------*/
  203. /* Private functions ---------------------------------------------------------*/
  204. /* Exported functions --------------------------------------------------------*/
  205. /** @defgroup OPAMP_Exported_Functions OPAMP Exported Functions
  206. * @{
  207. */
  208. /** @defgroup OPAMP_Exported_Functions_Group1 Initialization and de-initialization functions
  209. * @brief Initialization and Configuration functions
  210. *
  211. @verbatim
  212. ==============================================================================
  213. ##### Initialization and de-initialization functions #####
  214. ==============================================================================
  215. @endverbatim
  216. * @{
  217. */
  218. /**
  219. * @brief Initialize the OPAMP according to the specified
  220. * parameters in the OPAMP_InitTypeDef and initialize 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 updateotrlpotr;
  230. /* Check the OPAMP handle allocation and lock status */
  231. /* Init not allowed if calibration is ongoing */
  232. if(hopamp == NULL)
  233. {
  234. return HAL_ERROR;
  235. }
  236. else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
  237. {
  238. return HAL_ERROR;
  239. }
  240. else if(hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)
  241. {
  242. return HAL_ERROR;
  243. }
  244. else
  245. {
  246. /* Check the parameter */
  247. assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
  248. /* Set OPAMP parameters */
  249. assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode));
  250. assert_param(IS_OPAMP_FUNCTIONAL_NORMALMODE(hopamp->Init.Mode));
  251. assert_param(IS_OPAMP_NONINVERTING_INPUT(hopamp->Init.NonInvertingInput));
  252. #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
  253. if(hopamp->State == HAL_OPAMP_STATE_RESET)
  254. {
  255. if(hopamp->MspInitCallback == NULL)
  256. {
  257. hopamp->MspInitCallback = HAL_OPAMP_MspInit;
  258. }
  259. }
  260. #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
  261. if ((hopamp->Init.Mode) == OPAMP_STANDALONE_MODE)
  262. {
  263. assert_param(IS_OPAMP_INVERTING_INPUT_STANDALONE(hopamp->Init.InvertingInput));
  264. }
  265. if ((hopamp->Init.Mode) == OPAMP_PGA_MODE)
  266. {
  267. assert_param(IS_OPAMP_PGA_GAIN(hopamp->Init.PgaGain));
  268. assert_param(IS_OPAMP_PGACONNECT(hopamp->Init.PgaConnect));
  269. }
  270. assert_param(IS_OPAMP_TRIMMING(hopamp->Init.UserTrimming));
  271. if ((hopamp->Init.UserTrimming) == OPAMP_TRIMMING_USER)
  272. {
  273. if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
  274. {
  275. assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueP));
  276. assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueN));
  277. }
  278. else
  279. {
  280. assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValuePHighSpeed));
  281. assert_param(IS_OPAMP_TRIMMINGVALUE(hopamp->Init.TrimmingValueNHighSpeed));
  282. }
  283. }
  284. if(hopamp->State == HAL_OPAMP_STATE_RESET)
  285. {
  286. /* Allocate lock resource and initialize it */
  287. hopamp->Lock = HAL_UNLOCKED;
  288. }
  289. #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
  290. hopamp->MspInitCallback(hopamp);
  291. #else
  292. /* Call MSP init function */
  293. HAL_OPAMP_MspInit(hopamp);
  294. #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
  295. /* Set operating mode */
  296. CLEAR_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALON);
  297. /* In PGA mode InvertingInput is Not Applicable */
  298. if (hopamp->Init.Mode == OPAMP_PGA_MODE)
  299. {
  300. MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_INIT_MASK_PGA, \
  301. hopamp->Init.PowerMode | \
  302. hopamp->Init.Mode | \
  303. hopamp->Init.PgaGain | \
  304. hopamp->Init.PgaConnect | \
  305. hopamp->Init.NonInvertingInput | \
  306. hopamp->Init.UserTrimming);
  307. }
  308. if (hopamp->Init.Mode == OPAMP_FOLLOWER_MODE)
  309. {
  310. /* In Follower mode InvertingInput is Not Applicable */
  311. MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_INIT_MASK_FOLLOWER, \
  312. hopamp->Init.PowerMode | \
  313. hopamp->Init.Mode | \
  314. hopamp->Init.NonInvertingInput | \
  315. hopamp->Init.UserTrimming);
  316. }
  317. if (hopamp->Init.Mode == OPAMP_STANDALONE_MODE)
  318. {
  319. MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_INIT_MASK_STANDALONE, \
  320. hopamp->Init.PowerMode | \
  321. hopamp->Init.Mode | \
  322. hopamp->Init.InvertingInput | \
  323. hopamp->Init.NonInvertingInput | \
  324. hopamp->Init.UserTrimming);
  325. }
  326. if (hopamp->Init.UserTrimming == OPAMP_TRIMMING_USER)
  327. {
  328. /* Set power mode and associated calibration parameters */
  329. if (hopamp->Init.PowerMode != OPAMP_POWERMODE_HIGHSPEED)
  330. {
  331. /* OPAMP_POWERMODE_NORMAL */
  332. /* Set calibration mode (factory or user) and values for */
  333. /* transistors differential pair high (PMOS) and low (NMOS) for */
  334. /* normal mode. */
  335. updateotrlpotr = (((hopamp->Init.TrimmingValueP) << (OPAMP_INPUT_NONINVERTING)) \
  336. | (hopamp->Init.TrimmingValueN));
  337. MODIFY_REG(hopamp->Instance->OTR, OPAMP_OTR_TRIMOFFSETN | OPAMP_OTR_TRIMOFFSETP, updateotrlpotr);
  338. }
  339. else
  340. {
  341. /* OPAMP_POWERMODE_HIGHSPEED*/
  342. /* transistors differential pair high (PMOS) and low (NMOS) for */
  343. /* high speed mode. */
  344. updateotrlpotr = (((hopamp->Init.TrimmingValuePHighSpeed) << (OPAMP_INPUT_NONINVERTING)) \
  345. | (hopamp->Init.TrimmingValueNHighSpeed));
  346. MODIFY_REG(hopamp->Instance->HSOTR, OPAMP_OTR_TRIMOFFSETN | OPAMP_OTR_TRIMOFFSETP, updateotrlpotr);
  347. }
  348. }
  349. /* Update the OPAMP state*/
  350. if (hopamp->State == HAL_OPAMP_STATE_RESET)
  351. {
  352. /* From RESET state to READY State */
  353. hopamp->State = HAL_OPAMP_STATE_READY;
  354. }
  355. /* else: remain in READY or BUSY state (no update) */
  356. return status;
  357. }
  358. }
  359. /**
  360. * @brief DeInitialize the OPAMP peripheral
  361. * @note Deinitialization can be performed if the OPAMP configuration is locked.
  362. * (the lock is SW in H7)
  363. * @param hopamp OPAMP handle
  364. * @retval HAL status
  365. */
  366. HAL_StatusTypeDef HAL_OPAMP_DeInit(OPAMP_HandleTypeDef *hopamp)
  367. {
  368. HAL_StatusTypeDef status = HAL_OK;
  369. /* Check the OPAMP handle allocation */
  370. /* DeInit not allowed if calibration is on going */
  371. if(hopamp == NULL)
  372. {
  373. status = HAL_ERROR;
  374. }
  375. else if(hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)
  376. {
  377. status = HAL_ERROR;
  378. }
  379. else
  380. {
  381. /* Check the parameter */
  382. assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
  383. /* Set OPAMP_CSR register to reset value */
  384. WRITE_REG(hopamp->Instance->CSR, OPAMP_CSR_RESET_VALUE);
  385. /* DeInit the low level hardware */
  386. #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
  387. if(hopamp->MspDeInitCallback == NULL)
  388. {
  389. hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit;
  390. }
  391. /* DeInit the low level hardware */
  392. hopamp->MspDeInitCallback(hopamp);
  393. #else
  394. HAL_OPAMP_MspDeInit(hopamp);
  395. #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
  396. /* Update the OPAMP state*/
  397. hopamp->State = HAL_OPAMP_STATE_RESET;
  398. /* Process unlocked */
  399. __HAL_UNLOCK(hopamp);
  400. }
  401. return status;
  402. }
  403. /**
  404. * @brief Initialize the OPAMP MSP.
  405. * @param hopamp OPAMP handle
  406. * @retval None
  407. */
  408. __weak void HAL_OPAMP_MspInit(OPAMP_HandleTypeDef *hopamp)
  409. {
  410. /* Prevent unused argument(s) compilation warning */
  411. UNUSED(hopamp);
  412. /* NOTE : This function should not be modified, when the callback is needed,
  413. the function "HAL_OPAMP_MspInit()" must be implemented in the user file.
  414. */
  415. }
  416. /**
  417. * @brief DeInitialize OPAMP MSP.
  418. * @param hopamp OPAMP handle
  419. * @retval None
  420. */
  421. __weak void HAL_OPAMP_MspDeInit(OPAMP_HandleTypeDef *hopamp)
  422. {
  423. /* Prevent unused argument(s) compilation warning */
  424. UNUSED(hopamp);
  425. /* NOTE : This function should not be modified, when the callback is needed,
  426. the function "HAL_OPAMP_MspDeInit()" must be implemented in the user file.
  427. */
  428. }
  429. /**
  430. * @}
  431. */
  432. /** @defgroup OPAMP_Exported_Functions_Group2 IO operation functions
  433. * @brief IO operation functions
  434. *
  435. @verbatim
  436. ===============================================================================
  437. ##### IO operation functions #####
  438. ===============================================================================
  439. [..]
  440. This subsection provides a set of functions allowing to manage the OPAMP
  441. start, stop and calibration actions.
  442. @endverbatim
  443. * @{
  444. */
  445. /**
  446. * @brief Start the OPAMP.
  447. * @param hopamp OPAMP handle
  448. * @retval HAL status
  449. */
  450. HAL_StatusTypeDef HAL_OPAMP_Start(OPAMP_HandleTypeDef *hopamp)
  451. {
  452. HAL_StatusTypeDef status = HAL_OK;
  453. /* Check the OPAMP handle allocation */
  454. /* Check if OPAMP locked */
  455. if(hopamp == NULL)
  456. {
  457. status = HAL_ERROR;
  458. }
  459. else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
  460. {
  461. status = HAL_ERROR;
  462. }
  463. else
  464. {
  465. /* Check the parameter */
  466. assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
  467. if(hopamp->State == HAL_OPAMP_STATE_READY)
  468. {
  469. /* Enable the selected opamp */
  470. SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
  471. /* Update the OPAMP state*/
  472. /* From HAL_OPAMP_STATE_READY to HAL_OPAMP_STATE_BUSY */
  473. hopamp->State = HAL_OPAMP_STATE_BUSY;
  474. }
  475. else
  476. {
  477. status = HAL_ERROR;
  478. }
  479. }
  480. return status;
  481. }
  482. /**
  483. * @brief Stop the OPAMP.
  484. * @param hopamp OPAMP handle
  485. * @retval HAL status
  486. */
  487. HAL_StatusTypeDef HAL_OPAMP_Stop(OPAMP_HandleTypeDef *hopamp)
  488. {
  489. HAL_StatusTypeDef status = HAL_OK;
  490. /* Check the OPAMP handle allocation */
  491. /* Check if OPAMP locked */
  492. /* Check if OPAMP calibration ongoing */
  493. if(hopamp == NULL)
  494. {
  495. status = HAL_ERROR;
  496. }
  497. else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
  498. {
  499. status = HAL_ERROR;
  500. }
  501. else if(hopamp->State == HAL_OPAMP_STATE_CALIBBUSY)
  502. {
  503. status = HAL_ERROR;
  504. }
  505. else
  506. {
  507. /* Check the parameter */
  508. assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
  509. if(hopamp->State == HAL_OPAMP_STATE_BUSY)
  510. {
  511. /* Disable the selected opamp */
  512. CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
  513. /* Update the OPAMP state*/
  514. /* From HAL_OPAMP_STATE_BUSY to HAL_OPAMP_STATE_READY*/
  515. hopamp->State = HAL_OPAMP_STATE_READY;
  516. }
  517. else
  518. {
  519. status = HAL_ERROR;
  520. }
  521. }
  522. return status;
  523. }
  524. /**
  525. * @brief Run the self calibration of one OPAMP.
  526. * @note Calibration is performed in the mode specified in OPAMP init
  527. * structure (mode normal or high-speed). To perform calibration for
  528. * both modes, repeat this function twice after OPAMP init structure
  529. * accordingly updated.
  530. * @param hopamp handle
  531. * @retval Updated offset trimming values (PMOS & NMOS), user trimming is enabled
  532. * @retval HAL status
  533. */
  534. HAL_StatusTypeDef HAL_OPAMP_SelfCalibrate(OPAMP_HandleTypeDef *hopamp)
  535. {
  536. HAL_StatusTypeDef status = HAL_OK;
  537. uint32_t trimmingvaluen;
  538. uint32_t trimmingvaluep;
  539. uint32_t delta;
  540. uint32_t opampmode;
  541. __IO uint32_t* tmp_opamp_reg_trimming; /* Selection of register of trimming depending on power mode: OTR or HSOTR */
  542. /* Check the OPAMP handle allocation */
  543. /* Check if OPAMP locked */
  544. if(hopamp == NULL)
  545. {
  546. status = HAL_ERROR;
  547. }
  548. else if(hopamp->State == HAL_OPAMP_STATE_BUSYLOCKED)
  549. {
  550. status = HAL_ERROR;
  551. }
  552. else
  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. assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode));
  560. opampmode = READ_BIT(hopamp->Instance->CSR,OPAMP_CSR_VMSEL);
  561. /* Use of standalone mode */
  562. MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_VMSEL, OPAMP_STANDALONE_MODE);
  563. /* user trimming values are used for offset calibration */
  564. SET_BIT(hopamp->Instance->CSR, OPAMP_CSR_USERTRIM);
  565. /* Select trimming settings depending on power mode */
  566. if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
  567. {
  568. tmp_opamp_reg_trimming = &hopamp->Instance->OTR;
  569. }
  570. else
  571. {
  572. /* high speed Mode */
  573. tmp_opamp_reg_trimming = &hopamp->Instance->HSOTR;
  574. }
  575. /* Enable calibration */
  576. SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_CALON);
  577. /* Force internal reference on VP */
  578. SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_FORCEVP);
  579. /* 1st calibration - N */
  580. MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_90VDDA);
  581. /* Enable the selected opamp */
  582. SET_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
  583. /* Init trimming counter */
  584. /* Medium value */
  585. trimmingvaluen = 16U;
  586. delta = 8U;
  587. while (delta != 0U)
  588. {
  589. /* Set candidate trimming */
  590. /* OPAMP_POWERMODE_NORMAL */
  591. MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen);
  592. /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
  593. /* Offset trim time: during calibration, minimum time needed between */
  594. /* two steps to have 1 mV accuracy */
  595. HAL_Delay(OPAMP_TRIMMING_DELAY);
  596. if (READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT) != 0U)
  597. {
  598. /* OPAMP_CSR_CALOUT is HIGH try higher trimming */
  599. trimmingvaluen += delta;
  600. }
  601. else
  602. {
  603. /* OPAMP_CSR_CALOUT is LOW try lower trimming */
  604. trimmingvaluen -= delta;
  605. }
  606. /* Divide range by 2 to continue dichotomy sweep */
  607. delta >>= 1;
  608. }
  609. /* Still need to check if right calibration is current value or one step below */
  610. /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */
  611. MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen);
  612. /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
  613. /* Offset trim time: during calibration, minimum time needed between */
  614. /* two steps to have 1 mV accuracy */
  615. HAL_Delay(OPAMP_TRIMMING_DELAY);
  616. if ((READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT)) != 0U)
  617. {
  618. /* Trimming value is actually one value more */
  619. trimmingvaluen++;
  620. /* Set right trimming */
  621. MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETN, trimmingvaluen);
  622. }
  623. /* 2nd calibration - P */
  624. MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_CALSEL, OPAMP_VREF_10VDDA);
  625. /* Init trimming counter */
  626. /* Medium value */
  627. trimmingvaluep = 16U;
  628. delta = 8U;
  629. while (delta != 0U)
  630. {
  631. /* Set candidate trimming */
  632. /* OPAMP_POWERMODE_NORMAL */
  633. MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep<<OPAMP_INPUT_NONINVERTING));
  634. /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
  635. /* Offset trim time: during calibration, minimum time needed between */
  636. /* two steps to have 1 mV accuracy */
  637. HAL_Delay(OPAMP_TRIMMING_DELAY);
  638. if (READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT)!= 0U)
  639. {
  640. /* OPAMP_CSR_CALOUT is HIGH try higher trimming */
  641. trimmingvaluep += delta;
  642. }
  643. else
  644. {
  645. /* OPAMP_CSR_CALOUT is LOW try lower trimming */
  646. trimmingvaluep -= delta;
  647. }
  648. /* Divide range by 2 to continue dichotomy sweep */
  649. delta >>= 1U;
  650. }
  651. /* Still need to check if right calibration is current value or one step below */
  652. /* Indeed the first value that causes the OUTCAL bit to change from 1 to 0 */
  653. /* Set candidate trimming */
  654. MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep<<OPAMP_INPUT_NONINVERTING));
  655. /* OFFTRIMmax delay 2 ms as per datasheet (electrical characteristics */
  656. /* Offset trim time: during calibration, minimum time needed between */
  657. /* two steps to have 1 mV accuracy */
  658. HAL_Delay(OPAMP_TRIMMING_DELAY);
  659. if (READ_BIT(hopamp->Instance->CSR, OPAMP_CSR_CALOUT) != 0U)
  660. {
  661. /* Trimming value is actually one value more */
  662. trimmingvaluep++;
  663. MODIFY_REG(*tmp_opamp_reg_trimming, OPAMP_OTR_TRIMOFFSETP, (trimmingvaluep<<OPAMP_INPUT_NONINVERTING));
  664. }
  665. /* Disable calibration & set normal mode (operating mode) */
  666. CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_CALON);
  667. /* Disable the OPAMP */
  668. CLEAR_BIT (hopamp->Instance->CSR, OPAMP_CSR_OPAMPxEN);
  669. /* Set operating mode back */
  670. CLEAR_BIT(hopamp->Instance->CSR, OPAMP_CSR_FORCEVP);
  671. /* Self calibration is successful */
  672. /* Store calibration(user trimming) results in init structure. */
  673. /* Set user trimming mode */
  674. hopamp->Init.UserTrimming = OPAMP_TRIMMING_USER;
  675. /* Affect calibration parameters depending on mode normal/high speed */
  676. if (hopamp->Init.PowerMode != OPAMP_POWERMODE_HIGHSPEED)
  677. {
  678. /* Write calibration result N */
  679. hopamp->Init.TrimmingValueN = trimmingvaluen;
  680. /* Write calibration result P */
  681. hopamp->Init.TrimmingValueP = trimmingvaluep;
  682. }
  683. else
  684. {
  685. /* Write calibration result N */
  686. hopamp->Init.TrimmingValueNHighSpeed = trimmingvaluen;
  687. /* Write calibration result P */
  688. hopamp->Init.TrimmingValuePHighSpeed = trimmingvaluep;
  689. }
  690. /* Restore OPAMP mode after calibration */
  691. MODIFY_REG(hopamp->Instance->CSR, OPAMP_CSR_VMSEL, opampmode);
  692. }
  693. else
  694. {
  695. /* OPAMP can not be calibrated from this mode */
  696. status = HAL_ERROR;
  697. }
  698. }
  699. return status;
  700. }
  701. /**
  702. * @}
  703. */
  704. /** @defgroup OPAMP_Exported_Functions_Group3 Peripheral Control functions
  705. * @brief Peripheral Control functions
  706. *
  707. @verbatim
  708. ===============================================================================
  709. ##### Peripheral Control functions #####
  710. ===============================================================================
  711. [..]
  712. This subsection provides a set of functions allowing to control the OPAMP data
  713. transfers.
  714. @endverbatim
  715. * @{
  716. */
  717. /**
  718. * @brief Lock the selected OPAMP configuration.
  719. * @note On STM32H7, HAL OPAMP lock is software lock only (in
  720. * contrast of hardware lock available on some other STM32
  721. * devices)
  722. * @param hopamp OPAMP handle
  723. * @retval HAL status
  724. */
  725. HAL_StatusTypeDef HAL_OPAMP_Lock(OPAMP_HandleTypeDef *hopamp)
  726. {
  727. HAL_StatusTypeDef status = HAL_OK;
  728. /* Check the OPAMP handle allocation */
  729. /* Check if OPAMP locked */
  730. /* OPAMP can be locked when enabled and running in normal mode */
  731. /* It is meaningless otherwise */
  732. if(hopamp == NULL)
  733. {
  734. status = HAL_ERROR;
  735. }
  736. else if(hopamp->State != HAL_OPAMP_STATE_BUSY)
  737. {
  738. status = HAL_ERROR;
  739. }
  740. else
  741. {
  742. /* Check the parameter */
  743. assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
  744. /* OPAMP state changed to locked */
  745. hopamp->State = HAL_OPAMP_STATE_BUSYLOCKED;
  746. }
  747. return status;
  748. }
  749. /**
  750. * @brief Return the OPAMP factory trimming value.
  751. * @note On STM32H7 OPAMP, user can retrieve factory trimming if
  752. * OPAMP has never been set to user trimming before.
  753. * Therefore, this function must be called when OPAMP init
  754. * parameter "UserTrimming" is set to trimming factory,
  755. * and before OPAMP calibration (function
  756. * "HAL_OPAMP_SelfCalibrate()").
  757. * Otherwise, factory trimming value cannot be retrieved and
  758. * error status is returned.
  759. * @param hopamp OPAMP handle
  760. * @param trimmingoffset Trimming offset (P or N)
  761. * This parameter must be a value of @ref OPAMP_FactoryTrimming
  762. * @note Calibration parameter retrieved is corresponding to the mode
  763. * specified in OPAMP init structure (mode normal or high-speed).
  764. * To retrieve calibration parameters for both modes, repeat this
  765. * function after OPAMP init structure accordingly updated.
  766. * @retval Trimming value (P or N): range: 0->31
  767. * or OPAMP_FACTORYTRIMMING_DUMMY if trimming value is not available
  768. *
  769. */
  770. HAL_OPAMP_TrimmingValueTypeDef HAL_OPAMP_GetTrimOffset (OPAMP_HandleTypeDef *hopamp, uint32_t trimmingoffset)
  771. {
  772. HAL_OPAMP_TrimmingValueTypeDef trimmingvalue;
  773. __IO uint32_t* tmp_opamp_reg_trimming; /* Selection of register of trimming depending on power mode: OTR or LPOTR */
  774. /* Check the OPAMP handle allocation */
  775. /* Value can be retrieved in HAL_OPAMP_STATE_READY state */
  776. if(hopamp == NULL)
  777. {
  778. return OPAMP_FACTORYTRIMMING_DUMMY;
  779. }
  780. if(hopamp->State == HAL_OPAMP_STATE_READY)
  781. {
  782. /* Check the parameter */
  783. assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
  784. assert_param(IS_OPAMP_FACTORYTRIMMING(trimmingoffset));
  785. assert_param(IS_OPAMP_POWERMODE(hopamp->Init.PowerMode));
  786. /* Check the trimming mode */
  787. if (READ_BIT(hopamp->Instance->CSR,OPAMP_CSR_USERTRIM)!= 0U)
  788. {
  789. /* This function must called when OPAMP init parameter "UserTrimming" */
  790. /* is set to trimming factory, and before OPAMP calibration (function */
  791. /* "HAL_OPAMP_SelfCalibrate()"). */
  792. /* Otherwise, factory trimming value cannot be retrieved and error */
  793. /* status is returned. */
  794. trimmingvalue = OPAMP_FACTORYTRIMMING_DUMMY;
  795. }
  796. else
  797. {
  798. /* Select trimming settings depending on power mode */
  799. if (hopamp->Init.PowerMode == OPAMP_POWERMODE_NORMAL)
  800. {
  801. tmp_opamp_reg_trimming = &hopamp->Instance->OTR;
  802. }
  803. else
  804. {
  805. tmp_opamp_reg_trimming = &hopamp->Instance->HSOTR;
  806. }
  807. /* Get factory trimming */
  808. if (trimmingoffset == OPAMP_FACTORYTRIMMING_P)
  809. {
  810. /* OPAMP_FACTORYTRIMMING_P */
  811. trimmingvalue = ((*tmp_opamp_reg_trimming) & OPAMP_OTR_TRIMOFFSETP) >> OPAMP_INPUT_NONINVERTING;
  812. }
  813. else
  814. {
  815. /* OPAMP_FACTORYTRIMMING_N */
  816. trimmingvalue = (*tmp_opamp_reg_trimming) & OPAMP_OTR_TRIMOFFSETN;
  817. }
  818. }
  819. }
  820. else
  821. {
  822. return OPAMP_FACTORYTRIMMING_DUMMY;
  823. }
  824. return trimmingvalue;
  825. }
  826. /**
  827. * @}
  828. */
  829. /** @defgroup OPAMP_Exported_Functions_Group4 Peripheral State functions
  830. * @brief Peripheral State functions
  831. *
  832. @verbatim
  833. ===============================================================================
  834. ##### Peripheral State functions #####
  835. ===============================================================================
  836. [..]
  837. This subsection permits to get in run-time the status of the peripheral.
  838. @endverbatim
  839. * @{
  840. */
  841. /**
  842. * @brief Return the OPAMP handle state.
  843. * @param hopamp OPAMP handle
  844. * @retval HAL state
  845. */
  846. HAL_OPAMP_StateTypeDef HAL_OPAMP_GetState(OPAMP_HandleTypeDef *hopamp)
  847. {
  848. /* Check the OPAMP handle allocation */
  849. if(hopamp == NULL)
  850. {
  851. return HAL_OPAMP_STATE_RESET;
  852. }
  853. /* Check the parameter */
  854. assert_param(IS_OPAMP_ALL_INSTANCE(hopamp->Instance));
  855. /* Return OPAMP handle state */
  856. return hopamp->State;
  857. }
  858. /**
  859. * @}
  860. */
  861. #if (USE_HAL_OPAMP_REGISTER_CALLBACKS == 1)
  862. /**
  863. * @brief Register a User OPAMP Callback
  864. * To be used instead of the weak (surcharged) predefined callback
  865. * @param hopamp OPAMP handle
  866. * @param CallbackId ID of the callback to be registered
  867. * This parameter can be one of the following values:
  868. * @arg @ref HAL_OPAMP_MSPINIT_CB_ID OPAMP MspInit callback ID
  869. * @arg @ref HAL_OPAMP_MSPDEINIT_CB_ID OPAMP MspDeInit callback ID
  870. * @param pCallback pointer to the Callback function
  871. * @retval status
  872. */
  873. HAL_StatusTypeDef HAL_OPAMP_RegisterCallback (OPAMP_HandleTypeDef *hopamp, HAL_OPAMP_CallbackIDTypeDef CallbackId, pOPAMP_CallbackTypeDef pCallback)
  874. {
  875. HAL_StatusTypeDef status = HAL_OK;
  876. if(pCallback == NULL)
  877. {
  878. return HAL_ERROR;
  879. }
  880. /* Process locked */
  881. __HAL_LOCK(hopamp);
  882. if(hopamp->State == HAL_OPAMP_STATE_READY)
  883. {
  884. switch (CallbackId)
  885. {
  886. case HAL_OPAMP_MSPINIT_CB_ID :
  887. hopamp->MspInitCallback = pCallback;
  888. break;
  889. case HAL_OPAMP_MSPDEINIT_CB_ID :
  890. hopamp->MspDeInitCallback = pCallback;
  891. break;
  892. default :
  893. /* update return status */
  894. status = HAL_ERROR;
  895. break;
  896. }
  897. }
  898. else if (hopamp->State == HAL_OPAMP_STATE_RESET)
  899. {
  900. switch (CallbackId)
  901. {
  902. case HAL_OPAMP_MSPINIT_CB_ID :
  903. hopamp->MspInitCallback = pCallback;
  904. break;
  905. case HAL_OPAMP_MSPDEINIT_CB_ID :
  906. hopamp->MspDeInitCallback = pCallback;
  907. break;
  908. default :
  909. /* update return status */
  910. status = HAL_ERROR;
  911. break;
  912. }
  913. }
  914. else
  915. {
  916. /* update return status */
  917. status = HAL_ERROR;
  918. }
  919. /* Release Lock */
  920. __HAL_UNLOCK(hopamp);
  921. return status;
  922. }
  923. /**
  924. * @brief Unregister a User OPAMP Callback
  925. * OPAMP Callback is redirected to the weak (surcharged) predefined callback
  926. * @param hopamp OPAMP handle
  927. * @param CallbackId ID of the callback to be unregistered
  928. * This parameter can be one of the following values:
  929. * @arg @ref HAL_OPAMP_MSPINIT_CB_ID OPAMP MSP Init Callback ID
  930. * @arg @ref HAL_OPAMP_MSPDEINIT_CB_ID OPAMP MSP DeInit Callback ID
  931. * @arg @ref HAL_OPAMP_ALL_CB_ID OPAMP All Callbacks
  932. * @retval status
  933. */
  934. HAL_StatusTypeDef HAL_OPAMP_UnRegisterCallback (OPAMP_HandleTypeDef *hopamp, HAL_OPAMP_CallbackIDTypeDef CallbackId)
  935. {
  936. HAL_StatusTypeDef status = HAL_OK;
  937. /* Process locked */
  938. __HAL_LOCK(hopamp);
  939. if(hopamp->State == HAL_OPAMP_STATE_READY)
  940. {
  941. switch (CallbackId)
  942. {
  943. case HAL_OPAMP_MSPINIT_CB_ID :
  944. hopamp->MspInitCallback = HAL_OPAMP_MspInit;
  945. break;
  946. case HAL_OPAMP_MSPDEINIT_CB_ID :
  947. hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit;
  948. break;
  949. case HAL_OPAMP_ALL_CB_ID :
  950. hopamp->MspInitCallback = HAL_OPAMP_MspInit;
  951. hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit;
  952. break;
  953. default :
  954. /* update return status */
  955. status = HAL_ERROR;
  956. break;
  957. }
  958. }
  959. else if (hopamp->State == HAL_OPAMP_STATE_RESET)
  960. {
  961. switch (CallbackId)
  962. {
  963. case HAL_OPAMP_MSPINIT_CB_ID :
  964. hopamp->MspInitCallback = HAL_OPAMP_MspInit;
  965. break;
  966. case HAL_OPAMP_MSPDEINIT_CB_ID :
  967. hopamp->MspDeInitCallback = HAL_OPAMP_MspDeInit;
  968. break;
  969. default :
  970. /* update return status */
  971. status = HAL_ERROR;
  972. break;
  973. }
  974. }
  975. else
  976. {
  977. /* update return status */
  978. status = HAL_ERROR;
  979. }
  980. /* Release Lock */
  981. __HAL_UNLOCK(hopamp);
  982. return status;
  983. }
  984. #endif /* USE_HAL_OPAMP_REGISTER_CALLBACKS */
  985. /**
  986. * @}
  987. */
  988. /**
  989. * @}
  990. */
  991. #endif /* HAL_OPAMP_MODULE_ENABLED */
  992. /**
  993. * @}
  994. */
  995. /**
  996. * @}
  997. */
  998. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/