summaryrefslogtreecommitdiff
path: root/Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_lptim.c
blob: 422d989f064b68648445b84a4a8dba353f0fe171 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
/**
  ******************************************************************************
  * @file    stm32h7xx_ll_lptim.c
  * @author  MCD Application Team
  * @brief   LPTIM LL module driver.
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2017 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
#if defined(USE_FULL_LL_DRIVER)

/* Includes ------------------------------------------------------------------*/
#include "stm32h7xx_ll_lptim.h"
#include "stm32h7xx_ll_bus.h"
#include "stm32h7xx_ll_rcc.h"


#ifdef  USE_FULL_ASSERT
#include "stm32_assert.h"
#else
#define assert_param(expr) ((void)0U)
#endif /* USE_FULL_ASSERT */

/** @addtogroup STM32H7xx_LL_Driver
  * @{
  */

#if defined (LPTIM1) || defined (LPTIM2) || defined (LPTIM3) || defined (LPTIM4) || defined (LPTIM5)

/** @addtogroup LPTIM_LL
  * @{
  */

/* Private types -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private constants ---------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/
/** @addtogroup LPTIM_LL_Private_Macros
  * @{
  */
#define IS_LL_LPTIM_CLOCK_SOURCE(__VALUE__) (((__VALUE__) == LL_LPTIM_CLK_SOURCE_INTERNAL) \
                                             || ((__VALUE__) == LL_LPTIM_CLK_SOURCE_EXTERNAL))

#define IS_LL_LPTIM_CLOCK_PRESCALER(__VALUE__) (((__VALUE__) == LL_LPTIM_PRESCALER_DIV1)   \
                                                || ((__VALUE__) == LL_LPTIM_PRESCALER_DIV2)   \
                                                || ((__VALUE__) == LL_LPTIM_PRESCALER_DIV4)   \
                                                || ((__VALUE__) == LL_LPTIM_PRESCALER_DIV8)   \
                                                || ((__VALUE__) == LL_LPTIM_PRESCALER_DIV16)  \
                                                || ((__VALUE__) == LL_LPTIM_PRESCALER_DIV32)  \
                                                || ((__VALUE__) == LL_LPTIM_PRESCALER_DIV64)  \
                                                || ((__VALUE__) == LL_LPTIM_PRESCALER_DIV128))

#define IS_LL_LPTIM_WAVEFORM(__VALUE__) (((__VALUE__) == LL_LPTIM_OUTPUT_WAVEFORM_PWM) \
                                         || ((__VALUE__) == LL_LPTIM_OUTPUT_WAVEFORM_SETONCE))

#define IS_LL_LPTIM_OUTPUT_POLARITY(__VALUE__) (((__VALUE__) == LL_LPTIM_OUTPUT_POLARITY_REGULAR) \
                                                || ((__VALUE__) == LL_LPTIM_OUTPUT_POLARITY_INVERSE))
/**
  * @}
  */


/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/** @defgroup LPTIM_Private_Functions LPTIM Private Functions
  * @{
  */
/**
  * @}
  */
/* Exported functions --------------------------------------------------------*/
/** @addtogroup LPTIM_LL_Exported_Functions
  * @{
  */

/** @addtogroup LPTIM_LL_EF_Init
  * @{
  */

/**
  * @brief  Set LPTIMx registers to their reset values.
  * @param  LPTIMx LP Timer instance
  * @retval An ErrorStatus enumeration value:
  *          - SUCCESS: LPTIMx registers are de-initialized
  *          - ERROR: invalid LPTIMx instance
  */
ErrorStatus LL_LPTIM_DeInit(LPTIM_TypeDef *LPTIMx)
{
  ErrorStatus result = SUCCESS;

  /* Check the parameters */
  assert_param(IS_LPTIM_INSTANCE(LPTIMx));

  if (LPTIMx == LPTIM1)
  {
    LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_LPTIM1);
    LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_LPTIM1);
  }
  else if (LPTIMx == LPTIM2)
  {
    LL_APB4_GRP1_ForceReset(LL_APB4_GRP1_PERIPH_LPTIM2);
    LL_APB4_GRP1_ReleaseReset(LL_APB4_GRP1_PERIPH_LPTIM2);
  }
#if defined(LPTIM3)
  else if (LPTIMx == LPTIM3)
  {
    LL_APB4_GRP1_ForceReset(LL_APB4_GRP1_PERIPH_LPTIM3);
    LL_APB4_GRP1_ReleaseReset(LL_APB4_GRP1_PERIPH_LPTIM3);
  }
#endif /* LPTIM3 */
#if defined(LPTIM4)
  else if (LPTIMx == LPTIM4)
  {
    LL_APB4_GRP1_ForceReset(LL_APB4_GRP1_PERIPH_LPTIM4);
    LL_APB4_GRP1_ReleaseReset(LL_APB4_GRP1_PERIPH_LPTIM4);
  }
#endif /* LPTIM4 */
#if defined(LPTIM5)
  else if (LPTIMx == LPTIM5)
  {
    LL_APB4_GRP1_ForceReset(LL_APB4_GRP1_PERIPH_LPTIM5);
    LL_APB4_GRP1_ReleaseReset(LL_APB4_GRP1_PERIPH_LPTIM5);
  }
#endif /* LPTIM5 */
  else
  {
    result = ERROR;
  }

  return result;
}

/**
  * @brief  Set each fields of the LPTIM_InitStruct structure to its default
  *         value.
  * @param  LPTIM_InitStruct pointer to a @ref LL_LPTIM_InitTypeDef structure
  * @retval None
  */
void LL_LPTIM_StructInit(LL_LPTIM_InitTypeDef *LPTIM_InitStruct)
{
  /* Set the default configuration */
  LPTIM_InitStruct->ClockSource = LL_LPTIM_CLK_SOURCE_INTERNAL;
  LPTIM_InitStruct->Prescaler   = LL_LPTIM_PRESCALER_DIV1;
  LPTIM_InitStruct->Waveform    = LL_LPTIM_OUTPUT_WAVEFORM_PWM;
  LPTIM_InitStruct->Polarity    = LL_LPTIM_OUTPUT_POLARITY_REGULAR;
}

/**
  * @brief  Configure the LPTIMx peripheral according to the specified parameters.
  * @note LL_LPTIM_Init can only be called when the LPTIM instance is disabled.
  * @note LPTIMx can be disabled using unitary function @ref LL_LPTIM_Disable().
  * @param  LPTIMx LP Timer Instance
  * @param  LPTIM_InitStruct pointer to a @ref LL_LPTIM_InitTypeDef structure
  * @retval An ErrorStatus enumeration value:
  *          - SUCCESS: LPTIMx instance has been initialized
  *          - ERROR: LPTIMx instance hasn't been initialized
  */
ErrorStatus LL_LPTIM_Init(LPTIM_TypeDef *LPTIMx, const LL_LPTIM_InitTypeDef *LPTIM_InitStruct)
{
  ErrorStatus result = SUCCESS;
  /* Check the parameters */
  assert_param(IS_LPTIM_INSTANCE(LPTIMx));
  assert_param(IS_LL_LPTIM_CLOCK_SOURCE(LPTIM_InitStruct->ClockSource));
  assert_param(IS_LL_LPTIM_CLOCK_PRESCALER(LPTIM_InitStruct->Prescaler));
  assert_param(IS_LL_LPTIM_WAVEFORM(LPTIM_InitStruct->Waveform));
  assert_param(IS_LL_LPTIM_OUTPUT_POLARITY(LPTIM_InitStruct->Polarity));

  /* The LPTIMx_CFGR register must only be modified when the LPTIM is disabled
     (ENABLE bit is reset to 0).
  */
  if (LL_LPTIM_IsEnabled(LPTIMx) == 1UL)
  {
    result = ERROR;
  }
  else
  {
    /* Set CKSEL bitfield according to ClockSource value */
    /* Set PRESC bitfield according to Prescaler value */
    /* Set WAVE bitfield according to Waveform value */
    /* Set WAVEPOL bitfield according to Polarity value */
    MODIFY_REG(LPTIMx->CFGR,
               (LPTIM_CFGR_CKSEL | LPTIM_CFGR_PRESC | LPTIM_CFGR_WAVE | LPTIM_CFGR_WAVPOL),
               LPTIM_InitStruct->ClockSource | \
               LPTIM_InitStruct->Prescaler | \
               LPTIM_InitStruct->Waveform | \
               LPTIM_InitStruct->Polarity);
  }

  return result;
}

/**
  * @brief  Disable the LPTIM instance
  * @rmtoll CR           ENABLE        LL_LPTIM_Disable
  * @param  LPTIMx Low-Power Timer instance
  * @note   The following sequence is required to solve LPTIM disable HW limitation.
  *         Please check Errata Sheet ES0335 for more details under "MCU may remain
  *         stuck in LPTIM interrupt when entering Stop mode" section.
  * @retval None
  */
void LL_LPTIM_Disable(LPTIM_TypeDef *LPTIMx)
{
  LL_RCC_ClocksTypeDef rcc_clock;
  uint32_t tmpclksource = 0;
  uint32_t tmpIER;
  uint32_t tmpCFGR;
  uint32_t tmpCMP;
  uint32_t tmpARR;
  uint32_t primask_bit;
  uint32_t tmpCFGR2;

  /* Check the parameters */
  assert_param(IS_LPTIM_INSTANCE(LPTIMx));

  /* Enter critical section */
  primask_bit = __get_PRIMASK();
  __set_PRIMASK(1) ;

  /********** Save LPTIM Config *********/
  /* Save LPTIM source clock */
  switch ((uint32_t)LPTIMx)
  {
    case LPTIM1_BASE:
      tmpclksource = LL_RCC_GetLPTIMClockSource(LL_RCC_LPTIM1_CLKSOURCE);
      break;
    case LPTIM2_BASE:
      tmpclksource = LL_RCC_GetLPTIMClockSource(LL_RCC_LPTIM2_CLKSOURCE);
      break;
#if defined(LPTIM3)&&defined(LPTIM4)&&defined(LPTIM5)
    case LPTIM3_BASE:
    case LPTIM4_BASE:
    case LPTIM5_BASE:
      tmpclksource = LL_RCC_GetLPTIMClockSource(LL_RCC_LPTIM345_CLKSOURCE);
      break;
#elif defined(LPTIM3)
    case LPTIM3_BASE:
      tmpclksource = LL_RCC_GetLPTIMClockSource(LL_RCC_LPTIM3_CLKSOURCE);
      break;
#endif /* LPTIM3 && LPTIM4 && LPTIM5 */
    default:
      break;
  }

  /* Save LPTIM configuration registers */
  tmpIER = LPTIMx->IER;
  tmpCFGR = LPTIMx->CFGR;
  tmpCMP = LPTIMx->CMP;
  tmpARR = LPTIMx->ARR;
  tmpCFGR2 = LPTIMx->CFGR2;

  /************* Reset LPTIM ************/
  (void)LL_LPTIM_DeInit(LPTIMx);

  /********* Restore LPTIM Config *******/
  LL_RCC_GetSystemClocksFreq(&rcc_clock);

  if ((tmpCMP != 0UL) || (tmpARR != 0UL))
  {
    /* Force LPTIM source kernel clock from APB */
    switch ((uint32_t)LPTIMx)
    {
      case LPTIM1_BASE:
        LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM1_CLKSOURCE_PCLK1);
        break;
      case LPTIM2_BASE:
        LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM2_CLKSOURCE_PCLK4);
        break;
#if defined(LPTIM3)&&defined(LPTIM4)&&defined(LPTIM5)
      case LPTIM3_BASE:
      case LPTIM4_BASE:
      case LPTIM5_BASE:
        LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM345_CLKSOURCE_PCLK4);
        break;
#elif defined(LPTIM3)
      case LPTIM3_BASE:
        LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM3_CLKSOURCE_PCLK4);
        break;
#endif /* LPTIM3 && LPTIM4 && LPTIM5*/
      default:
        break;
    }

    if (tmpCMP != 0UL)
    {
      /* Restore CMP and ARR registers (LPTIM should be enabled first) */
      LPTIMx->CR |= LPTIM_CR_ENABLE;
      LPTIMx->CMP = tmpCMP;

      /* Polling on CMP write ok status after above restore operation */
      do
      {
        rcc_clock.SYSCLK_Frequency--; /* Used for timeout */
      } while (((LL_LPTIM_IsActiveFlag_CMPOK(LPTIMx) != 1UL)) && ((rcc_clock.SYSCLK_Frequency) > 0UL));

      LL_LPTIM_ClearFlag_CMPOK(LPTIMx);
    }

    if (tmpARR != 0UL)
    {
      LPTIMx->CR |= LPTIM_CR_ENABLE;
      LPTIMx->ARR = tmpARR;

      LL_RCC_GetSystemClocksFreq(&rcc_clock);
      /* Polling on ARR write ok status after above restore operation */
      do
      {
        rcc_clock.SYSCLK_Frequency--; /* Used for timeout */
      } while (((LL_LPTIM_IsActiveFlag_ARROK(LPTIMx) != 1UL)) && ((rcc_clock.SYSCLK_Frequency) > 0UL));

      LL_LPTIM_ClearFlag_ARROK(LPTIMx);
    }


    /* Restore LPTIM source kernel clock */
    LL_RCC_SetLPTIMClockSource(tmpclksource);
  }

  /* Restore configuration registers (LPTIM should be disabled first) */
  LPTIMx->CR &= ~(LPTIM_CR_ENABLE);
  LPTIMx->IER = tmpIER;
  LPTIMx->CFGR = tmpCFGR;
  LPTIMx->CFGR2 = tmpCFGR2;

  /* Exit critical section: restore previous priority mask */
  __set_PRIMASK(primask_bit);
}

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

#endif /* LPTIM1 || LPTIM2 ||  LPTIM3 || LPTIM4 || LPTIM5 */

/**
  * @}
  */

#endif /* USE_FULL_LL_DRIVER */