эх как она работает...

This commit is contained in:
2022-02-02 16:23:29 +03:00
parent e2d6f639e8
commit b5c77d2b7c
70 changed files with 38010 additions and 55590 deletions

View File

@@ -1,764 +0,0 @@
/**
******************************************************************************
* @file stm32l4xx_hal.c
* @author MCD Application Team
* @brief HAL module driver.
* This is the common part of the HAL initialization
*
******************************************************************************
* @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.
*
******************************************************************************
@verbatim
==============================================================================
##### How to use this driver #####
==============================================================================
[..]
The common HAL driver contains a set of generic and common APIs that can be
used by the PPP peripheral drivers and the user to start using the HAL.
[..]
The HAL contains two APIs' categories:
(+) Common HAL APIs
(+) Services HAL APIs
@endverbatim
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32l4xx_hal.h"
/** @addtogroup STM32L4xx_HAL_Driver
* @{
*/
/** @defgroup HAL HAL
* @brief HAL module driver
* @{
*/
#ifdef HAL_MODULE_ENABLED
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/**
* @brief STM32L4xx HAL Driver version number
*/
#define STM32L4XX_HAL_VERSION_MAIN (0x01U) /*!< [31:24] main version */
#define STM32L4XX_HAL_VERSION_SUB1 (0x0DU) /*!< [23:16] sub1 version */
#define STM32L4XX_HAL_VERSION_SUB2 (0x02U) /*!< [15:8] sub2 version */
#define STM32L4XX_HAL_VERSION_RC (0x00U) /*!< [7:0] release candidate */
#define STM32L4XX_HAL_VERSION ((STM32L4XX_HAL_VERSION_MAIN << 24U)\
|(STM32L4XX_HAL_VERSION_SUB1 << 16U)\
|(STM32L4XX_HAL_VERSION_SUB2 << 8U)\
|(STM32L4XX_HAL_VERSION_RC))
#if defined(VREFBUF)
#define VREFBUF_TIMEOUT_VALUE 10U /* 10 ms (to be confirmed) */
#endif /* VREFBUF */
/* ------------ SYSCFG registers bit address in the alias region ------------ */
#define SYSCFG_OFFSET (SYSCFG_BASE - PERIPH_BASE)
/* --- MEMRMP Register ---*/
/* Alias word address of FB_MODE bit */
#define MEMRMP_OFFSET SYSCFG_OFFSET
#define FB_MODE_BitNumber 8U
#define FB_MODE_BB (PERIPH_BB_BASE + (MEMRMP_OFFSET * 32U) + (FB_MODE_BitNumber * 4U))
/* --- SCSR Register ---*/
/* Alias word address of SRAM2ER bit */
#define SCSR_OFFSET (SYSCFG_OFFSET + 0x18U)
#define BRER_BitNumber 0U
#define SCSR_SRAM2ER_BB (PERIPH_BB_BASE + (SCSR_OFFSET * 32U) + (BRER_BitNumber * 4U))
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Exported variables --------------------------------------------------------*/
/** @defgroup HAL_Exported_Variables HAL Exported Variables
* @{
*/
__IO uint32_t uwTick;
uint32_t uwTickPrio = (1UL << __NVIC_PRIO_BITS); /* Invalid priority */
HAL_TickFreqTypeDef uwTickFreq = HAL_TICK_FREQ_DEFAULT; /* 1KHz */
/**
* @}
*/
/* Exported functions --------------------------------------------------------*/
/** @defgroup HAL_Exported_Functions HAL Exported Functions
* @{
*/
/** @defgroup HAL_Exported_Functions_Group1 Initialization and de-initialization Functions
* @brief Initialization and de-initialization functions
*
@verbatim
===============================================================================
##### Initialization and de-initialization functions #####
===============================================================================
[..] This section provides functions allowing to:
(+) Initialize the Flash interface, the NVIC allocation and initial time base
clock configuration.
(+) De-initialize common part of the HAL.
(+) Configure the time base source to have 1ms time base with a dedicated
Tick interrupt priority.
(++) SysTick timer is used by default as source of time base, but user
can eventually implement his proper time base source (a general purpose
timer for example or other time source), keeping in mind that Time base
duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
handled in milliseconds basis.
(++) Time base configuration function (HAL_InitTick ()) is called automatically
at the beginning of the program after reset by HAL_Init() or at any time
when clock is configured, by HAL_RCC_ClockConfig().
(++) Source of time base is configured to generate interrupts at regular
time intervals. Care must be taken if HAL_Delay() is called from a
peripheral ISR process, the Tick interrupt line must have higher priority
(numerically lower) than the peripheral interrupt. Otherwise the caller
ISR process will be blocked.
(++) functions affecting time base configurations are declared as __weak
to make override possible in case of other implementations in user file.
@endverbatim
* @{
*/
/**
* @brief Configure the Flash prefetch, the Instruction and Data caches,
* the time base source, NVIC and any required global low level hardware
* by calling the HAL_MspInit() callback function to be optionally defined in user file
* stm32l4xx_hal_msp.c.
*
* @note HAL_Init() function is called at the beginning of program after reset and before
* the clock configuration.
*
* @note In the default implementation the System Timer (Systick) is used as source of time base.
* The Systick configuration is based on MSI clock, as MSI is the clock
* used after a system Reset and the NVIC configuration is set to Priority group 4.
* Once done, time base tick starts incrementing: the tick variable counter is incremented
* each 1ms in the SysTick_Handler() interrupt handler.
*
* @retval HAL status
*/
HAL_StatusTypeDef HAL_Init(void)
{
HAL_StatusTypeDef status = HAL_OK;
/* Configure Flash prefetch, Instruction cache, Data cache */
/* Default configuration at reset is: */
/* - Prefetch disabled */
/* - Instruction cache enabled */
/* - Data cache enabled */
#if (INSTRUCTION_CACHE_ENABLE == 0)
__HAL_FLASH_INSTRUCTION_CACHE_DISABLE();
#endif /* INSTRUCTION_CACHE_ENABLE */
#if (DATA_CACHE_ENABLE == 0)
__HAL_FLASH_DATA_CACHE_DISABLE();
#endif /* DATA_CACHE_ENABLE */
#if (PREFETCH_ENABLE != 0)
__HAL_FLASH_PREFETCH_BUFFER_ENABLE();
#endif /* PREFETCH_ENABLE */
/* Set Interrupt Group Priority */
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
/* Use SysTick as time base source and configure 1ms tick (default clock after Reset is MSI) */
if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK)
{
status = HAL_ERROR;
}
else
{
/* Init the low level hardware */
HAL_MspInit();
}
/* Return function status */
return status;
}
/**
* @brief De-initialize common part of the HAL and stop the source of time base.
* @note This function is optional.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_DeInit(void)
{
/* Reset of all peripherals */
__HAL_RCC_APB1_FORCE_RESET();
__HAL_RCC_APB1_RELEASE_RESET();
__HAL_RCC_APB2_FORCE_RESET();
__HAL_RCC_APB2_RELEASE_RESET();
__HAL_RCC_AHB1_FORCE_RESET();
__HAL_RCC_AHB1_RELEASE_RESET();
__HAL_RCC_AHB2_FORCE_RESET();
__HAL_RCC_AHB2_RELEASE_RESET();
__HAL_RCC_AHB3_FORCE_RESET();
__HAL_RCC_AHB3_RELEASE_RESET();
/* De-Init the low level hardware */
HAL_MspDeInit();
/* Return function status */
return HAL_OK;
}
/**
* @brief Initialize the MSP.
* @retval None
*/
__weak void HAL_MspInit(void)
{
/* NOTE : This function should not be modified, when the callback is needed,
the HAL_MspInit could be implemented in the user file
*/
}
/**
* @brief DeInitialize the MSP.
* @retval None
*/
__weak void HAL_MspDeInit(void)
{
/* NOTE : This function should not be modified, when the callback is needed,
the HAL_MspDeInit could be implemented in the user file
*/
}
/**
* @brief This function configures the source of the time base:
* The time source is configured to have 1ms time base with a dedicated
* Tick interrupt priority.
* @note This function is called automatically at the beginning of program after
* reset by HAL_Init() or at any time when clock is reconfigured by HAL_RCC_ClockConfig().
* @note In the default implementation, SysTick timer is the source of time base.
* It is used to generate interrupts at regular time intervals.
* Care must be taken if HAL_Delay() is called from a peripheral ISR process,
* The SysTick interrupt must have higher priority (numerically lower)
* than the peripheral interrupt. Otherwise the caller ISR process will be blocked.
* The function is declared as __weak to be overwritten in case of other
* implementation in user file.
* @param TickPriority Tick interrupt priority.
* @retval HAL status
*/
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check uwTickFreq for MisraC 2012 (even if uwTickFreq is a enum type that doesn't take the value zero)*/
if ((uint32_t)uwTickFreq != 0U)
{
/*Configure the SysTick to have interrupt in 1ms time basis*/
if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / (uint32_t)uwTickFreq)) == 0U)
{
/* Configure the SysTick IRQ priority */
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
{
HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
uwTickPrio = TickPriority;
}
else
{
status = HAL_ERROR;
}
}
else
{
status = HAL_ERROR;
}
}
else
{
status = HAL_ERROR;
}
/* Return function status */
return status;
}
/**
* @}
*/
/** @defgroup HAL_Exported_Functions_Group2 HAL Control functions
* @brief HAL Control functions
*
@verbatim
===============================================================================
##### HAL Control functions #####
===============================================================================
[..] This section provides functions allowing to:
(+) Provide a tick value in millisecond
(+) Provide a blocking delay in millisecond
(+) Suspend the time base source interrupt
(+) Resume the time base source interrupt
(+) Get the HAL API driver version
(+) Get the device identifier
(+) Get the device revision identifier
@endverbatim
* @{
*/
/**
* @brief This function is called to increment a global variable "uwTick"
* used as application time base.
* @note In the default implementation, this variable is incremented each 1ms
* in SysTick ISR.
* @note This function is declared as __weak to be overwritten in case of other
* implementations in user file.
* @retval None
*/
__weak void HAL_IncTick(void)
{
uwTick += (uint32_t)uwTickFreq;
}
/**
* @brief Provide a tick value in millisecond.
* @note This function is declared as __weak to be overwritten in case of other
* implementations in user file.
* @retval tick value
*/
__weak uint32_t HAL_GetTick(void)
{
return uwTick;
}
/**
* @brief This function returns a tick priority.
* @retval tick priority
*/
uint32_t HAL_GetTickPrio(void)
{
return uwTickPrio;
}
/**
* @brief Set new tick Freq.
* @param Freq tick frequency
* @retval HAL status
*/
HAL_StatusTypeDef HAL_SetTickFreq(HAL_TickFreqTypeDef Freq)
{
HAL_StatusTypeDef status = HAL_OK;
HAL_TickFreqTypeDef prevTickFreq;
if (uwTickFreq != Freq)
{
/* Back up uwTickFreq frequency */
prevTickFreq = uwTickFreq;
/* Update uwTickFreq global variable used by HAL_InitTick() */
uwTickFreq = Freq;
/* Apply the new tick Freq */
status = HAL_InitTick(uwTickPrio);
if (status != HAL_OK)
{
/* Restore previous tick frequency */
uwTickFreq = prevTickFreq;
}
}
return status;
}
/**
* @brief Return tick frequency.
* @retval tick period in Hz
*/
HAL_TickFreqTypeDef HAL_GetTickFreq(void)
{
return uwTickFreq;
}
/**
* @brief This function provides minimum delay (in milliseconds) based
* on variable incremented.
* @note In the default implementation , SysTick timer is the source of time base.
* It is used to generate interrupts at regular time intervals where uwTick
* is incremented.
* @note This function is declared as __weak to be overwritten in case of other
* implementations in user file.
* @param Delay specifies the delay time length, in milliseconds.
* @retval None
*/
__weak void HAL_Delay(uint32_t Delay)
{
uint32_t tickstart = HAL_GetTick();
uint32_t wait = Delay;
/* Add a period to guaranty minimum wait */
if (wait < HAL_MAX_DELAY)
{
wait += (uint32_t)uwTickFreq;
}
while ((HAL_GetTick() - tickstart) < wait)
{
}
}
/**
* @brief Suspend Tick increment.
* @note In the default implementation , SysTick timer is the source of time base. It is
* used to generate interrupts at regular time intervals. Once HAL_SuspendTick()
* is called, the SysTick interrupt will be disabled and so Tick increment
* is suspended.
* @note This function is declared as __weak to be overwritten in case of other
* implementations in user file.
* @retval None
*/
__weak void HAL_SuspendTick(void)
{
/* Disable SysTick Interrupt */
SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;
}
/**
* @brief Resume Tick increment.
* @note In the default implementation , SysTick timer is the source of time base. It is
* used to generate interrupts at regular time intervals. Once HAL_ResumeTick()
* is called, the SysTick interrupt will be enabled and so Tick increment
* is resumed.
* @note This function is declared as __weak to be overwritten in case of other
* implementations in user file.
* @retval None
*/
__weak void HAL_ResumeTick(void)
{
/* Enable SysTick Interrupt */
SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;
}
/**
* @brief Return the HAL revision.
* @retval version : 0xXYZR (8bits for each decimal, R for RC)
*/
uint32_t HAL_GetHalVersion(void)
{
return STM32L4XX_HAL_VERSION;
}
/**
* @brief Return the device revision identifier.
* @retval Device revision identifier
*/
uint32_t HAL_GetREVID(void)
{
return((DBGMCU->IDCODE & DBGMCU_IDCODE_REV_ID) >> 16);
}
/**
* @brief Return the device identifier.
* @retval Device identifier
*/
uint32_t HAL_GetDEVID(void)
{
return(DBGMCU->IDCODE & DBGMCU_IDCODE_DEV_ID);
}
/**
* @brief Return the first word of the unique device identifier (UID based on 96 bits)
* @retval Device identifier
*/
uint32_t HAL_GetUIDw0(void)
{
return(READ_REG(*((uint32_t *)UID_BASE)));
}
/**
* @brief Return the second word of the unique device identifier (UID based on 96 bits)
* @retval Device identifier
*/
uint32_t HAL_GetUIDw1(void)
{
return(READ_REG(*((uint32_t *)(UID_BASE + 4U))));
}
/**
* @brief Return the third word of the unique device identifier (UID based on 96 bits)
* @retval Device identifier
*/
uint32_t HAL_GetUIDw2(void)
{
return(READ_REG(*((uint32_t *)(UID_BASE + 8U))));
}
/**
* @}
*/
/** @defgroup HAL_Exported_Functions_Group3 HAL Debug functions
* @brief HAL Debug functions
*
@verbatim
===============================================================================
##### HAL Debug functions #####
===============================================================================
[..] This section provides functions allowing to:
(+) Enable/Disable Debug module during SLEEP mode
(+) Enable/Disable Debug module during STOP0/STOP1/STOP2 modes
(+) Enable/Disable Debug module during STANDBY mode
@endverbatim
* @{
*/
/**
* @brief Enable the Debug Module during SLEEP mode.
* @retval None
*/
void HAL_DBGMCU_EnableDBGSleepMode(void)
{
SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_SLEEP);
}
/**
* @brief Disable the Debug Module during SLEEP mode.
* @retval None
*/
void HAL_DBGMCU_DisableDBGSleepMode(void)
{
CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_SLEEP);
}
/**
* @brief Enable the Debug Module during STOP0/STOP1/STOP2 modes.
* @retval None
*/
void HAL_DBGMCU_EnableDBGStopMode(void)
{
SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOP);
}
/**
* @brief Disable the Debug Module during STOP0/STOP1/STOP2 modes.
* @retval None
*/
void HAL_DBGMCU_DisableDBGStopMode(void)
{
CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STOP);
}
/**
* @brief Enable the Debug Module during STANDBY mode.
* @retval None
*/
void HAL_DBGMCU_EnableDBGStandbyMode(void)
{
SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBY);
}
/**
* @brief Disable the Debug Module during STANDBY mode.
* @retval None
*/
void HAL_DBGMCU_DisableDBGStandbyMode(void)
{
CLEAR_BIT(DBGMCU->CR, DBGMCU_CR_DBG_STANDBY);
}
/**
* @}
*/
/** @defgroup HAL_Exported_Functions_Group4 HAL SYSCFG configuration functions
* @brief HAL SYSCFG configuration functions
*
@verbatim
===============================================================================
##### HAL SYSCFG configuration functions #####
===============================================================================
[..] This section provides functions allowing to:
(+) Start a hardware SRAM2 erase operation
(+) Enable/Disable the Internal FLASH Bank Swapping
(+) Configure the Voltage reference buffer
(+) Enable/Disable the Voltage reference buffer
(+) Enable/Disable the I/O analog switch voltage booster
@endverbatim
* @{
*/
/**
* @brief Start a hardware SRAM2 erase operation.
* @note As long as SRAM2 is not erased the SRAM2ER bit will be set.
* This bit is automatically reset at the end of the SRAM2 erase operation.
* @retval None
*/
void HAL_SYSCFG_SRAM2Erase(void)
{
/* unlock the write protection of the SRAM2ER bit */
SYSCFG->SKR = 0xCA;
SYSCFG->SKR = 0x53;
/* Starts a hardware SRAM2 erase operation*/
*(__IO uint32_t *) SCSR_SRAM2ER_BB = 0x00000001UL;
}
/**
* @brief Enable the Internal FLASH Bank Swapping.
*
* @note This function can be used only for STM32L4xx devices.
*
* @note Flash Bank2 mapped at 0x08000000 (and aliased @0x00000000)
* and Flash Bank1 mapped at 0x08100000 (and aliased at 0x00100000)
*
* @retval None
*/
void HAL_SYSCFG_EnableMemorySwappingBank(void)
{
*(__IO uint32_t *)FB_MODE_BB = 0x00000001UL;
}
/**
* @brief Disable the Internal FLASH Bank Swapping.
*
* @note This function can be used only for STM32L4xx devices.
*
* @note The default state : Flash Bank1 mapped at 0x08000000 (and aliased @0x0000 0000)
* and Flash Bank2 mapped at 0x08100000 (and aliased at 0x00100000)
*
* @retval None
*/
void HAL_SYSCFG_DisableMemorySwappingBank(void)
{
*(__IO uint32_t *)FB_MODE_BB = 0x00000000UL;
}
#if defined(VREFBUF)
/**
* @brief Configure the internal voltage reference buffer voltage scale.
* @param VoltageScaling specifies the output voltage to achieve
* This parameter can be one of the following values:
* @arg SYSCFG_VREFBUF_VOLTAGE_SCALE0: VREF_OUT1 around 2.048 V.
* This requires VDDA equal to or higher than 2.4 V.
* @arg SYSCFG_VREFBUF_VOLTAGE_SCALE1: VREF_OUT2 around 2.5 V.
* This requires VDDA equal to or higher than 2.8 V.
* @retval None
*/
void HAL_SYSCFG_VREFBUF_VoltageScalingConfig(uint32_t VoltageScaling)
{
/* Check the parameters */
assert_param(IS_SYSCFG_VREFBUF_VOLTAGE_SCALE(VoltageScaling));
MODIFY_REG(VREFBUF->CSR, VREFBUF_CSR_VRS, VoltageScaling);
}
/**
* @brief Configure the internal voltage reference buffer high impedance mode.
* @param Mode specifies the high impedance mode
* This parameter can be one of the following values:
* @arg SYSCFG_VREFBUF_HIGH_IMPEDANCE_DISABLE: VREF+ pin is internally connect to VREFINT output.
* @arg SYSCFG_VREFBUF_HIGH_IMPEDANCE_ENABLE: VREF+ pin is high impedance.
* @retval None
*/
void HAL_SYSCFG_VREFBUF_HighImpedanceConfig(uint32_t Mode)
{
/* Check the parameters */
assert_param(IS_SYSCFG_VREFBUF_HIGH_IMPEDANCE(Mode));
MODIFY_REG(VREFBUF->CSR, VREFBUF_CSR_HIZ, Mode);
}
/**
* @brief Tune the Internal Voltage Reference buffer (VREFBUF).
* @retval None
*/
void HAL_SYSCFG_VREFBUF_TrimmingConfig(uint32_t TrimmingValue)
{
/* Check the parameters */
assert_param(IS_SYSCFG_VREFBUF_TRIMMING(TrimmingValue));
MODIFY_REG(VREFBUF->CCR, VREFBUF_CCR_TRIM, TrimmingValue);
}
/**
* @brief Enable the Internal Voltage Reference buffer (VREFBUF).
* @retval HAL_OK/HAL_TIMEOUT
*/
HAL_StatusTypeDef HAL_SYSCFG_EnableVREFBUF(void)
{
uint32_t tickstart;
SET_BIT(VREFBUF->CSR, VREFBUF_CSR_ENVR);
/* Get Start Tick*/
tickstart = HAL_GetTick();
/* Wait for VRR bit */
while(READ_BIT(VREFBUF->CSR, VREFBUF_CSR_VRR) == 0U)
{
if((HAL_GetTick() - tickstart) > VREFBUF_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
return HAL_OK;
}
/**
* @brief Disable the Internal Voltage Reference buffer (VREFBUF).
*
* @retval None
*/
void HAL_SYSCFG_DisableVREFBUF(void)
{
CLEAR_BIT(VREFBUF->CSR, VREFBUF_CSR_ENVR);
}
#endif /* VREFBUF */
/**
* @brief Enable the I/O analog switch voltage booster
*
* @retval None
*/
void HAL_SYSCFG_EnableIOAnalogSwitchBooster(void)
{
SET_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_BOOSTEN);
}
/**
* @brief Disable the I/O analog switch voltage booster
*
* @retval None
*/
void HAL_SYSCFG_DisableIOAnalogSwitchBooster(void)
{
CLEAR_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_BOOSTEN);
}
/**
* @}
*/
/**
* @}
*/
#endif /* HAL_MODULE_ENABLED */
/**
* @}
*/
/**
* @}
*/

View File

@@ -1,517 +0,0 @@
/**
******************************************************************************
* @file stm32l4xx_hal_cortex.c
* @author MCD Application Team
* @brief CORTEX HAL module driver.
* This file provides firmware functions to manage the following
* functionalities of the CORTEX:
* + Initialization and Configuration functions
* + Peripheral Control functions
*
@verbatim
==============================================================================
##### How to use this driver #####
==============================================================================
[..]
*** How to configure Interrupts using CORTEX HAL driver ***
===========================================================
[..]
This section provides functions allowing to configure the NVIC interrupts (IRQ).
The Cortex-M4 exceptions are managed by CMSIS functions.
(#) Configure the NVIC Priority Grouping using HAL_NVIC_SetPriorityGrouping() function.
(#) Configure the priority of the selected IRQ Channels using HAL_NVIC_SetPriority().
(#) Enable the selected IRQ Channels using HAL_NVIC_EnableIRQ().
-@- When the NVIC_PRIORITYGROUP_0 is selected, IRQ pre-emption is no more possible.
The pending IRQ priority will be managed only by the sub priority.
-@- IRQ priority order (sorted by highest to lowest priority):
(+@) Lowest pre-emption priority
(+@) Lowest sub priority
(+@) Lowest hardware priority (IRQ number)
[..]
*** How to configure SysTick using CORTEX HAL driver ***
========================================================
[..]
Setup SysTick Timer for time base.
(+) The HAL_SYSTICK_Config() function calls the SysTick_Config() function which
is a CMSIS function that:
(++) Configures the SysTick Reload register with value passed as function parameter.
(++) Configures the SysTick IRQ priority to the lowest value (0x0F).
(++) Resets the SysTick Counter register.
(++) Configures the SysTick Counter clock source to be Core Clock Source (HCLK).
(++) Enables the SysTick Interrupt.
(++) Starts the SysTick Counter.
(+) You can change the SysTick Clock source to be HCLK_Div8 by calling the macro
__HAL_CORTEX_SYSTICKCLK_CONFIG(SYSTICK_CLKSOURCE_HCLK_DIV8) just after the
HAL_SYSTICK_Config() function call. The __HAL_CORTEX_SYSTICKCLK_CONFIG() macro is defined
inside the stm32l4xx_hal_cortex.h file.
(+) You can change the SysTick IRQ priority by calling the
HAL_NVIC_SetPriority(SysTick_IRQn,...) function just after the HAL_SYSTICK_Config() function
call. The HAL_NVIC_SetPriority() call the NVIC_SetPriority() function which is a CMSIS function.
(+) To adjust the SysTick time base, use the following formula:
Reload Value = SysTick Counter Clock (Hz) x Desired Time base (s)
(++) Reload Value is the parameter to be passed for HAL_SYSTICK_Config() function
(++) Reload Value should not exceed 0xFFFFFF
@endverbatim
******************************************************************************
The table below gives the allowed values of the pre-emption priority and subpriority according
to the Priority Grouping configuration performed by HAL_NVIC_SetPriorityGrouping() function.
==========================================================================================================================
NVIC_PriorityGroup | NVIC_IRQChannelPreemptionPriority | NVIC_IRQChannelSubPriority | Description
==========================================================================================================================
NVIC_PRIORITYGROUP_0 | 0 | 0-15 | 0 bit for pre-emption priority
| | | 4 bits for subpriority
--------------------------------------------------------------------------------------------------------------------------
NVIC_PRIORITYGROUP_1 | 0-1 | 0-7 | 1 bit for pre-emption priority
| | | 3 bits for subpriority
--------------------------------------------------------------------------------------------------------------------------
NVIC_PRIORITYGROUP_2 | 0-3 | 0-3 | 2 bits for pre-emption priority
| | | 2 bits for subpriority
--------------------------------------------------------------------------------------------------------------------------
NVIC_PRIORITYGROUP_3 | 0-7 | 0-1 | 3 bits for pre-emption priority
| | | 1 bit for subpriority
--------------------------------------------------------------------------------------------------------------------------
NVIC_PRIORITYGROUP_4 | 0-15 | 0 | 4 bits for pre-emption priority
| | | 0 bit for subpriority
==========================================================================================================================
******************************************************************************
* @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.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32l4xx_hal.h"
/** @addtogroup STM32L4xx_HAL_Driver
* @{
*/
/** @addtogroup CORTEX
* @{
*/
#ifdef HAL_CORTEX_MODULE_ENABLED
/* Private types -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private constants ---------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/** @addtogroup CORTEX_Exported_Functions
* @{
*/
/** @addtogroup CORTEX_Exported_Functions_Group1
* @brief Initialization and Configuration functions
*
@verbatim
==============================================================================
##### Initialization and Configuration functions #####
==============================================================================
[..]
This section provides the CORTEX HAL driver functions allowing to configure Interrupts
SysTick functionalities
@endverbatim
* @{
*/
/**
* @brief Set the priority grouping field (pre-emption priority and subpriority)
* using the required unlock sequence.
* @param PriorityGroup: The priority grouping bits length.
* This parameter can be one of the following values:
* @arg NVIC_PRIORITYGROUP_0: 0 bit for pre-emption priority,
* 4 bits for subpriority
* @arg NVIC_PRIORITYGROUP_1: 1 bit for pre-emption priority,
* 3 bits for subpriority
* @arg NVIC_PRIORITYGROUP_2: 2 bits for pre-emption priority,
* 2 bits for subpriority
* @arg NVIC_PRIORITYGROUP_3: 3 bits for pre-emption priority,
* 1 bit for subpriority
* @arg NVIC_PRIORITYGROUP_4: 4 bits for pre-emption priority,
* 0 bit for subpriority
* @note When the NVIC_PriorityGroup_0 is selected, IRQ pre-emption is no more possible.
* The pending IRQ priority will be managed only by the subpriority.
* @retval None
*/
void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
{
/* Check the parameters */
assert_param(IS_NVIC_PRIORITY_GROUP(PriorityGroup));
/* Set the PRIGROUP[10:8] bits according to the PriorityGroup parameter value */
NVIC_SetPriorityGrouping(PriorityGroup);
}
/**
* @brief Set the priority of an interrupt.
* @param IRQn: External interrupt number.
* This parameter can be an enumerator of IRQn_Type enumeration
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32l4xxxx.h))
* @param PreemptPriority: The pre-emption priority for the IRQn channel.
* This parameter can be a value between 0 and 15
* A lower priority value indicates a higher priority
* @param SubPriority: the subpriority level for the IRQ channel.
* This parameter can be a value between 0 and 15
* A lower priority value indicates a higher priority.
* @retval None
*/
void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority)
{
uint32_t prioritygroup = 0x00;
/* Check the parameters */
assert_param(IS_NVIC_SUB_PRIORITY(SubPriority));
assert_param(IS_NVIC_PREEMPTION_PRIORITY(PreemptPriority));
prioritygroup = NVIC_GetPriorityGrouping();
NVIC_SetPriority(IRQn, NVIC_EncodePriority(prioritygroup, PreemptPriority, SubPriority));
}
/**
* @brief Enable a device specific interrupt in the NVIC interrupt controller.
* @note To configure interrupts priority correctly, the NVIC_PriorityGroupConfig()
* function should be called before.
* @param IRQn External interrupt number.
* This parameter can be an enumerator of IRQn_Type enumeration
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32l4xxxx.h))
* @retval None
*/
void HAL_NVIC_EnableIRQ(IRQn_Type IRQn)
{
/* Check the parameters */
assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
/* Enable interrupt */
NVIC_EnableIRQ(IRQn);
}
/**
* @brief Disable a device specific interrupt in the NVIC interrupt controller.
* @param IRQn External interrupt number.
* This parameter can be an enumerator of IRQn_Type enumeration
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32l4xxxx.h))
* @retval None
*/
void HAL_NVIC_DisableIRQ(IRQn_Type IRQn)
{
/* Check the parameters */
assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
/* Disable interrupt */
NVIC_DisableIRQ(IRQn);
}
/**
* @brief Initiate a system reset request to reset the MCU.
* @retval None
*/
void HAL_NVIC_SystemReset(void)
{
/* System Reset */
NVIC_SystemReset();
}
/**
* @brief Initialize the System Timer with interrupt enabled and start the System Tick Timer (SysTick):
* Counter is in free running mode to generate periodic interrupts.
* @param TicksNumb: Specifies the ticks Number of ticks between two interrupts.
* @retval status: - 0 Function succeeded.
* - 1 Function failed.
*/
uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb)
{
return SysTick_Config(TicksNumb);
}
/**
* @}
*/
/** @addtogroup CORTEX_Exported_Functions_Group2
* @brief Cortex control functions
*
@verbatim
==============================================================================
##### Peripheral Control functions #####
==============================================================================
[..]
This subsection provides a set of functions allowing to control the CORTEX
(NVIC, SYSTICK, MPU) functionalities.
@endverbatim
* @{
*/
/**
* @brief Get the priority grouping field from the NVIC Interrupt Controller.
* @retval Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field)
*/
uint32_t HAL_NVIC_GetPriorityGrouping(void)
{
/* Get the PRIGROUP[10:8] field value */
return NVIC_GetPriorityGrouping();
}
/**
* @brief Get the priority of an interrupt.
* @param IRQn: External interrupt number.
* This parameter can be an enumerator of IRQn_Type enumeration
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32l4xxxx.h))
* @param PriorityGroup: the priority grouping bits length.
* This parameter can be one of the following values:
* @arg NVIC_PRIORITYGROUP_0: 0 bit for pre-emption priority,
* 4 bits for subpriority
* @arg NVIC_PRIORITYGROUP_1: 1 bit for pre-emption priority,
* 3 bits for subpriority
* @arg NVIC_PRIORITYGROUP_2: 2 bits for pre-emption priority,
* 2 bits for subpriority
* @arg NVIC_PRIORITYGROUP_3: 3 bits for pre-emption priority,
* 1 bit for subpriority
* @arg NVIC_PRIORITYGROUP_4: 4 bits for pre-emption priority,
* 0 bit for subpriority
* @param pPreemptPriority: Pointer on the Preemptive priority value (starting from 0).
* @param pSubPriority: Pointer on the Subpriority value (starting from 0).
* @retval None
*/
void HAL_NVIC_GetPriority(IRQn_Type IRQn, uint32_t PriorityGroup, uint32_t *pPreemptPriority, uint32_t *pSubPriority)
{
/* Check the parameters */
assert_param(IS_NVIC_PRIORITY_GROUP(PriorityGroup));
/* Get priority for Cortex-M system or device specific interrupts */
NVIC_DecodePriority(NVIC_GetPriority(IRQn), PriorityGroup, pPreemptPriority, pSubPriority);
}
/**
* @brief Set Pending bit of an external interrupt.
* @param IRQn External interrupt number
* This parameter can be an enumerator of IRQn_Type enumeration
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32l4xxxx.h))
* @retval None
*/
void HAL_NVIC_SetPendingIRQ(IRQn_Type IRQn)
{
/* Check the parameters */
assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
/* Set interrupt pending */
NVIC_SetPendingIRQ(IRQn);
}
/**
* @brief Get Pending Interrupt (read the pending register in the NVIC
* and return the pending bit for the specified interrupt).
* @param IRQn External interrupt number.
* This parameter can be an enumerator of IRQn_Type enumeration
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32l4xxxx.h))
* @retval status: - 0 Interrupt status is not pending.
* - 1 Interrupt status is pending.
*/
uint32_t HAL_NVIC_GetPendingIRQ(IRQn_Type IRQn)
{
/* Check the parameters */
assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
/* Return 1 if pending else 0 */
return NVIC_GetPendingIRQ(IRQn);
}
/**
* @brief Clear the pending bit of an external interrupt.
* @param IRQn External interrupt number.
* This parameter can be an enumerator of IRQn_Type enumeration
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32l4xxxx.h))
* @retval None
*/
void HAL_NVIC_ClearPendingIRQ(IRQn_Type IRQn)
{
/* Check the parameters */
assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
/* Clear pending interrupt */
NVIC_ClearPendingIRQ(IRQn);
}
/**
* @brief Get active interrupt (read the active register in NVIC and return the active bit).
* @param IRQn External interrupt number
* This parameter can be an enumerator of IRQn_Type enumeration
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32l4xxxx.h))
* @retval status: - 0 Interrupt status is not pending.
* - 1 Interrupt status is pending.
*/
uint32_t HAL_NVIC_GetActive(IRQn_Type IRQn)
{
/* Return 1 if active else 0 */
return NVIC_GetActive(IRQn);
}
/**
* @brief Configure the SysTick clock source.
* @param CLKSource: specifies the SysTick clock source.
* This parameter can be one of the following values:
* @arg SYSTICK_CLKSOURCE_HCLK_DIV8: AHB clock divided by 8 selected as SysTick clock source.
* @arg SYSTICK_CLKSOURCE_HCLK: AHB clock selected as SysTick clock source.
* @retval None
*/
void HAL_SYSTICK_CLKSourceConfig(uint32_t CLKSource)
{
/* Check the parameters */
assert_param(IS_SYSTICK_CLK_SOURCE(CLKSource));
if (CLKSource == SYSTICK_CLKSOURCE_HCLK)
{
SysTick->CTRL |= SYSTICK_CLKSOURCE_HCLK;
}
else
{
SysTick->CTRL &= ~SYSTICK_CLKSOURCE_HCLK;
}
}
/**
* @brief Handle SYSTICK interrupt request.
* @retval None
*/
void HAL_SYSTICK_IRQHandler(void)
{
HAL_SYSTICK_Callback();
}
/**
* @brief SYSTICK callback.
* @retval None
*/
__weak void HAL_SYSTICK_Callback(void)
{
/* NOTE : This function should not be modified, when the callback is needed,
the HAL_SYSTICK_Callback could be implemented in the user file
*/
}
#if (__MPU_PRESENT == 1)
/**
* @brief Enable the MPU.
* @param MPU_Control: Specifies the control mode of the MPU during hard fault,
* NMI, FAULTMASK and privileged accessto the default memory
* This parameter can be one of the following values:
* @arg MPU_HFNMI_PRIVDEF_NONE
* @arg MPU_HARDFAULT_NMI
* @arg MPU_PRIVILEGED_DEFAULT
* @arg MPU_HFNMI_PRIVDEF
* @retval None
*/
void HAL_MPU_Enable(uint32_t MPU_Control)
{
/* Enable the MPU */
MPU->CTRL = (MPU_Control | MPU_CTRL_ENABLE_Msk);
/* Ensure MPU setting take effects */
__DSB();
__ISB();
}
/**
* @brief Disable the MPU.
* @retval None
*/
void HAL_MPU_Disable(void)
{
/* Make sure outstanding transfers are done */
__DMB();
/* Disable the MPU and clear the control register*/
MPU->CTRL = 0;
}
/**
* @brief Initialize and configure the Region and the memory to be protected.
* @param MPU_Init: Pointer to a MPU_Region_InitTypeDef structure that contains
* the initialization and configuration information.
* @retval None
*/
void HAL_MPU_ConfigRegion(MPU_Region_InitTypeDef *MPU_Init)
{
/* Check the parameters */
assert_param(IS_MPU_REGION_NUMBER(MPU_Init->Number));
assert_param(IS_MPU_REGION_ENABLE(MPU_Init->Enable));
/* Set the Region number */
MPU->RNR = MPU_Init->Number;
if ((MPU_Init->Enable) != RESET)
{
/* Check the parameters */
assert_param(IS_MPU_INSTRUCTION_ACCESS(MPU_Init->DisableExec));
assert_param(IS_MPU_REGION_PERMISSION_ATTRIBUTE(MPU_Init->AccessPermission));
assert_param(IS_MPU_TEX_LEVEL(MPU_Init->TypeExtField));
assert_param(IS_MPU_ACCESS_SHAREABLE(MPU_Init->IsShareable));
assert_param(IS_MPU_ACCESS_CACHEABLE(MPU_Init->IsCacheable));
assert_param(IS_MPU_ACCESS_BUFFERABLE(MPU_Init->IsBufferable));
assert_param(IS_MPU_SUB_REGION_DISABLE(MPU_Init->SubRegionDisable));
assert_param(IS_MPU_REGION_SIZE(MPU_Init->Size));
MPU->RBAR = MPU_Init->BaseAddress;
MPU->RASR = ((uint32_t)MPU_Init->DisableExec << MPU_RASR_XN_Pos) |
((uint32_t)MPU_Init->AccessPermission << MPU_RASR_AP_Pos) |
((uint32_t)MPU_Init->TypeExtField << MPU_RASR_TEX_Pos) |
((uint32_t)MPU_Init->IsShareable << MPU_RASR_S_Pos) |
((uint32_t)MPU_Init->IsCacheable << MPU_RASR_C_Pos) |
((uint32_t)MPU_Init->IsBufferable << MPU_RASR_B_Pos) |
((uint32_t)MPU_Init->SubRegionDisable << MPU_RASR_SRD_Pos) |
((uint32_t)MPU_Init->Size << MPU_RASR_SIZE_Pos) |
((uint32_t)MPU_Init->Enable << MPU_RASR_ENABLE_Pos);
}
else
{
MPU->RBAR = 0x00;
MPU->RASR = 0x00;
}
}
#endif /* __MPU_PRESENT */
/**
* @}
*/
/**
* @}
*/
#endif /* HAL_CORTEX_MODULE_ENABLED */
/**
* @}
*/
/**
* @}
*/

View File

@@ -1,1174 +0,0 @@
/**
******************************************************************************
* @file stm32l4xx_hal_dma.c
* @author MCD Application Team
* @brief DMA HAL module driver.
* This file provides firmware functions to manage the following
* functionalities of the Direct Memory Access (DMA) peripheral:
* + Initialization and de-initialization functions
* + IO operation functions
* + Peripheral State and errors functions
*
******************************************************************************
* @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.
*
******************************************************************************
@verbatim
==============================================================================
##### How to use this driver #####
==============================================================================
[..]
(#) Enable and configure the peripheral to be connected to the DMA Channel
(except for internal SRAM / FLASH memories: no initialization is
necessary). Please refer to the Reference manual for connection between peripherals
and DMA requests.
(#) For a given Channel, program the required configuration through the following parameters:
Channel request, Transfer Direction, Source and Destination data formats,
Circular or Normal mode, Channel Priority level, Source and Destination Increment mode
using HAL_DMA_Init() function.
Prior to HAL_DMA_Init the peripheral clock shall be enabled for both DMA & DMAMUX
thanks to:
(##) DMA1 or DMA2: __HAL_RCC_DMA1_CLK_ENABLE() or __HAL_RCC_DMA2_CLK_ENABLE() ;
(##) DMAMUX1: __HAL_RCC_DMAMUX1_CLK_ENABLE();
(#) Use HAL_DMA_GetState() function to return the DMA state and HAL_DMA_GetError() in case of error
detection.
(#) Use HAL_DMA_Abort() function to abort the current transfer
-@- In Memory-to-Memory transfer mode, Circular mode is not allowed.
*** Polling mode IO operation ***
=================================
[..]
(+) Use HAL_DMA_Start() to start DMA transfer after the configuration of Source
address and destination address and the Length of data to be transferred
(+) Use HAL_DMA_PollForTransfer() to poll for the end of current transfer, in this
case a fixed Timeout can be configured by User depending from his application.
*** Interrupt mode IO operation ***
===================================
[..]
(+) Configure the DMA interrupt priority using HAL_NVIC_SetPriority()
(+) Enable the DMA IRQ handler using HAL_NVIC_EnableIRQ()
(+) Use HAL_DMA_Start_IT() to start DMA transfer after the configuration of
Source address and destination address and the Length of data to be transferred.
In this case the DMA interrupt is configured
(+) Use HAL_DMA_IRQHandler() called under DMA_IRQHandler() Interrupt subroutine
(+) At the end of data transfer HAL_DMA_IRQHandler() function is executed and user can
add his own function to register callbacks with HAL_DMA_RegisterCallback().
*** DMA HAL driver macros list ***
=============================================
[..]
Below the list of macros in DMA HAL driver.
(+) __HAL_DMA_ENABLE: Enable the specified DMA Channel.
(+) __HAL_DMA_DISABLE: Disable the specified DMA Channel.
(+) __HAL_DMA_GET_FLAG: Get the DMA Channel pending flags.
(+) __HAL_DMA_CLEAR_FLAG: Clear the DMA Channel pending flags.
(+) __HAL_DMA_ENABLE_IT: Enable the specified DMA Channel interrupts.
(+) __HAL_DMA_DISABLE_IT: Disable the specified DMA Channel interrupts.
(+) __HAL_DMA_GET_IT_SOURCE: Check whether the specified DMA Channel interrupt is enabled or not.
[..]
(@) You can refer to the DMA HAL driver header file for more useful macros
@endverbatim
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32l4xx_hal.h"
/** @addtogroup STM32L4xx_HAL_Driver
* @{
*/
/** @defgroup DMA DMA
* @brief DMA HAL module driver
* @{
*/
#ifdef HAL_DMA_MODULE_ENABLED
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/** @defgroup DMA_Private_Functions DMA Private Functions
* @{
*/
static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
#if defined(DMAMUX1)
static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma);
static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma);
#endif /* DMAMUX1 */
/**
* @}
*/
/* Exported functions ---------------------------------------------------------*/
/** @defgroup DMA_Exported_Functions DMA Exported Functions
* @{
*/
/** @defgroup DMA_Exported_Functions_Group1 Initialization and de-initialization functions
* @brief Initialization and de-initialization functions
*
@verbatim
===============================================================================
##### Initialization and de-initialization functions #####
===============================================================================
[..]
This section provides functions allowing to initialize the DMA Channel source
and destination addresses, incrementation and data sizes, transfer direction,
circular/normal mode selection, memory-to-memory mode selection and Channel priority value.
[..]
The HAL_DMA_Init() function follows the DMA configuration procedures as described in
reference manual.
@endverbatim
* @{
*/
/**
* @brief Initialize the DMA according to the specified
* parameters in the DMA_InitTypeDef and initialize the associated handle.
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA Channel.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma)
{
uint32_t tmp;
/* Check the DMA handle allocation */
if(hdma == NULL)
{
return HAL_ERROR;
}
/* Check the parameters */
assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
assert_param(IS_DMA_DIRECTION(hdma->Init.Direction));
assert_param(IS_DMA_PERIPHERAL_INC_STATE(hdma->Init.PeriphInc));
assert_param(IS_DMA_MEMORY_INC_STATE(hdma->Init.MemInc));
assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(hdma->Init.PeriphDataAlignment));
assert_param(IS_DMA_MEMORY_DATA_SIZE(hdma->Init.MemDataAlignment));
assert_param(IS_DMA_MODE(hdma->Init.Mode));
assert_param(IS_DMA_PRIORITY(hdma->Init.Priority));
assert_param(IS_DMA_ALL_REQUEST(hdma->Init.Request));
/* Compute the channel index */
if ((uint32_t)(hdma->Instance) < (uint32_t)(DMA2_Channel1))
{
/* DMA1 */
hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2U;
hdma->DmaBaseAddress = DMA1;
}
else
{
/* DMA2 */
hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA2_Channel1) / ((uint32_t)DMA2_Channel2 - (uint32_t)DMA2_Channel1)) << 2U;
hdma->DmaBaseAddress = DMA2;
}
/* Change DMA peripheral state */
hdma->State = HAL_DMA_STATE_BUSY;
/* Get the CR register value */
tmp = hdma->Instance->CCR;
/* Clear PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR and MEM2MEM bits */
tmp &= ((uint32_t)~(DMA_CCR_PL | DMA_CCR_MSIZE | DMA_CCR_PSIZE |
DMA_CCR_MINC | DMA_CCR_PINC | DMA_CCR_CIRC |
DMA_CCR_DIR | DMA_CCR_MEM2MEM));
/* Prepare the DMA Channel configuration */
tmp |= hdma->Init.Direction |
hdma->Init.PeriphInc | hdma->Init.MemInc |
hdma->Init.PeriphDataAlignment | hdma->Init.MemDataAlignment |
hdma->Init.Mode | hdma->Init.Priority;
/* Write to DMA Channel CR register */
hdma->Instance->CCR = tmp;
#if defined(DMAMUX1)
/* Initialize parameters for DMAMUX channel :
DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask
*/
DMA_CalcDMAMUXChannelBaseAndMask(hdma);
if(hdma->Init.Direction == DMA_MEMORY_TO_MEMORY)
{
/* if memory to memory force the request to 0*/
hdma->Init.Request = DMA_REQUEST_MEM2MEM;
}
/* Set peripheral request to DMAMUX channel */
hdma->DMAmuxChannel->CCR = (hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID);
/* Clear the DMAMUX synchro overrun flag */
hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
if(((hdma->Init.Request > 0U) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR3)))
{
/* Initialize parameters for DMAMUX request generator :
DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask
*/
DMA_CalcDMAMUXRequestGenBaseAndMask(hdma);
/* Reset the DMAMUX request generator register*/
hdma->DMAmuxRequestGen->RGCR = 0U;
/* Clear the DMAMUX request generator overrun flag */
hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
}
else
{
hdma->DMAmuxRequestGen = 0U;
hdma->DMAmuxRequestGenStatus = 0U;
hdma->DMAmuxRequestGenStatusMask = 0U;
}
#endif /* DMAMUX1 */
#if !defined (DMAMUX1)
/* Set request selection */
if(hdma->Init.Direction != DMA_MEMORY_TO_MEMORY)
{
/* Write to DMA channel selection register */
if (DMA1 == hdma->DmaBaseAddress)
{
/* Reset request selection for DMA1 Channelx */
DMA1_CSELR->CSELR &= ~(DMA_CSELR_C1S << (hdma->ChannelIndex & 0x1cU));
/* Configure request selection for DMA1 Channelx */
DMA1_CSELR->CSELR |= (uint32_t) (hdma->Init.Request << (hdma->ChannelIndex & 0x1cU));
}
else /* DMA2 */
{
/* Reset request selection for DMA2 Channelx */
DMA2_CSELR->CSELR &= ~(DMA_CSELR_C1S << (hdma->ChannelIndex & 0x1cU));
/* Configure request selection for DMA2 Channelx */
DMA2_CSELR->CSELR |= (uint32_t) (hdma->Init.Request << (hdma->ChannelIndex & 0x1cU));
}
}
#endif /* STM32L431xx || STM32L432xx || STM32L433xx || STM32L442xx || STM32L443xx */
/* STM32L471xx || STM32L475xx || STM32L476xx || STM32L442xx || STM32L486xx */
/* STM32L496xx || STM32L4A6xx */
/* Initialise the error code */
hdma->ErrorCode = HAL_DMA_ERROR_NONE;
/* Initialize the DMA state*/
hdma->State = HAL_DMA_STATE_READY;
/* Allocate lock resource and initialize it */
hdma->Lock = HAL_UNLOCKED;
return HAL_OK;
}
/**
* @brief DeInitialize the DMA peripheral.
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA Channel.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_DMA_DeInit(DMA_HandleTypeDef *hdma)
{
/* Check the DMA handle allocation */
if (NULL == hdma )
{
return HAL_ERROR;
}
/* Check the parameters */
assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
/* Disable the selected DMA Channelx */
__HAL_DMA_DISABLE(hdma);
/* Compute the channel index */
if ((uint32_t)(hdma->Instance) < (uint32_t)(DMA2_Channel1))
{
/* DMA1 */
hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2U;
hdma->DmaBaseAddress = DMA1;
}
else
{
/* DMA2 */
hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA2_Channel1) / ((uint32_t)DMA2_Channel2 - (uint32_t)DMA2_Channel1)) << 2U;
hdma->DmaBaseAddress = DMA2;
}
/* Reset DMA Channel control register */
hdma->Instance->CCR = 0U;
/* Clear all flags */
hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1CU));
#if !defined (DMAMUX1)
/* Reset DMA channel selection register */
if (DMA1 == hdma->DmaBaseAddress)
{
/* DMA1 */
DMA1_CSELR->CSELR &= ~(DMA_CSELR_C1S << (hdma->ChannelIndex & 0x1cU));
}
else
{
/* DMA2 */
DMA2_CSELR->CSELR &= ~(DMA_CSELR_C1S << (hdma->ChannelIndex & 0x1cU));
}
#endif /* STM32L431xx || STM32L432xx || STM32L433xx || STM32L442xx || STM32L443xx */
/* STM32L471xx || STM32L475xx || STM32L476xx || STM32L442xx || STM32L486xx */
/* STM32L496xx || STM32L4A6xx */
#if defined(DMAMUX1)
/* Initialize parameters for DMAMUX channel :
DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask */
DMA_CalcDMAMUXChannelBaseAndMask(hdma);
/* Reset the DMAMUX channel that corresponds to the DMA channel */
hdma->DMAmuxChannel->CCR = 0U;
/* Clear the DMAMUX synchro overrun flag */
hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
/* Reset Request generator parameters if any */
if(((hdma->Init.Request > 0U) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR3)))
{
/* Initialize parameters for DMAMUX request generator :
DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask
*/
DMA_CalcDMAMUXRequestGenBaseAndMask(hdma);
/* Reset the DMAMUX request generator register*/
hdma->DMAmuxRequestGen->RGCR = 0U;
/* Clear the DMAMUX request generator overrun flag */
hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
}
hdma->DMAmuxRequestGen = 0U;
hdma->DMAmuxRequestGenStatus = 0U;
hdma->DMAmuxRequestGenStatusMask = 0U;
#endif /* DMAMUX1 */
/* Clean callbacks */
hdma->XferCpltCallback = NULL;
hdma->XferHalfCpltCallback = NULL;
hdma->XferErrorCallback = NULL;
hdma->XferAbortCallback = NULL;
/* Initialise the error code */
hdma->ErrorCode = HAL_DMA_ERROR_NONE;
/* Initialize the DMA state */
hdma->State = HAL_DMA_STATE_RESET;
/* Release Lock */
__HAL_UNLOCK(hdma);
return HAL_OK;
}
/**
* @}
*/
/** @defgroup DMA_Exported_Functions_Group2 Input and Output operation functions
* @brief Input and Output operation functions
*
@verbatim
===============================================================================
##### IO operation functions #####
===============================================================================
[..] This section provides functions allowing to:
(+) Configure the source, destination address and data length and Start DMA transfer
(+) Configure the source, destination address and data length and
Start DMA transfer with interrupt
(+) Abort DMA transfer
(+) Poll for transfer complete
(+) Handle DMA interrupt request
@endverbatim
* @{
*/
/**
* @brief Start the DMA Transfer.
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA Channel.
* @param SrcAddress The source memory Buffer address
* @param DstAddress The destination memory Buffer address
* @param DataLength The length of data to be transferred from source to destination
* @retval HAL status
*/
HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check the parameters */
assert_param(IS_DMA_BUFFER_SIZE(DataLength));
/* Process locked */
__HAL_LOCK(hdma);
if(HAL_DMA_STATE_READY == hdma->State)
{
/* Change DMA peripheral state */
hdma->State = HAL_DMA_STATE_BUSY;
hdma->ErrorCode = HAL_DMA_ERROR_NONE;
/* Disable the peripheral */
__HAL_DMA_DISABLE(hdma);
/* Configure the source, destination address and the data length & clear flags*/
DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
/* Enable the Peripheral */
__HAL_DMA_ENABLE(hdma);
}
else
{
/* Process Unlocked */
__HAL_UNLOCK(hdma);
status = HAL_BUSY;
}
return status;
}
/**
* @brief Start the DMA Transfer with interrupt enabled.
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA Channel.
* @param SrcAddress The source memory Buffer address
* @param DstAddress The destination memory Buffer address
* @param DataLength The length of data to be transferred from source to destination
* @retval HAL status
*/
HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check the parameters */
assert_param(IS_DMA_BUFFER_SIZE(DataLength));
/* Process locked */
__HAL_LOCK(hdma);
if(HAL_DMA_STATE_READY == hdma->State)
{
/* Change DMA peripheral state */
hdma->State = HAL_DMA_STATE_BUSY;
hdma->ErrorCode = HAL_DMA_ERROR_NONE;
/* Disable the peripheral */
__HAL_DMA_DISABLE(hdma);
/* Configure the source, destination address and the data length & clear flags*/
DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
/* Enable the transfer complete interrupt */
/* Enable the transfer Error interrupt */
if(NULL != hdma->XferHalfCpltCallback )
{
/* Enable the Half transfer complete interrupt as well */
__HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
}
else
{
__HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
__HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_TE));
}
#ifdef DMAMUX1
/* Check if DMAMUX Synchronization is enabled*/
if((hdma->DMAmuxChannel->CCR & DMAMUX_CxCR_SE) != 0U)
{
/* Enable DMAMUX sync overrun IT*/
hdma->DMAmuxChannel->CCR |= DMAMUX_CxCR_SOIE;
}
if(hdma->DMAmuxRequestGen != 0U)
{
/* if using DMAMUX request generator, enable the DMAMUX request generator overrun IT*/
/* enable the request gen overrun IT*/
hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE;
}
#endif /* DMAMUX1 */
/* Enable the Peripheral */
__HAL_DMA_ENABLE(hdma);
}
else
{
/* Process Unlocked */
__HAL_UNLOCK(hdma);
/* Remain BUSY */
status = HAL_BUSY;
}
return status;
}
/**
* @brief Abort the DMA Transfer.
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA Channel.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check the DMA peripheral state */
if(hdma->State != HAL_DMA_STATE_BUSY)
{
hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
/* Process Unlocked */
__HAL_UNLOCK(hdma);
return HAL_ERROR;
}
else
{
/* Disable DMA IT */
__HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
#if defined(DMAMUX1)
/* disable the DMAMUX sync overrun IT*/
hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;
#endif /* DMAMUX1 */
/* Disable the channel */
__HAL_DMA_DISABLE(hdma);
/* Clear all flags */
hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1CU));
#if defined(DMAMUX1)
/* Clear the DMAMUX synchro overrun flag */
hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
if(hdma->DMAmuxRequestGen != 0U)
{
/* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/
/* disable the request gen overrun IT*/
hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;
/* Clear the DMAMUX request generator overrun flag */
hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
}
#endif /* DMAMUX1 */
/* Change the DMA state */
hdma->State = HAL_DMA_STATE_READY;
/* Process Unlocked */
__HAL_UNLOCK(hdma);
return status;
}
}
/**
* @brief Aborts the DMA Transfer in Interrupt mode.
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA Channel.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma)
{
HAL_StatusTypeDef status = HAL_OK;
if(HAL_DMA_STATE_BUSY != hdma->State)
{
/* no transfer ongoing */
hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
status = HAL_ERROR;
}
else
{
/* Disable DMA IT */
__HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
/* Disable the channel */
__HAL_DMA_DISABLE(hdma);
#if defined(DMAMUX1)
/* disable the DMAMUX sync overrun IT*/
hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;
/* Clear all flags */
hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1CU));
/* Clear the DMAMUX synchro overrun flag */
hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
if(hdma->DMAmuxRequestGen != 0U)
{
/* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/
/* disable the request gen overrun IT*/
hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;
/* Clear the DMAMUX request generator overrun flag */
hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
}
#else
/* Clear all flags */
hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1CU));
#endif /* DMAMUX1 */
/* Change the DMA state */
hdma->State = HAL_DMA_STATE_READY;
/* Process Unlocked */
__HAL_UNLOCK(hdma);
/* Call User Abort callback */
if(hdma->XferAbortCallback != NULL)
{
hdma->XferAbortCallback(hdma);
}
}
return status;
}
/**
* @brief Polling for transfer complete.
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA Channel.
* @param CompleteLevel Specifies the DMA level complete.
* @param Timeout Timeout duration.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, HAL_DMA_LevelCompleteTypeDef CompleteLevel, uint32_t Timeout)
{
uint32_t temp;
uint32_t tickstart;
if(HAL_DMA_STATE_BUSY != hdma->State)
{
/* no transfer ongoing */
hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
__HAL_UNLOCK(hdma);
return HAL_ERROR;
}
/* Polling mode not supported in circular mode */
if ((hdma->Instance->CCR & DMA_CCR_CIRC) != 0U)
{
hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;
return HAL_ERROR;
}
/* Get the level transfer complete flag */
if (HAL_DMA_FULL_TRANSFER == CompleteLevel)
{
/* Transfer Complete flag */
temp = DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1CU);
}
else
{
/* Half Transfer Complete flag */
temp = DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1CU);
}
/* Get tick */
tickstart = HAL_GetTick();
while((hdma->DmaBaseAddress->ISR & temp) == 0U)
{
if((hdma->DmaBaseAddress->ISR & (DMA_FLAG_TE1 << (hdma->ChannelIndex& 0x1CU))) != 0U)
{
/* When a DMA transfer error occurs */
/* A hardware clear of its EN bits is performed */
/* Clear all flags */
hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1CU));
/* Update error code */
hdma->ErrorCode = HAL_DMA_ERROR_TE;
/* Change the DMA state */
hdma->State= HAL_DMA_STATE_READY;
/* Process Unlocked */
__HAL_UNLOCK(hdma);
return HAL_ERROR;
}
/* Check for the Timeout */
if(Timeout != HAL_MAX_DELAY)
{
if(((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
{
/* Update error code */
hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT;
/* Change the DMA state */
hdma->State = HAL_DMA_STATE_READY;
/* Process Unlocked */
__HAL_UNLOCK(hdma);
return HAL_ERROR;
}
}
}
#if defined(DMAMUX1)
/*Check for DMAMUX Request generator (if used) overrun status */
if(hdma->DMAmuxRequestGen != 0U)
{
/* if using DMAMUX request generator Check for DMAMUX request generator overrun */
if((hdma->DMAmuxRequestGenStatus->RGSR & hdma->DMAmuxRequestGenStatusMask) != 0U)
{
/* Disable the request gen overrun interrupt */
hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE;
/* Clear the DMAMUX request generator overrun flag */
hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
/* Update error code */
hdma->ErrorCode |= HAL_DMA_ERROR_REQGEN;
}
}
/* Check for DMAMUX Synchronization overrun */
if((hdma->DMAmuxChannelStatus->CSR & hdma->DMAmuxChannelStatusMask) != 0U)
{
/* Clear the DMAMUX synchro overrun flag */
hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
/* Update error code */
hdma->ErrorCode |= HAL_DMA_ERROR_SYNC;
}
#endif /* DMAMUX1 */
if(HAL_DMA_FULL_TRANSFER == CompleteLevel)
{
/* Clear the transfer complete flag */
hdma->DmaBaseAddress->IFCR = (DMA_FLAG_TC1 << (hdma->ChannelIndex& 0x1CU));
/* Process unlocked */
__HAL_UNLOCK(hdma);
/* The selected Channelx EN bit is cleared (DMA is disabled and
all transfers are complete) */
hdma->State = HAL_DMA_STATE_READY;
}
else
{
/* Clear the half transfer complete flag */
hdma->DmaBaseAddress->IFCR = (DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1CU));
}
return HAL_OK;
}
/**
* @brief Handle DMA interrupt request.
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA Channel.
* @retval None
*/
void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
{
uint32_t flag_it = hdma->DmaBaseAddress->ISR;
uint32_t source_it = hdma->Instance->CCR;
/* Half Transfer Complete Interrupt management ******************************/
if (((flag_it & (DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1CU))) != 0U) && ((source_it & DMA_IT_HT) != 0U))
{
/* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
{
/* Disable the half transfer interrupt */
__HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
}
/* Clear the half transfer complete flag */
hdma->DmaBaseAddress->IFCR = DMA_ISR_HTIF1 << (hdma->ChannelIndex & 0x1CU);
/* DMA peripheral state is not updated in Half Transfer */
/* but in Transfer Complete case */
if(hdma->XferHalfCpltCallback != NULL)
{
/* Half transfer callback */
hdma->XferHalfCpltCallback(hdma);
}
}
/* Transfer Complete Interrupt management ***********************************/
else if (((flag_it & (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1CU))) != 0U) && ((source_it & DMA_IT_TC) != 0U))
{
if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
{
/* Disable the transfer complete interrupt if the DMA mode is not CIRCULAR */
/* Disable the transfer complete and error interrupt */
/* if the DMA mode is not CIRCULAR */
__HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE | DMA_IT_TC);
/* Change the DMA state */
hdma->State = HAL_DMA_STATE_READY;
}
/* Clear the transfer complete flag */
hdma->DmaBaseAddress->IFCR = (DMA_ISR_TCIF1 << (hdma->ChannelIndex & 0x1CU));
/* Process Unlocked */
__HAL_UNLOCK(hdma);
if(hdma->XferCpltCallback != NULL)
{
/* Transfer complete callback */
hdma->XferCpltCallback(hdma);
}
}
/* Transfer Error Interrupt management **************************************/
else if (((flag_it & (DMA_FLAG_TE1 << (hdma->ChannelIndex & 0x1CU))) != 0U) && ((source_it & DMA_IT_TE) != 0U))
{
/* When a DMA transfer error occurs */
/* A hardware clear of its EN bits is performed */
/* Disable ALL DMA IT */
__HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
/* Clear all flags */
hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1CU));
/* Update error code */
hdma->ErrorCode = HAL_DMA_ERROR_TE;
/* Change the DMA state */
hdma->State = HAL_DMA_STATE_READY;
/* Process Unlocked */
__HAL_UNLOCK(hdma);
if (hdma->XferErrorCallback != NULL)
{
/* Transfer error callback */
hdma->XferErrorCallback(hdma);
}
}
else
{
/* Nothing To Do */
}
return;
}
/**
* @brief Register callbacks
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA Channel.
* @param CallbackID User Callback identifier
* a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
* @param pCallback pointer to private callbacsk function which has pointer to
* a DMA_HandleTypeDef structure as parameter.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_DMA_RegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID, void (* pCallback)( DMA_HandleTypeDef * _hdma))
{
HAL_StatusTypeDef status = HAL_OK;
/* Process locked */
__HAL_LOCK(hdma);
if(HAL_DMA_STATE_READY == hdma->State)
{
switch (CallbackID)
{
case HAL_DMA_XFER_CPLT_CB_ID:
hdma->XferCpltCallback = pCallback;
break;
case HAL_DMA_XFER_HALFCPLT_CB_ID:
hdma->XferHalfCpltCallback = pCallback;
break;
case HAL_DMA_XFER_ERROR_CB_ID:
hdma->XferErrorCallback = pCallback;
break;
case HAL_DMA_XFER_ABORT_CB_ID:
hdma->XferAbortCallback = pCallback;
break;
default:
status = HAL_ERROR;
break;
}
}
else
{
status = HAL_ERROR;
}
/* Release Lock */
__HAL_UNLOCK(hdma);
return status;
}
/**
* @brief UnRegister callbacks
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA Channel.
* @param CallbackID User Callback identifier
* a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID)
{
HAL_StatusTypeDef status = HAL_OK;
/* Process locked */
__HAL_LOCK(hdma);
if(HAL_DMA_STATE_READY == hdma->State)
{
switch (CallbackID)
{
case HAL_DMA_XFER_CPLT_CB_ID:
hdma->XferCpltCallback = NULL;
break;
case HAL_DMA_XFER_HALFCPLT_CB_ID:
hdma->XferHalfCpltCallback = NULL;
break;
case HAL_DMA_XFER_ERROR_CB_ID:
hdma->XferErrorCallback = NULL;
break;
case HAL_DMA_XFER_ABORT_CB_ID:
hdma->XferAbortCallback = NULL;
break;
case HAL_DMA_XFER_ALL_CB_ID:
hdma->XferCpltCallback = NULL;
hdma->XferHalfCpltCallback = NULL;
hdma->XferErrorCallback = NULL;
hdma->XferAbortCallback = NULL;
break;
default:
status = HAL_ERROR;
break;
}
}
else
{
status = HAL_ERROR;
}
/* Release Lock */
__HAL_UNLOCK(hdma);
return status;
}
/**
* @}
*/
/** @defgroup DMA_Exported_Functions_Group3 Peripheral State and Errors functions
* @brief Peripheral State and Errors functions
*
@verbatim
===============================================================================
##### Peripheral State and Errors functions #####
===============================================================================
[..]
This subsection provides functions allowing to
(+) Check the DMA state
(+) Get error code
@endverbatim
* @{
*/
/**
* @brief Return the DMA handle state.
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA Channel.
* @retval HAL state
*/
HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma)
{
/* Return DMA handle state */
return hdma->State;
}
/**
* @brief Return the DMA error code.
* @param hdma : pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA Channel.
* @retval DMA Error Code
*/
uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma)
{
return hdma->ErrorCode;
}
/**
* @}
*/
/**
* @}
*/
/** @addtogroup DMA_Private_Functions
* @{
*/
/**
* @brief Sets the DMA Transfer parameter.
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA Channel.
* @param SrcAddress The source memory Buffer address
* @param DstAddress The destination memory Buffer address
* @param DataLength The length of data to be transferred from source to destination
* @retval HAL status
*/
static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
{
#if defined(DMAMUX1)
/* Clear the DMAMUX synchro overrun flag */
hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
if(hdma->DMAmuxRequestGen != 0U)
{
/* Clear the DMAMUX request generator overrun flag */
hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
}
#endif
/* Clear all flags */
hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1CU));
/* Configure DMA Channel data length */
hdma->Instance->CNDTR = DataLength;
/* Memory to Peripheral */
if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
{
/* Configure DMA Channel destination address */
hdma->Instance->CPAR = DstAddress;
/* Configure DMA Channel source address */
hdma->Instance->CMAR = SrcAddress;
}
/* Peripheral to Memory */
else
{
/* Configure DMA Channel source address */
hdma->Instance->CPAR = SrcAddress;
/* Configure DMA Channel destination address */
hdma->Instance->CMAR = DstAddress;
}
}
#if defined(DMAMUX1)
/**
* @brief Updates the DMA handle with the DMAMUX channel and status mask depending on channel number
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA Channel.
* @retval None
*/
static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma)
{
uint32_t channel_number;
/* check if instance is not outside the DMA channel range */
if ((uint32_t)hdma->Instance < (uint32_t)DMA2_Channel1)
{
/* DMA1 */
hdma->DMAmuxChannel = (DMAMUX1_Channel0 + (hdma->ChannelIndex >> 2U));
}
else
{
/* DMA2 */
hdma->DMAmuxChannel = (DMAMUX1_Channel7 + (hdma->ChannelIndex >> 2U));
}
channel_number = (((uint32_t)hdma->Instance & 0xFFU) - 8U) / 20U;
hdma->DMAmuxChannelStatus = DMAMUX1_ChannelStatus;
hdma->DMAmuxChannelStatusMask = 1UL << (channel_number & 0x1FU);
}
/**
* @brief Updates the DMA handle with the DMAMUX request generator params
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA Channel.
* @retval None
*/
static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma)
{
uint32_t request = hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID;
/* DMA Channels are connected to DMAMUX1 request generator blocks*/
hdma->DMAmuxRequestGen = (DMAMUX_RequestGen_TypeDef *)((uint32_t)(((uint32_t)DMAMUX1_RequestGenerator0) + ((request - 1U) * 4U)));
hdma->DMAmuxRequestGenStatus = DMAMUX1_RequestGenStatus;
/* here "Request" is either DMA_REQUEST_GENERATOR0 to DMA_REQUEST_GENERATOR3, i.e. <= 4*/
hdma->DMAmuxRequestGenStatusMask = 1UL << ((request - 1U) & 0x3U);
}
#endif /* DMAMUX1 */
/**
* @}
*/
/**
* @}
*/
#endif /* HAL_DMA_MODULE_ENABLED */
/**
* @}
*/
/**
* @}
*/

View File

@@ -1,307 +0,0 @@
/**
******************************************************************************
* @file stm32l4xx_hal_dma_ex.c
* @author MCD Application Team
* @brief DMA Extension HAL module driver
* This file provides firmware functions to manage the following
* functionalities of the DMA Extension peripheral:
* + Extended features functions
*
******************************************************************************
* @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.
*
******************************************************************************
@verbatim
==============================================================================
##### How to use this driver #####
==============================================================================
[..]
The DMA Extension HAL driver can be used as follows:
(+) Configure the DMA_MUX Synchronization Block using HAL_DMAEx_ConfigMuxSync function.
(+) Configure the DMA_MUX Request Generator Block using HAL_DMAEx_ConfigMuxRequestGenerator function.
Functions HAL_DMAEx_EnableMuxRequestGenerator and HAL_DMAEx_DisableMuxRequestGenerator can then be used
to respectively enable/disable the request generator.
(+) To handle the DMAMUX Interrupts, the function HAL_DMAEx_MUX_IRQHandler should be called from
the DMAMUX IRQ handler i.e DMAMUX1_OVR_IRQHandler.
As only one interrupt line is available for all DMAMUX channels and request generators , HAL_DMAEx_MUX_IRQHandler should be
called with, as parameter, the appropriate DMA handle as many as used DMAs in the user project
(exception done if a given DMA is not using the DMAMUX SYNC block neither a request generator)
-@- In Memory-to-Memory transfer mode, Multi (Double) Buffer mode is not allowed.
-@- When Multi (Double) Buffer mode is enabled, the transfer is circular by default.
-@- In Multi (Double) buffer mode, it is possible to update the base address for
the AHB memory port on the fly (DMA_CM0ARx or DMA_CM1ARx) when the channel is enabled.
@endverbatim
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32l4xx_hal.h"
#if defined(DMAMUX1)
/** @addtogroup STM32L4xx_HAL_Driver
* @{
*/
/** @defgroup DMAEx DMAEx
* @brief DMA Extended HAL module driver
* @{
*/
#ifdef HAL_DMA_MODULE_ENABLED
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private Constants ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/** @defgroup DMAEx_Exported_Functions DMAEx Exported Functions
* @{
*/
/** @defgroup DMAEx_Exported_Functions_Group1 DMAEx Extended features functions
* @brief Extended features functions
*
@verbatim
===============================================================================
##### Extended features functions #####
===============================================================================
[..] This section provides functions allowing to:
(+) Configure the DMAMUX Synchronization Block using HAL_DMAEx_ConfigMuxSync function.
(+) Configure the DMAMUX Request Generator Block using HAL_DMAEx_ConfigMuxRequestGenerator function.
Functions HAL_DMAEx_EnableMuxRequestGenerator and HAL_DMAEx_DisableMuxRequestGenerator can then be used
to respectively enable/disable the request generator.
@endverbatim
* @{
*/
/**
* @brief Configure the DMAMUX synchronization parameters for a given DMA channel (instance).
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA channel.
* @param pSyncConfig : pointer to HAL_DMA_MuxSyncConfigTypeDef : contains the DMAMUX synchronization parameters
* @retval HAL status
*/
HAL_StatusTypeDef HAL_DMAEx_ConfigMuxSync(DMA_HandleTypeDef *hdma, HAL_DMA_MuxSyncConfigTypeDef *pSyncConfig)
{
/* Check the parameters */
assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
assert_param(IS_DMAMUX_SYNC_SIGNAL_ID(pSyncConfig->SyncSignalID));
assert_param(IS_DMAMUX_SYNC_POLARITY(pSyncConfig-> SyncPolarity));
assert_param(IS_DMAMUX_SYNC_STATE(pSyncConfig->SyncEnable));
assert_param(IS_DMAMUX_SYNC_EVENT(pSyncConfig->EventEnable));
assert_param(IS_DMAMUX_SYNC_REQUEST_NUMBER(pSyncConfig->RequestNumber));
/*Check if the DMA state is ready */
if(hdma->State == HAL_DMA_STATE_READY)
{
/* Process Locked */
__HAL_LOCK(hdma);
/* Set the new synchronization parameters (and keep the request ID filled during the Init)*/
MODIFY_REG( hdma->DMAmuxChannel->CCR, \
(~DMAMUX_CxCR_DMAREQ_ID) , \
((pSyncConfig->SyncSignalID) << DMAMUX_CxCR_SYNC_ID_Pos) | ((pSyncConfig->RequestNumber - 1U) << DMAMUX_CxCR_NBREQ_Pos) | \
pSyncConfig->SyncPolarity | ((uint32_t)pSyncConfig->SyncEnable << DMAMUX_CxCR_SE_Pos) | \
((uint32_t)pSyncConfig->EventEnable << DMAMUX_CxCR_EGE_Pos));
/* Process UnLocked */
__HAL_UNLOCK(hdma);
return HAL_OK;
}
else
{
/*DMA State not Ready*/
return HAL_ERROR;
}
}
/**
* @brief Configure the DMAMUX request generator block used by the given DMA channel (instance).
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA channel.
* @param pRequestGeneratorConfig : pointer to HAL_DMA_MuxRequestGeneratorConfigTypeDef :
* contains the request generator parameters.
*
* @retval HAL status
*/
HAL_StatusTypeDef HAL_DMAEx_ConfigMuxRequestGenerator (DMA_HandleTypeDef *hdma, HAL_DMA_MuxRequestGeneratorConfigTypeDef *pRequestGeneratorConfig)
{
/* Check the parameters */
assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
assert_param(IS_DMAMUX_REQUEST_GEN_SIGNAL_ID(pRequestGeneratorConfig->SignalID));
assert_param(IS_DMAMUX_REQUEST_GEN_POLARITY(pRequestGeneratorConfig->Polarity));
assert_param(IS_DMAMUX_REQUEST_GEN_REQUEST_NUMBER(pRequestGeneratorConfig->RequestNumber));
/* check if the DMA state is ready
and DMA is using a DMAMUX request generator block
*/
if((hdma->State == HAL_DMA_STATE_READY) && (hdma->DMAmuxRequestGen != 0U))
{
/* Process Locked */
__HAL_LOCK(hdma);
/* Set the request generator new parameters */
hdma->DMAmuxRequestGen->RGCR = pRequestGeneratorConfig->SignalID | \
((pRequestGeneratorConfig->RequestNumber - 1U) << DMAMUX_RGxCR_GNBREQ_Pos)| \
pRequestGeneratorConfig->Polarity;
/* Process UnLocked */
__HAL_UNLOCK(hdma);
return HAL_OK;
}
else
{
return HAL_ERROR;
}
}
/**
* @brief Enable the DMAMUX request generator block used by the given DMA channel (instance).
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA channel.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_DMAEx_EnableMuxRequestGenerator (DMA_HandleTypeDef *hdma)
{
/* Check the parameters */
assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
/* check if the DMA state is ready
and DMA is using a DMAMUX request generator block
*/
if((hdma->State != HAL_DMA_STATE_RESET) && (hdma->DMAmuxRequestGen != 0))
{
/* Enable the request generator*/
hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_GE;
return HAL_OK;
}
else
{
return HAL_ERROR;
}
}
/**
* @brief Disable the DMAMUX request generator block used by the given DMA channel (instance).
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA channel.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_DMAEx_DisableMuxRequestGenerator (DMA_HandleTypeDef *hdma)
{
/* Check the parameters */
assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
/* check if the DMA state is ready
and DMA is using a DMAMUX request generator block
*/
if((hdma->State != HAL_DMA_STATE_RESET) && (hdma->DMAmuxRequestGen != 0))
{
/* Disable the request generator*/
hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_GE;
return HAL_OK;
}
else
{
return HAL_ERROR;
}
}
/**
* @brief Handles DMAMUX interrupt request.
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA channel.
* @retval None
*/
void HAL_DMAEx_MUX_IRQHandler(DMA_HandleTypeDef *hdma)
{
/* Check for DMAMUX Synchronization overrun */
if((hdma->DMAmuxChannelStatus->CSR & hdma->DMAmuxChannelStatusMask) != 0U)
{
/* Disable the synchro overrun interrupt */
hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;
/* Clear the DMAMUX synchro overrun flag */
hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
/* Update error code */
hdma->ErrorCode |= HAL_DMA_ERROR_SYNC;
if(hdma->XferErrorCallback != NULL)
{
/* Transfer error callback */
hdma->XferErrorCallback(hdma);
}
}
if(hdma->DMAmuxRequestGen != 0)
{
/* if using a DMAMUX request generator block Check for DMAMUX request generator overrun */
if((hdma->DMAmuxRequestGenStatus->RGSR & hdma->DMAmuxRequestGenStatusMask) != 0U)
{
/* Disable the request gen overrun interrupt */
hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;
/* Clear the DMAMUX request generator overrun flag */
hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
/* Update error code */
hdma->ErrorCode |= HAL_DMA_ERROR_REQGEN;
if(hdma->XferErrorCallback != NULL)
{
/* Transfer error callback */
hdma->XferErrorCallback(hdma);
}
}
}
}
/**
* @}
*/
/**
* @}
*/
#endif /* HAL_DMA_MODULE_ENABLED */
/**
* @}
*/
/**
* @}
*/
#endif /* DMAMUX1 */

View File

@@ -1,632 +0,0 @@
/**
******************************************************************************
* @file stm32l4xx_hal_exti.c
* @author MCD Application Team
* @brief EXTI HAL module driver.
* This file provides firmware functions to manage the following
* functionalities of the Extended Interrupts and events controller (EXTI) peripheral:
* + Initialization and de-initialization functions
* + IO operation functions
*
******************************************************************************
* @attention
*
* Copyright (c) 2018 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.
*
******************************************************************************
@verbatim
==============================================================================
##### EXTI Peripheral features #####
==============================================================================
[..]
(+) Each Exti line can be configured within this driver.
(+) Exti line can be configured in 3 different modes
(++) Interrupt
(++) Event
(++) Both of them
(+) Configurable Exti lines can be configured with 3 different triggers
(++) Rising
(++) Falling
(++) Both of them
(+) When set in interrupt mode, configurable Exti lines have two different
interrupts pending registers which allow to distinguish which transition
occurs:
(++) Rising edge pending interrupt
(++) Falling
(+) Exti lines 0 to 15 are linked to gpio pin number 0 to 15. Gpio port can
be selected through multiplexer.
##### How to use this driver #####
==============================================================================
[..]
(#) Configure the EXTI line using HAL_EXTI_SetConfigLine().
(++) Choose the interrupt line number by setting "Line" member from
EXTI_ConfigTypeDef structure.
(++) Configure the interrupt and/or event mode using "Mode" member from
EXTI_ConfigTypeDef structure.
(++) For configurable lines, configure rising and/or falling trigger
"Trigger" member from EXTI_ConfigTypeDef structure.
(++) For Exti lines linked to gpio, choose gpio port using "GPIOSel"
member from GPIO_InitTypeDef structure.
(#) Get current Exti configuration of a dedicated line using
HAL_EXTI_GetConfigLine().
(++) Provide exiting handle as parameter.
(++) Provide pointer on EXTI_ConfigTypeDef structure as second parameter.
(#) Clear Exti configuration of a dedicated line using HAL_EXTI_GetConfigLine().
(++) Provide exiting handle as parameter.
(#) Register callback to treat Exti interrupts using HAL_EXTI_RegisterCallback().
(++) Provide exiting handle as first parameter.
(++) Provide which callback will be registered using one value from
EXTI_CallbackIDTypeDef.
(++) Provide callback function pointer.
(#) Get interrupt pending bit using HAL_EXTI_GetPending().
(#) Clear interrupt pending bit using HAL_EXTI_GetPending().
(#) Generate software interrupt using HAL_EXTI_GenerateSWI().
@endverbatim
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32l4xx_hal.h"
/** @addtogroup STM32L4xx_HAL_Driver
* @{
*/
/** @addtogroup EXTI
* @{
*/
/** MISRA C:2012 deviation rule has been granted for following rule:
* Rule-18.1_b - Medium: Array `EXTICR' 1st subscript interval [0,7] may be out
* of bounds [0,3] in following API :
* HAL_EXTI_SetConfigLine
* HAL_EXTI_GetConfigLine
* HAL_EXTI_ClearConfigLine
*/
#ifdef HAL_EXTI_MODULE_ENABLED
/* Private typedef -----------------------------------------------------------*/
/* Private defines ------------------------------------------------------------*/
/** @defgroup EXTI_Private_Constants EXTI Private Constants
* @{
*/
#define EXTI_MODE_OFFSET 0x08u /* 0x20: offset between MCU IMR/EMR registers */
#define EXTI_CONFIG_OFFSET 0x08u /* 0x20: offset between MCU Rising/Falling configuration registers */
/**
* @}
*/
/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/** @addtogroup EXTI_Exported_Functions
* @{
*/
/** @addtogroup EXTI_Exported_Functions_Group1
* @brief Configuration functions
*
@verbatim
===============================================================================
##### Configuration functions #####
===============================================================================
@endverbatim
* @{
*/
/**
* @brief Set configuration of a dedicated Exti line.
* @param hexti Exti handle.
* @param pExtiConfig Pointer on EXTI configuration to be set.
* @retval HAL Status.
*/
HAL_StatusTypeDef HAL_EXTI_SetConfigLine(EXTI_HandleTypeDef *hexti, EXTI_ConfigTypeDef *pExtiConfig)
{
__IO uint32_t *regaddr;
uint32_t regval;
uint32_t linepos;
uint32_t maskline;
uint32_t offset;
/* Check null pointer */
if ((hexti == NULL) || (pExtiConfig == NULL))
{
return HAL_ERROR;
}
/* Check parameters */
assert_param(IS_EXTI_LINE(pExtiConfig->Line));
assert_param(IS_EXTI_MODE(pExtiConfig->Mode));
/* Assign line number to handle */
hexti->Line = pExtiConfig->Line;
/* Compute line register offset and line mask */
offset = ((pExtiConfig->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
linepos = (pExtiConfig->Line & EXTI_PIN_MASK);
maskline = (1uL << linepos);
/* Configure triggers for configurable lines */
if ((pExtiConfig->Line & EXTI_CONFIG) != 0x00u)
{
assert_param(IS_EXTI_TRIGGER(pExtiConfig->Trigger));
/* Configure rising trigger */
regaddr = (&EXTI->RTSR1 + (EXTI_CONFIG_OFFSET * offset));
regval = *regaddr;
/* Mask or set line */
if ((pExtiConfig->Trigger & EXTI_TRIGGER_RISING) != 0x00u)
{
regval |= maskline;
}
else
{
regval &= ~maskline;
}
/* Store rising trigger mode */
*regaddr = regval;
/* Configure falling trigger */
regaddr = (&EXTI->FTSR1 + (EXTI_CONFIG_OFFSET * offset));
regval = *regaddr;
/* Mask or set line */
if ((pExtiConfig->Trigger & EXTI_TRIGGER_FALLING) != 0x00u)
{
regval |= maskline;
}
else
{
regval &= ~maskline;
}
/* Store falling trigger mode */
*regaddr = regval;
/* Configure gpio port selection in case of gpio exti line */
if ((pExtiConfig->Line & EXTI_GPIO) == EXTI_GPIO)
{
assert_param(IS_EXTI_GPIO_PORT(pExtiConfig->GPIOSel));
assert_param(IS_EXTI_GPIO_PIN(linepos));
regval = SYSCFG->EXTICR[linepos >> 2u];
regval &= ~(SYSCFG_EXTICR1_EXTI0 << (SYSCFG_EXTICR1_EXTI1_Pos * (linepos & 0x03u)));
regval |= (pExtiConfig->GPIOSel << (SYSCFG_EXTICR1_EXTI1_Pos * (linepos & 0x03u)));
SYSCFG->EXTICR[linepos >> 2u] = regval;
}
}
/* Configure interrupt mode : read current mode */
regaddr = (&EXTI->IMR1 + (EXTI_MODE_OFFSET * offset));
regval = *regaddr;
/* Mask or set line */
if ((pExtiConfig->Mode & EXTI_MODE_INTERRUPT) != 0x00u)
{
regval |= maskline;
}
else
{
regval &= ~maskline;
}
/* Store interrupt mode */
*regaddr = regval;
/* The event mode cannot be configured if the line does not support it */
assert_param(((pExtiConfig->Line & EXTI_EVENT) == EXTI_EVENT) || ((pExtiConfig->Mode & EXTI_MODE_EVENT) != EXTI_MODE_EVENT));
/* Configure event mode : read current mode */
regaddr = (&EXTI->EMR1 + (EXTI_MODE_OFFSET * offset));
regval = *regaddr;
/* Mask or set line */
if ((pExtiConfig->Mode & EXTI_MODE_EVENT) != 0x00u)
{
regval |= maskline;
}
else
{
regval &= ~maskline;
}
/* Store event mode */
*regaddr = regval;
return HAL_OK;
}
/**
* @brief Get configuration of a dedicated Exti line.
* @param hexti Exti handle.
* @param pExtiConfig Pointer on structure to store Exti configuration.
* @retval HAL Status.
*/
HAL_StatusTypeDef HAL_EXTI_GetConfigLine(EXTI_HandleTypeDef *hexti, EXTI_ConfigTypeDef *pExtiConfig)
{
__IO uint32_t *regaddr;
uint32_t regval;
uint32_t linepos;
uint32_t maskline;
uint32_t offset;
/* Check null pointer */
if ((hexti == NULL) || (pExtiConfig == NULL))
{
return HAL_ERROR;
}
/* Check the parameter */
assert_param(IS_EXTI_LINE(hexti->Line));
/* Store handle line number to configuration structure */
pExtiConfig->Line = hexti->Line;
/* Compute line register offset and line mask */
offset = ((pExtiConfig->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
linepos = (pExtiConfig->Line & EXTI_PIN_MASK);
maskline = (1uL << linepos);
/* 1] Get core mode : interrupt */
regaddr = (&EXTI->IMR1 + (EXTI_MODE_OFFSET * offset));
regval = *regaddr;
/* Check if selected line is enable */
if ((regval & maskline) != 0x00u)
{
pExtiConfig->Mode = EXTI_MODE_INTERRUPT;
}
else
{
pExtiConfig->Mode = EXTI_MODE_NONE;
}
/* Get event mode */
regaddr = (&EXTI->EMR1 + (EXTI_MODE_OFFSET * offset));
regval = *regaddr;
/* Check if selected line is enable */
if ((regval & maskline) != 0x00u)
{
pExtiConfig->Mode |= EXTI_MODE_EVENT;
}
/* Get default Trigger and GPIOSel configuration */
pExtiConfig->Trigger = EXTI_TRIGGER_NONE;
pExtiConfig->GPIOSel = 0x00u;
/* 2] Get trigger for configurable lines : rising */
if ((pExtiConfig->Line & EXTI_CONFIG) != 0x00u)
{
regaddr = (&EXTI->RTSR1 + (EXTI_CONFIG_OFFSET * offset));
regval = *regaddr;
/* Check if configuration of selected line is enable */
if ((regval & maskline) != 0x00u)
{
pExtiConfig->Trigger = EXTI_TRIGGER_RISING;
}
/* Get falling configuration */
regaddr = (&EXTI->FTSR1 + (EXTI_CONFIG_OFFSET * offset));
regval = *regaddr;
/* Check if configuration of selected line is enable */
if ((regval & maskline) != 0x00u)
{
pExtiConfig->Trigger |= EXTI_TRIGGER_FALLING;
}
/* Get Gpio port selection for gpio lines */
if ((pExtiConfig->Line & EXTI_GPIO) == EXTI_GPIO)
{
assert_param(IS_EXTI_GPIO_PIN(linepos));
regval = SYSCFG->EXTICR[linepos >> 2u];
pExtiConfig->GPIOSel = ((regval << (SYSCFG_EXTICR1_EXTI1_Pos * (3uL - (linepos & 0x03u)))) >> 24);
}
}
return HAL_OK;
}
/**
* @brief Clear whole configuration of a dedicated Exti line.
* @param hexti Exti handle.
* @retval HAL Status.
*/
HAL_StatusTypeDef HAL_EXTI_ClearConfigLine(EXTI_HandleTypeDef *hexti)
{
__IO uint32_t *regaddr;
uint32_t regval;
uint32_t linepos;
uint32_t maskline;
uint32_t offset;
/* Check null pointer */
if (hexti == NULL)
{
return HAL_ERROR;
}
/* Check the parameter */
assert_param(IS_EXTI_LINE(hexti->Line));
/* compute line register offset and line mask */
offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
linepos = (hexti->Line & EXTI_PIN_MASK);
maskline = (1uL << linepos);
/* 1] Clear interrupt mode */
regaddr = (&EXTI->IMR1 + (EXTI_MODE_OFFSET * offset));
regval = (*regaddr & ~maskline);
*regaddr = regval;
/* 2] Clear event mode */
regaddr = (&EXTI->EMR1 + (EXTI_MODE_OFFSET * offset));
regval = (*regaddr & ~maskline);
*regaddr = regval;
/* 3] Clear triggers in case of configurable lines */
if ((hexti->Line & EXTI_CONFIG) != 0x00u)
{
regaddr = (&EXTI->RTSR1 + (EXTI_CONFIG_OFFSET * offset));
regval = (*regaddr & ~maskline);
*regaddr = regval;
regaddr = (&EXTI->FTSR1 + (EXTI_CONFIG_OFFSET * offset));
regval = (*regaddr & ~maskline);
*regaddr = regval;
/* Get Gpio port selection for gpio lines */
if ((hexti->Line & EXTI_GPIO) == EXTI_GPIO)
{
assert_param(IS_EXTI_GPIO_PIN(linepos));
regval = SYSCFG->EXTICR[linepos >> 2u];
regval &= ~(SYSCFG_EXTICR1_EXTI0 << (SYSCFG_EXTICR1_EXTI1_Pos * (linepos & 0x03u)));
SYSCFG->EXTICR[linepos >> 2u] = regval;
}
}
return HAL_OK;
}
/**
* @brief Register callback for a dedicated Exti line.
* @param hexti Exti handle.
* @param CallbackID User callback identifier.
* This parameter can be one of @arg @ref EXTI_CallbackIDTypeDef values.
* @param pPendingCbfn function pointer to be stored as callback.
* @retval HAL Status.
*/
HAL_StatusTypeDef HAL_EXTI_RegisterCallback(EXTI_HandleTypeDef *hexti, EXTI_CallbackIDTypeDef CallbackID, void (*pPendingCbfn)(void))
{
HAL_StatusTypeDef status = HAL_OK;
switch (CallbackID)
{
case HAL_EXTI_COMMON_CB_ID:
hexti->PendingCallback = pPendingCbfn;
break;
default:
status = HAL_ERROR;
break;
}
return status;
}
/**
* @brief Store line number as handle private field.
* @param hexti Exti handle.
* @param ExtiLine Exti line number.
* This parameter can be from 0 to @ref EXTI_LINE_NB.
* @retval HAL Status.
*/
HAL_StatusTypeDef HAL_EXTI_GetHandle(EXTI_HandleTypeDef *hexti, uint32_t ExtiLine)
{
/* Check the parameters */
assert_param(IS_EXTI_LINE(ExtiLine));
/* Check null pointer */
if (hexti == NULL)
{
return HAL_ERROR;
}
else
{
/* Store line number as handle private field */
hexti->Line = ExtiLine;
return HAL_OK;
}
}
/**
* @}
*/
/** @addtogroup EXTI_Exported_Functions_Group2
* @brief EXTI IO functions.
*
@verbatim
===============================================================================
##### IO operation functions #####
===============================================================================
@endverbatim
* @{
*/
/**
* @brief Handle EXTI interrupt request.
* @param hexti Exti handle.
* @retval none.
*/
void HAL_EXTI_IRQHandler(EXTI_HandleTypeDef *hexti)
{
__IO uint32_t *regaddr;
uint32_t regval;
uint32_t maskline;
uint32_t offset;
/* Compute line register offset and line mask */
offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
maskline = (1uL << (hexti->Line & EXTI_PIN_MASK));
/* Get pending bit */
regaddr = (&EXTI->PR1 + (EXTI_CONFIG_OFFSET * offset));
regval = (*regaddr & maskline);
if (regval != 0x00u)
{
/* Clear pending bit */
*regaddr = maskline;
/* Call callback */
if (hexti->PendingCallback != NULL)
{
hexti->PendingCallback();
}
}
}
/**
* @brief Get interrupt pending bit of a dedicated line.
* @param hexti Exti handle.
* @param Edge Specify which pending edge as to be checked.
* This parameter can be one of the following values:
* @arg @ref EXTI_TRIGGER_RISING_FALLING
* This parameter is kept for compatibility with other series.
* @retval 1 if interrupt is pending else 0.
*/
uint32_t HAL_EXTI_GetPending(EXTI_HandleTypeDef *hexti, uint32_t Edge)
{
__IO uint32_t *regaddr;
uint32_t regval;
uint32_t linepos;
uint32_t maskline;
uint32_t offset;
/* Check parameters */
assert_param(IS_EXTI_LINE(hexti->Line));
assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
assert_param(IS_EXTI_PENDING_EDGE(Edge));
/* Compute line register offset and line mask */
offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
linepos = (hexti->Line & EXTI_PIN_MASK);
maskline = (1uL << linepos);
/* Get pending bit */
regaddr = (&EXTI->PR1 + (EXTI_CONFIG_OFFSET * offset));
/* return 1 if bit is set else 0 */
regval = ((*regaddr & maskline) >> linepos);
return regval;
}
/**
* @brief Clear interrupt pending bit of a dedicated line.
* @param hexti Exti handle.
* @param Edge Specify which pending edge as to be clear.
* This parameter can be one of the following values:
* @arg @ref EXTI_TRIGGER_RISING_FALLING
* This parameter is kept for compatibility with other series.
* @retval None.
*/
void HAL_EXTI_ClearPending(EXTI_HandleTypeDef *hexti, uint32_t Edge)
{
__IO uint32_t *regaddr;
uint32_t maskline;
uint32_t offset;
/* Check parameters */
assert_param(IS_EXTI_LINE(hexti->Line));
assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
assert_param(IS_EXTI_PENDING_EDGE(Edge));
/* compute line register offset and line mask */
offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
maskline = (1uL << (hexti->Line & EXTI_PIN_MASK));
/* Get pending register address */
regaddr = (&EXTI->PR1 + (EXTI_CONFIG_OFFSET * offset));
/* Clear Pending bit */
*regaddr = maskline;
}
/**
* @brief Generate a software interrupt for a dedicated line.
* @param hexti Exti handle.
* @retval None.
*/
void HAL_EXTI_GenerateSWI(EXTI_HandleTypeDef *hexti)
{
__IO uint32_t *regaddr;
uint32_t maskline;
uint32_t offset;
/* Check parameters */
assert_param(IS_EXTI_LINE(hexti->Line));
assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
/* compute line register offset and line mask */
offset = ((hexti->Line & EXTI_REG_MASK) >> EXTI_REG_SHIFT);
maskline = (1uL << (hexti->Line & EXTI_PIN_MASK));
regaddr = (&EXTI->SWIER1 + (EXTI_CONFIG_OFFSET * offset));
*regaddr = maskline;
}
/**
* @}
*/
/**
* @}
*/
#endif /* HAL_EXTI_MODULE_ENABLED */
/**
* @}
*/
/**
* @}
*/

View File

@@ -1,764 +0,0 @@
/**
******************************************************************************
* @file stm32l4xx_hal_flash.c
* @author MCD Application Team
* @brief FLASH HAL module driver.
* This file provides firmware functions to manage the following
* functionalities of the internal FLASH memory:
* + Program operations functions
* + Memory Control functions
* + Peripheral Errors functions
*
@verbatim
==============================================================================
##### FLASH peripheral features #####
==============================================================================
[..] The Flash memory interface manages CPU AHB I-Code and D-Code accesses
to the Flash memory. It implements the erase and program Flash memory operations
and the read and write protection mechanisms.
[..] The Flash memory interface accelerates code execution with a system of instruction
prefetch and cache lines.
[..] The FLASH main features are:
(+) Flash memory read operations
(+) Flash memory program/erase operations
(+) Read / write protections
(+) Option bytes programming
(+) Prefetch on I-Code
(+) 32 cache lines of 4*64 bits on I-Code
(+) 8 cache lines of 4*64 bits on D-Code
(+) Error code correction (ECC) : Data in flash are 72-bits word
(8 bits added per double word)
##### How to use this driver #####
==============================================================================
[..]
This driver provides functions and macros to configure and program the FLASH
memory of all STM32L4xx devices.
(#) Flash Memory IO Programming functions:
(++) Lock and Unlock the FLASH interface using HAL_FLASH_Unlock() and
HAL_FLASH_Lock() functions
(++) Program functions: double word and fast program (full row programming)
(++) There Two modes of programming :
(+++) Polling mode using HAL_FLASH_Program() function
(+++) Interrupt mode using HAL_FLASH_Program_IT() function
(#) Interrupts and flags management functions :
(++) Handle FLASH interrupts by calling HAL_FLASH_IRQHandler()
(++) Callback functions are called when the flash operations are finished :
HAL_FLASH_EndOfOperationCallback() when everything is ok, otherwise
HAL_FLASH_OperationErrorCallback()
(++) Get error flag status by calling HAL_GetError()
(#) Option bytes management functions :
(++) Lock and Unlock the option bytes using HAL_FLASH_OB_Unlock() and
HAL_FLASH_OB_Lock() functions
(++) Launch the reload of the option bytes using HAL_FLASH_Launch() function.
In this case, a reset is generated
[..]
In addition to these functions, this driver includes a set of macros allowing
to handle the following operations:
(+) Set the latency
(+) Enable/Disable the prefetch buffer
(+) Enable/Disable the Instruction cache and the Data cache
(+) Reset the Instruction cache and the Data cache
(+) Enable/Disable the Flash power-down during low-power run and sleep modes
(+) Enable/Disable the Flash interrupts
(+) Monitor the Flash flags status
@endverbatim
******************************************************************************
* @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.
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32l4xx_hal.h"
/** @addtogroup STM32L4xx_HAL_Driver
* @{
*/
/** @defgroup FLASH FLASH
* @brief FLASH HAL module driver
* @{
*/
#ifdef HAL_FLASH_MODULE_ENABLED
/* Private typedef -----------------------------------------------------------*/
/* Private defines -----------------------------------------------------------*/
#if defined (STM32L4P5xx) || defined (STM32L4Q5xx) || defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
#define FLASH_NB_DOUBLE_WORDS_IN_ROW 64
#else
#define FLASH_NB_DOUBLE_WORDS_IN_ROW 32
#endif
/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/** @defgroup FLASH_Private_Variables FLASH Private Variables
* @{
*/
/**
* @brief Variable used for Program/Erase sectors under interruption
*/
FLASH_ProcessTypeDef pFlash = {.Lock = HAL_UNLOCKED, \
.ErrorCode = HAL_FLASH_ERROR_NONE, \
.ProcedureOnGoing = FLASH_PROC_NONE, \
.Address = 0U, \
.Bank = FLASH_BANK_1, \
.Page = 0U, \
.NbPagesToErase = 0U, \
.CacheToReactivate = FLASH_CACHE_DISABLED};
/**
* @}
*/
/* Private function prototypes -----------------------------------------------*/
/** @defgroup FLASH_Private_Functions FLASH Private Functions
* @{
*/
static void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data);
static void FLASH_Program_Fast(uint32_t Address, uint32_t DataAddress);
/**
* @}
*/
/* Exported functions --------------------------------------------------------*/
/** @defgroup FLASH_Exported_Functions FLASH Exported Functions
* @{
*/
/** @defgroup FLASH_Exported_Functions_Group1 Programming operation functions
* @brief Programming operation functions
*
@verbatim
===============================================================================
##### Programming operation functions #####
===============================================================================
[..]
This subsection provides a set of functions allowing to manage the FLASH
program operations.
@endverbatim
* @{
*/
/**
* @brief Program double word or fast program of a row at a specified address.
* @param TypeProgram Indicate the way to program at a specified address.
* This parameter can be a value of @ref FLASH_Type_Program
* @param Address specifies the address to be programmed.
* @param Data specifies the data to be programmed
* This parameter is the data for the double word program and the address where
* are stored the data for the row fast program
*
* @retval HAL_StatusTypeDef HAL Status
*/
HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
{
HAL_StatusTypeDef status;
uint32_t prog_bit = 0;
/* Process Locked */
__HAL_LOCK(&pFlash);
/* Check the parameters */
assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
if(status == HAL_OK)
{
pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
/* Deactivate the data cache if they are activated to avoid data misbehavior */
if(READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != 0U)
{
/* Disable data cache */
__HAL_FLASH_DATA_CACHE_DISABLE();
pFlash.CacheToReactivate = FLASH_CACHE_DCACHE_ENABLED;
}
else
{
pFlash.CacheToReactivate = FLASH_CACHE_DISABLED;
}
if(TypeProgram == FLASH_TYPEPROGRAM_DOUBLEWORD)
{
/* Program double-word (64-bit) at a specified address */
FLASH_Program_DoubleWord(Address, Data);
prog_bit = FLASH_CR_PG;
}
else if((TypeProgram == FLASH_TYPEPROGRAM_FAST) || (TypeProgram == FLASH_TYPEPROGRAM_FAST_AND_LAST))
{
/* Fast program a 32 row double-word (64-bit) at a specified address */
FLASH_Program_Fast(Address, (uint32_t)Data);
/* If it is the last row, the bit will be cleared at the end of the operation */
if(TypeProgram == FLASH_TYPEPROGRAM_FAST_AND_LAST)
{
prog_bit = FLASH_CR_FSTPG;
}
}
else
{
/* Nothing to do */
}
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
/* If the program operation is completed, disable the PG or FSTPG Bit */
if (prog_bit != 0U)
{
CLEAR_BIT(FLASH->CR, prog_bit);
}
/* Flush the caches to be sure of the data consistency */
FLASH_FlushCaches();
}
/* Process Unlocked */
__HAL_UNLOCK(&pFlash);
return status;
}
/**
* @brief Program double word or fast program of a row at a specified address with interrupt enabled.
* @param TypeProgram Indicate the way to program at a specified address.
* This parameter can be a value of @ref FLASH_Type_Program
* @param Address specifies the address to be programmed.
* @param Data specifies the data to be programmed
* This parameter is the data for the double word program and the address where
* are stored the data for the row fast program
*
* @retval HAL Status
*/
HAL_StatusTypeDef HAL_FLASH_Program_IT(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check the parameters */
assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
/* Process Locked */
__HAL_LOCK(&pFlash);
pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
/* Deactivate the data cache if they are activated to avoid data misbehavior */
if(READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != 0U)
{
/* Disable data cache */
__HAL_FLASH_DATA_CACHE_DISABLE();
pFlash.CacheToReactivate = FLASH_CACHE_DCACHE_ENABLED;
}
else
{
pFlash.CacheToReactivate = FLASH_CACHE_DISABLED;
}
/* Set internal variables used by the IRQ handler */
if(TypeProgram == FLASH_TYPEPROGRAM_FAST_AND_LAST)
{
pFlash.ProcedureOnGoing = FLASH_PROC_PROGRAM_LAST;
}
else
{
pFlash.ProcedureOnGoing = FLASH_PROC_PROGRAM;
}
pFlash.Address = Address;
/* Enable End of Operation and Error interrupts */
__HAL_FLASH_ENABLE_IT(FLASH_IT_EOP | FLASH_IT_OPERR);
if(TypeProgram == FLASH_TYPEPROGRAM_DOUBLEWORD)
{
/* Program double-word (64-bit) at a specified address */
FLASH_Program_DoubleWord(Address, Data);
}
else if((TypeProgram == FLASH_TYPEPROGRAM_FAST) || (TypeProgram == FLASH_TYPEPROGRAM_FAST_AND_LAST))
{
/* Fast program a 32 row double-word (64-bit) at a specified address */
FLASH_Program_Fast(Address, (uint32_t)Data);
}
else
{
/* Nothing to do */
}
return status;
}
/**
* @brief Handle FLASH interrupt request.
* @retval None
*/
void HAL_FLASH_IRQHandler(void)
{
uint32_t tmp_page;
uint32_t error;
FLASH_ProcedureTypeDef procedure;
/* If the operation is completed, disable the PG, PNB, MER1, MER2 and PER Bit */
CLEAR_BIT(FLASH->CR, (FLASH_CR_PG | FLASH_CR_MER1 | FLASH_CR_PER | FLASH_CR_PNB));
#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \
defined (STM32L496xx) || defined (STM32L4A6xx) || \
defined (STM32L4P5xx) || defined (STM32L4Q5xx) || \
defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
CLEAR_BIT(FLASH->CR, FLASH_CR_MER2);
#endif
/* Disable the FSTPG Bit only if it is the last row programmed */
if(pFlash.ProcedureOnGoing == FLASH_PROC_PROGRAM_LAST)
{
CLEAR_BIT(FLASH->CR, FLASH_CR_FSTPG);
}
/* Check FLASH operation error flags */
error = (FLASH->SR & FLASH_FLAG_SR_ERRORS);
if (error !=0U)
{
/*Save the error code*/
pFlash.ErrorCode |= error;
/* Clear error programming flags */
__HAL_FLASH_CLEAR_FLAG(error);
/* Flush the caches to be sure of the data consistency */
FLASH_FlushCaches() ;
/* FLASH error interrupt user callback */
procedure = pFlash.ProcedureOnGoing;
if(procedure == FLASH_PROC_PAGE_ERASE)
{
HAL_FLASH_OperationErrorCallback(pFlash.Page);
}
else if(procedure == FLASH_PROC_MASS_ERASE)
{
HAL_FLASH_OperationErrorCallback(pFlash.Bank);
}
else if((procedure == FLASH_PROC_PROGRAM) ||
(procedure == FLASH_PROC_PROGRAM_LAST))
{
HAL_FLASH_OperationErrorCallback(pFlash.Address);
}
else
{
HAL_FLASH_OperationErrorCallback(0U);
}
/*Stop the procedure ongoing*/
pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
}
/* Check FLASH End of Operation flag */
if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP) != 0U)
{
/* Clear FLASH End of Operation pending bit */
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
if(pFlash.ProcedureOnGoing == FLASH_PROC_PAGE_ERASE)
{
/* Nb of pages to erased can be decreased */
pFlash.NbPagesToErase--;
/* Check if there are still pages to erase*/
if(pFlash.NbPagesToErase != 0U)
{
/* Indicate user which page has been erased*/
HAL_FLASH_EndOfOperationCallback(pFlash.Page);
/* Increment page number */
pFlash.Page++;
tmp_page = pFlash.Page;
FLASH_PageErase(tmp_page, pFlash.Bank);
}
else
{
/* No more pages to Erase */
/* Reset Address and stop Erase pages procedure */
pFlash.Page = 0xFFFFFFFFU;
pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
/* Flush the caches to be sure of the data consistency */
FLASH_FlushCaches() ;
/* FLASH EOP interrupt user callback */
HAL_FLASH_EndOfOperationCallback(pFlash.Page);
}
}
else
{
/* Flush the caches to be sure of the data consistency */
FLASH_FlushCaches() ;
procedure = pFlash.ProcedureOnGoing;
if(procedure == FLASH_PROC_MASS_ERASE)
{
/* MassErase ended. Return the selected bank */
/* FLASH EOP interrupt user callback */
HAL_FLASH_EndOfOperationCallback(pFlash.Bank);
}
else if((procedure == FLASH_PROC_PROGRAM) ||
(procedure == FLASH_PROC_PROGRAM_LAST))
{
/* Program ended. Return the selected address */
/* FLASH EOP interrupt user callback */
HAL_FLASH_EndOfOperationCallback(pFlash.Address);
}
else
{
/* Nothing to do */
}
/*Clear the procedure ongoing*/
pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
}
}
if(pFlash.ProcedureOnGoing == FLASH_PROC_NONE)
{
/* Disable End of Operation and Error interrupts */
__HAL_FLASH_DISABLE_IT(FLASH_IT_EOP | FLASH_IT_OPERR);
/* Process Unlocked */
__HAL_UNLOCK(&pFlash);
}
}
/**
* @brief FLASH end of operation interrupt callback.
* @param ReturnValue The value saved in this parameter depends on the ongoing procedure
* Mass Erase: Bank number which has been requested to erase
* Page Erase: Page which has been erased
* (if 0xFFFFFFFF, it means that all the selected pages have been erased)
* Program: Address which was selected for data program
* @retval None
*/
__weak void HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(ReturnValue);
/* NOTE : This function should not be modified, when the callback is needed,
the HAL_FLASH_EndOfOperationCallback could be implemented in the user file
*/
}
/**
* @brief FLASH operation error interrupt callback.
* @param ReturnValue The value saved in this parameter depends on the ongoing procedure
* Mass Erase: Bank number which has been requested to erase
* Page Erase: Page number which returned an error
* Program: Address which was selected for data program
* @retval None
*/
__weak void HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(ReturnValue);
/* NOTE : This function should not be modified, when the callback is needed,
the HAL_FLASH_OperationErrorCallback could be implemented in the user file
*/
}
/**
* @}
*/
/** @defgroup FLASH_Exported_Functions_Group2 Peripheral Control functions
* @brief Management functions
*
@verbatim
===============================================================================
##### Peripheral Control functions #####
===============================================================================
[..]
This subsection provides a set of functions allowing to control the FLASH
memory operations.
@endverbatim
* @{
*/
/**
* @brief Unlock the FLASH control register access.
* @retval HAL Status
*/
HAL_StatusTypeDef HAL_FLASH_Unlock(void)
{
HAL_StatusTypeDef status = HAL_OK;
if(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0U)
{
/* Authorize the FLASH Registers access */
WRITE_REG(FLASH->KEYR, FLASH_KEY1);
WRITE_REG(FLASH->KEYR, FLASH_KEY2);
/* Verify Flash is unlocked */
if(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0U)
{
status = HAL_ERROR;
}
}
return status;
}
/**
* @brief Lock the FLASH control register access.
* @retval HAL Status
*/
HAL_StatusTypeDef HAL_FLASH_Lock(void)
{
/* Set the LOCK Bit to lock the FLASH Registers access */
SET_BIT(FLASH->CR, FLASH_CR_LOCK);
return HAL_OK;
}
/**
* @brief Unlock the FLASH Option Bytes Registers access.
* @retval HAL Status
*/
HAL_StatusTypeDef HAL_FLASH_OB_Unlock(void)
{
if(READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK) != 0U)
{
/* Authorizes the Option Byte register programming */
WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY1);
WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY2);
}
else
{
return HAL_ERROR;
}
return HAL_OK;
}
/**
* @brief Lock the FLASH Option Bytes Registers access.
* @retval HAL Status
*/
HAL_StatusTypeDef HAL_FLASH_OB_Lock(void)
{
/* Set the OPTLOCK Bit to lock the FLASH Option Byte Registers access */
SET_BIT(FLASH->CR, FLASH_CR_OPTLOCK);
return HAL_OK;
}
/**
* @brief Launch the option byte loading.
* @retval HAL Status
*/
HAL_StatusTypeDef HAL_FLASH_OB_Launch(void)
{
/* Set the bit to force the option byte reloading */
SET_BIT(FLASH->CR, FLASH_CR_OBL_LAUNCH);
/* Wait for last operation to be completed */
return(FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE));
}
/**
* @}
*/
/** @defgroup FLASH_Exported_Functions_Group3 Peripheral State and Errors functions
* @brief Peripheral Errors functions
*
@verbatim
===============================================================================
##### Peripheral Errors functions #####
===============================================================================
[..]
This subsection permits to get in run-time Errors of the FLASH peripheral.
@endverbatim
* @{
*/
/**
* @brief Get the specific FLASH error flag.
* @retval FLASH_ErrorCode: The returned value can be:
* @arg HAL_FLASH_ERROR_RD: FLASH Read Protection error flag (PCROP)
* @arg HAL_FLASH_ERROR_PGS: FLASH Programming Sequence error flag
* @arg HAL_FLASH_ERROR_PGP: FLASH Programming Parallelism error flag
* @arg HAL_FLASH_ERROR_PGA: FLASH Programming Alignment error flag
* @arg HAL_FLASH_ERROR_WRP: FLASH Write protected error flag
* @arg HAL_FLASH_ERROR_OPERATION: FLASH operation Error flag
* @arg HAL_FLASH_ERROR_NONE: No error set
* @arg HAL_FLASH_ERROR_OP: FLASH Operation error
* @arg HAL_FLASH_ERROR_PROG: FLASH Programming error
* @arg HAL_FLASH_ERROR_WRP: FLASH Write protection error
* @arg HAL_FLASH_ERROR_PGA: FLASH Programming alignment error
* @arg HAL_FLASH_ERROR_SIZ: FLASH Size error
* @arg HAL_FLASH_ERROR_PGS: FLASH Programming sequence error
* @arg HAL_FLASH_ERROR_MIS: FLASH Fast programming data miss error
* @arg HAL_FLASH_ERROR_FAST: FLASH Fast programming error
* @arg HAL_FLASH_ERROR_RD: FLASH PCROP read error
* @arg HAL_FLASH_ERROR_OPTV: FLASH Option validity error
* @arg FLASH_FLAG_PEMPTY : FLASH Boot from not programmed flash (apply only for STM32L43x/STM32L44x devices)
*/
uint32_t HAL_FLASH_GetError(void)
{
return pFlash.ErrorCode;
}
/**
* @}
*/
/**
* @}
*/
/* Private functions ---------------------------------------------------------*/
/** @addtogroup FLASH_Private_Functions
* @{
*/
/**
* @brief Wait for a FLASH operation to complete.
* @param Timeout maximum flash operation timeout
* @retval HAL_StatusTypeDef HAL Status
*/
HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout)
{
/* Wait for the FLASH operation to complete by polling on BUSY flag to be reset.
Even if the FLASH operation fails, the BUSY flag will be reset and an error
flag will be set */
uint32_t tickstart = HAL_GetTick();
uint32_t error;
while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY))
{
if(Timeout != HAL_MAX_DELAY)
{
if((HAL_GetTick() - tickstart) >= Timeout)
{
return HAL_TIMEOUT;
}
}
}
error = (FLASH->SR & FLASH_FLAG_SR_ERRORS);
if(error != 0u)
{
/*Save the error code*/
pFlash.ErrorCode |= error;
/* Clear error programming flags */
__HAL_FLASH_CLEAR_FLAG(error);
return HAL_ERROR;
}
/* Check FLASH End of Operation flag */
if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP))
{
/* Clear FLASH End of Operation pending bit */
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
}
/* If there is an error flag set */
return HAL_OK;
}
/**
* @brief Program double-word (64-bit) at a specified address.
* @param Address specifies the address to be programmed.
* @param Data specifies the data to be programmed.
* @retval None
*/
static void FLASH_Program_DoubleWord(uint32_t Address, uint64_t Data)
{
/* Check the parameters */
assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
/* Set PG bit */
SET_BIT(FLASH->CR, FLASH_CR_PG);
/* Program first word */
*(__IO uint32_t*)Address = (uint32_t)Data;
/* Barrier to ensure programming is performed in 2 steps, in right order
(independently of compiler optimization behavior) */
__ISB();
/* Program second word */
*(__IO uint32_t*)(Address+4U) = (uint32_t)(Data >> 32);
}
/**
* @brief Fast program a row double-word (64-bit) at a specified address.
* @param Address specifies the address to be programmed.
* @param DataAddress specifies the address where the data are stored.
* @retval None
*/
static void FLASH_Program_Fast(uint32_t Address, uint32_t DataAddress)
{
uint32_t primask_bit;
uint8_t row_index = (2*FLASH_NB_DOUBLE_WORDS_IN_ROW);
__IO uint32_t *dest_addr = (__IO uint32_t*)Address;
__IO uint32_t *src_addr = (__IO uint32_t*)DataAddress;
/* Check the parameters */
assert_param(IS_FLASH_MAIN_MEM_ADDRESS(Address));
/* Set FSTPG bit */
SET_BIT(FLASH->CR, FLASH_CR_FSTPG);
/* Disable interrupts to avoid any interruption during the loop */
primask_bit = __get_PRIMASK();
__disable_irq();
/* Program the double word of the row */
do
{
*dest_addr = *src_addr;
dest_addr++;
src_addr++;
row_index--;
} while (row_index != 0U);
/* Re-enable the interrupts */
__set_PRIMASK(primask_bit);
}
/**
* @}
*/
#endif /* HAL_FLASH_MODULE_ENABLED */
/**
* @}
*/
/**
* @}
*/

View File

@@ -1,1316 +0,0 @@
/**
******************************************************************************
* @file stm32l4xx_hal_flash_ex.c
* @author MCD Application Team
* @brief Extended FLASH HAL module driver.
* This file provides firmware functions to manage the following
* functionalities of the FLASH extended peripheral:
* + Extended programming operations functions
*
@verbatim
==============================================================================
##### Flash Extended features #####
==============================================================================
[..] Comparing to other previous devices, the FLASH interface for STM32L4xx
devices contains the following additional features
(+) Capacity up to 2 Mbyte with dual bank architecture supporting read-while-write
capability (RWW)
(+) Dual bank memory organization
(+) PCROP protection for all banks
##### How to use this driver #####
==============================================================================
[..] This driver provides functions to configure and program the FLASH memory
of all STM32L4xx devices. It includes
(#) Flash Memory Erase functions:
(++) Lock and Unlock the FLASH interface using HAL_FLASH_Unlock() and
HAL_FLASH_Lock() functions
(++) Erase function: Erase page, erase all sectors
(++) There are two modes of erase :
(+++) Polling Mode using HAL_FLASHEx_Erase()
(+++) Interrupt Mode using HAL_FLASHEx_Erase_IT()
(#) Option Bytes Programming function: Use HAL_FLASHEx_OBProgram() to :
(++) Set/Reset the write protection
(++) Set the Read protection Level
(++) Program the user Option Bytes
(++) Configure the PCROP protection
(#) Get Option Bytes Configuration function: Use HAL_FLASHEx_OBGetConfig() to :
(++) Get the value of a write protection area
(++) Know if the read protection is activated
(++) Get the value of the user Option Bytes
(++) Get the value of a PCROP area
@endverbatim
******************************************************************************
* @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.
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32l4xx_hal.h"
/** @addtogroup STM32L4xx_HAL_Driver
* @{
*/
/** @defgroup FLASHEx FLASHEx
* @brief FLASH Extended HAL module driver
* @{
*/
#ifdef HAL_FLASH_MODULE_ENABLED
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/** @defgroup FLASHEx_Private_Functions FLASHEx Private Functions
* @{
*/
static void FLASH_MassErase(uint32_t Banks);
static HAL_StatusTypeDef FLASH_OB_WRPConfig(uint32_t WRPArea, uint32_t WRPStartOffset, uint32_t WRDPEndOffset);
static HAL_StatusTypeDef FLASH_OB_RDPConfig(uint32_t RDPLevel);
static HAL_StatusTypeDef FLASH_OB_UserConfig(uint32_t UserType, uint32_t UserConfig);
static HAL_StatusTypeDef FLASH_OB_PCROPConfig(uint32_t PCROPConfig, uint32_t PCROPStartAddr, uint32_t PCROPEndAddr);
static void FLASH_OB_GetWRP(uint32_t WRPArea, uint32_t * WRPStartOffset, uint32_t * WRDPEndOffset);
static uint32_t FLASH_OB_GetRDP(void);
static uint32_t FLASH_OB_GetUser(void);
static void FLASH_OB_GetPCROP(uint32_t * PCROPConfig, uint32_t * PCROPStartAddr, uint32_t * PCROPEndAddr);
/**
* @}
*/
/* Exported functions -------------------------------------------------------*/
/** @defgroup FLASHEx_Exported_Functions FLASHEx Exported Functions
* @{
*/
/** @defgroup FLASHEx_Exported_Functions_Group1 Extended IO operation functions
* @brief Extended IO operation functions
*
@verbatim
===============================================================================
##### Extended programming operation functions #####
===============================================================================
[..]
This subsection provides a set of functions allowing to manage the Extended FLASH
programming operations Operations.
@endverbatim
* @{
*/
/**
* @brief Perform a mass erase or erase the specified FLASH memory pages.
* @param[in] pEraseInit: pointer to an FLASH_EraseInitTypeDef structure that
* contains the configuration information for the erasing.
*
* @param[out] PageError : pointer to variable that contains the configuration
* information on faulty page in case of error (0xFFFFFFFF means that all
* the pages have been correctly erased)
*
* @retval HAL Status
*/
HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *PageError)
{
HAL_StatusTypeDef status;
uint32_t page_index;
/* Process Locked */
__HAL_LOCK(&pFlash);
/* Check the parameters */
assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase));
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
if (status == HAL_OK)
{
pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
/* Deactivate the cache if they are activated to avoid data misbehavior */
if(READ_BIT(FLASH->ACR, FLASH_ACR_ICEN) != 0U)
{
if(READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != 0U)
{
/* Disable data cache */
__HAL_FLASH_DATA_CACHE_DISABLE();
pFlash.CacheToReactivate = FLASH_CACHE_ICACHE_DCACHE_ENABLED;
}
else
{
pFlash.CacheToReactivate = FLASH_CACHE_ICACHE_ENABLED;
}
}
else if(READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != 0U)
{
/* Disable data cache */
__HAL_FLASH_DATA_CACHE_DISABLE();
pFlash.CacheToReactivate = FLASH_CACHE_DCACHE_ENABLED;
}
else
{
pFlash.CacheToReactivate = FLASH_CACHE_DISABLED;
}
if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE)
{
/* Mass erase to be done */
FLASH_MassErase(pEraseInit->Banks);
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \
defined (STM32L496xx) || defined (STM32L4A6xx) || \
defined (STM32L4P5xx) || defined (STM32L4Q5xx) || \
defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
/* If the erase operation is completed, disable the MER1 and MER2 Bits */
CLEAR_BIT(FLASH->CR, (FLASH_CR_MER1 | FLASH_CR_MER2));
#else
/* If the erase operation is completed, disable the MER1 Bit */
CLEAR_BIT(FLASH->CR, (FLASH_CR_MER1));
#endif
}
else
{
/*Initialization of PageError variable*/
*PageError = 0xFFFFFFFFU;
for(page_index = pEraseInit->Page; page_index < (pEraseInit->Page + pEraseInit->NbPages); page_index++)
{
FLASH_PageErase(page_index, pEraseInit->Banks);
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
/* If the erase operation is completed, disable the PER Bit */
CLEAR_BIT(FLASH->CR, (FLASH_CR_PER | FLASH_CR_PNB));
if (status != HAL_OK)
{
/* In case of error, stop erase procedure and return the faulty address */
*PageError = page_index;
break;
}
}
}
/* Flush the caches to be sure of the data consistency */
FLASH_FlushCaches();
}
/* Process Unlocked */
__HAL_UNLOCK(&pFlash);
return status;
}
/**
* @brief Perform a mass erase or erase the specified FLASH memory pages with interrupt enabled.
* @param pEraseInit pointer to an FLASH_EraseInitTypeDef structure that
* contains the configuration information for the erasing.
*
* @retval HAL Status
*/
HAL_StatusTypeDef HAL_FLASHEx_Erase_IT(FLASH_EraseInitTypeDef *pEraseInit)
{
HAL_StatusTypeDef status = HAL_OK;
/* Process Locked */
__HAL_LOCK(&pFlash);
/* Check the parameters */
assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase));
pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
/* Deactivate the cache if they are activated to avoid data misbehavior */
if(READ_BIT(FLASH->ACR, FLASH_ACR_ICEN) != 0U)
{
if(READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != 0U)
{
/* Disable data cache */
__HAL_FLASH_DATA_CACHE_DISABLE();
pFlash.CacheToReactivate = FLASH_CACHE_ICACHE_DCACHE_ENABLED;
}
else
{
pFlash.CacheToReactivate = FLASH_CACHE_ICACHE_ENABLED;
}
}
else if(READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != 0U)
{
/* Disable data cache */
__HAL_FLASH_DATA_CACHE_DISABLE();
pFlash.CacheToReactivate = FLASH_CACHE_DCACHE_ENABLED;
}
else
{
pFlash.CacheToReactivate = FLASH_CACHE_DISABLED;
}
/* Enable End of Operation and Error interrupts */
__HAL_FLASH_ENABLE_IT(FLASH_IT_EOP | FLASH_IT_OPERR);
pFlash.Bank = pEraseInit->Banks;
if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE)
{
/* Mass erase to be done */
pFlash.ProcedureOnGoing = FLASH_PROC_MASS_ERASE;
FLASH_MassErase(pEraseInit->Banks);
}
else
{
/* Erase by page to be done */
pFlash.ProcedureOnGoing = FLASH_PROC_PAGE_ERASE;
pFlash.NbPagesToErase = pEraseInit->NbPages;
pFlash.Page = pEraseInit->Page;
/*Erase 1st page and wait for IT */
FLASH_PageErase(pEraseInit->Page, pEraseInit->Banks);
}
return status;
}
/**
* @brief Program Option bytes.
* @param pOBInit pointer to an FLASH_OBInitStruct structure that
* contains the configuration information for the programming.
*
* @retval HAL Status
*/
HAL_StatusTypeDef HAL_FLASHEx_OBProgram(FLASH_OBProgramInitTypeDef *pOBInit)
{
HAL_StatusTypeDef status = HAL_OK;
/* Process Locked */
__HAL_LOCK(&pFlash);
/* Check the parameters */
assert_param(IS_OPTIONBYTE(pOBInit->OptionType));
pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
/* Write protection configuration */
if((pOBInit->OptionType & OPTIONBYTE_WRP) != 0U)
{
/* Configure of Write protection on the selected area */
if(FLASH_OB_WRPConfig(pOBInit->WRPArea, pOBInit->WRPStartOffset, pOBInit->WRPEndOffset) != HAL_OK)
{
status = HAL_ERROR;
}
}
/* Read protection configuration */
if((pOBInit->OptionType & OPTIONBYTE_RDP) != 0U)
{
/* Configure the Read protection level */
if(FLASH_OB_RDPConfig(pOBInit->RDPLevel) != HAL_OK)
{
status = HAL_ERROR;
}
}
/* User Configuration */
if((pOBInit->OptionType & OPTIONBYTE_USER) != 0U)
{
/* Configure the user option bytes */
if(FLASH_OB_UserConfig(pOBInit->USERType, pOBInit->USERConfig) != HAL_OK)
{
status = HAL_ERROR;
}
}
/* PCROP Configuration */
if((pOBInit->OptionType & OPTIONBYTE_PCROP) != 0U)
{
if (pOBInit->PCROPStartAddr != pOBInit->PCROPEndAddr)
{
/* Configure the Proprietary code readout protection */
if(FLASH_OB_PCROPConfig(pOBInit->PCROPConfig, pOBInit->PCROPStartAddr, pOBInit->PCROPEndAddr) != HAL_OK)
{
status = HAL_ERROR;
}
}
}
/* Process Unlocked */
__HAL_UNLOCK(&pFlash);
return status;
}
/**
* @brief Get the Option bytes configuration.
* @param pOBInit pointer to an FLASH_OBInitStruct structure that contains the
* configuration information.
* @note The fields pOBInit->WRPArea and pOBInit->PCROPConfig should indicate
* which area is requested for the WRP and PCROP, else no information will be returned
*
* @retval None
*/
void HAL_FLASHEx_OBGetConfig(FLASH_OBProgramInitTypeDef *pOBInit)
{
pOBInit->OptionType = (OPTIONBYTE_RDP | OPTIONBYTE_USER);
#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \
defined (STM32L496xx) || defined (STM32L4A6xx) || \
defined (STM32L4P5xx) || defined (STM32L4Q5xx) || \
defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
if((pOBInit->WRPArea == OB_WRPAREA_BANK1_AREAA) || (pOBInit->WRPArea == OB_WRPAREA_BANK1_AREAB) ||
(pOBInit->WRPArea == OB_WRPAREA_BANK2_AREAA) || (pOBInit->WRPArea == OB_WRPAREA_BANK2_AREAB))
#else
if((pOBInit->WRPArea == OB_WRPAREA_BANK1_AREAA) || (pOBInit->WRPArea == OB_WRPAREA_BANK1_AREAB))
#endif
{
pOBInit->OptionType |= OPTIONBYTE_WRP;
/* Get write protection on the selected area */
FLASH_OB_GetWRP(pOBInit->WRPArea, &(pOBInit->WRPStartOffset), &(pOBInit->WRPEndOffset));
}
/* Get Read protection level */
pOBInit->RDPLevel = FLASH_OB_GetRDP();
/* Get the user option bytes */
pOBInit->USERConfig = FLASH_OB_GetUser();
#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \
defined (STM32L496xx) || defined (STM32L4A6xx) || \
defined (STM32L4P5xx) || defined (STM32L4Q5xx) || \
defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
if((pOBInit->PCROPConfig == FLASH_BANK_1) || (pOBInit->PCROPConfig == FLASH_BANK_2))
#else
if(pOBInit->PCROPConfig == FLASH_BANK_1)
#endif
{
pOBInit->OptionType |= OPTIONBYTE_PCROP;
/* Get the Proprietary code readout protection */
FLASH_OB_GetPCROP(&(pOBInit->PCROPConfig), &(pOBInit->PCROPStartAddr), &(pOBInit->PCROPEndAddr));
}
}
/**
* @}
*/
#if defined (FLASH_CFGR_LVEN)
/** @defgroup FLASHEx_Exported_Functions_Group2 Extended specific configuration functions
* @brief Extended specific configuration functions
*
@verbatim
===============================================================================
##### Extended specific configuration functions #####
===============================================================================
[..]
This subsection provides a set of functions allowing to manage the Extended FLASH
specific configurations.
@endverbatim
* @{
*/
/**
* @brief Configuration of the LVE pin of the Flash (managed by power controller
* or forced to low in order to use an external SMPS)
* @param ConfigLVE Configuration of the LVE pin,
* This parameter can be one of the following values:
* @arg FLASH_LVE_PIN_CTRL: LVE FLASH pin controlled by power controller
* @arg FLASH_LVE_PIN_FORCED: LVE FLASH pin enforced to low (external SMPS used)
*
* @note Before enforcing the LVE pin to low, the SOC should be in low voltage
* range 2 and the voltage VDD12 should be higher than 1.08V and SMPS is ON.
*
* @retval HAL Status
*/
HAL_StatusTypeDef HAL_FLASHEx_ConfigLVEPin(uint32_t ConfigLVE)
{
HAL_StatusTypeDef status;
/* Process Locked */
__HAL_LOCK(&pFlash);
/* Check the parameters */
assert_param(IS_FLASH_LVE_PIN(ConfigLVE));
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
if (status == HAL_OK)
{
/* Check that the voltage scaling is range 2 */
if (HAL_PWREx_GetVoltageRange() == PWR_REGULATOR_VOLTAGE_SCALE2)
{
/* Configure the LVEN bit */
MODIFY_REG(FLASH->CFGR, FLASH_CFGR_LVEN, ConfigLVE);
/* Check that the bit has been correctly configured */
if (READ_BIT(FLASH->CFGR, FLASH_CFGR_LVEN) != ConfigLVE)
{
status = HAL_ERROR;
}
}
else
{
/* Not allow to force Flash LVE pin if not in voltage range 2 */
status = HAL_ERROR;
}
}
/* Process Unlocked */
__HAL_UNLOCK(&pFlash);
return status;
}
/**
* @}
*/
#endif /* FLASH_CFGR_LVEN */
/**
* @}
*/
/* Private functions ---------------------------------------------------------*/
/** @addtogroup FLASHEx_Private_Functions
* @{
*/
/**
* @brief Mass erase of FLASH memory.
* @param Banks Banks to be erased
* This parameter can be one of the following values:
* @arg FLASH_BANK_1: Bank1 to be erased
* @arg FLASH_BANK_2: Bank2 to be erased
* @arg FLASH_BANK_BOTH: Bank1 and Bank2 to be erased
* @retval None
*/
static void FLASH_MassErase(uint32_t Banks)
{
#if defined (STM32L4P5xx) || defined (STM32L4Q5xx) || defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
if (READ_BIT(FLASH->OPTR, FLASH_OPTR_DBANK) != 0U)
#endif
{
/* Check the parameters */
assert_param(IS_FLASH_BANK(Banks));
/* Set the Mass Erase Bit for the bank 1 if requested */
if((Banks & FLASH_BANK_1) != 0U)
{
SET_BIT(FLASH->CR, FLASH_CR_MER1);
}
#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \
defined (STM32L496xx) || defined (STM32L4A6xx) || \
defined (STM32L4P5xx) || defined (STM32L4Q5xx) || \
defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
/* Set the Mass Erase Bit for the bank 2 if requested */
if((Banks & FLASH_BANK_2) != 0U)
{
SET_BIT(FLASH->CR, FLASH_CR_MER2);
}
#endif
}
#if defined (STM32L4P5xx) || defined (STM32L4Q5xx) || defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
else
{
SET_BIT(FLASH->CR, (FLASH_CR_MER1 | FLASH_CR_MER2));
}
#endif
/* Proceed to erase all sectors */
SET_BIT(FLASH->CR, FLASH_CR_STRT);
}
/**
* @brief Erase the specified FLASH memory page.
* @param Page FLASH page to erase
* This parameter must be a value between 0 and (max number of pages in the bank - 1)
* @param Banks Bank(s) where the page will be erased
* This parameter can be one of the following values:
* @arg FLASH_BANK_1: Page in bank 1 to be erased
* @arg FLASH_BANK_2: Page in bank 2 to be erased
* @retval None
*/
void FLASH_PageErase(uint32_t Page, uint32_t Banks)
{
/* Check the parameters */
assert_param(IS_FLASH_PAGE(Page));
#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \
defined (STM32L496xx) || defined (STM32L4A6xx) || \
defined (STM32L4P5xx) || defined (STM32L4Q5xx) || \
defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
#if defined (STM32L4P5xx) || defined (STM32L4Q5xx) || defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
if(READ_BIT(FLASH->OPTR, FLASH_OPTR_DBANK) == 0U)
{
CLEAR_BIT(FLASH->CR, FLASH_CR_BKER);
}
else
#endif
{
assert_param(IS_FLASH_BANK_EXCLUSIVE(Banks));
if((Banks & FLASH_BANK_1) != 0U)
{
CLEAR_BIT(FLASH->CR, FLASH_CR_BKER);
}
else
{
SET_BIT(FLASH->CR, FLASH_CR_BKER);
}
}
#else
/* Prevent unused argument(s) compilation warning */
UNUSED(Banks);
#endif
/* Proceed to erase the page */
MODIFY_REG(FLASH->CR, FLASH_CR_PNB, ((Page & 0xFFU) << FLASH_CR_PNB_Pos));
SET_BIT(FLASH->CR, FLASH_CR_PER);
SET_BIT(FLASH->CR, FLASH_CR_STRT);
}
/**
* @brief Flush the instruction and data caches.
* @retval None
*/
void FLASH_FlushCaches(void)
{
FLASH_CacheTypeDef cache = pFlash.CacheToReactivate;
/* Flush instruction cache */
if((cache == FLASH_CACHE_ICACHE_ENABLED) ||
(cache == FLASH_CACHE_ICACHE_DCACHE_ENABLED))
{
/* Disable instruction cache */
__HAL_FLASH_INSTRUCTION_CACHE_DISABLE();
/* Reset instruction cache */
__HAL_FLASH_INSTRUCTION_CACHE_RESET();
/* Enable instruction cache */
__HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
}
/* Flush data cache */
if((cache == FLASH_CACHE_DCACHE_ENABLED) ||
(cache == FLASH_CACHE_ICACHE_DCACHE_ENABLED))
{
/* Reset data cache */
__HAL_FLASH_DATA_CACHE_RESET();
/* Enable data cache */
__HAL_FLASH_DATA_CACHE_ENABLE();
}
/* Reset internal variable */
pFlash.CacheToReactivate = FLASH_CACHE_DISABLED;
}
/**
* @brief Configure the write protection of the desired pages.
*
* @note When the memory read protection level is selected (RDP level = 1),
* it is not possible to program or erase Flash memory if the CPU debug
* features are connected (JTAG or single wire) or boot code is being
* executed from RAM or System flash, even if WRP is not activated.
* @note To configure the WRP options, the option lock bit OPTLOCK must be
* cleared with the call of the HAL_FLASH_OB_Unlock() function.
* @note To validate the WRP options, the option bytes must be reloaded
* through the call of the HAL_FLASH_OB_Launch() function.
*
* @param WRPArea specifies the area to be configured.
* This parameter can be one of the following values:
* @arg OB_WRPAREA_BANK1_AREAA: Flash Bank 1 Area A
* @arg OB_WRPAREA_BANK1_AREAB: Flash Bank 1 Area B
* @arg OB_WRPAREA_BANK2_AREAA: Flash Bank 2 Area A (don't apply for STM32L43x/STM32L44x devices)
* @arg OB_WRPAREA_BANK2_AREAB: Flash Bank 2 Area B (don't apply for STM32L43x/STM32L44x devices)
*
* @param WRPStartOffset specifies the start page of the write protected area
* This parameter can be page number between 0 and (max number of pages in the bank - 1)
*
* @param WRDPEndOffset specifies the end page of the write protected area
* This parameter can be page number between WRPStartOffset and (max number of pages in the bank - 1)
*
* @retval HAL Status
*/
static HAL_StatusTypeDef FLASH_OB_WRPConfig(uint32_t WRPArea, uint32_t WRPStartOffset, uint32_t WRDPEndOffset)
{
HAL_StatusTypeDef status;
/* Check the parameters */
assert_param(IS_OB_WRPAREA(WRPArea));
assert_param(IS_FLASH_PAGE(WRPStartOffset));
assert_param(IS_FLASH_PAGE(WRDPEndOffset));
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
if(status == HAL_OK)
{
/* Configure the write protected area */
if(WRPArea == OB_WRPAREA_BANK1_AREAA)
{
MODIFY_REG(FLASH->WRP1AR, (FLASH_WRP1AR_WRP1A_STRT | FLASH_WRP1AR_WRP1A_END),
(WRPStartOffset | (WRDPEndOffset << 16)));
}
else if(WRPArea == OB_WRPAREA_BANK1_AREAB)
{
MODIFY_REG(FLASH->WRP1BR, (FLASH_WRP1BR_WRP1B_STRT | FLASH_WRP1BR_WRP1B_END),
(WRPStartOffset | (WRDPEndOffset << 16)));
}
#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \
defined (STM32L496xx) || defined (STM32L4A6xx) || \
defined (STM32L4P5xx) || defined (STM32L4Q5xx) || \
defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
else if(WRPArea == OB_WRPAREA_BANK2_AREAA)
{
MODIFY_REG(FLASH->WRP2AR, (FLASH_WRP2AR_WRP2A_STRT | FLASH_WRP2AR_WRP2A_END),
(WRPStartOffset | (WRDPEndOffset << 16)));
}
else if(WRPArea == OB_WRPAREA_BANK2_AREAB)
{
MODIFY_REG(FLASH->WRP2BR, (FLASH_WRP2BR_WRP2B_STRT | FLASH_WRP2BR_WRP2B_END),
(WRPStartOffset | (WRDPEndOffset << 16)));
}
#endif
else
{
/* Nothing to do */
}
/* Set OPTSTRT Bit */
SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
/* If the option byte program operation is completed, disable the OPTSTRT Bit */
CLEAR_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
}
return status;
}
/**
* @brief Set the read protection level.
*
* @note To configure the RDP level, the option lock bit OPTLOCK must be
* cleared with the call of the HAL_FLASH_OB_Unlock() function.
* @note To validate the RDP level, the option bytes must be reloaded
* through the call of the HAL_FLASH_OB_Launch() function.
* @note !!! Warning : When enabling OB_RDP level 2 it's no more possible
* to go back to level 1 or 0 !!!
*
* @param RDPLevel specifies the read protection level.
* This parameter can be one of the following values:
* @arg OB_RDP_LEVEL_0: No protection
* @arg OB_RDP_LEVEL_1: Read protection of the memory
* @arg OB_RDP_LEVEL_2: Full chip protection
*
* @retval HAL status
*/
static HAL_StatusTypeDef FLASH_OB_RDPConfig(uint32_t RDPLevel)
{
HAL_StatusTypeDef status;
/* Check the parameters */
assert_param(IS_OB_RDP_LEVEL(RDPLevel));
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
if(status == HAL_OK)
{
/* Configure the RDP level in the option bytes register */
MODIFY_REG(FLASH->OPTR, FLASH_OPTR_RDP, RDPLevel);
/* Set OPTSTRT Bit */
SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
/* If the option byte program operation is completed, disable the OPTSTRT Bit */
CLEAR_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
}
return status;
}
/**
* @brief Program the FLASH User Option Byte.
*
* @note To configure the user option bytes, the option lock bit OPTLOCK must
* be cleared with the call of the HAL_FLASH_OB_Unlock() function.
* @note To validate the user option bytes, the option bytes must be reloaded
* through the call of the HAL_FLASH_OB_Launch() function.
*
* @param UserType The FLASH User Option Bytes to be modified
* @param UserConfig The FLASH User Option Bytes values:
* BOR_LEV(Bit8-10), nRST_STOP(Bit12), nRST_STDBY(Bit13), IWDG_SW(Bit16),
* IWDG_STOP(Bit17), IWDG_STDBY(Bit18), WWDG_SW(Bit19), BFB2(Bit20),
* DUALBANK(Bit21), nBOOT1(Bit23), SRAM2_PE(Bit24) and SRAM2_RST(Bit25).
*
* @retval HAL status
*/
static HAL_StatusTypeDef FLASH_OB_UserConfig(uint32_t UserType, uint32_t UserConfig)
{
uint32_t optr_reg_val = 0;
uint32_t optr_reg_mask = 0;
HAL_StatusTypeDef status;
/* Check the parameters */
assert_param(IS_OB_USER_TYPE(UserType));
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
if(status == HAL_OK)
{
if((UserType & OB_USER_BOR_LEV) != 0U)
{
/* BOR level option byte should be modified */
assert_param(IS_OB_USER_BOR_LEVEL(UserConfig & FLASH_OPTR_BOR_LEV));
/* Set value and mask for BOR level option byte */
optr_reg_val |= (UserConfig & FLASH_OPTR_BOR_LEV);
optr_reg_mask |= FLASH_OPTR_BOR_LEV;
}
if((UserType & OB_USER_nRST_STOP) != 0U)
{
/* nRST_STOP option byte should be modified */
assert_param(IS_OB_USER_STOP(UserConfig & FLASH_OPTR_nRST_STOP));
/* Set value and mask for nRST_STOP option byte */
optr_reg_val |= (UserConfig & FLASH_OPTR_nRST_STOP);
optr_reg_mask |= FLASH_OPTR_nRST_STOP;
}
if((UserType & OB_USER_nRST_STDBY) != 0U)
{
/* nRST_STDBY option byte should be modified */
assert_param(IS_OB_USER_STANDBY(UserConfig & FLASH_OPTR_nRST_STDBY));
/* Set value and mask for nRST_STDBY option byte */
optr_reg_val |= (UserConfig & FLASH_OPTR_nRST_STDBY);
optr_reg_mask |= FLASH_OPTR_nRST_STDBY;
}
if((UserType & OB_USER_nRST_SHDW) != 0U)
{
/* nRST_SHDW option byte should be modified */
assert_param(IS_OB_USER_SHUTDOWN(UserConfig & FLASH_OPTR_nRST_SHDW));
/* Set value and mask for nRST_SHDW option byte */
optr_reg_val |= (UserConfig & FLASH_OPTR_nRST_SHDW);
optr_reg_mask |= FLASH_OPTR_nRST_SHDW;
}
if((UserType & OB_USER_IWDG_SW) != 0U)
{
/* IWDG_SW option byte should be modified */
assert_param(IS_OB_USER_IWDG(UserConfig & FLASH_OPTR_IWDG_SW));
/* Set value and mask for IWDG_SW option byte */
optr_reg_val |= (UserConfig & FLASH_OPTR_IWDG_SW);
optr_reg_mask |= FLASH_OPTR_IWDG_SW;
}
if((UserType & OB_USER_IWDG_STOP) != 0U)
{
/* IWDG_STOP option byte should be modified */
assert_param(IS_OB_USER_IWDG_STOP(UserConfig & FLASH_OPTR_IWDG_STOP));
/* Set value and mask for IWDG_STOP option byte */
optr_reg_val |= (UserConfig & FLASH_OPTR_IWDG_STOP);
optr_reg_mask |= FLASH_OPTR_IWDG_STOP;
}
if((UserType & OB_USER_IWDG_STDBY) != 0U)
{
/* IWDG_STDBY option byte should be modified */
assert_param(IS_OB_USER_IWDG_STDBY(UserConfig & FLASH_OPTR_IWDG_STDBY));
/* Set value and mask for IWDG_STDBY option byte */
optr_reg_val |= (UserConfig & FLASH_OPTR_IWDG_STDBY);
optr_reg_mask |= FLASH_OPTR_IWDG_STDBY;
}
if((UserType & OB_USER_WWDG_SW) != 0U)
{
/* WWDG_SW option byte should be modified */
assert_param(IS_OB_USER_WWDG(UserConfig & FLASH_OPTR_WWDG_SW));
/* Set value and mask for WWDG_SW option byte */
optr_reg_val |= (UserConfig & FLASH_OPTR_WWDG_SW);
optr_reg_mask |= FLASH_OPTR_WWDG_SW;
}
#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \
defined (STM32L496xx) || defined (STM32L4A6xx) || \
defined (STM32L4P5xx) || defined (STM32L4Q5xx) || \
defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
if((UserType & OB_USER_BFB2) != 0U)
{
/* BFB2 option byte should be modified */
assert_param(IS_OB_USER_BFB2(UserConfig & FLASH_OPTR_BFB2));
/* Set value and mask for BFB2 option byte */
optr_reg_val |= (UserConfig & FLASH_OPTR_BFB2);
optr_reg_mask |= FLASH_OPTR_BFB2;
}
if((UserType & OB_USER_DUALBANK) != 0U)
{
#if defined (STM32L4P5xx) || defined (STM32L4Q5xx) || defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
/* DUALBANK option byte should be modified */
assert_param(IS_OB_USER_DUALBANK(UserConfig & FLASH_OPTR_DB1M));
/* Set value and mask for DUALBANK option byte */
optr_reg_val |= (UserConfig & FLASH_OPTR_DB1M);
optr_reg_mask |= FLASH_OPTR_DB1M;
#else
/* DUALBANK option byte should be modified */
assert_param(IS_OB_USER_DUALBANK(UserConfig & FLASH_OPTR_DUALBANK));
/* Set value and mask for DUALBANK option byte */
optr_reg_val |= (UserConfig & FLASH_OPTR_DUALBANK);
optr_reg_mask |= FLASH_OPTR_DUALBANK;
#endif
}
#endif
if((UserType & OB_USER_nBOOT1) != 0U)
{
/* nBOOT1 option byte should be modified */
assert_param(IS_OB_USER_BOOT1(UserConfig & FLASH_OPTR_nBOOT1));
/* Set value and mask for nBOOT1 option byte */
optr_reg_val |= (UserConfig & FLASH_OPTR_nBOOT1);
optr_reg_mask |= FLASH_OPTR_nBOOT1;
}
if((UserType & OB_USER_SRAM2_PE) != 0U)
{
/* SRAM2_PE option byte should be modified */
assert_param(IS_OB_USER_SRAM2_PARITY(UserConfig & FLASH_OPTR_SRAM2_PE));
/* Set value and mask for SRAM2_PE option byte */
optr_reg_val |= (UserConfig & FLASH_OPTR_SRAM2_PE);
optr_reg_mask |= FLASH_OPTR_SRAM2_PE;
}
if((UserType & OB_USER_SRAM2_RST) != 0U)
{
/* SRAM2_RST option byte should be modified */
assert_param(IS_OB_USER_SRAM2_RST(UserConfig & FLASH_OPTR_SRAM2_RST));
/* Set value and mask for SRAM2_RST option byte */
optr_reg_val |= (UserConfig & FLASH_OPTR_SRAM2_RST);
optr_reg_mask |= FLASH_OPTR_SRAM2_RST;
}
#if defined (STM32L412xx) || defined (STM32L422xx) || defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || \
defined (STM32L442xx) || defined (STM32L443xx) || defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || \
defined (STM32L496xx) || defined (STM32L4A6xx) || \
defined (STM32L4P5xx) || defined (STM32L4Q5xx) || \
defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
if((UserType & OB_USER_nSWBOOT0) != 0U)
{
/* nSWBOOT0 option byte should be modified */
assert_param(IS_OB_USER_SWBOOT0(UserConfig & FLASH_OPTR_nSWBOOT0));
/* Set value and mask for nSWBOOT0 option byte */
optr_reg_val |= (UserConfig & FLASH_OPTR_nSWBOOT0);
optr_reg_mask |= FLASH_OPTR_nSWBOOT0;
}
if((UserType & OB_USER_nBOOT0) != 0U)
{
/* nBOOT0 option byte should be modified */
assert_param(IS_OB_USER_BOOT0(UserConfig & FLASH_OPTR_nBOOT0));
/* Set value and mask for nBOOT0 option byte */
optr_reg_val |= (UserConfig & FLASH_OPTR_nBOOT0);
optr_reg_mask |= FLASH_OPTR_nBOOT0;
}
#endif
/* Configure the option bytes register */
MODIFY_REG(FLASH->OPTR, optr_reg_mask, optr_reg_val);
/* Set OPTSTRT Bit */
SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
/* If the option byte program operation is completed, disable the OPTSTRT Bit */
CLEAR_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
}
return status;
}
/**
* @brief Configure the Proprietary code readout protection of the desired addresses.
*
* @note To configure the PCROP options, the option lock bit OPTLOCK must be
* cleared with the call of the HAL_FLASH_OB_Unlock() function.
* @note To validate the PCROP options, the option bytes must be reloaded
* through the call of the HAL_FLASH_OB_Launch() function.
*
* @param PCROPConfig specifies the configuration (Bank to be configured and PCROP_RDP option).
* This parameter must be a combination of FLASH_BANK_1 or FLASH_BANK_2
* with OB_PCROP_RDP_NOT_ERASE or OB_PCROP_RDP_ERASE
*
* @param PCROPStartAddr specifies the start address of the Proprietary code readout protection
* This parameter can be an address between begin and end of the bank
*
* @param PCROPEndAddr specifies the end address of the Proprietary code readout protection
* This parameter can be an address between PCROPStartAddr and end of the bank
*
* @retval HAL Status
*/
static HAL_StatusTypeDef FLASH_OB_PCROPConfig(uint32_t PCROPConfig, uint32_t PCROPStartAddr, uint32_t PCROPEndAddr)
{
HAL_StatusTypeDef status;
uint32_t reg_value;
uint32_t bank1_addr;
#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \
defined (STM32L496xx) || defined (STM32L4A6xx) || \
defined (STM32L4P5xx) || defined (STM32L4Q5xx) || \
defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
uint32_t bank2_addr;
#endif
/* Check the parameters */
assert_param(IS_FLASH_BANK_EXCLUSIVE(PCROPConfig & FLASH_BANK_BOTH));
assert_param(IS_OB_PCROP_RDP(PCROPConfig & FLASH_PCROP1ER_PCROP_RDP));
assert_param(IS_FLASH_MAIN_MEM_ADDRESS(PCROPStartAddr));
assert_param(IS_FLASH_MAIN_MEM_ADDRESS(PCROPEndAddr));
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
if(status == HAL_OK)
{
#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \
defined (STM32L496xx) || defined (STM32L4A6xx) || \
defined (STM32L4P5xx) || defined (STM32L4Q5xx) || \
defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
/* Get the information about the bank swapping */
if (READ_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_FB_MODE) == 0U)
{
bank1_addr = FLASH_BASE;
bank2_addr = FLASH_BASE + FLASH_BANK_SIZE;
}
else
{
bank1_addr = FLASH_BASE + FLASH_BANK_SIZE;
bank2_addr = FLASH_BASE;
}
#else
bank1_addr = FLASH_BASE;
#endif
#if defined (STM32L4P5xx) || defined (STM32L4Q5xx) || defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
if (READ_BIT(FLASH->OPTR, FLASH_OPTR_DBANK) == 0U)
{
/* Configure the Proprietary code readout protection */
if((PCROPConfig & FLASH_BANK_BOTH) == FLASH_BANK_1)
{
reg_value = ((PCROPStartAddr - FLASH_BASE) >> 4);
MODIFY_REG(FLASH->PCROP1SR, FLASH_PCROP1SR_PCROP1_STRT, reg_value);
reg_value = ((PCROPEndAddr - FLASH_BASE) >> 4);
MODIFY_REG(FLASH->PCROP1ER, FLASH_PCROP1ER_PCROP1_END, reg_value);
}
else if((PCROPConfig & FLASH_BANK_BOTH) == FLASH_BANK_2)
{
reg_value = ((PCROPStartAddr - FLASH_BASE) >> 4);
MODIFY_REG(FLASH->PCROP2SR, FLASH_PCROP2SR_PCROP2_STRT, reg_value);
reg_value = ((PCROPEndAddr - FLASH_BASE) >> 4);
MODIFY_REG(FLASH->PCROP2ER, FLASH_PCROP2ER_PCROP2_END, reg_value);
}
else
{
/* Nothing to do */
}
}
else
#endif
{
/* Configure the Proprietary code readout protection */
if((PCROPConfig & FLASH_BANK_BOTH) == FLASH_BANK_1)
{
reg_value = ((PCROPStartAddr - bank1_addr) >> 3);
MODIFY_REG(FLASH->PCROP1SR, FLASH_PCROP1SR_PCROP1_STRT, reg_value);
reg_value = ((PCROPEndAddr - bank1_addr) >> 3);
MODIFY_REG(FLASH->PCROP1ER, FLASH_PCROP1ER_PCROP1_END, reg_value);
}
#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \
defined (STM32L496xx) || defined (STM32L4A6xx) || \
defined (STM32L4P5xx) || defined (STM32L4Q5xx) || \
defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
else if((PCROPConfig & FLASH_BANK_BOTH) == FLASH_BANK_2)
{
reg_value = ((PCROPStartAddr - bank2_addr) >> 3);
MODIFY_REG(FLASH->PCROP2SR, FLASH_PCROP2SR_PCROP2_STRT, reg_value);
reg_value = ((PCROPEndAddr - bank2_addr) >> 3);
MODIFY_REG(FLASH->PCROP2ER, FLASH_PCROP2ER_PCROP2_END, reg_value);
}
#endif
else
{
/* Nothing to do */
}
}
MODIFY_REG(FLASH->PCROP1ER, FLASH_PCROP1ER_PCROP_RDP, (PCROPConfig & FLASH_PCROP1ER_PCROP_RDP));
/* Set OPTSTRT Bit */
SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
/* If the option byte program operation is completed, disable the OPTSTRT Bit */
CLEAR_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
}
return status;
}
/**
* @brief Return the FLASH Write Protection Option Bytes value.
*
* @param[in] WRPArea: specifies the area to be returned.
* This parameter can be one of the following values:
* @arg OB_WRPAREA_BANK1_AREAA: Flash Bank 1 Area A
* @arg OB_WRPAREA_BANK1_AREAB: Flash Bank 1 Area B
* @arg OB_WRPAREA_BANK2_AREAA: Flash Bank 2 Area A (don't apply to STM32L43x/STM32L44x devices)
* @arg OB_WRPAREA_BANK2_AREAB: Flash Bank 2 Area B (don't apply to STM32L43x/STM32L44x devices)
*
* @param[out] WRPStartOffset: specifies the address where to copied the start page
* of the write protected area
*
* @param[out] WRDPEndOffset: specifies the address where to copied the end page of
* the write protected area
*
* @retval None
*/
static void FLASH_OB_GetWRP(uint32_t WRPArea, uint32_t * WRPStartOffset, uint32_t * WRDPEndOffset)
{
/* Get the configuration of the write protected area */
if(WRPArea == OB_WRPAREA_BANK1_AREAA)
{
*WRPStartOffset = READ_BIT(FLASH->WRP1AR, FLASH_WRP1AR_WRP1A_STRT);
*WRDPEndOffset = (READ_BIT(FLASH->WRP1AR, FLASH_WRP1AR_WRP1A_END) >> 16);
}
else if(WRPArea == OB_WRPAREA_BANK1_AREAB)
{
*WRPStartOffset = READ_BIT(FLASH->WRP1BR, FLASH_WRP1BR_WRP1B_STRT);
*WRDPEndOffset = (READ_BIT(FLASH->WRP1BR, FLASH_WRP1BR_WRP1B_END) >> 16);
}
#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \
defined (STM32L496xx) || defined (STM32L4A6xx) || \
defined (STM32L4P5xx) || defined (STM32L4Q5xx) || \
defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
else if(WRPArea == OB_WRPAREA_BANK2_AREAA)
{
*WRPStartOffset = READ_BIT(FLASH->WRP2AR, FLASH_WRP2AR_WRP2A_STRT);
*WRDPEndOffset = (READ_BIT(FLASH->WRP2AR, FLASH_WRP2AR_WRP2A_END) >> 16);
}
else if(WRPArea == OB_WRPAREA_BANK2_AREAB)
{
*WRPStartOffset = READ_BIT(FLASH->WRP2BR, FLASH_WRP2BR_WRP2B_STRT);
*WRDPEndOffset = (READ_BIT(FLASH->WRP2BR, FLASH_WRP2BR_WRP2B_END) >> 16);
}
#endif
else
{
/* Nothing to do */
}
}
/**
* @brief Return the FLASH Read Protection level.
* @retval FLASH ReadOut Protection Status:
* This return value can be one of the following values:
* @arg OB_RDP_LEVEL_0: No protection
* @arg OB_RDP_LEVEL_1: Read protection of the memory
* @arg OB_RDP_LEVEL_2: Full chip protection
*/
static uint32_t FLASH_OB_GetRDP(void)
{
uint32_t rdp_level = READ_BIT(FLASH->OPTR, FLASH_OPTR_RDP);
if ((rdp_level != OB_RDP_LEVEL_0) && (rdp_level != OB_RDP_LEVEL_2))
{
return (OB_RDP_LEVEL_1);
}
else
{
return (READ_BIT(FLASH->OPTR, FLASH_OPTR_RDP));
}
}
/**
* @brief Return the FLASH User Option Byte value.
* @retval The FLASH User Option Bytes values:
* For STM32L47x/STM32L48x devices :
* BOR_LEV(Bit8-10), nRST_STOP(Bit12), nRST_STDBY(Bit13), nRST_SHDW(Bit14),
* IWDG_SW(Bit16), IWDG_STOP(Bit17), IWDG_STDBY(Bit18), WWDG_SW(Bit19),
* BFB2(Bit20), DUALBANK(Bit21), nBOOT1(Bit23), SRAM2_PE(Bit24) and SRAM2_RST(Bit25).
* For STM32L43x/STM32L44x devices :
* BOR_LEV(Bit8-10), nRST_STOP(Bit12), nRST_STDBY(Bit13), nRST_SHDW(Bit14),
* IWDG_SW(Bit16), IWDG_STOP(Bit17), IWDG_STDBY(Bit18), WWDG_SW(Bit19),
* nBOOT1(Bit23), SRAM2_PE(Bit24), SRAM2_RST(Bit25), nSWBOOT0(Bit26) and nBOOT0(Bit27).
*/
static uint32_t FLASH_OB_GetUser(void)
{
uint32_t user_config = READ_REG(FLASH->OPTR);
CLEAR_BIT(user_config, FLASH_OPTR_RDP);
return user_config;
}
/**
* @brief Return the FLASH Write Protection Option Bytes value.
*
* @param PCROPConfig [inout]: specifies the configuration (Bank to be configured and PCROP_RDP option).
* This parameter must be a combination of FLASH_BANK_1 or FLASH_BANK_2
* with OB_PCROP_RDP_NOT_ERASE or OB_PCROP_RDP_ERASE
*
* @param PCROPStartAddr [out]: specifies the address where to copied the start address
* of the Proprietary code readout protection
*
* @param PCROPEndAddr [out]: specifies the address where to copied the end address of
* the Proprietary code readout protection
*
* @retval None
*/
static void FLASH_OB_GetPCROP(uint32_t * PCROPConfig, uint32_t * PCROPStartAddr, uint32_t * PCROPEndAddr)
{
uint32_t reg_value;
uint32_t bank1_addr;
#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \
defined (STM32L496xx) || defined (STM32L4A6xx) || \
defined (STM32L4P5xx) || defined (STM32L4Q5xx) || \
defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
uint32_t bank2_addr;
#endif
#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \
defined (STM32L496xx) || defined (STM32L4A6xx) || \
defined (STM32L4P5xx) || defined (STM32L4Q5xx) || \
defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
/* Get the information about the bank swapping */
if (READ_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_FB_MODE) == 0U)
{
bank1_addr = FLASH_BASE;
bank2_addr = FLASH_BASE + FLASH_BANK_SIZE;
}
else
{
bank1_addr = FLASH_BASE + FLASH_BANK_SIZE;
bank2_addr = FLASH_BASE;
}
#else
bank1_addr = FLASH_BASE;
#endif
#if defined (STM32L4P5xx) || defined (STM32L4Q5xx) || defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
if (READ_BIT(FLASH->OPTR, FLASH_OPTR_DBANK) == 0U)
{
if(((*PCROPConfig) & FLASH_BANK_BOTH) == FLASH_BANK_1)
{
reg_value = (READ_REG(FLASH->PCROP1SR) & FLASH_PCROP1SR_PCROP1_STRT);
*PCROPStartAddr = (reg_value << 4) + FLASH_BASE;
reg_value = (READ_REG(FLASH->PCROP1ER) & FLASH_PCROP1ER_PCROP1_END);
*PCROPEndAddr = (reg_value << 4) + FLASH_BASE + 0xFU;
}
else if(((*PCROPConfig) & FLASH_BANK_BOTH) == FLASH_BANK_2)
{
reg_value = (READ_REG(FLASH->PCROP2SR) & FLASH_PCROP2SR_PCROP2_STRT);
*PCROPStartAddr = (reg_value << 4) + FLASH_BASE;
reg_value = (READ_REG(FLASH->PCROP2ER) & FLASH_PCROP2ER_PCROP2_END);
*PCROPEndAddr = (reg_value << 4) + FLASH_BASE + 0xFU;;
}
else
{
/* Nothing to do */
}
}
else
#endif
{
if(((*PCROPConfig) & FLASH_BANK_BOTH) == FLASH_BANK_1)
{
reg_value = (READ_REG(FLASH->PCROP1SR) & FLASH_PCROP1SR_PCROP1_STRT);
*PCROPStartAddr = (reg_value << 3) + bank1_addr;
reg_value = (READ_REG(FLASH->PCROP1ER) & FLASH_PCROP1ER_PCROP1_END);
*PCROPEndAddr = (reg_value << 3) + bank1_addr + 0x7U;
}
#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) || \
defined (STM32L496xx) || defined (STM32L4A6xx) || \
defined (STM32L4P5xx) || defined (STM32L4Q5xx) || \
defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
else if(((*PCROPConfig) & FLASH_BANK_BOTH) == FLASH_BANK_2)
{
reg_value = (READ_REG(FLASH->PCROP2SR) & FLASH_PCROP2SR_PCROP2_STRT);
*PCROPStartAddr = (reg_value << 3) + bank2_addr;
reg_value = (READ_REG(FLASH->PCROP2ER) & FLASH_PCROP2ER_PCROP2_END);
*PCROPEndAddr = (reg_value << 3) + bank2_addr + 0x7U;
}
#endif
else
{
/* Nothing to do */
}
}
*PCROPConfig |= (READ_REG(FLASH->PCROP1ER) & FLASH_PCROP1ER_PCROP_RDP);
}
/**
* @}
*/
/**
* @}
*/
#endif /* HAL_FLASH_MODULE_ENABLED */
/**
* @}
*/
/**
* @}
*/

View File

@@ -1,251 +0,0 @@
/**
******************************************************************************
* @file stm32l4xx_hal_flash_ramfunc.c
* @author MCD Application Team
* @brief FLASH RAMFUNC driver.
* This file provides a Flash firmware functions which should be
* executed from internal SRAM
* + FLASH HalfPage Programming
* + FLASH Power Down in Run mode
*
* @verbatim
==============================================================================
##### Flash RAM functions #####
==============================================================================
*** ARM Compiler ***
--------------------
[..] RAM functions are defined using the toolchain options.
Functions that are executed in RAM should reside in a separate
source module. Using the 'Options for File' dialog you can simply change
the 'Code / Const' area of a module to a memory space in physical RAM.
Available memory areas are declared in the 'Target' tab of the
Options for Target' dialog.
*** ICCARM Compiler ***
-----------------------
[..] RAM functions are defined using a specific toolchain keyword "__ramfunc".
*** GNU Compiler ***
--------------------
[..] RAM functions are defined using a specific toolchain attribute
"__attribute__((section(".RamFunc")))".
@endverbatim
******************************************************************************
* @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.
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32l4xx_hal.h"
/** @addtogroup STM32L4xx_HAL_Driver
* @{
*/
/** @defgroup FLASH_RAMFUNC FLASH_RAMFUNC
* @brief FLASH functions executed from RAM
* @{
*/
#ifdef HAL_FLASH_MODULE_ENABLED
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Exported functions -------------------------------------------------------*/
/** @defgroup FLASH_RAMFUNC_Exported_Functions FLASH in RAM function Exported Functions
* @{
*/
/** @defgroup FLASH_RAMFUNC_Exported_Functions_Group1 Peripheral features functions
* @brief Data transfers functions
*
@verbatim
===============================================================================
##### ramfunc functions #####
===============================================================================
[..]
This subsection provides a set of functions that should be executed from RAM.
@endverbatim
* @{
*/
/**
* @brief Enable the Power down in Run Mode
* @note This function should be called and executed from SRAM memory
* @retval HAL status
*/
__RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_EnableRunPowerDown(void)
{
/* Enable the Power Down in Run mode*/
__HAL_FLASH_POWER_DOWN_ENABLE();
return HAL_OK;
}
/**
* @brief Disable the Power down in Run Mode
* @note This function should be called and executed from SRAM memory
* @retval HAL status
*/
__RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_DisableRunPowerDown(void)
{
/* Disable the Power Down in Run mode*/
__HAL_FLASH_POWER_DOWN_DISABLE();
return HAL_OK;
}
#if defined (STM32L4P5xx) || defined (STM32L4Q5xx) || defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
/**
* @brief Program the FLASH DBANK User Option Byte.
*
* @note To configure the user option bytes, the option lock bit OPTLOCK must
* be cleared with the call of the HAL_FLASH_OB_Unlock() function.
* @note To modify the DBANK option byte, no PCROP region should be defined.
* To deactivate PCROP, user should perform RDP changing
*
* @param DBankConfig The FLASH DBANK User Option Byte value.
* This parameter can be one of the following values:
* @arg OB_DBANK_128_BITS: Single-bank with 128-bits data
* @arg OB_DBANK_64_BITS: Dual-bank with 64-bits data
*
* @retval HAL status
*/
__RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_OB_DBankConfig(uint32_t DBankConfig)
{
uint32_t count, reg;
HAL_StatusTypeDef status = HAL_ERROR;
/* Process Locked */
__HAL_LOCK(&pFlash);
/* Check if the PCROP is disabled */
reg = FLASH->PCROP1SR;
if (reg > FLASH->PCROP1ER)
{
reg = FLASH->PCROP2SR;
if (reg > FLASH->PCROP2ER)
{
/* Disable Flash prefetch */
__HAL_FLASH_PREFETCH_BUFFER_DISABLE();
if (READ_BIT(FLASH->ACR, FLASH_ACR_ICEN) != 0U)
{
/* Disable Flash instruction cache */
__HAL_FLASH_INSTRUCTION_CACHE_DISABLE();
/* Flush Flash instruction cache */
__HAL_FLASH_INSTRUCTION_CACHE_RESET();
}
if (READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != 0U)
{
/* Disable Flash data cache */
__HAL_FLASH_DATA_CACHE_DISABLE();
/* Flush Flash data cache */
__HAL_FLASH_DATA_CACHE_RESET();
}
/* Disable WRP zone 1 of 1st bank if needed */
reg = FLASH->WRP1AR;
if (((reg & FLASH_WRP1AR_WRP1A_STRT) >> FLASH_WRP1AR_WRP1A_STRT_Pos) <=
((reg & FLASH_WRP1AR_WRP1A_END) >> FLASH_WRP1AR_WRP1A_END_Pos))
{
MODIFY_REG(FLASH->WRP1AR, (FLASH_WRP1AR_WRP1A_STRT | FLASH_WRP1AR_WRP1A_END), FLASH_WRP1AR_WRP1A_STRT);
}
/* Disable WRP zone 2 of 1st bank if needed */
reg = FLASH->WRP1BR;
if (((reg & FLASH_WRP1BR_WRP1B_STRT) >> FLASH_WRP1BR_WRP1B_STRT_Pos) <=
((reg & FLASH_WRP1BR_WRP1B_END) >> FLASH_WRP1BR_WRP1B_END_Pos))
{
MODIFY_REG(FLASH->WRP1BR, (FLASH_WRP1BR_WRP1B_STRT | FLASH_WRP1BR_WRP1B_END), FLASH_WRP1BR_WRP1B_STRT);
}
/* Disable WRP zone 1 of 2nd bank if needed */
reg = FLASH->WRP2AR;
if (((reg & FLASH_WRP2AR_WRP2A_STRT) >> FLASH_WRP2AR_WRP2A_STRT_Pos) <=
((reg & FLASH_WRP2AR_WRP2A_END) >> FLASH_WRP2AR_WRP2A_END_Pos))
{
MODIFY_REG(FLASH->WRP2AR, (FLASH_WRP2AR_WRP2A_STRT | FLASH_WRP2AR_WRP2A_END), FLASH_WRP2AR_WRP2A_STRT);
}
/* Disable WRP zone 2 of 2nd bank if needed */
reg = FLASH->WRP2BR;
if (((reg & FLASH_WRP2BR_WRP2B_STRT) >> FLASH_WRP2BR_WRP2B_STRT_Pos) <=
((reg & FLASH_WRP2BR_WRP2B_END) >> FLASH_WRP2BR_WRP2B_END_Pos))
{
MODIFY_REG(FLASH->WRP2BR, (FLASH_WRP2BR_WRP2B_STRT | FLASH_WRP2BR_WRP2B_END), FLASH_WRP2BR_WRP2B_STRT);
}
/* Modify the DBANK user option byte */
MODIFY_REG(FLASH->OPTR, FLASH_OPTR_DBANK, DBankConfig);
/* Set OPTSTRT Bit */
SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
/* Wait for last operation to be completed */
/* 8 is the number of required instruction cycles for the below loop statement (timeout expressed in ms) */
count = FLASH_TIMEOUT_VALUE * (SystemCoreClock / 8U / 1000U);
do
{
if (count == 0U)
{
break;
}
count--;
} while (__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY) != RESET);
/* If the option byte program operation is completed, disable the OPTSTRT Bit */
CLEAR_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
/* Set the bit to force the option byte reloading */
SET_BIT(FLASH->CR, FLASH_CR_OBL_LAUNCH);
}
}
/* Process Unlocked */
__HAL_UNLOCK(&pFlash);
return status;
}
#endif
/**
* @}
*/
/**
* @}
*/
#endif /* HAL_FLASH_MODULE_ENABLED */
/**
* @}
*/
/**
* @}
*/

View File

@@ -1,551 +0,0 @@
/**
******************************************************************************
* @file stm32l4xx_hal_gpio.c
* @author MCD Application Team
* @brief GPIO HAL module driver.
* This file provides firmware functions to manage the following
* functionalities of the General Purpose Input/Output (GPIO) peripheral:
* + Initialization and de-initialization functions
* + IO operation functions
*
******************************************************************************
* @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.
*
******************************************************************************
@verbatim
==============================================================================
##### GPIO Peripheral features #####
==============================================================================
[..]
(+) Each port bit of the general-purpose I/O (GPIO) ports can be individually
configured by software in several modes:
(++) Input mode
(++) Analog mode
(++) Output mode
(++) Alternate function mode
(++) External interrupt/event lines
(+) During and just after reset, the alternate functions and external interrupt
lines are not active and the I/O ports are configured in input floating mode.
(+) All GPIO pins have weak internal pull-up and pull-down resistors, which can be
activated or not.
(+) In Output or Alternate mode, each IO can be configured on open-drain or push-pull
type and the IO speed can be selected depending on the VDD value.
(+) The microcontroller IO pins are connected to onboard peripherals/modules through a
multiplexer that allows only one peripheral alternate function (AF) connected
to an IO pin at a time. In this way, there can be no conflict between peripherals
sharing the same IO pin.
(+) All ports have external interrupt/event capability. To use external interrupt
lines, the port must be configured in input mode. All available GPIO pins are
connected to the 16 external interrupt/event lines from EXTI0 to EXTI15.
(+) The external interrupt/event controller consists of up to 39 edge detectors
(16 lines are connected to GPIO) for generating event/interrupt requests (each
input line can be independently configured to select the type (interrupt or event)
and the corresponding trigger event (rising or falling or both). Each line can
also be masked independently.
##### How to use this driver #####
==============================================================================
[..]
(#) Enable the GPIO AHB clock using the following function: __HAL_RCC_GPIOx_CLK_ENABLE().
(#) Configure the GPIO pin(s) using HAL_GPIO_Init().
(++) Configure the IO mode using "Mode" member from GPIO_InitTypeDef structure
(++) Activate Pull-up, Pull-down resistor using "Pull" member from GPIO_InitTypeDef
structure.
(++) In case of Output or alternate function mode selection: the speed is
configured through "Speed" member from GPIO_InitTypeDef structure.
(++) In alternate mode is selection, the alternate function connected to the IO
is configured through "Alternate" member from GPIO_InitTypeDef structure.
(++) Analog mode is required when a pin is to be used as ADC channel
or DAC output.
(++) In case of external interrupt/event selection the "Mode" member from
GPIO_InitTypeDef structure select the type (interrupt or event) and
the corresponding trigger event (rising or falling or both).
(#) In case of external interrupt/event mode selection, configure NVIC IRQ priority
mapped to the EXTI line using HAL_NVIC_SetPriority() and enable it using
HAL_NVIC_EnableIRQ().
(#) To get the level of a pin configured in input mode use HAL_GPIO_ReadPin().
(#) To set/reset the level of a pin configured in output mode use
HAL_GPIO_WritePin()/HAL_GPIO_TogglePin().
(#) To lock pin configuration until next reset use HAL_GPIO_LockPin().
(#) During and just after reset, the alternate functions are not
active and the GPIO pins are configured in input floating mode (except JTAG
pins).
(#) The LSE oscillator pins OSC32_IN and OSC32_OUT can be used as general purpose
(PC14 and PC15, respectively) when the LSE oscillator is off. The LSE has
priority over the GPIO function.
(#) The HSE oscillator pins OSC_IN/OSC_OUT can be used as
general purpose PH0 and PH1, respectively, when the HSE oscillator is off.
The HSE has priority over the GPIO function.
@endverbatim
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32l4xx_hal.h"
/** @addtogroup STM32L4xx_HAL_Driver
* @{
*/
/** @defgroup GPIO GPIO
* @brief GPIO HAL module driver
* @{
*/
/** MISRA C:2012 deviation rule has been granted for following rules:
* Rule-12.2 - Medium: RHS argument is in interval [0,INF] which is out of
* range of the shift operator in following API :
* HAL_GPIO_Init
* HAL_GPIO_DeInit
*/
#ifdef HAL_GPIO_MODULE_ENABLED
/* Private typedef -----------------------------------------------------------*/
/* Private defines -----------------------------------------------------------*/
/** @addtogroup GPIO_Private_Defines GPIO Private Defines
* @{
*/
#define GPIO_NUMBER (16u)
/**
* @}
*/
/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/** @defgroup GPIO_Exported_Functions GPIO Exported Functions
* @{
*/
/** @defgroup GPIO_Exported_Functions_Group1 Initialization/de-initialization functions
* @brief Initialization and Configuration functions
*
@verbatim
===============================================================================
##### Initialization and de-initialization functions #####
===============================================================================
@endverbatim
* @{
*/
/**
* @brief Initialize the GPIOx peripheral according to the specified parameters in the GPIO_Init.
* @param GPIOx where x can be (A..H) to select the GPIO peripheral for STM32L4 family
* @param GPIO_Init pointer to a GPIO_InitTypeDef structure that contains
* the configuration information for the specified GPIO peripheral.
* @retval None
*/
void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)
{
uint32_t position = 0x00u;
uint32_t iocurrent;
uint32_t temp;
/* Check the parameters */
assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
assert_param(IS_GPIO_PIN(GPIO_Init->Pin));
assert_param(IS_GPIO_MODE(GPIO_Init->Mode));
/* Configure the port pins */
while (((GPIO_Init->Pin) >> position) != 0x00u)
{
/* Get current io position */
iocurrent = (GPIO_Init->Pin) & (1uL << position);
if (iocurrent != 0x00u)
{
/*--------------------- GPIO Mode Configuration ------------------------*/
/* In case of Output or Alternate function mode selection */
if (((GPIO_Init->Mode & GPIO_MODE) == MODE_OUTPUT) || ((GPIO_Init->Mode & GPIO_MODE) == MODE_AF))
{
/* Check the Speed parameter */
assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));
/* Configure the IO Speed */
temp = GPIOx->OSPEEDR;
temp &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2u));
temp |= (GPIO_Init->Speed << (position * 2u));
GPIOx->OSPEEDR = temp;
/* Configure the IO Output Type */
temp = GPIOx->OTYPER;
temp &= ~(GPIO_OTYPER_OT0 << position) ;
temp |= (((GPIO_Init->Mode & OUTPUT_TYPE) >> OUTPUT_TYPE_Pos) << position);
GPIOx->OTYPER = temp;
}
#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx)
/* In case of Analog mode, check if ADC control mode is selected */
if((GPIO_Init->Mode & GPIO_MODE_ANALOG) == GPIO_MODE_ANALOG)
{
/* Configure the IO Output Type */
temp = GPIOx->ASCR;
temp &= ~(GPIO_ASCR_ASC0 << position) ;
temp |= (((GPIO_Init->Mode & GPIO_MODE_ANALOG_ADC_CONTROL) >> 3) << position);
GPIOx->ASCR = temp;
}
#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx */
/* Activate the Pull-up or Pull down resistor for the current IO */
if ((GPIO_Init->Mode & GPIO_MODE) != MODE_ANALOG)
{
/* Check the Pull parameter */
assert_param(IS_GPIO_PULL(GPIO_Init->Pull));
temp = GPIOx->PUPDR;
temp &= ~(GPIO_PUPDR_PUPD0 << (position * 2U));
temp |= ((GPIO_Init->Pull) << (position * 2U));
GPIOx->PUPDR = temp;
}
/* In case of Alternate function mode selection */
if ((GPIO_Init->Mode & GPIO_MODE) == MODE_AF)
{
/* Check the Alternate function parameters */
assert_param(IS_GPIO_AF_INSTANCE(GPIOx));
assert_param(IS_GPIO_AF(GPIO_Init->Alternate));
/* Configure Alternate function mapped with the current IO */
temp = GPIOx->AFR[position >> 3u];
temp &= ~(0xFu << ((position & 0x07u) * 4u));
temp |= ((GPIO_Init->Alternate) << ((position & 0x07u) * 4u));
GPIOx->AFR[position >> 3u] = temp;
}
/* Configure IO Direction mode (Input, Output, Alternate or Analog) */
temp = GPIOx->MODER;
temp &= ~(GPIO_MODER_MODE0 << (position * 2u));
temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2u));
GPIOx->MODER = temp;
/*--------------------- EXTI Mode Configuration ------------------------*/
/* Configure the External Interrupt or event for the current IO */
if ((GPIO_Init->Mode & EXTI_MODE) != 0x00u)
{
/* Enable SYSCFG Clock */
__HAL_RCC_SYSCFG_CLK_ENABLE();
temp = SYSCFG->EXTICR[position >> 2u];
temp &= ~(0x0FuL << (4u * (position & 0x03u)));
temp |= (GPIO_GET_INDEX(GPIOx) << (4u * (position & 0x03u)));
SYSCFG->EXTICR[position >> 2u] = temp;
/* Clear Rising Falling edge configuration */
temp = EXTI->RTSR1;
temp &= ~(iocurrent);
if ((GPIO_Init->Mode & TRIGGER_RISING) != 0x00u)
{
temp |= iocurrent;
}
EXTI->RTSR1 = temp;
temp = EXTI->FTSR1;
temp &= ~(iocurrent);
if ((GPIO_Init->Mode & TRIGGER_FALLING) != 0x00u)
{
temp |= iocurrent;
}
EXTI->FTSR1 = temp;
/* Clear EXTI line configuration */
temp = EXTI->EMR1;
temp &= ~(iocurrent);
if ((GPIO_Init->Mode & EXTI_EVT) != 0x00u)
{
temp |= iocurrent;
}
EXTI->EMR1 = temp;
temp = EXTI->IMR1;
temp &= ~(iocurrent);
if ((GPIO_Init->Mode & EXTI_IT) != 0x00u)
{
temp |= iocurrent;
}
EXTI->IMR1 = temp;
}
}
position++;
}
}
/**
* @brief De-initialize the GPIOx peripheral registers to their default reset values.
* @param GPIOx where x can be (A..H) to select the GPIO peripheral for STM32L4 family
* @param GPIO_Pin specifies the port bit to be written.
* This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
* @retval None
*/
void HAL_GPIO_DeInit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin)
{
uint32_t position = 0x00u;
uint32_t iocurrent;
uint32_t tmp;
/* Check the parameters */
assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
assert_param(IS_GPIO_PIN(GPIO_Pin));
/* Configure the port pins */
while ((GPIO_Pin >> position) != 0x00u)
{
/* Get current io position */
iocurrent = (GPIO_Pin) & (1uL << position);
if (iocurrent != 0x00u)
{
/*------------------------- EXTI Mode Configuration --------------------*/
/* Clear the External Interrupt or Event for the current IO */
tmp = SYSCFG->EXTICR[position >> 2u];
tmp &= (0x0FuL << (4u * (position & 0x03u)));
if (tmp == (GPIO_GET_INDEX(GPIOx) << (4u * (position & 0x03u))))
{
/* Clear EXTI line configuration */
EXTI->IMR1 &= ~(iocurrent);
EXTI->EMR1 &= ~(iocurrent);
/* Clear Rising Falling edge configuration */
EXTI->FTSR1 &= ~(iocurrent);
EXTI->RTSR1 &= ~(iocurrent);
tmp = 0x0FuL << (4u * (position & 0x03u));
SYSCFG->EXTICR[position >> 2u] &= ~tmp;
}
/*------------------------- GPIO Mode Configuration --------------------*/
/* Configure IO in Analog Mode */
GPIOx->MODER |= (GPIO_MODER_MODE0 << (position * 2u));
/* Configure the default Alternate Function in current IO */
GPIOx->AFR[position >> 3u] &= ~(0xFu << ((position & 0x07u) * 4u)) ;
/* Configure the default value for IO Speed */
GPIOx->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2u));
/* Configure the default value IO Output Type */
GPIOx->OTYPER &= ~(GPIO_OTYPER_OT0 << position) ;
/* Deactivate the Pull-up and Pull-down resistor for the current IO */
GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPD0 << (position * 2u));
#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx)
/* Deactivate the Control bit of Analog mode for the current IO */
GPIOx->ASCR &= ~(GPIO_ASCR_ASC0<< position);
#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx */
}
position++;
}
}
/**
* @}
*/
/** @defgroup GPIO_Exported_Functions_Group2 IO operation functions
* @brief GPIO Read, Write, Toggle, Lock and EXTI management functions.
*
@verbatim
===============================================================================
##### IO operation functions #####
===============================================================================
@endverbatim
* @{
*/
/**
* @brief Read the specified input port pin.
* @param GPIOx where x can be (A..H) to select the GPIO peripheral for STM32L4 family
* @param GPIO_Pin specifies the port bit to read.
* This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
* @retval The input port pin value.
*/
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
GPIO_PinState bitstatus;
/* Check the parameters */
assert_param(IS_GPIO_PIN(GPIO_Pin));
if ((GPIOx->IDR & GPIO_Pin) != 0x00u)
{
bitstatus = GPIO_PIN_SET;
}
else
{
bitstatus = GPIO_PIN_RESET;
}
return bitstatus;
}
/**
* @brief Set or clear the selected data port bit.
*
* @note This function uses GPIOx_BSRR and GPIOx_BRR registers to allow atomic read/modify
* accesses. In this way, there is no risk of an IRQ occurring between
* the read and the modify access.
*
* @param GPIOx where x can be (A..H) to select the GPIO peripheral for STM32L4 family
* @param GPIO_Pin specifies the port bit to be written.
* This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
* @param PinState specifies the value to be written to the selected bit.
* This parameter can be one of the GPIO_PinState enum values:
* @arg GPIO_PIN_RESET: to clear the port pin
* @arg GPIO_PIN_SET: to set the port pin
* @retval None
*/
void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
{
/* Check the parameters */
assert_param(IS_GPIO_PIN(GPIO_Pin));
assert_param(IS_GPIO_PIN_ACTION(PinState));
if(PinState != GPIO_PIN_RESET)
{
GPIOx->BSRR = (uint32_t)GPIO_Pin;
}
else
{
GPIOx->BRR = (uint32_t)GPIO_Pin;
}
}
/**
* @brief Toggle the specified GPIO pin.
* @param GPIOx where x can be (A..H) to select the GPIO peripheral for STM32L4 family
* @param GPIO_Pin specifies the pin to be toggled.
* @retval None
*/
void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
uint32_t odr;
/* Check the parameters */
assert_param(IS_GPIO_PIN(GPIO_Pin));
/* get current Output Data Register value */
odr = GPIOx->ODR;
/* Set selected pins that were at low level, and reset ones that were high */
GPIOx->BSRR = ((odr & GPIO_Pin) << GPIO_NUMBER) | (~odr & GPIO_Pin);
}
/**
* @brief Lock GPIO Pins configuration registers.
* @note The locked registers are GPIOx_MODER, GPIOx_OTYPER, GPIOx_OSPEEDR,
* GPIOx_PUPDR, GPIOx_AFRL and GPIOx_AFRH.
* @note The configuration of the locked GPIO pins can no longer be modified
* until the next reset.
* @param GPIOx where x can be (A..H) to select the GPIO peripheral for STM32L4 family
* @param GPIO_Pin specifies the port bits to be locked.
* This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
* @retval None
*/
HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
__IO uint32_t tmp = GPIO_LCKR_LCKK;
/* Check the parameters */
assert_param(IS_GPIO_LOCK_INSTANCE(GPIOx));
assert_param(IS_GPIO_PIN(GPIO_Pin));
/* Apply lock key write sequence */
tmp |= GPIO_Pin;
/* Set LCKx bit(s): LCKK='1' + LCK[15-0] */
GPIOx->LCKR = tmp;
/* Reset LCKx bit(s): LCKK='0' + LCK[15-0] */
GPIOx->LCKR = GPIO_Pin;
/* Set LCKx bit(s): LCKK='1' + LCK[15-0] */
GPIOx->LCKR = tmp;
/* Read LCKK register. This read is mandatory to complete key lock sequence */
tmp = GPIOx->LCKR;
/* Read again in order to confirm lock is active */
if ((GPIOx->LCKR & GPIO_LCKR_LCKK) != 0x00u)
{
return HAL_OK;
}
else
{
return HAL_ERROR;
}
}
/**
* @brief Handle EXTI interrupt request.
* @param GPIO_Pin Specifies the port pin connected to corresponding EXTI line.
* @retval None
*/
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
/* EXTI line interrupt detected */
if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)
{
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
HAL_GPIO_EXTI_Callback(GPIO_Pin);
}
}
/**
* @brief EXTI line detection callback.
* @param GPIO_Pin Specifies the port pin connected to corresponding EXTI line.
* @retval None
*/
__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(GPIO_Pin);
/* NOTE: This function should not be modified, when the callback is needed,
the HAL_GPIO_EXTI_Callback could be implemented in the user file
*/
}
/**
* @}
*/
/**
* @}
*/
#endif /* HAL_GPIO_MODULE_ENABLED */
/**
* @}
*/
/**
* @}
*/

File diff suppressed because it is too large Load Diff

View File

@@ -1,368 +0,0 @@
/**
******************************************************************************
* @file stm32l4xx_hal_i2c_ex.c
* @author MCD Application Team
* @brief I2C Extended HAL module driver.
* This file provides firmware functions to manage the following
* functionalities of I2C Extended peripheral:
* + Filter Mode Functions
* + WakeUp Mode Functions
* + FastModePlus Functions
*
******************************************************************************
* @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.
*
******************************************************************************
@verbatim
==============================================================================
##### I2C peripheral Extended features #####
==============================================================================
[..] Comparing to other previous devices, the I2C interface for STM32L4xx
devices contains the following additional features
(+) Possibility to disable or enable Analog Noise Filter
(+) Use of a configured Digital Noise Filter
(+) Disable or enable wakeup from Stop mode(s)
(+) Disable or enable Fast Mode Plus
##### How to use this driver #####
==============================================================================
[..] This driver provides functions to configure Noise Filter and Wake Up Feature
(#) Configure I2C Analog noise filter using the function HAL_I2CEx_ConfigAnalogFilter()
(#) Configure I2C Digital noise filter using the function HAL_I2CEx_ConfigDigitalFilter()
(#) Configure the enable or disable of I2C Wake Up Mode using the functions :
(++) HAL_I2CEx_EnableWakeUp()
(++) HAL_I2CEx_DisableWakeUp()
(#) Configure the enable or disable of fast mode plus driving capability using the functions :
(++) HAL_I2CEx_EnableFastModePlus()
(++) HAL_I2CEx_DisableFastModePlus()
@endverbatim
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32l4xx_hal.h"
/** @addtogroup STM32L4xx_HAL_Driver
* @{
*/
/** @defgroup I2CEx I2CEx
* @brief I2C Extended HAL module driver
* @{
*/
#ifdef HAL_I2C_MODULE_ENABLED
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/** @defgroup I2CEx_Exported_Functions I2C Extended Exported Functions
* @{
*/
/** @defgroup I2CEx_Exported_Functions_Group1 Filter Mode Functions
* @brief Filter Mode Functions
*
@verbatim
===============================================================================
##### Filter Mode Functions #####
===============================================================================
[..] This section provides functions allowing to:
(+) Configure Noise Filters
@endverbatim
* @{
*/
/**
* @brief Configure I2C Analog noise filter.
* @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
* the configuration information for the specified I2Cx peripheral.
* @param AnalogFilter New state of the Analog filter.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_I2CEx_ConfigAnalogFilter(I2C_HandleTypeDef *hi2c, uint32_t AnalogFilter)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance));
assert_param(IS_I2C_ANALOG_FILTER(AnalogFilter));
if (hi2c->State == HAL_I2C_STATE_READY)
{
/* Process Locked */
__HAL_LOCK(hi2c);
hi2c->State = HAL_I2C_STATE_BUSY;
/* Disable the selected I2C peripheral */
__HAL_I2C_DISABLE(hi2c);
/* Reset I2Cx ANOFF bit */
hi2c->Instance->CR1 &= ~(I2C_CR1_ANFOFF);
/* Set analog filter bit*/
hi2c->Instance->CR1 |= AnalogFilter;
__HAL_I2C_ENABLE(hi2c);
hi2c->State = HAL_I2C_STATE_READY;
/* Process Unlocked */
__HAL_UNLOCK(hi2c);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
/**
* @brief Configure I2C Digital noise filter.
* @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
* the configuration information for the specified I2Cx peripheral.
* @param DigitalFilter Coefficient of digital noise filter between Min_Data=0x00 and Max_Data=0x0F.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_I2CEx_ConfigDigitalFilter(I2C_HandleTypeDef *hi2c, uint32_t DigitalFilter)
{
uint32_t tmpreg;
/* Check the parameters */
assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance));
assert_param(IS_I2C_DIGITAL_FILTER(DigitalFilter));
if (hi2c->State == HAL_I2C_STATE_READY)
{
/* Process Locked */
__HAL_LOCK(hi2c);
hi2c->State = HAL_I2C_STATE_BUSY;
/* Disable the selected I2C peripheral */
__HAL_I2C_DISABLE(hi2c);
/* Get the old register value */
tmpreg = hi2c->Instance->CR1;
/* Reset I2Cx DNF bits [11:8] */
tmpreg &= ~(I2C_CR1_DNF);
/* Set I2Cx DNF coefficient */
tmpreg |= DigitalFilter << 8U;
/* Store the new register value */
hi2c->Instance->CR1 = tmpreg;
__HAL_I2C_ENABLE(hi2c);
hi2c->State = HAL_I2C_STATE_READY;
/* Process Unlocked */
__HAL_UNLOCK(hi2c);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
/**
* @}
*/
/** @defgroup I2CEx_Exported_Functions_Group2 WakeUp Mode Functions
* @brief WakeUp Mode Functions
*
@verbatim
===============================================================================
##### WakeUp Mode Functions #####
===============================================================================
[..] This section provides functions allowing to:
(+) Configure Wake Up Feature
@endverbatim
* @{
*/
/**
* @brief Enable I2C wakeup from Stop mode(s).
* @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
* the configuration information for the specified I2Cx peripheral.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_I2CEx_EnableWakeUp(I2C_HandleTypeDef *hi2c)
{
/* Check the parameters */
assert_param(IS_I2C_WAKEUP_FROMSTOP_INSTANCE(hi2c->Instance));
if (hi2c->State == HAL_I2C_STATE_READY)
{
/* Process Locked */
__HAL_LOCK(hi2c);
hi2c->State = HAL_I2C_STATE_BUSY;
/* Disable the selected I2C peripheral */
__HAL_I2C_DISABLE(hi2c);
/* Enable wakeup from stop mode */
hi2c->Instance->CR1 |= I2C_CR1_WUPEN;
__HAL_I2C_ENABLE(hi2c);
hi2c->State = HAL_I2C_STATE_READY;
/* Process Unlocked */
__HAL_UNLOCK(hi2c);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
/**
* @brief Disable I2C wakeup from Stop mode(s).
* @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
* the configuration information for the specified I2Cx peripheral.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_I2CEx_DisableWakeUp(I2C_HandleTypeDef *hi2c)
{
/* Check the parameters */
assert_param(IS_I2C_WAKEUP_FROMSTOP_INSTANCE(hi2c->Instance));
if (hi2c->State == HAL_I2C_STATE_READY)
{
/* Process Locked */
__HAL_LOCK(hi2c);
hi2c->State = HAL_I2C_STATE_BUSY;
/* Disable the selected I2C peripheral */
__HAL_I2C_DISABLE(hi2c);
/* Enable wakeup from stop mode */
hi2c->Instance->CR1 &= ~(I2C_CR1_WUPEN);
__HAL_I2C_ENABLE(hi2c);
hi2c->State = HAL_I2C_STATE_READY;
/* Process Unlocked */
__HAL_UNLOCK(hi2c);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
/**
* @}
*/
/** @defgroup I2CEx_Exported_Functions_Group3 Fast Mode Plus Functions
* @brief Fast Mode Plus Functions
*
@verbatim
===============================================================================
##### Fast Mode Plus Functions #####
===============================================================================
[..] This section provides functions allowing to:
(+) Configure Fast Mode Plus
@endverbatim
* @{
*/
/**
* @brief Enable the I2C fast mode plus driving capability.
* @param ConfigFastModePlus Selects the pin.
* This parameter can be one of the @ref I2CEx_FastModePlus values
* @note For I2C1, fast mode plus driving capability can be enabled on all selected
* I2C1 pins using I2C_FASTMODEPLUS_I2C1 parameter or independently
* on each one of the following pins PB6, PB7, PB8 and PB9.
* @note For remaining I2C1 pins (PA14, PA15...) fast mode plus driving capability
* can be enabled only by using I2C_FASTMODEPLUS_I2C1 parameter.
* @note For all I2C2 pins fast mode plus driving capability can be enabled
* only by using I2C_FASTMODEPLUS_I2C2 parameter.
* @note For all I2C3 pins fast mode plus driving capability can be enabled
* only by using I2C_FASTMODEPLUS_I2C3 parameter.
* @note For all I2C4 pins fast mode plus driving capability can be enabled
* only by using I2C_FASTMODEPLUS_I2C4 parameter.
* @retval None
*/
void HAL_I2CEx_EnableFastModePlus(uint32_t ConfigFastModePlus)
{
/* Check the parameter */
assert_param(IS_I2C_FASTMODEPLUS(ConfigFastModePlus));
/* Enable SYSCFG clock */
__HAL_RCC_SYSCFG_CLK_ENABLE();
/* Enable fast mode plus driving capability for selected pin */
SET_BIT(SYSCFG->CFGR1, (uint32_t)ConfigFastModePlus);
}
/**
* @brief Disable the I2C fast mode plus driving capability.
* @param ConfigFastModePlus Selects the pin.
* This parameter can be one of the @ref I2CEx_FastModePlus values
* @note For I2C1, fast mode plus driving capability can be disabled on all selected
* I2C1 pins using I2C_FASTMODEPLUS_I2C1 parameter or independently
* on each one of the following pins PB6, PB7, PB8 and PB9.
* @note For remaining I2C1 pins (PA14, PA15...) fast mode plus driving capability
* can be disabled only by using I2C_FASTMODEPLUS_I2C1 parameter.
* @note For all I2C2 pins fast mode plus driving capability can be disabled
* only by using I2C_FASTMODEPLUS_I2C2 parameter.
* @note For all I2C3 pins fast mode plus driving capability can be disabled
* only by using I2C_FASTMODEPLUS_I2C3 parameter.
* @note For all I2C4 pins fast mode plus driving capability can be disabled
* only by using I2C_FASTMODEPLUS_I2C4 parameter.
* @retval None
*/
void HAL_I2CEx_DisableFastModePlus(uint32_t ConfigFastModePlus)
{
/* Check the parameter */
assert_param(IS_I2C_FASTMODEPLUS(ConfigFastModePlus));
/* Enable SYSCFG clock */
__HAL_RCC_SYSCFG_CLK_ENABLE();
/* Disable fast mode plus driving capability for selected pin */
CLEAR_BIT(SYSCFG->CFGR1, (uint32_t)ConfigFastModePlus);
}
/**
* @}
*/
/**
* @}
*/
#endif /* HAL_I2C_MODULE_ENABLED */
/**
* @}
*/
/**
* @}
*/

View File

@@ -1,658 +0,0 @@
/**
******************************************************************************
* @file stm32l4xx_hal_pwr.c
* @author MCD Application Team
* @brief PWR HAL module driver.
* This file provides firmware functions to manage the following
* functionalities of the Power Controller (PWR) peripheral:
* + Initialization/de-initialization functions
* + Peripheral Control functions
*
******************************************************************************
* @attention
*
* Copyright (c) 2019 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.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32l4xx_hal.h"
/** @addtogroup STM32L4xx_HAL_Driver
* @{
*/
/** @defgroup PWR PWR
* @brief PWR HAL module driver
* @{
*/
#ifdef HAL_PWR_MODULE_ENABLED
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/** @defgroup PWR_Private_Defines PWR Private Defines
* @{
*/
/** @defgroup PWR_PVD_Mode_Mask PWR PVD Mode Mask
* @{
*/
#define PVD_MODE_IT ((uint32_t)0x00010000) /*!< Mask for interruption yielded by PVD threshold crossing */
#define PVD_MODE_EVT ((uint32_t)0x00020000) /*!< Mask for event yielded by PVD threshold crossing */
#define PVD_RISING_EDGE ((uint32_t)0x00000001) /*!< Mask for rising edge set as PVD trigger */
#define PVD_FALLING_EDGE ((uint32_t)0x00000002) /*!< Mask for falling edge set as PVD trigger */
/**
* @}
*/
/**
* @}
*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/** @defgroup PWR_Exported_Functions PWR Exported Functions
* @{
*/
/** @defgroup PWR_Exported_Functions_Group1 Initialization and de-initialization functions
* @brief Initialization and de-initialization functions
*
@verbatim
===============================================================================
##### Initialization and de-initialization functions #####
===============================================================================
[..]
@endverbatim
* @{
*/
/**
* @brief Deinitialize the HAL PWR peripheral registers to their default reset values.
* @retval None
*/
void HAL_PWR_DeInit(void)
{
__HAL_RCC_PWR_FORCE_RESET();
__HAL_RCC_PWR_RELEASE_RESET();
}
/**
* @brief Enable access to the backup domain
* (RTC registers, RTC backup data registers).
* @note After reset, the backup domain is protected against
* possible unwanted write accesses.
* @note RTCSEL that sets the RTC clock source selection is in the RTC back-up domain.
* In order to set or modify the RTC clock, the backup domain access must be
* disabled.
* @note LSEON bit that switches on and off the LSE crystal belongs as well to the
* back-up domain.
* @retval None
*/
void HAL_PWR_EnableBkUpAccess(void)
{
SET_BIT(PWR->CR1, PWR_CR1_DBP);
}
/**
* @brief Disable access to the backup domain
* (RTC registers, RTC backup data registers).
* @retval None
*/
void HAL_PWR_DisableBkUpAccess(void)
{
CLEAR_BIT(PWR->CR1, PWR_CR1_DBP);
}
/**
* @}
*/
/** @defgroup PWR_Exported_Functions_Group2 Peripheral Control functions
* @brief Low Power modes configuration functions
*
@verbatim
===============================================================================
##### Peripheral Control functions #####
===============================================================================
[..]
*** PVD configuration ***
=========================
[..]
(+) The PVD is used to monitor the VDD power supply by comparing it to a
threshold selected by the PVD Level (PLS[2:0] bits in PWR_CR2 register).
(+) PVDO flag is available to indicate if VDD/VDDA is higher or lower
than the PVD threshold. This event is internally connected to the EXTI
line16 and can generate an interrupt if enabled. This is done through
__HAL_PVD_EXTI_ENABLE_IT() macro.
(+) The PVD is stopped in Standby mode.
*** WakeUp pin configuration ***
================================
[..]
(+) WakeUp pins are used to wakeup the system from Standby mode or Shutdown mode.
The polarity of these pins can be set to configure event detection on high
level (rising edge) or low level (falling edge).
*** Low Power modes configuration ***
=====================================
[..]
The devices feature 8 low-power modes:
(+) Low-power Run mode: core and peripherals are running, main regulator off, low power regulator on.
(+) Sleep mode: Cortex-M4 core stopped, peripherals kept running, main and low power regulators on.
(+) Low-power Sleep mode: Cortex-M4 core stopped, peripherals kept running, main regulator off, low power regulator on.
(+) Stop 0 mode: all clocks are stopped except LSI and LSE, main and low power regulators on.
(+) Stop 1 mode: all clocks are stopped except LSI and LSE, main regulator off, low power regulator on.
(+) Stop 2 mode: all clocks are stopped except LSI and LSE, main regulator off, low power regulator on, reduced set of waking up IPs compared to Stop 1 mode.
(+) Standby mode with SRAM2: all clocks are stopped except LSI and LSE, SRAM2 content preserved, main regulator off, low power regulator on.
(+) Standby mode without SRAM2: all clocks are stopped except LSI and LSE, main and low power regulators off.
(+) Shutdown mode: all clocks are stopped except LSE, main and low power regulators off.
*** Low-power run mode ***
==========================
[..]
(+) Entry: (from main run mode)
(++) set LPR bit with HAL_PWREx_EnableLowPowerRunMode() API after having decreased the system clock below 2 MHz.
(+) Exit:
(++) clear LPR bit then wait for REGLP bit to be reset with HAL_PWREx_DisableLowPowerRunMode() API. Only
then can the system clock frequency be increased above 2 MHz.
*** Sleep mode / Low-power sleep mode ***
=========================================
[..]
(+) Entry:
The Sleep mode / Low-power Sleep mode is entered through HAL_PWR_EnterSLEEPMode() API
in specifying whether or not the regulator is forced to low-power mode and if exit is interrupt or event-triggered.
(++) PWR_MAINREGULATOR_ON: Sleep mode (regulator in main mode).
(++) PWR_LOWPOWERREGULATOR_ON: Low-power sleep (regulator in low power mode).
In the latter case, the system clock frequency must have been decreased below 2 MHz beforehand.
(++) PWR_SLEEPENTRY_WFI: enter SLEEP mode with WFI instruction
(++) PWR_SLEEPENTRY_WFE: enter SLEEP mode with WFE instruction
(+) WFI Exit:
(++) Any peripheral interrupt acknowledged by the nested vectored interrupt
controller (NVIC) or any wake-up event.
(+) WFE Exit:
(++) Any wake-up event such as an EXTI line configured in event mode.
[..] When exiting the Low-power sleep mode by issuing an interrupt or a wakeup event,
the MCU is in Low-power Run mode.
*** Stop 0, Stop 1 and Stop 2 modes ***
===============================
[..]
(+) Entry:
The Stop 0, Stop 1 or Stop 2 modes are entered through the following API's:
(++) HAL_PWREx_EnterSTOP0Mode() for mode 0 or HAL_PWREx_EnterSTOP1Mode() for mode 1 or for porting reasons HAL_PWR_EnterSTOPMode().
(++) HAL_PWREx_EnterSTOP2Mode() for mode 2.
(+) Regulator setting (applicable to HAL_PWR_EnterSTOPMode() only):
(++) PWR_MAINREGULATOR_ON
(++) PWR_LOWPOWERREGULATOR_ON
(+) Exit (interrupt or event-triggered, specified when entering STOP mode):
(++) PWR_STOPENTRY_WFI: enter Stop mode with WFI instruction
(++) PWR_STOPENTRY_WFE: enter Stop mode with WFE instruction
(+) WFI Exit:
(++) Any EXTI Line (Internal or External) configured in Interrupt mode.
(++) Some specific communication peripherals (USART, LPUART, I2C) interrupts
when programmed in wakeup mode.
(+) WFE Exit:
(++) Any EXTI Line (Internal or External) configured in Event mode.
[..]
When exiting Stop 0 and Stop 1 modes, the MCU is either in Run mode or in Low-power Run mode
depending on the LPR bit setting.
When exiting Stop 2 mode, the MCU is in Run mode.
*** Standby mode ***
====================
[..]
The Standby mode offers two options:
(+) option a) all clocks off except LSI and LSE, RRS bit set (keeps voltage regulator in low power mode).
SRAM and registers contents are lost except for the SRAM2 content, the RTC registers, RTC backup registers
and Standby circuitry.
(+) option b) all clocks off except LSI and LSE, RRS bit cleared (voltage regulator then disabled).
SRAM and register contents are lost except for the RTC registers, RTC backup registers
and Standby circuitry.
(++) Entry:
(+++) The Standby mode is entered through HAL_PWR_EnterSTANDBYMode() API.
SRAM1 and register contents are lost except for registers in the Backup domain and
Standby circuitry. SRAM2 content can be preserved if the bit RRS is set in PWR_CR3 register.
To enable this feature, the user can resort to HAL_PWREx_EnableSRAM2ContentRetention() API
to set RRS bit.
(++) Exit:
(+++) WKUP pin rising edge, RTC alarm or wakeup, tamper event, time-stamp event,
external reset in NRST pin, IWDG reset.
[..] After waking up from Standby mode, program execution restarts in the same way as after a Reset.
*** Shutdown mode ***
======================
[..]
In Shutdown mode,
voltage regulator is disabled, all clocks are off except LSE, RRS bit is cleared.
SRAM and registers contents are lost except for backup domain registers.
(+) Entry:
The Shutdown mode is entered through HAL_PWREx_EnterSHUTDOWNMode() API.
(+) Exit:
(++) WKUP pin rising edge, RTC alarm or wakeup, tamper event, time-stamp event,
external reset in NRST pin.
[..] After waking up from Shutdown mode, program execution restarts in the same way as after a Reset.
*** Auto-wakeup (AWU) from low-power mode ***
=============================================
[..]
The MCU can be woken up from low-power mode by an RTC Alarm event, an RTC
Wakeup event, a tamper event or a time-stamp event, without depending on
an external interrupt (Auto-wakeup mode).
(+) RTC auto-wakeup (AWU) from the Stop, Standby and Shutdown modes
(++) To wake up from the Stop mode with an RTC alarm event, it is necessary to
configure the RTC to generate the RTC alarm using the HAL_RTC_SetAlarm_IT() function.
(++) To wake up from the Stop mode with an RTC Tamper or time stamp event, it
is necessary to configure the RTC to detect the tamper or time stamp event using the
HAL_RTCEx_SetTimeStamp_IT() or HAL_RTCEx_SetTamper_IT() functions.
(++) To wake up from the Stop mode with an RTC WakeUp event, it is necessary to
configure the RTC to generate the RTC WakeUp event using the HAL_RTCEx_SetWakeUpTimer_IT() function.
@endverbatim
* @{
*/
/**
* @brief Configure the voltage threshold detected by the Power Voltage Detector (PVD).
* @param sConfigPVD: pointer to a PWR_PVDTypeDef structure that contains the PVD
* configuration information.
* @note Refer to the electrical characteristics of your device datasheet for
* more details about the voltage thresholds corresponding to each
* detection level.
* @retval None
*/
HAL_StatusTypeDef HAL_PWR_ConfigPVD(PWR_PVDTypeDef *sConfigPVD)
{
/* Check the parameters */
assert_param(IS_PWR_PVD_LEVEL(sConfigPVD->PVDLevel));
assert_param(IS_PWR_PVD_MODE(sConfigPVD->Mode));
/* Set PLS bits according to PVDLevel value */
MODIFY_REG(PWR->CR2, PWR_CR2_PLS, sConfigPVD->PVDLevel);
/* Clear any previous config. Keep it clear if no event or IT mode is selected */
__HAL_PWR_PVD_EXTI_DISABLE_EVENT();
__HAL_PWR_PVD_EXTI_DISABLE_IT();
__HAL_PWR_PVD_EXTI_DISABLE_FALLING_EDGE();
__HAL_PWR_PVD_EXTI_DISABLE_RISING_EDGE();
/* Configure interrupt mode */
if((sConfigPVD->Mode & PVD_MODE_IT) == PVD_MODE_IT)
{
__HAL_PWR_PVD_EXTI_ENABLE_IT();
}
/* Configure event mode */
if((sConfigPVD->Mode & PVD_MODE_EVT) == PVD_MODE_EVT)
{
__HAL_PWR_PVD_EXTI_ENABLE_EVENT();
}
/* Configure the edge */
if((sConfigPVD->Mode & PVD_RISING_EDGE) == PVD_RISING_EDGE)
{
__HAL_PWR_PVD_EXTI_ENABLE_RISING_EDGE();
}
if((sConfigPVD->Mode & PVD_FALLING_EDGE) == PVD_FALLING_EDGE)
{
__HAL_PWR_PVD_EXTI_ENABLE_FALLING_EDGE();
}
return HAL_OK;
}
/**
* @brief Enable the Power Voltage Detector (PVD).
* @retval None
*/
void HAL_PWR_EnablePVD(void)
{
SET_BIT(PWR->CR2, PWR_CR2_PVDE);
}
/**
* @brief Disable the Power Voltage Detector (PVD).
* @retval None
*/
void HAL_PWR_DisablePVD(void)
{
CLEAR_BIT(PWR->CR2, PWR_CR2_PVDE);
}
/**
* @brief Enable the WakeUp PINx functionality.
* @param WakeUpPinPolarity: Specifies which Wake-Up pin to enable.
* This parameter can be one of the following legacy values which set the default polarity
* i.e. detection on high level (rising edge):
* @arg @ref PWR_WAKEUP_PIN1, PWR_WAKEUP_PIN2, PWR_WAKEUP_PIN3, PWR_WAKEUP_PIN4, PWR_WAKEUP_PIN5
*
* or one of the following value where the user can explicitly specify the enabled pin and
* the chosen polarity:
* @arg @ref PWR_WAKEUP_PIN1_HIGH or PWR_WAKEUP_PIN1_LOW
* @arg @ref PWR_WAKEUP_PIN2_HIGH or PWR_WAKEUP_PIN2_LOW
* @arg @ref PWR_WAKEUP_PIN3_HIGH or PWR_WAKEUP_PIN3_LOW
* @arg @ref PWR_WAKEUP_PIN4_HIGH or PWR_WAKEUP_PIN4_LOW
* @arg @ref PWR_WAKEUP_PIN5_HIGH or PWR_WAKEUP_PIN5_LOW
* @note PWR_WAKEUP_PINx and PWR_WAKEUP_PINx_HIGH are equivalent.
* @retval None
*/
void HAL_PWR_EnableWakeUpPin(uint32_t WakeUpPinPolarity)
{
assert_param(IS_PWR_WAKEUP_PIN(WakeUpPinPolarity));
/* Specifies the Wake-Up pin polarity for the event detection
(rising or falling edge) */
MODIFY_REG(PWR->CR4, (PWR_CR3_EWUP & WakeUpPinPolarity), (WakeUpPinPolarity >> PWR_WUP_POLARITY_SHIFT));
/* Enable wake-up pin */
SET_BIT(PWR->CR3, (PWR_CR3_EWUP & WakeUpPinPolarity));
}
/**
* @brief Disable the WakeUp PINx functionality.
* @param WakeUpPinx: Specifies the Power Wake-Up pin to disable.
* This parameter can be one of the following values:
* @arg @ref PWR_WAKEUP_PIN1, PWR_WAKEUP_PIN2, PWR_WAKEUP_PIN3, PWR_WAKEUP_PIN4, PWR_WAKEUP_PIN5
* @retval None
*/
void HAL_PWR_DisableWakeUpPin(uint32_t WakeUpPinx)
{
assert_param(IS_PWR_WAKEUP_PIN(WakeUpPinx));
CLEAR_BIT(PWR->CR3, (PWR_CR3_EWUP & WakeUpPinx));
}
/**
* @brief Enter Sleep or Low-power Sleep mode.
* @note In Sleep/Low-power Sleep mode, all I/O pins keep the same state as in Run mode.
* @param Regulator: Specifies the regulator state in Sleep/Low-power Sleep mode.
* This parameter can be one of the following values:
* @arg @ref PWR_MAINREGULATOR_ON Sleep mode (regulator in main mode)
* @arg @ref PWR_LOWPOWERREGULATOR_ON Low-power Sleep mode (regulator in low-power mode)
* @note Low-power Sleep mode is entered from Low-power Run mode. Therefore, if not yet
* in Low-power Run mode before calling HAL_PWR_EnterSLEEPMode() with Regulator set
* to PWR_LOWPOWERREGULATOR_ON, the user can optionally configure the
* Flash in power-down monde in setting the SLEEP_PD bit in FLASH_ACR register.
* Additionally, the clock frequency must be reduced below 2 MHz.
* Setting SLEEP_PD in FLASH_ACR then appropriately reducing the clock frequency must
* be done before calling HAL_PWR_EnterSLEEPMode() API.
* @note When exiting Low-power Sleep mode, the MCU is in Low-power Run mode. To move in
* Run mode, the user must resort to HAL_PWREx_DisableLowPowerRunMode() API.
* @param SLEEPEntry: Specifies if Sleep mode is entered with WFI or WFE instruction.
* This parameter can be one of the following values:
* @arg @ref PWR_SLEEPENTRY_WFI enter Sleep or Low-power Sleep mode with WFI instruction
* @arg @ref PWR_SLEEPENTRY_WFE enter Sleep or Low-power Sleep mode with WFE instruction
* @note When WFI entry is used, tick interrupt have to be disabled if not desired as
* the interrupt wake up source.
* @retval None
*/
void HAL_PWR_EnterSLEEPMode(uint32_t Regulator, uint8_t SLEEPEntry)
{
/* Check the parameters */
assert_param(IS_PWR_REGULATOR(Regulator));
assert_param(IS_PWR_SLEEP_ENTRY(SLEEPEntry));
/* Set Regulator parameter */
if (Regulator == PWR_MAINREGULATOR_ON)
{
/* If in low-power run mode at this point, exit it */
if (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_REGLPF))
{
if (HAL_PWREx_DisableLowPowerRunMode() != HAL_OK)
{
return ;
}
}
/* Regulator now in main mode. */
}
else
{
/* If in run mode, first move to low-power run mode.
The system clock frequency must be below 2 MHz at this point. */
if (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_REGLPF) == RESET)
{
HAL_PWREx_EnableLowPowerRunMode();
}
}
/* Clear SLEEPDEEP bit of Cortex System Control Register */
CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
/* Select SLEEP mode entry -------------------------------------------------*/
if(SLEEPEntry == PWR_SLEEPENTRY_WFI)
{
/* Request Wait For Interrupt */
__WFI();
}
else
{
/* Request Wait For Event */
__SEV();
__WFE();
__WFE();
}
}
/**
* @brief Enter Stop mode
* @note This API is named HAL_PWR_EnterSTOPMode to ensure compatibility with legacy code running
* on devices where only "Stop mode" is mentioned with main or low power regulator ON.
* @note In Stop mode, all I/O pins keep the same state as in Run mode.
* @note All clocks in the VCORE domain are stopped; the PLL, the MSI,
* the HSI and the HSE oscillators are disabled. Some peripherals with the wakeup capability
* (I2Cx, USARTx and LPUART) can switch on the HSI to receive a frame, and switch off the HSI
* after receiving the frame if it is not a wakeup frame. In this case, the HSI clock is propagated
* only to the peripheral requesting it.
* SRAM1, SRAM2 and register contents are preserved.
* The BOR is available.
* The voltage regulator can be configured either in normal (Stop 0) or low-power mode (Stop 1).
* @note When exiting Stop 0 or Stop 1 mode by issuing an interrupt or a wakeup event,
* the HSI RC oscillator is selected as system clock if STOPWUCK bit in RCC_CFGR register
* is set; the MSI oscillator is selected if STOPWUCK is cleared.
* @note When the voltage regulator operates in low power mode (Stop 1), an additional
* startup delay is incurred when waking up.
* By keeping the internal regulator ON during Stop mode (Stop 0), the consumption
* is higher although the startup time is reduced.
* @param Regulator: Specifies the regulator state in Stop mode.
* This parameter can be one of the following values:
* @arg @ref PWR_MAINREGULATOR_ON Stop 0 mode (main regulator ON)
* @arg @ref PWR_LOWPOWERREGULATOR_ON Stop 1 mode (low power regulator ON)
* @param STOPEntry: Specifies Stop 0 or Stop 1 mode is entered with WFI or WFE instruction.
* This parameter can be one of the following values:
* @arg @ref PWR_STOPENTRY_WFI Enter Stop 0 or Stop 1 mode with WFI instruction.
* @arg @ref PWR_STOPENTRY_WFE Enter Stop 0 or Stop 1 mode with WFE instruction.
* @retval None
*/
void HAL_PWR_EnterSTOPMode(uint32_t Regulator, uint8_t STOPEntry)
{
/* Check the parameters */
assert_param(IS_PWR_REGULATOR(Regulator));
if(Regulator == PWR_LOWPOWERREGULATOR_ON)
{
HAL_PWREx_EnterSTOP1Mode(STOPEntry);
}
else
{
HAL_PWREx_EnterSTOP0Mode(STOPEntry);
}
}
/**
* @brief Enter Standby mode.
* @note In Standby mode, the PLL, the HSI, the MSI and the HSE oscillators are switched
* off. The voltage regulator is disabled, except when SRAM2 content is preserved
* in which case the regulator is in low-power mode.
* SRAM1 and register contents are lost except for registers in the Backup domain and
* Standby circuitry. SRAM2 content can be preserved if the bit RRS is set in PWR_CR3 register.
* To enable this feature, the user can resort to HAL_PWREx_EnableSRAM2ContentRetention() API
* to set RRS bit.
* The BOR is available.
* @note The I/Os can be configured either with a pull-up or pull-down or can be kept in analog state.
* HAL_PWREx_EnableGPIOPullUp() and HAL_PWREx_EnableGPIOPullDown() respectively enable Pull Up and
* Pull Down state, HAL_PWREx_DisableGPIOPullUp() and HAL_PWREx_DisableGPIOPullDown() disable the
* same.
* These states are effective in Standby mode only if APC bit is set through
* HAL_PWREx_EnablePullUpPullDownConfig() API.
* @retval None
*/
void HAL_PWR_EnterSTANDBYMode(void)
{
/* Set Stand-by mode */
MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_CR1_LPMS_STANDBY);
/* Set SLEEPDEEP bit of Cortex System Control Register */
SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
/* This option is used to ensure that store operations are completed */
#if defined ( __CC_ARM)
__force_stores();
#endif
/* Request Wait For Interrupt */
__WFI();
}
/**
* @brief Indicate Sleep-On-Exit when returning from Handler mode to Thread mode.
* @note Set SLEEPONEXIT bit of SCR register. When this bit is set, the processor
* re-enters SLEEP mode when an interruption handling is over.
* Setting this bit is useful when the processor is expected to run only on
* interruptions handling.
* @retval None
*/
void HAL_PWR_EnableSleepOnExit(void)
{
/* Set SLEEPONEXIT bit of Cortex System Control Register */
SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPONEXIT_Msk));
}
/**
* @brief Disable Sleep-On-Exit feature when returning from Handler mode to Thread mode.
* @note Clear SLEEPONEXIT bit of SCR register. When this bit is set, the processor
* re-enters SLEEP mode when an interruption handling is over.
* @retval None
*/
void HAL_PWR_DisableSleepOnExit(void)
{
/* Clear SLEEPONEXIT bit of Cortex System Control Register */
CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPONEXIT_Msk));
}
/**
* @brief Enable CORTEX M4 SEVONPEND bit.
* @note Set SEVONPEND bit of SCR register. When this bit is set, this causes
* WFE to wake up when an interrupt moves from inactive to pended.
* @retval None
*/
void HAL_PWR_EnableSEVOnPend(void)
{
/* Set SEVONPEND bit of Cortex System Control Register */
SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SEVONPEND_Msk));
}
/**
* @brief Disable CORTEX M4 SEVONPEND bit.
* @note Clear SEVONPEND bit of SCR register. When this bit is set, this causes
* WFE to wake up when an interrupt moves from inactive to pended.
* @retval None
*/
void HAL_PWR_DisableSEVOnPend(void)
{
/* Clear SEVONPEND bit of Cortex System Control Register */
CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SEVONPEND_Msk));
}
/**
* @brief PWR PVD interrupt callback
* @retval None
*/
__weak void HAL_PWR_PVDCallback(void)
{
/* NOTE : This function should not be modified; when the callback is needed,
the HAL_PWR_PVDCallback can be implemented in the user file
*/
}
/**
* @}
*/
/**
* @}
*/
#endif /* HAL_PWR_MODULE_ENABLED */
/**
* @}
*/
/**
* @}
*/

View File

@@ -1,1474 +0,0 @@
/**
******************************************************************************
* @file stm32l4xx_hal_pwr_ex.c
* @author MCD Application Team
* @brief Extended PWR HAL module driver.
* This file provides firmware functions to manage the following
* functionalities of the Power Controller (PWR) peripheral:
* + Extended Initialization and de-initialization functions
* + Extended Peripheral Control functions
*
******************************************************************************
* @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.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32l4xx_hal.h"
/** @addtogroup STM32L4xx_HAL_Driver
* @{
*/
/** @defgroup PWREx PWREx
* @brief PWR Extended HAL module driver
* @{
*/
#ifdef HAL_PWR_MODULE_ENABLED
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#if defined (STM32L412xx) || defined (STM32L422xx) || defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || defined (STM32L443xx)
#define PWR_PORTH_AVAILABLE_PINS ((uint32_t)0x0000000B) /* PH0/PH1/PH3 */
#elif defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx)
#define PWR_PORTH_AVAILABLE_PINS ((uint32_t)0x0000000B) /* PH0/PH1/PH3 */
#elif defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx)
#define PWR_PORTH_AVAILABLE_PINS ((uint32_t)0x00000003) /* PH0/PH1 */
#elif defined (STM32L496xx) || defined (STM32L4A6xx) || defined (STM32L4P5xx) || defined (STM32L4Q5xx) || defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
#define PWR_PORTH_AVAILABLE_PINS ((uint32_t)0x0000FFFF) /* PH0..PH15 */
#endif
#if defined (STM32L496xx) || defined (STM32L4A6xx) || defined (STM32L4P5xx) || defined (STM32L4Q5xx) || defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
#define PWR_PORTI_AVAILABLE_PINS ((uint32_t)0x00000FFF) /* PI0..PI11 */
#endif
/** @defgroup PWR_Extended_Private_Defines PWR Extended Private Defines
* @{
*/
/** @defgroup PWREx_PVM_Mode_Mask PWR PVM Mode Mask
* @{
*/
#define PVM_MODE_IT ((uint32_t)0x00010000) /*!< Mask for interruption yielded by PVM threshold crossing */
#define PVM_MODE_EVT ((uint32_t)0x00020000) /*!< Mask for event yielded by PVM threshold crossing */
#define PVM_RISING_EDGE ((uint32_t)0x00000001) /*!< Mask for rising edge set as PVM trigger */
#define PVM_FALLING_EDGE ((uint32_t)0x00000002) /*!< Mask for falling edge set as PVM trigger */
/**
* @}
*/
/** @defgroup PWREx_TimeOut_Value PWR Extended Flag Setting Time Out Value
* @{
*/
#define PWR_FLAG_SETTING_DELAY_US 50UL /*!< Time out value for REGLPF and VOSF flags setting */
/**
* @}
*/
/**
* @}
*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/** @defgroup PWREx_Exported_Functions PWR Extended Exported Functions
* @{
*/
/** @defgroup PWREx_Exported_Functions_Group1 Extended Peripheral Control functions
* @brief Extended Peripheral Control functions
*
@verbatim
===============================================================================
##### Extended Peripheral Initialization and de-initialization functions #####
===============================================================================
[..]
@endverbatim
* @{
*/
/**
* @brief Return Voltage Scaling Range.
* @retval VOS bit field (PWR_REGULATOR_VOLTAGE_SCALE1 or PWR_REGULATOR_VOLTAGE_SCALE2
* or PWR_REGULATOR_VOLTAGE_SCALE1_BOOST when applicable)
*/
uint32_t HAL_PWREx_GetVoltageRange(void)
{
#if defined(PWR_CR5_R1MODE)
if (READ_BIT(PWR->CR1, PWR_CR1_VOS) == PWR_REGULATOR_VOLTAGE_SCALE2)
{
return PWR_REGULATOR_VOLTAGE_SCALE2;
}
else if (READ_BIT(PWR->CR5, PWR_CR5_R1MODE) == PWR_CR5_R1MODE)
{
/* PWR_CR5_R1MODE bit set means that Range 1 Boost is disabled */
return PWR_REGULATOR_VOLTAGE_SCALE1;
}
else
{
return PWR_REGULATOR_VOLTAGE_SCALE1_BOOST;
}
#else
return (PWR->CR1 & PWR_CR1_VOS);
#endif
}
/**
* @brief Configure the main internal regulator output voltage.
* @param VoltageScaling specifies the regulator output voltage to achieve
* a tradeoff between performance and power consumption.
* This parameter can be one of the following values:
@if STM32L4S9xx
* @arg @ref PWR_REGULATOR_VOLTAGE_SCALE1_BOOST when available, Regulator voltage output range 1 boost mode,
* typical output voltage at 1.2 V,
* system frequency up to 120 MHz.
@endif
* @arg @ref PWR_REGULATOR_VOLTAGE_SCALE1 Regulator voltage output range 1 mode,
* typical output voltage at 1.2 V,
* system frequency up to 80 MHz.
* @arg @ref PWR_REGULATOR_VOLTAGE_SCALE2 Regulator voltage output range 2 mode,
* typical output voltage at 1.0 V,
* system frequency up to 26 MHz.
* @note When moving from Range 1 to Range 2, the system frequency must be decreased to
* a value below 26 MHz before calling HAL_PWREx_ControlVoltageScaling() API.
* When moving from Range 2 to Range 1, the system frequency can be increased to
* a value up to 80 MHz after calling HAL_PWREx_ControlVoltageScaling() API. For
* some devices, the system frequency can be increased up to 120 MHz.
* @note When moving from Range 2 to Range 1, the API waits for VOSF flag to be
* cleared before returning the status. If the flag is not cleared within
* 50 microseconds, HAL_TIMEOUT status is reported.
* @retval HAL Status
*/
HAL_StatusTypeDef HAL_PWREx_ControlVoltageScaling(uint32_t VoltageScaling)
{
uint32_t wait_loop_index;
assert_param(IS_PWR_VOLTAGE_SCALING_RANGE(VoltageScaling));
#if defined(PWR_CR5_R1MODE)
if (VoltageScaling == PWR_REGULATOR_VOLTAGE_SCALE1_BOOST)
{
/* If current range is range 2 */
if (READ_BIT(PWR->CR1, PWR_CR1_VOS) == PWR_REGULATOR_VOLTAGE_SCALE2)
{
/* Make sure Range 1 Boost is enabled */
CLEAR_BIT(PWR->CR5, PWR_CR5_R1MODE);
/* Set Range 1 */
MODIFY_REG(PWR->CR1, PWR_CR1_VOS, PWR_REGULATOR_VOLTAGE_SCALE1);
/* Wait until VOSF is cleared */
wait_loop_index = ((PWR_FLAG_SETTING_DELAY_US * SystemCoreClock) / 1000000U) + 1;
while ((HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_VOSF)) && (wait_loop_index != 0U))
{
wait_loop_index--;
}
if (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_VOSF))
{
return HAL_TIMEOUT;
}
}
/* If current range is range 1 normal or boost mode */
else
{
/* Enable Range 1 Boost (no issue if bit already reset) */
CLEAR_BIT(PWR->CR5, PWR_CR5_R1MODE);
}
}
else if (VoltageScaling == PWR_REGULATOR_VOLTAGE_SCALE1)
{
/* If current range is range 2 */
if (READ_BIT(PWR->CR1, PWR_CR1_VOS) == PWR_REGULATOR_VOLTAGE_SCALE2)
{
/* Make sure Range 1 Boost is disabled */
SET_BIT(PWR->CR5, PWR_CR5_R1MODE);
/* Set Range 1 */
MODIFY_REG(PWR->CR1, PWR_CR1_VOS, PWR_REGULATOR_VOLTAGE_SCALE1);
/* Wait until VOSF is cleared */
wait_loop_index = ((PWR_FLAG_SETTING_DELAY_US * SystemCoreClock) / 1000000U) + 1;
while ((HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_VOSF)) && (wait_loop_index != 0U))
{
wait_loop_index--;
}
if (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_VOSF))
{
return HAL_TIMEOUT;
}
}
/* If current range is range 1 normal or boost mode */
else
{
/* Disable Range 1 Boost (no issue if bit already set) */
SET_BIT(PWR->CR5, PWR_CR5_R1MODE);
}
}
else
{
/* Set Range 2 */
MODIFY_REG(PWR->CR1, PWR_CR1_VOS, PWR_REGULATOR_VOLTAGE_SCALE2);
/* No need to wait for VOSF to be cleared for this transition */
/* PWR_CR5_R1MODE bit setting has no effect in Range 2 */
}
#else
/* If Set Range 1 */
if (VoltageScaling == PWR_REGULATOR_VOLTAGE_SCALE1)
{
if (READ_BIT(PWR->CR1, PWR_CR1_VOS) != PWR_REGULATOR_VOLTAGE_SCALE1)
{
/* Set Range 1 */
MODIFY_REG(PWR->CR1, PWR_CR1_VOS, PWR_REGULATOR_VOLTAGE_SCALE1);
/* Wait until VOSF is cleared */
wait_loop_index = ((PWR_FLAG_SETTING_DELAY_US * SystemCoreClock) / 1000000U) + 1U;
while ((HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_VOSF)) && (wait_loop_index != 0U))
{
wait_loop_index--;
}
if (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_VOSF))
{
return HAL_TIMEOUT;
}
}
}
else
{
if (READ_BIT(PWR->CR1, PWR_CR1_VOS) != PWR_REGULATOR_VOLTAGE_SCALE2)
{
/* Set Range 2 */
MODIFY_REG(PWR->CR1, PWR_CR1_VOS, PWR_REGULATOR_VOLTAGE_SCALE2);
/* No need to wait for VOSF to be cleared for this transition */
}
}
#endif
return HAL_OK;
}
/**
* @brief Enable battery charging.
* When VDD is present, charge the external battery on VBAT through an internal resistor.
* @param ResistorSelection specifies the resistor impedance.
* This parameter can be one of the following values:
* @arg @ref PWR_BATTERY_CHARGING_RESISTOR_5 5 kOhms resistor
* @arg @ref PWR_BATTERY_CHARGING_RESISTOR_1_5 1.5 kOhms resistor
* @retval None
*/
void HAL_PWREx_EnableBatteryCharging(uint32_t ResistorSelection)
{
assert_param(IS_PWR_BATTERY_RESISTOR_SELECT(ResistorSelection));
/* Specify resistor selection */
MODIFY_REG(PWR->CR4, PWR_CR4_VBRS, ResistorSelection);
/* Enable battery charging */
SET_BIT(PWR->CR4, PWR_CR4_VBE);
}
/**
* @brief Disable battery charging.
* @retval None
*/
void HAL_PWREx_DisableBatteryCharging(void)
{
CLEAR_BIT(PWR->CR4, PWR_CR4_VBE);
}
#if defined(PWR_CR2_USV)
/**
* @brief Enable VDDUSB supply.
* @note Remove VDDUSB electrical and logical isolation, once VDDUSB supply is present.
* @retval None
*/
void HAL_PWREx_EnableVddUSB(void)
{
SET_BIT(PWR->CR2, PWR_CR2_USV);
}
/**
* @brief Disable VDDUSB supply.
* @retval None
*/
void HAL_PWREx_DisableVddUSB(void)
{
CLEAR_BIT(PWR->CR2, PWR_CR2_USV);
}
#endif /* PWR_CR2_USV */
#if defined(PWR_CR2_IOSV)
/**
* @brief Enable VDDIO2 supply.
* @note Remove VDDIO2 electrical and logical isolation, once VDDIO2 supply is present.
* @retval None
*/
void HAL_PWREx_EnableVddIO2(void)
{
SET_BIT(PWR->CR2, PWR_CR2_IOSV);
}
/**
* @brief Disable VDDIO2 supply.
* @retval None
*/
void HAL_PWREx_DisableVddIO2(void)
{
CLEAR_BIT(PWR->CR2, PWR_CR2_IOSV);
}
#endif /* PWR_CR2_IOSV */
/**
* @brief Enable Internal Wake-up Line.
* @retval None
*/
void HAL_PWREx_EnableInternalWakeUpLine(void)
{
SET_BIT(PWR->CR3, PWR_CR3_EIWF);
}
/**
* @brief Disable Internal Wake-up Line.
* @retval None
*/
void HAL_PWREx_DisableInternalWakeUpLine(void)
{
CLEAR_BIT(PWR->CR3, PWR_CR3_EIWF);
}
/**
* @brief Enable GPIO pull-up state in Standby and Shutdown modes.
* @note Set the relevant PUy bits of PWR_PUCRx register to configure the I/O in
* pull-up state in Standby and Shutdown modes.
* @note This state is effective in Standby and Shutdown modes only if APC bit
* is set through HAL_PWREx_EnablePullUpPullDownConfig() API.
* @note The configuration is lost when exiting the Shutdown mode due to the
* power-on reset, maintained when exiting the Standby mode.
* @note To avoid any conflict at Standby and Shutdown modes exits, the corresponding
* PDy bit of PWR_PDCRx register is cleared unless it is reserved.
* @note Even if a PUy bit to set is reserved, the other PUy bits entered as input
* parameter at the same time are set.
* @param GPIO Specify the IO port. This parameter can be PWR_GPIO_A, ..., PWR_GPIO_H
* (or PWR_GPIO_I depending on the devices) to select the GPIO peripheral.
* @param GPIONumber Specify the I/O pins numbers.
* This parameter can be one of the following values:
* PWR_GPIO_BIT_0, ..., PWR_GPIO_BIT_15 (except for the port where less
* I/O pins are available) or the logical OR of several of them to set
* several bits for a given port in a single API call.
* @retval HAL Status
*/
HAL_StatusTypeDef HAL_PWREx_EnableGPIOPullUp(uint32_t GPIO, uint32_t GPIONumber)
{
HAL_StatusTypeDef status = HAL_OK;
assert_param(IS_PWR_GPIO(GPIO));
assert_param(IS_PWR_GPIO_BIT_NUMBER(GPIONumber));
switch (GPIO)
{
case PWR_GPIO_A:
SET_BIT(PWR->PUCRA, (GPIONumber & (~(PWR_GPIO_BIT_14))));
CLEAR_BIT(PWR->PDCRA, (GPIONumber & (~(PWR_GPIO_BIT_13|PWR_GPIO_BIT_15))));
break;
case PWR_GPIO_B:
SET_BIT(PWR->PUCRB, GPIONumber);
CLEAR_BIT(PWR->PDCRB, (GPIONumber & (~(PWR_GPIO_BIT_4))));
break;
case PWR_GPIO_C:
SET_BIT(PWR->PUCRC, GPIONumber);
CLEAR_BIT(PWR->PDCRC, GPIONumber);
break;
#if defined(GPIOD)
case PWR_GPIO_D:
SET_BIT(PWR->PUCRD, GPIONumber);
CLEAR_BIT(PWR->PDCRD, GPIONumber);
break;
#endif
#if defined(GPIOE)
case PWR_GPIO_E:
SET_BIT(PWR->PUCRE, GPIONumber);
CLEAR_BIT(PWR->PDCRE, GPIONumber);
break;
#endif
#if defined(GPIOF)
case PWR_GPIO_F:
SET_BIT(PWR->PUCRF, GPIONumber);
CLEAR_BIT(PWR->PDCRF, GPIONumber);
break;
#endif
#if defined(GPIOG)
case PWR_GPIO_G:
SET_BIT(PWR->PUCRG, GPIONumber);
CLEAR_BIT(PWR->PDCRG, GPIONumber);
break;
#endif
case PWR_GPIO_H:
SET_BIT(PWR->PUCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS));
#if defined (STM32L496xx) || defined (STM32L4A6xx)
CLEAR_BIT(PWR->PDCRH, ((GPIONumber & PWR_PORTH_AVAILABLE_PINS) & (~(PWR_GPIO_BIT_3))));
#else
CLEAR_BIT(PWR->PDCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS));
#endif
break;
#if defined(GPIOI)
case PWR_GPIO_I:
SET_BIT(PWR->PUCRI, (GPIONumber & PWR_PORTI_AVAILABLE_PINS));
CLEAR_BIT(PWR->PDCRI, (GPIONumber & PWR_PORTI_AVAILABLE_PINS));
break;
#endif
default:
status = HAL_ERROR;
break;
}
return status;
}
/**
* @brief Disable GPIO pull-up state in Standby mode and Shutdown modes.
* @note Reset the relevant PUy bits of PWR_PUCRx register used to configure the I/O
* in pull-up state in Standby and Shutdown modes.
* @note Even if a PUy bit to reset is reserved, the other PUy bits entered as input
* parameter at the same time are reset.
* @param GPIO Specifies the IO port. This parameter can be PWR_GPIO_A, ..., PWR_GPIO_H
* (or PWR_GPIO_I depending on the devices) to select the GPIO peripheral.
* @param GPIONumber Specify the I/O pins numbers.
* This parameter can be one of the following values:
* PWR_GPIO_BIT_0, ..., PWR_GPIO_BIT_15 (except for the port where less
* I/O pins are available) or the logical OR of several of them to reset
* several bits for a given port in a single API call.
* @retval HAL Status
*/
HAL_StatusTypeDef HAL_PWREx_DisableGPIOPullUp(uint32_t GPIO, uint32_t GPIONumber)
{
HAL_StatusTypeDef status = HAL_OK;
assert_param(IS_PWR_GPIO(GPIO));
assert_param(IS_PWR_GPIO_BIT_NUMBER(GPIONumber));
switch (GPIO)
{
case PWR_GPIO_A:
CLEAR_BIT(PWR->PUCRA, (GPIONumber & (~(PWR_GPIO_BIT_14))));
break;
case PWR_GPIO_B:
CLEAR_BIT(PWR->PUCRB, GPIONumber);
break;
case PWR_GPIO_C:
CLEAR_BIT(PWR->PUCRC, GPIONumber);
break;
#if defined(GPIOD)
case PWR_GPIO_D:
CLEAR_BIT(PWR->PUCRD, GPIONumber);
break;
#endif
#if defined(GPIOE)
case PWR_GPIO_E:
CLEAR_BIT(PWR->PUCRE, GPIONumber);
break;
#endif
#if defined(GPIOF)
case PWR_GPIO_F:
CLEAR_BIT(PWR->PUCRF, GPIONumber);
break;
#endif
#if defined(GPIOG)
case PWR_GPIO_G:
CLEAR_BIT(PWR->PUCRG, GPIONumber);
break;
#endif
case PWR_GPIO_H:
CLEAR_BIT(PWR->PUCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS));
break;
#if defined(GPIOI)
case PWR_GPIO_I:
CLEAR_BIT(PWR->PUCRI, (GPIONumber & PWR_PORTI_AVAILABLE_PINS));
break;
#endif
default:
status = HAL_ERROR;
break;
}
return status;
}
/**
* @brief Enable GPIO pull-down state in Standby and Shutdown modes.
* @note Set the relevant PDy bits of PWR_PDCRx register to configure the I/O in
* pull-down state in Standby and Shutdown modes.
* @note This state is effective in Standby and Shutdown modes only if APC bit
* is set through HAL_PWREx_EnablePullUpPullDownConfig() API.
* @note The configuration is lost when exiting the Shutdown mode due to the
* power-on reset, maintained when exiting the Standby mode.
* @note To avoid any conflict at Standby and Shutdown modes exits, the corresponding
* PUy bit of PWR_PUCRx register is cleared unless it is reserved.
* @note Even if a PDy bit to set is reserved, the other PDy bits entered as input
* parameter at the same time are set.
* @param GPIO Specify the IO port. This parameter can be PWR_GPIO_A..PWR_GPIO_H
* (or PWR_GPIO_I depending on the devices) to select the GPIO peripheral.
* @param GPIONumber Specify the I/O pins numbers.
* This parameter can be one of the following values:
* PWR_GPIO_BIT_0, ..., PWR_GPIO_BIT_15 (except for the port where less
* I/O pins are available) or the logical OR of several of them to set
* several bits for a given port in a single API call.
* @retval HAL Status
*/
HAL_StatusTypeDef HAL_PWREx_EnableGPIOPullDown(uint32_t GPIO, uint32_t GPIONumber)
{
HAL_StatusTypeDef status = HAL_OK;
assert_param(IS_PWR_GPIO(GPIO));
assert_param(IS_PWR_GPIO_BIT_NUMBER(GPIONumber));
switch (GPIO)
{
case PWR_GPIO_A:
SET_BIT(PWR->PDCRA, (GPIONumber & (~(PWR_GPIO_BIT_13|PWR_GPIO_BIT_15))));
CLEAR_BIT(PWR->PUCRA, (GPIONumber & (~(PWR_GPIO_BIT_14))));
break;
case PWR_GPIO_B:
SET_BIT(PWR->PDCRB, (GPIONumber & (~(PWR_GPIO_BIT_4))));
CLEAR_BIT(PWR->PUCRB, GPIONumber);
break;
case PWR_GPIO_C:
SET_BIT(PWR->PDCRC, GPIONumber);
CLEAR_BIT(PWR->PUCRC, GPIONumber);
break;
#if defined(GPIOD)
case PWR_GPIO_D:
SET_BIT(PWR->PDCRD, GPIONumber);
CLEAR_BIT(PWR->PUCRD, GPIONumber);
break;
#endif
#if defined(GPIOE)
case PWR_GPIO_E:
SET_BIT(PWR->PDCRE, GPIONumber);
CLEAR_BIT(PWR->PUCRE, GPIONumber);
break;
#endif
#if defined(GPIOF)
case PWR_GPIO_F:
SET_BIT(PWR->PDCRF, GPIONumber);
CLEAR_BIT(PWR->PUCRF, GPIONumber);
break;
#endif
#if defined(GPIOG)
case PWR_GPIO_G:
SET_BIT(PWR->PDCRG, GPIONumber);
CLEAR_BIT(PWR->PUCRG, GPIONumber);
break;
#endif
case PWR_GPIO_H:
#if defined (STM32L496xx) || defined (STM32L4A6xx)
SET_BIT(PWR->PDCRH, ((GPIONumber & PWR_PORTH_AVAILABLE_PINS) & (~(PWR_GPIO_BIT_3))));
#else
SET_BIT(PWR->PDCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS));
#endif
CLEAR_BIT(PWR->PUCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS));
break;
#if defined(GPIOI)
case PWR_GPIO_I:
SET_BIT(PWR->PDCRI, (GPIONumber & PWR_PORTI_AVAILABLE_PINS));
CLEAR_BIT(PWR->PUCRI, (GPIONumber & PWR_PORTI_AVAILABLE_PINS));
break;
#endif
default:
status = HAL_ERROR;
break;
}
return status;
}
/**
* @brief Disable GPIO pull-down state in Standby and Shutdown modes.
* @note Reset the relevant PDy bits of PWR_PDCRx register used to configure the I/O
* in pull-down state in Standby and Shutdown modes.
* @note Even if a PDy bit to reset is reserved, the other PDy bits entered as input
* parameter at the same time are reset.
* @param GPIO Specifies the IO port. This parameter can be PWR_GPIO_A..PWR_GPIO_H
* (or PWR_GPIO_I depending on the devices) to select the GPIO peripheral.
* @param GPIONumber Specify the I/O pins numbers.
* This parameter can be one of the following values:
* PWR_GPIO_BIT_0, ..., PWR_GPIO_BIT_15 (except for the port where less
* I/O pins are available) or the logical OR of several of them to reset
* several bits for a given port in a single API call.
* @retval HAL Status
*/
HAL_StatusTypeDef HAL_PWREx_DisableGPIOPullDown(uint32_t GPIO, uint32_t GPIONumber)
{
HAL_StatusTypeDef status = HAL_OK;
assert_param(IS_PWR_GPIO(GPIO));
assert_param(IS_PWR_GPIO_BIT_NUMBER(GPIONumber));
switch (GPIO)
{
case PWR_GPIO_A:
CLEAR_BIT(PWR->PDCRA, (GPIONumber & (~(PWR_GPIO_BIT_13|PWR_GPIO_BIT_15))));
break;
case PWR_GPIO_B:
CLEAR_BIT(PWR->PDCRB, (GPIONumber & (~(PWR_GPIO_BIT_4))));
break;
case PWR_GPIO_C:
CLEAR_BIT(PWR->PDCRC, GPIONumber);
break;
#if defined(GPIOD)
case PWR_GPIO_D:
CLEAR_BIT(PWR->PDCRD, GPIONumber);
break;
#endif
#if defined(GPIOE)
case PWR_GPIO_E:
CLEAR_BIT(PWR->PDCRE, GPIONumber);
break;
#endif
#if defined(GPIOF)
case PWR_GPIO_F:
CLEAR_BIT(PWR->PDCRF, GPIONumber);
break;
#endif
#if defined(GPIOG)
case PWR_GPIO_G:
CLEAR_BIT(PWR->PDCRG, GPIONumber);
break;
#endif
case PWR_GPIO_H:
#if defined (STM32L496xx) || defined (STM32L4A6xx)
CLEAR_BIT(PWR->PDCRH, ((GPIONumber & PWR_PORTH_AVAILABLE_PINS) & (~(PWR_GPIO_BIT_3))));
#else
CLEAR_BIT(PWR->PDCRH, (GPIONumber & PWR_PORTH_AVAILABLE_PINS));
#endif
break;
#if defined(GPIOI)
case PWR_GPIO_I:
CLEAR_BIT(PWR->PDCRI, (GPIONumber & PWR_PORTI_AVAILABLE_PINS));
break;
#endif
default:
status = HAL_ERROR;
break;
}
return status;
}
/**
* @brief Enable pull-up and pull-down configuration.
* @note When APC bit is set, the I/O pull-up and pull-down configurations defined in
* PWR_PUCRx and PWR_PDCRx registers are applied in Standby and Shutdown modes.
* @note Pull-up set by PUy bit of PWR_PUCRx register is not activated if the corresponding
* PDy bit of PWR_PDCRx register is also set (pull-down configuration priority is higher).
* HAL_PWREx_EnableGPIOPullUp() and HAL_PWREx_EnableGPIOPullDown() API's ensure there
* is no conflict when setting PUy or PDy bit.
* @retval None
*/
void HAL_PWREx_EnablePullUpPullDownConfig(void)
{
SET_BIT(PWR->CR3, PWR_CR3_APC);
}
/**
* @brief Disable pull-up and pull-down configuration.
* @note When APC bit is cleared, the I/O pull-up and pull-down configurations defined in
* PWR_PUCRx and PWR_PDCRx registers are not applied in Standby and Shutdown modes.
* @retval None
*/
void HAL_PWREx_DisablePullUpPullDownConfig(void)
{
CLEAR_BIT(PWR->CR3, PWR_CR3_APC);
}
/**
* @brief Enable Full SRAM2 content retention in Standby mode.
* @retval None
*/
void HAL_PWREx_EnableSRAM2ContentRetention(void)
{
(void) HAL_PWREx_SetSRAM2ContentRetention(PWR_FULL_SRAM2_RETENTION);
}
/**
* @brief Disable SRAM2 content retention in Standby mode.
* @retval None
*/
void HAL_PWREx_DisableSRAM2ContentRetention(void)
{
(void) HAL_PWREx_SetSRAM2ContentRetention(PWR_NO_SRAM2_RETENTION);
}
/**
* @brief Enable SRAM2 content retention in Standby mode.
* @param SRAM2Size: specifies the SRAM2 size kept in Standby mode
* This parameter can be one of the following values:
* @arg @ref PWR_NO_SRAM2_RETENTION SRAM2 is powered off in Standby mode (SRAM2 content is lost)
* @arg @ref PWR_FULL_SRAM2_RETENTION Full SRAM2 is powered by the low-power regulator in Standby mode
* @arg @ref PWR_4KBYTES_SRAM2_RETENTION Only 4 Kbytes of SRAM2 is powered by the low-power regulator in Standby mode
* @note PWR_4KBYTES_SRAM2_RETENTION parameter is not available on all devices
* @retval HAL Status
*/
HAL_StatusTypeDef HAL_PWREx_SetSRAM2ContentRetention(uint32_t SRAM2Size)
{
assert_param(IS_PWR_SRAM2_RETENTION(SRAM2Size));
if (SRAM2Size == PWR_NO_SRAM2_RETENTION)
{
CLEAR_BIT(PWR->CR3, PWR_CR3_RRS);
}
else if (SRAM2Size == PWR_FULL_SRAM2_RETENTION)
{
MODIFY_REG(PWR->CR3, PWR_CR3_RRS, PWR_FULL_SRAM2_RETENTION);
}
#if defined(PWR_CR3_RRS_1)
else if (SRAM2Size == PWR_4KBYTES_SRAM2_RETENTION)
{
MODIFY_REG(PWR->CR3, PWR_CR3_RRS, PWR_4KBYTES_SRAM2_RETENTION);
}
#endif /* PWR_CR3_RRS_1 */
else {
return HAL_ERROR;
}
return HAL_OK;
}
#if defined(PWR_CR3_ENULP)
/**
* @brief Enable Ultra Low Power BORL, BORH and PVD for STOP2 and Standby modes.
* @note All the other modes are not affected by this bit.
* @retval None
*/
void HAL_PWREx_EnableBORPVD_ULP(void)
{
SET_BIT(PWR->CR3, PWR_CR3_ENULP);
}
/**
* @brief Disable Ultra Low Power BORL, BORH and PVD for STOP2 and Standby modes.
* @note All the other modes are not affected by this bit
* @retval None
*/
void HAL_PWREx_DisableBORPVD_ULP(void)
{
CLEAR_BIT(PWR->CR3, PWR_CR3_ENULP);
}
#endif /* PWR_CR3_ENULP */
#if defined(PWR_CR4_EXT_SMPS_ON)
/**
* @brief Enable the CFLDO working @ 0.95V.
* @note When external SMPS is used & CFLDO operating in Range 2, the regulated voltage of the
* internal CFLDO can be reduced to 0.95V.
* @retval None
*/
void HAL_PWREx_EnableExtSMPS_0V95(void)
{
SET_BIT(PWR->CR4, PWR_CR4_EXT_SMPS_ON);
}
/**
* @brief Disable the CFLDO working @ 0.95V
* @note Before SMPS is switched off, the regulated voltage of the
* internal CFLDO shall be set to 1.00V.
* 1.00V. is also default operating Range 2 voltage.
* @retval None
*/
void HAL_PWREx_DisableExtSMPS_0V95(void)
{
CLEAR_BIT(PWR->CR4, PWR_CR4_EXT_SMPS_ON);
}
#endif /* PWR_CR4_EXT_SMPS_ON */
#if defined(PWR_CR1_RRSTP)
/**
* @brief Enable SRAM3 content retention in Stop 2 mode.
* @note When RRSTP bit is set, SRAM3 is powered by the low-power regulator in
* Stop 2 mode and its content is kept.
* @retval None
*/
void HAL_PWREx_EnableSRAM3ContentRetention(void)
{
SET_BIT(PWR->CR1, PWR_CR1_RRSTP);
}
/**
* @brief Disable SRAM3 content retention in Stop 2 mode.
* @note When RRSTP bit is reset, SRAM3 is powered off in Stop 2 mode
* and its content is lost.
* @retval None
*/
void HAL_PWREx_DisableSRAM3ContentRetention(void)
{
CLEAR_BIT(PWR->CR1, PWR_CR1_RRSTP);
}
#endif /* PWR_CR1_RRSTP */
#if defined(PWR_CR3_DSIPDEN)
/**
* @brief Enable pull-down activation on DSI pins.
* @retval None
*/
void HAL_PWREx_EnableDSIPinsPDActivation(void)
{
SET_BIT(PWR->CR3, PWR_CR3_DSIPDEN);
}
/**
* @brief Disable pull-down activation on DSI pins.
* @retval None
*/
void HAL_PWREx_DisableDSIPinsPDActivation(void)
{
CLEAR_BIT(PWR->CR3, PWR_CR3_DSIPDEN);
}
#endif /* PWR_CR3_DSIPDEN */
#if defined(PWR_CR2_PVME1)
/**
* @brief Enable the Power Voltage Monitoring 1: VDDUSB versus 1.2V.
* @retval None
*/
void HAL_PWREx_EnablePVM1(void)
{
SET_BIT(PWR->CR2, PWR_PVM_1);
}
/**
* @brief Disable the Power Voltage Monitoring 1: VDDUSB versus 1.2V.
* @retval None
*/
void HAL_PWREx_DisablePVM1(void)
{
CLEAR_BIT(PWR->CR2, PWR_PVM_1);
}
#endif /* PWR_CR2_PVME1 */
#if defined(PWR_CR2_PVME2)
/**
* @brief Enable the Power Voltage Monitoring 2: VDDIO2 versus 0.9V.
* @retval None
*/
void HAL_PWREx_EnablePVM2(void)
{
SET_BIT(PWR->CR2, PWR_PVM_2);
}
/**
* @brief Disable the Power Voltage Monitoring 2: VDDIO2 versus 0.9V.
* @retval None
*/
void HAL_PWREx_DisablePVM2(void)
{
CLEAR_BIT(PWR->CR2, PWR_PVM_2);
}
#endif /* PWR_CR2_PVME2 */
/**
* @brief Enable the Power Voltage Monitoring 3: VDDA versus 1.62V.
* @retval None
*/
void HAL_PWREx_EnablePVM3(void)
{
SET_BIT(PWR->CR2, PWR_PVM_3);
}
/**
* @brief Disable the Power Voltage Monitoring 3: VDDA versus 1.62V.
* @retval None
*/
void HAL_PWREx_DisablePVM3(void)
{
CLEAR_BIT(PWR->CR2, PWR_PVM_3);
}
/**
* @brief Enable the Power Voltage Monitoring 4: VDDA versus 2.2V.
* @retval None
*/
void HAL_PWREx_EnablePVM4(void)
{
SET_BIT(PWR->CR2, PWR_PVM_4);
}
/**
* @brief Disable the Power Voltage Monitoring 4: VDDA versus 2.2V.
* @retval None
*/
void HAL_PWREx_DisablePVM4(void)
{
CLEAR_BIT(PWR->CR2, PWR_PVM_4);
}
/**
* @brief Configure the Peripheral Voltage Monitoring (PVM).
* @param sConfigPVM: pointer to a PWR_PVMTypeDef structure that contains the
* PVM configuration information.
* @note The API configures a single PVM according to the information contained
* in the input structure. To configure several PVMs, the API must be singly
* called for each PVM used.
* @note Refer to the electrical characteristics of your device datasheet for
* more details about the voltage thresholds corresponding to each
* detection level and to each monitored supply.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_PWREx_ConfigPVM(PWR_PVMTypeDef *sConfigPVM)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check the parameters */
assert_param(IS_PWR_PVM_TYPE(sConfigPVM->PVMType));
assert_param(IS_PWR_PVM_MODE(sConfigPVM->Mode));
/* Configure EXTI 35 to 38 interrupts if so required:
scan through PVMType to detect which PVMx is set and
configure the corresponding EXTI line accordingly. */
switch (sConfigPVM->PVMType)
{
#if defined(PWR_CR2_PVME1)
case PWR_PVM_1:
/* Clear any previous config. Keep it clear if no event or IT mode is selected */
__HAL_PWR_PVM1_EXTI_DISABLE_EVENT();
__HAL_PWR_PVM1_EXTI_DISABLE_IT();
__HAL_PWR_PVM1_EXTI_DISABLE_FALLING_EDGE();
__HAL_PWR_PVM1_EXTI_DISABLE_RISING_EDGE();
/* Configure interrupt mode */
if((sConfigPVM->Mode & PVM_MODE_IT) == PVM_MODE_IT)
{
__HAL_PWR_PVM1_EXTI_ENABLE_IT();
}
/* Configure event mode */
if((sConfigPVM->Mode & PVM_MODE_EVT) == PVM_MODE_EVT)
{
__HAL_PWR_PVM1_EXTI_ENABLE_EVENT();
}
/* Configure the edge */
if((sConfigPVM->Mode & PVM_RISING_EDGE) == PVM_RISING_EDGE)
{
__HAL_PWR_PVM1_EXTI_ENABLE_RISING_EDGE();
}
if((sConfigPVM->Mode & PVM_FALLING_EDGE) == PVM_FALLING_EDGE)
{
__HAL_PWR_PVM1_EXTI_ENABLE_FALLING_EDGE();
}
break;
#endif /* PWR_CR2_PVME1 */
#if defined(PWR_CR2_PVME2)
case PWR_PVM_2:
/* Clear any previous config. Keep it clear if no event or IT mode is selected */
__HAL_PWR_PVM2_EXTI_DISABLE_EVENT();
__HAL_PWR_PVM2_EXTI_DISABLE_IT();
__HAL_PWR_PVM2_EXTI_DISABLE_FALLING_EDGE();
__HAL_PWR_PVM2_EXTI_DISABLE_RISING_EDGE();
/* Configure interrupt mode */
if((sConfigPVM->Mode & PVM_MODE_IT) == PVM_MODE_IT)
{
__HAL_PWR_PVM2_EXTI_ENABLE_IT();
}
/* Configure event mode */
if((sConfigPVM->Mode & PVM_MODE_EVT) == PVM_MODE_EVT)
{
__HAL_PWR_PVM2_EXTI_ENABLE_EVENT();
}
/* Configure the edge */
if((sConfigPVM->Mode & PVM_RISING_EDGE) == PVM_RISING_EDGE)
{
__HAL_PWR_PVM2_EXTI_ENABLE_RISING_EDGE();
}
if((sConfigPVM->Mode & PVM_FALLING_EDGE) == PVM_FALLING_EDGE)
{
__HAL_PWR_PVM2_EXTI_ENABLE_FALLING_EDGE();
}
break;
#endif /* PWR_CR2_PVME2 */
case PWR_PVM_3:
/* Clear any previous config. Keep it clear if no event or IT mode is selected */
__HAL_PWR_PVM3_EXTI_DISABLE_EVENT();
__HAL_PWR_PVM3_EXTI_DISABLE_IT();
__HAL_PWR_PVM3_EXTI_DISABLE_FALLING_EDGE();
__HAL_PWR_PVM3_EXTI_DISABLE_RISING_EDGE();
/* Configure interrupt mode */
if((sConfigPVM->Mode & PVM_MODE_IT) == PVM_MODE_IT)
{
__HAL_PWR_PVM3_EXTI_ENABLE_IT();
}
/* Configure event mode */
if((sConfigPVM->Mode & PVM_MODE_EVT) == PVM_MODE_EVT)
{
__HAL_PWR_PVM3_EXTI_ENABLE_EVENT();
}
/* Configure the edge */
if((sConfigPVM->Mode & PVM_RISING_EDGE) == PVM_RISING_EDGE)
{
__HAL_PWR_PVM3_EXTI_ENABLE_RISING_EDGE();
}
if((sConfigPVM->Mode & PVM_FALLING_EDGE) == PVM_FALLING_EDGE)
{
__HAL_PWR_PVM3_EXTI_ENABLE_FALLING_EDGE();
}
break;
case PWR_PVM_4:
/* Clear any previous config. Keep it clear if no event or IT mode is selected */
__HAL_PWR_PVM4_EXTI_DISABLE_EVENT();
__HAL_PWR_PVM4_EXTI_DISABLE_IT();
__HAL_PWR_PVM4_EXTI_DISABLE_FALLING_EDGE();
__HAL_PWR_PVM4_EXTI_DISABLE_RISING_EDGE();
/* Configure interrupt mode */
if((sConfigPVM->Mode & PVM_MODE_IT) == PVM_MODE_IT)
{
__HAL_PWR_PVM4_EXTI_ENABLE_IT();
}
/* Configure event mode */
if((sConfigPVM->Mode & PVM_MODE_EVT) == PVM_MODE_EVT)
{
__HAL_PWR_PVM4_EXTI_ENABLE_EVENT();
}
/* Configure the edge */
if((sConfigPVM->Mode & PVM_RISING_EDGE) == PVM_RISING_EDGE)
{
__HAL_PWR_PVM4_EXTI_ENABLE_RISING_EDGE();
}
if((sConfigPVM->Mode & PVM_FALLING_EDGE) == PVM_FALLING_EDGE)
{
__HAL_PWR_PVM4_EXTI_ENABLE_FALLING_EDGE();
}
break;
default:
status = HAL_ERROR;
break;
}
return status;
}
/**
* @brief Enter Low-power Run mode
* @note In Low-power Run mode, all I/O pins keep the same state as in Run mode.
* @note When Regulator is set to PWR_LOWPOWERREGULATOR_ON, the user can optionally configure the
* Flash in power-down monde in setting the RUN_PD bit in FLASH_ACR register.
* Additionally, the clock frequency must be reduced below 2 MHz.
* Setting RUN_PD in FLASH_ACR then appropriately reducing the clock frequency must
* be done before calling HAL_PWREx_EnableLowPowerRunMode() API.
* @retval None
*/
void HAL_PWREx_EnableLowPowerRunMode(void)
{
/* Set Regulator parameter */
SET_BIT(PWR->CR1, PWR_CR1_LPR);
}
/**
* @brief Exit Low-power Run mode.
* @note Before HAL_PWREx_DisableLowPowerRunMode() completion, the function checks that
* REGLPF has been properly reset (otherwise, HAL_PWREx_DisableLowPowerRunMode
* returns HAL_TIMEOUT status). The system clock frequency can then be
* increased above 2 MHz.
* @retval HAL Status
*/
HAL_StatusTypeDef HAL_PWREx_DisableLowPowerRunMode(void)
{
uint32_t wait_loop_index;
/* Clear LPR bit */
CLEAR_BIT(PWR->CR1, PWR_CR1_LPR);
/* Wait until REGLPF is reset */
wait_loop_index = ((PWR_FLAG_SETTING_DELAY_US * SystemCoreClock) / 1000000U) + 1U;
while ((HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_REGLPF)) && (wait_loop_index != 0U))
{
wait_loop_index--;
}
if (HAL_IS_BIT_SET(PWR->SR2, PWR_SR2_REGLPF))
{
return HAL_TIMEOUT;
}
return HAL_OK;
}
/**
* @brief Enter Stop 0 mode.
* @note In Stop 0 mode, main and low voltage regulators are ON.
* @note In Stop 0 mode, all I/O pins keep the same state as in Run mode.
* @note All clocks in the VCORE domain are stopped; the PLL, the MSI,
* the HSI and the HSE oscillators are disabled. Some peripherals with the wakeup capability
* (I2Cx, USARTx and LPUART) can switch on the HSI to receive a frame, and switch off the HSI
* after receiving the frame if it is not a wakeup frame. In this case, the HSI clock is propagated
* only to the peripheral requesting it.
* SRAM1, SRAM2 and register contents are preserved.
* The BOR is available.
* @note When exiting Stop 0 mode by issuing an interrupt or a wakeup event,
* the HSI RC oscillator is selected as system clock if STOPWUCK bit in RCC_CFGR register
* is set; the MSI oscillator is selected if STOPWUCK is cleared.
* @note By keeping the internal regulator ON during Stop 0 mode, the consumption
* is higher although the startup time is reduced.
* @param STOPEntry specifies if Stop mode in entered with WFI or WFE instruction.
* This parameter can be one of the following values:
* @arg @ref PWR_STOPENTRY_WFI Enter Stop mode with WFI instruction
* @arg @ref PWR_STOPENTRY_WFE Enter Stop mode with WFE instruction
* @retval None
*/
void HAL_PWREx_EnterSTOP0Mode(uint8_t STOPEntry)
{
/* Check the parameters */
assert_param(IS_PWR_STOP_ENTRY(STOPEntry));
/* Stop 0 mode with Main Regulator */
MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_CR1_LPMS_STOP0);
/* Set SLEEPDEEP bit of Cortex System Control Register */
SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
/* Select Stop mode entry --------------------------------------------------*/
if(STOPEntry == PWR_STOPENTRY_WFI)
{
/* Request Wait For Interrupt */
__WFI();
}
else
{
/* Request Wait For Event */
__SEV();
__WFE();
__WFE();
}
/* Reset SLEEPDEEP bit of Cortex System Control Register */
CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
}
/**
* @brief Enter Stop 1 mode.
* @note In Stop 1 mode, only low power voltage regulator is ON.
* @note In Stop 1 mode, all I/O pins keep the same state as in Run mode.
* @note All clocks in the VCORE domain are stopped; the PLL, the MSI,
* the HSI and the HSE oscillators are disabled. Some peripherals with the wakeup capability
* (I2Cx, USARTx and LPUART) can switch on the HSI to receive a frame, and switch off the HSI
* after receiving the frame if it is not a wakeup frame. In this case, the HSI clock is propagated
* only to the peripheral requesting it.
* SRAM1, SRAM2 and register contents are preserved.
* The BOR is available.
* @note When exiting Stop 1 mode by issuing an interrupt or a wakeup event,
* the HSI RC oscillator is selected as system clock if STOPWUCK bit in RCC_CFGR register
* is set; the MSI oscillator is selected if STOPWUCK is cleared.
* @note Due to low power mode, an additional startup delay is incurred when waking up from Stop 1 mode.
* @param STOPEntry specifies if Stop mode in entered with WFI or WFE instruction.
* This parameter can be one of the following values:
* @arg @ref PWR_STOPENTRY_WFI Enter Stop mode with WFI instruction
* @arg @ref PWR_STOPENTRY_WFE Enter Stop mode with WFE instruction
* @retval None
*/
void HAL_PWREx_EnterSTOP1Mode(uint8_t STOPEntry)
{
/* Check the parameters */
assert_param(IS_PWR_STOP_ENTRY(STOPEntry));
/* Stop 1 mode with Low-Power Regulator */
MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_CR1_LPMS_STOP1);
/* Set SLEEPDEEP bit of Cortex System Control Register */
SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
/* Select Stop mode entry --------------------------------------------------*/
if(STOPEntry == PWR_STOPENTRY_WFI)
{
/* Request Wait For Interrupt */
__WFI();
}
else
{
/* Request Wait For Event */
__SEV();
__WFE();
__WFE();
}
/* Reset SLEEPDEEP bit of Cortex System Control Register */
CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
}
/**
* @brief Enter Stop 2 mode.
* @note In Stop 2 mode, only low power voltage regulator is ON.
* @note In Stop 2 mode, all I/O pins keep the same state as in Run mode.
* @note All clocks in the VCORE domain are stopped, the PLL, the MSI,
* the HSI and the HSE oscillators are disabled. Some peripherals with wakeup capability
* (LCD, LPTIM1, I2C3 and LPUART) can switch on the HSI to receive a frame, and switch off the HSI after
* receiving the frame if it is not a wakeup frame. In this case the HSI clock is propagated only
* to the peripheral requesting it.
* SRAM1, SRAM2 and register contents are preserved.
* SRAM3 content is preserved depending on RRSTP bit setting (not available on all devices).
* The BOR is available.
* The voltage regulator is set in low-power mode but LPR bit must be cleared to enter stop 2 mode.
* Otherwise, Stop 1 mode is entered.
* @note When exiting Stop 2 mode by issuing an interrupt or a wakeup event,
* the HSI RC oscillator is selected as system clock if STOPWUCK bit in RCC_CFGR register
* is set; the MSI oscillator is selected if STOPWUCK is cleared.
* @param STOPEntry specifies if Stop mode in entered with WFI or WFE instruction.
* This parameter can be one of the following values:
* @arg @ref PWR_STOPENTRY_WFI Enter Stop mode with WFI instruction
* @arg @ref PWR_STOPENTRY_WFE Enter Stop mode with WFE instruction
* @retval None
*/
void HAL_PWREx_EnterSTOP2Mode(uint8_t STOPEntry)
{
/* Check the parameter */
assert_param(IS_PWR_STOP_ENTRY(STOPEntry));
/* Set Stop mode 2 */
MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_CR1_LPMS_STOP2);
/* Set SLEEPDEEP bit of Cortex System Control Register */
SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
/* Select Stop mode entry --------------------------------------------------*/
if(STOPEntry == PWR_STOPENTRY_WFI)
{
/* Request Wait For Interrupt */
__WFI();
}
else
{
/* Request Wait For Event */
__SEV();
__WFE();
__WFE();
}
/* Reset SLEEPDEEP bit of Cortex System Control Register */
CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
}
/**
* @brief Enter Shutdown mode.
* @note In Shutdown mode, the PLL, the HSI, the MSI, the LSI and the HSE oscillators are switched
* off. The voltage regulator is disabled and Vcore domain is powered off.
* SRAM1, SRAM2 and registers contents are lost except for registers in the Backup domain.
* The BOR is not available.
* @note The I/Os can be configured either with a pull-up or pull-down or can be kept in analog state.
* @retval None
*/
void HAL_PWREx_EnterSHUTDOWNMode(void)
{
/* Set Shutdown mode */
MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_CR1_LPMS_SHUTDOWN);
/* Set SLEEPDEEP bit of Cortex System Control Register */
SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
/* This option is used to ensure that store operations are completed */
#if defined ( __CC_ARM)
__force_stores();
#endif
/* Request Wait For Interrupt */
__WFI();
}
/**
* @brief This function handles the PWR PVD/PVMx interrupt request.
* @note This API should be called under the PVD_PVM_IRQHandler().
* @retval None
*/
void HAL_PWREx_PVD_PVM_IRQHandler(void)
{
/* Check PWR exti flag */
if(__HAL_PWR_PVD_EXTI_GET_FLAG() != 0x0U)
{
/* PWR PVD interrupt user callback */
HAL_PWR_PVDCallback();
/* Clear PVD exti pending bit */
__HAL_PWR_PVD_EXTI_CLEAR_FLAG();
}
/* Next, successively check PVMx exti flags */
#if defined(PWR_CR2_PVME1)
if(__HAL_PWR_PVM1_EXTI_GET_FLAG() != 0x0U)
{
/* PWR PVM1 interrupt user callback */
HAL_PWREx_PVM1Callback();
/* Clear PVM1 exti pending bit */
__HAL_PWR_PVM1_EXTI_CLEAR_FLAG();
}
#endif /* PWR_CR2_PVME1 */
#if defined(PWR_CR2_PVME2)
if(__HAL_PWR_PVM2_EXTI_GET_FLAG() != 0x0U)
{
/* PWR PVM2 interrupt user callback */
HAL_PWREx_PVM2Callback();
/* Clear PVM2 exti pending bit */
__HAL_PWR_PVM2_EXTI_CLEAR_FLAG();
}
#endif /* PWR_CR2_PVME2 */
if(__HAL_PWR_PVM3_EXTI_GET_FLAG() != 0x0U)
{
/* PWR PVM3 interrupt user callback */
HAL_PWREx_PVM3Callback();
/* Clear PVM3 exti pending bit */
__HAL_PWR_PVM3_EXTI_CLEAR_FLAG();
}
if(__HAL_PWR_PVM4_EXTI_GET_FLAG() != 0x0U)
{
/* PWR PVM4 interrupt user callback */
HAL_PWREx_PVM4Callback();
/* Clear PVM4 exti pending bit */
__HAL_PWR_PVM4_EXTI_CLEAR_FLAG();
}
}
#if defined(PWR_CR2_PVME1)
/**
* @brief PWR PVM1 interrupt callback
* @retval None
*/
__weak void HAL_PWREx_PVM1Callback(void)
{
/* NOTE : This function should not be modified; when the callback is needed,
HAL_PWREx_PVM1Callback() API can be implemented in the user file
*/
}
#endif /* PWR_CR2_PVME1 */
#if defined(PWR_CR2_PVME2)
/**
* @brief PWR PVM2 interrupt callback
* @retval None
*/
__weak void HAL_PWREx_PVM2Callback(void)
{
/* NOTE : This function should not be modified; when the callback is needed,
HAL_PWREx_PVM2Callback() API can be implemented in the user file
*/
}
#endif /* PWR_CR2_PVME2 */
/**
* @brief PWR PVM3 interrupt callback
* @retval None
*/
__weak void HAL_PWREx_PVM3Callback(void)
{
/* NOTE : This function should not be modified; when the callback is needed,
HAL_PWREx_PVM3Callback() API can be implemented in the user file
*/
}
/**
* @brief PWR PVM4 interrupt callback
* @retval None
*/
__weak void HAL_PWREx_PVM4Callback(void)
{
/* NOTE : This function should not be modified; when the callback is needed,
HAL_PWREx_PVM4Callback() API can be implemented in the user file
*/
}
/**
* @}
*/
/**
* @}
*/
#endif /* HAL_PWR_MODULE_ENABLED */
/**
* @}
*/
/**
* @}
*/

View File

@@ -1,1948 +0,0 @@
/**
******************************************************************************
* @file stm32l4xx_hal_rcc.c
* @author MCD Application Team
* @brief RCC HAL module driver.
* This file provides firmware functions to manage the following
* functionalities of the Reset and Clock Control (RCC) peripheral:
* + Initialization and de-initialization functions
* + Peripheral Control functions
*
@verbatim
==============================================================================
##### RCC specific features #####
==============================================================================
[..]
After reset the device is running from Multiple Speed Internal oscillator
(4 MHz) with Flash 0 wait state. Flash prefetch buffer, D-Cache
and I-Cache are disabled, and all peripherals are off except internal
SRAM, Flash and JTAG.
(+) There is no prescaler on High speed (AHBs) and Low speed (APBs) busses:
all peripherals mapped on these busses are running at MSI speed.
(+) The clock for all peripherals is switched off, except the SRAM and FLASH.
(+) All GPIOs are in analog mode, except the JTAG pins which
are assigned to be used for debug purpose.
[..]
Once the device started from reset, the user application has to:
(+) Configure the clock source to be used to drive the System clock
(if the application needs higher frequency/performance)
(+) Configure the System clock frequency and Flash settings
(+) Configure the AHB and APB busses prescalers
(+) Enable the clock for the peripheral(s) to be used
(+) Configure the clock source(s) for peripherals which clocks are not
derived from the System clock (SAIx, RTC, ADC, USB OTG FS/SDMMC1/RNG)
@endverbatim
******************************************************************************
* @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.
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32l4xx_hal.h"
/** @addtogroup STM32L4xx_HAL_Driver
* @{
*/
/** @defgroup RCC RCC
* @brief RCC HAL module driver
* @{
*/
#ifdef HAL_RCC_MODULE_ENABLED
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/** @defgroup RCC_Private_Constants RCC Private Constants
* @{
*/
#define HSE_TIMEOUT_VALUE HSE_STARTUP_TIMEOUT
#define HSI_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */
#define MSI_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */
#if defined(RCC_CSR_LSIPREDIV)
#define LSI_TIMEOUT_VALUE 17U /* 17 ms (16 ms starting time + 1) */
#else
#define LSI_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */
#endif /* RCC_CSR_LSIPREDIV */
#define HSI48_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */
#define PLL_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */
#define CLOCKSWITCH_TIMEOUT_VALUE 5000U /* 5 s */
/**
* @}
*/
/* Private macro -------------------------------------------------------------*/
/** @defgroup RCC_Private_Macros RCC Private Macros
* @{
*/
#define __MCO1_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define MCO1_GPIO_PORT GPIOA
#define MCO1_PIN GPIO_PIN_8
#define RCC_PLL_OSCSOURCE_CONFIG(__HAL_RCC_PLLSOURCE__) \
(MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, (__HAL_RCC_PLLSOURCE__)))
/**
* @}
*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/** @defgroup RCC_Private_Functions RCC Private Functions
* @{
*/
static HAL_StatusTypeDef RCC_SetFlashLatencyFromMSIRange(uint32_t msirange);
#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \
defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
static uint32_t RCC_GetSysClockFreqFromPLLSource(void);
#endif
/**
* @}
*/
/* Exported functions --------------------------------------------------------*/
/** @defgroup RCC_Exported_Functions RCC Exported Functions
* @{
*/
/** @defgroup RCC_Exported_Functions_Group1 Initialization and de-initialization functions
* @brief Initialization and Configuration functions
*
@verbatim
===============================================================================
##### Initialization and de-initialization functions #####
===============================================================================
[..]
This section provides functions allowing to configure the internal and external oscillators
(HSE, HSI, LSE, MSI, LSI, PLL, CSS and MCO) and the System busses clocks (SYSCLK, AHB, APB1
and APB2).
[..] Internal/external clock and PLL configuration
(+) HSI (high-speed internal): 16 MHz factory-trimmed RC used directly or through
the PLL as System clock source.
(+) MSI (Multiple Speed Internal): Its frequency is software trimmable from 100KHZ to 48MHZ.
It can be used to generate the clock for the USB OTG FS (48 MHz).
The number of flash wait states is automatically adjusted when MSI range is updated with
HAL_RCC_OscConfig() and the MSI is used as System clock source.
(+) LSI (low-speed internal): 32 KHz low consumption RC used as IWDG and/or RTC
clock source.
(+) HSE (high-speed external): 4 to 48 MHz crystal oscillator used directly or
through the PLL as System clock source. Can be used also optionally as RTC clock source.
(+) LSE (low-speed external): 32.768 KHz oscillator used optionally as RTC clock source.
(+) PLL (clocked by HSI, HSE or MSI) providing up to three independent output clocks:
(++) The first output is used to generate the high speed system clock (up to 80MHz).
(++) The second output is used to generate the clock for the USB OTG FS (48 MHz),
the random analog generator (<=48 MHz) and the SDMMC1 (<= 48 MHz).
(++) The third output is used to generate an accurate clock to achieve
high-quality audio performance on SAI interface.
(+) PLLSAI1 (clocked by HSI, HSE or MSI) providing up to three independent output clocks:
(++) The first output is used to generate SAR ADC1 clock.
(++) The second output is used to generate the clock for the USB OTG FS (48 MHz),
the random analog generator (<=48 MHz) and the SDMMC1 (<= 48 MHz).
(++) The third output is used to generate an accurate clock to achieve
high-quality audio performance on SAI interface.
(+) PLLSAI2 (clocked by HSI, HSE or MSI) providing up to three independent output clocks:
(++) The first output is used to generate an accurate clock to achieve
high-quality audio performance on SAI interface.
(++) The second output is used to generate either SAR ADC2 clock if ADC2 is present
or LCD clock if LTDC is present.
(++) The third output is used to generate DSI clock if DSI is present.
(+) CSS (Clock security system): once enabled, if a HSE clock failure occurs
(HSE used directly or through PLL as System clock source), the System clock
is automatically switched to HSI and an interrupt is generated if enabled.
The interrupt is linked to the Cortex-M4 NMI (Non-Maskable Interrupt)
exception vector.
(+) MCO (microcontroller clock output): used to output MSI, LSI, HSI, LSE, HSE or
main PLL clock (through a configurable prescaler) on PA8 pin.
[..] System, AHB and APB busses clocks configuration
(+) Several clock sources can be used to drive the System clock (SYSCLK): MSI, HSI,
HSE and main PLL.
The AHB clock (HCLK) is derived from System clock through configurable
prescaler and used to clock the CPU, memory and peripherals mapped
on AHB bus (DMA, GPIO...). APB1 (PCLK1) and APB2 (PCLK2) clocks are derived
from AHB clock through configurable prescalers and used to clock
the peripherals mapped on these busses. You can use
"HAL_RCC_GetSysClockFreq()" function to retrieve the frequencies of these clocks.
-@- All the peripheral clocks are derived from the System clock (SYSCLK) except:
(+@) SAI: the SAI clock can be derived either from a specific PLL (PLLSAI1) or (PLLSAI2) or
from an external clock mapped on the SAI_CKIN pin.
You have to use HAL_RCCEx_PeriphCLKConfig() function to configure this clock.
(+@) RTC: the RTC clock can be derived either from the LSI, LSE or HSE clock
divided by 2 to 31.
You have to use __HAL_RCC_RTC_ENABLE() and HAL_RCCEx_PeriphCLKConfig() function
to configure this clock.
(+@) USB OTG FS, SDMMC1 and RNG: USB OTG FS requires a frequency equal to 48 MHz
to work correctly, while the SDMMC1 and RNG peripherals require a frequency
equal or lower than to 48 MHz. This clock is derived of the main PLL or PLLSAI1
through PLLQ divider. You have to enable the peripheral clock and use
HAL_RCCEx_PeriphCLKConfig() function to configure this clock.
(+@) IWDG clock which is always the LSI clock.
(+) The maximum frequency of the SYSCLK, HCLK, PCLK1 and PCLK2 is 80 MHz.
The clock source frequency should be adapted depending on the device voltage range
as listed in the Reference Manual "Clock source frequency versus voltage scaling" chapter.
@endverbatim
Table 1. HCLK clock frequency for other STM32L4 devices
+-------------------------------------------------------+
| Latency | HCLK clock frequency (MHz) |
| |-------------------------------------|
| | voltage range 1 | voltage range 2 |
| | 1.2 V | 1.0 V |
|-----------------|------------------|------------------|
|0WS(1 CPU cycles)| 0 < HCLK <= 16 | 0 < HCLK <= 6 |
|-----------------|------------------|------------------|
|1WS(2 CPU cycles)| 16 < HCLK <= 32 | 6 < HCLK <= 12 |
|-----------------|------------------|------------------|
|2WS(3 CPU cycles)| 32 < HCLK <= 48 | 12 < HCLK <= 18 |
|-----------------|------------------|------------------|
|3WS(4 CPU cycles)| 48 < HCLK <= 64 | 18 < HCLK <= 26 |
|-----------------|------------------|------------------|
|4WS(5 CPU cycles)| 64 < HCLK <= 80 | 18 < HCLK <= 26 |
+-------------------------------------------------------+
Table 2. HCLK clock frequency for STM32L4+ devices
+--------------------------------------------------------+
| Latency | HCLK clock frequency (MHz) |
| |--------------------------------------|
| | voltage range 1 | voltage range 2 |
| | 1.2 V | 1.0 V |
|-----------------|-------------------|------------------|
|0WS(1 CPU cycles)| 0 < HCLK <= 20 | 0 < HCLK <= 8 |
|-----------------|-------------------|------------------|
|1WS(2 CPU cycles)| 20 < HCLK <= 40 | 8 < HCLK <= 16 |
|-----------------|-------------------|------------------|
|2WS(3 CPU cycles)| 40 < HCLK <= 60 | 16 < HCLK <= 26 |
|-----------------|-------------------|------------------|
|3WS(4 CPU cycles)| 60 < HCLK <= 80 | 16 < HCLK <= 26 |
|-----------------|-------------------|------------------|
|4WS(5 CPU cycles)| 80 < HCLK <= 100 | 16 < HCLK <= 26 |
|-----------------|-------------------|------------------|
|5WS(6 CPU cycles)| 100 < HCLK <= 120 | 16 < HCLK <= 26 |
+--------------------------------------------------------+
* @{
*/
/**
* @brief Reset the RCC clock configuration to the default reset state.
* @note The default reset state of the clock configuration is given below:
* - MSI ON and used as system clock source
* - HSE, HSI, PLL, PLLSAI1 and PLLSAI2 OFF
* - AHB, APB1 and APB2 prescalers set to 1.
* - CSS, MCO1 OFF
* - All interrupts disabled
* - All interrupt and reset flags cleared
* @note This function does not modify the configuration of the
* - Peripheral clock sources
* - LSI, LSE and RTC clocks (Backup domain)
* @retval HAL status
*/
HAL_StatusTypeDef HAL_RCC_DeInit(void)
{
uint32_t tickstart;
/* Reset to default System clock */
/* Set MSION bit */
SET_BIT(RCC->CR, RCC_CR_MSION);
/* Insure MSIRDY bit is set before writing default MSIRANGE value */
/* Get start tick */
tickstart = HAL_GetTick();
/* Wait till MSI is ready */
while(READ_BIT(RCC->CR, RCC_CR_MSIRDY) == 0U)
{
if((HAL_GetTick() - tickstart) > MSI_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
/* Set MSIRANGE default value */
MODIFY_REG(RCC->CR, RCC_CR_MSIRANGE, RCC_MSIRANGE_6);
/* Reset CFGR register (MSI is selected as system clock source) */
CLEAR_REG(RCC->CFGR);
/* Update the SystemCoreClock global variable for MSI as system clock source */
SystemCoreClock = MSI_VALUE;
/* Configure the source of time base considering new system clock settings */
if(HAL_InitTick(uwTickPrio) != HAL_OK)
{
return HAL_ERROR;
}
/* Insure MSI selected as system clock source */
/* Get start tick */
tickstart = HAL_GetTick();
/* Wait till system clock source is ready */
while(READ_BIT(RCC->CFGR, RCC_CFGR_SWS) != RCC_CFGR_SWS_MSI)
{
if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
/* Reset HSION, HSIKERON, HSIASFS, HSEON, HSECSSON, PLLON, PLLSAIxON bits */
#if defined(RCC_PLLSAI2_SUPPORT)
CLEAR_BIT(RCC->CR, RCC_CR_HSEON | RCC_CR_HSION | RCC_CR_HSIKERON| RCC_CR_HSIASFS | RCC_CR_PLLON | RCC_CR_PLLSAI1ON | RCC_CR_PLLSAI2ON);
#elif defined(RCC_PLLSAI1_SUPPORT)
CLEAR_BIT(RCC->CR, RCC_CR_HSEON | RCC_CR_HSION | RCC_CR_HSIKERON| RCC_CR_HSIASFS | RCC_CR_PLLON | RCC_CR_PLLSAI1ON);
#else
CLEAR_BIT(RCC->CR, RCC_CR_HSEON | RCC_CR_HSION | RCC_CR_HSIKERON| RCC_CR_HSIASFS | RCC_CR_PLLON);
#endif /* RCC_PLLSAI2_SUPPORT */
/* Insure PLLRDY, PLLSAI1RDY and PLLSAI2RDY (if present) are reset */
/* Get start tick */
tickstart = HAL_GetTick();
#if defined(RCC_PLLSAI2_SUPPORT)
while(READ_BIT(RCC->CR, RCC_CR_PLLRDY | RCC_CR_PLLSAI1RDY | RCC_CR_PLLSAI2RDY) != 0U)
#elif defined(RCC_PLLSAI1_SUPPORT)
while(READ_BIT(RCC->CR, RCC_CR_PLLRDY | RCC_CR_PLLSAI1RDY) != 0U)
#else
while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) != 0U)
#endif
{
if((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
/* Reset PLLCFGR register */
CLEAR_REG(RCC->PLLCFGR);
SET_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN_4 );
#if defined(RCC_PLLSAI1_SUPPORT)
/* Reset PLLSAI1CFGR register */
CLEAR_REG(RCC->PLLSAI1CFGR);
SET_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N_4 );
#endif /* RCC_PLLSAI1_SUPPORT */
#if defined(RCC_PLLSAI2_SUPPORT)
/* Reset PLLSAI2CFGR register */
CLEAR_REG(RCC->PLLSAI2CFGR);
SET_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N_4 );
#endif /* RCC_PLLSAI2_SUPPORT */
/* Reset HSEBYP bit */
CLEAR_BIT(RCC->CR, RCC_CR_HSEBYP);
/* Disable all interrupts */
CLEAR_REG(RCC->CIER);
/* Clear all interrupt flags */
WRITE_REG(RCC->CICR, 0xFFFFFFFFU);
/* Clear all reset flags */
SET_BIT(RCC->CSR, RCC_CSR_RMVF);
return HAL_OK;
}
/**
* @brief Initialize the RCC Oscillators according to the specified parameters in the
* RCC_OscInitTypeDef.
* @param RCC_OscInitStruct pointer to an RCC_OscInitTypeDef structure that
* contains the configuration information for the RCC Oscillators.
* @note The PLL is not disabled when used as system clock.
* @note The PLL source is not updated when used as PLLSAI(s) clock source.
* @note Transitions LSE Bypass to LSE On and LSE On to LSE Bypass are not
* supported by this macro. User should request a transition to LSE Off
* first and then LSE On or LSE Bypass.
* @note Transition HSE Bypass to HSE On and HSE On to HSE Bypass are not
* supported by this macro. User should request a transition to HSE Off
* first and then HSE On or HSE Bypass.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct)
{
uint32_t tickstart;
HAL_StatusTypeDef status;
uint32_t sysclk_source, pll_config;
/* Check Null pointer */
if(RCC_OscInitStruct == NULL)
{
return HAL_ERROR;
}
/* Check the parameters */
assert_param(IS_RCC_OSCILLATORTYPE(RCC_OscInitStruct->OscillatorType));
sysclk_source = __HAL_RCC_GET_SYSCLK_SOURCE();
pll_config = __HAL_RCC_GET_PLL_OSCSOURCE();
/*----------------------------- MSI Configuration --------------------------*/
if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_MSI) == RCC_OSCILLATORTYPE_MSI)
{
/* Check the parameters */
assert_param(IS_RCC_MSI(RCC_OscInitStruct->MSIState));
assert_param(IS_RCC_MSICALIBRATION_VALUE(RCC_OscInitStruct->MSICalibrationValue));
assert_param(IS_RCC_MSI_CLOCK_RANGE(RCC_OscInitStruct->MSIClockRange));
/* Check if MSI is used as system clock or as PLL source when PLL is selected as system clock */
if((sysclk_source == RCC_CFGR_SWS_MSI) ||
((sysclk_source == RCC_CFGR_SWS_PLL) && (pll_config == RCC_PLLSOURCE_MSI)))
{
if((READ_BIT(RCC->CR, RCC_CR_MSIRDY) != 0U) && (RCC_OscInitStruct->MSIState == RCC_MSI_OFF))
{
return HAL_ERROR;
}
/* Otherwise, just the calibration and MSI range change are allowed */
else
{
/* To correctly read data from FLASH memory, the number of wait states (LATENCY)
must be correctly programmed according to the frequency of the CPU clock
(HCLK) and the supply voltage of the device. */
if(RCC_OscInitStruct->MSIClockRange > __HAL_RCC_GET_MSI_RANGE())
{
/* First increase number of wait states update if necessary */
if(RCC_SetFlashLatencyFromMSIRange(RCC_OscInitStruct->MSIClockRange) != HAL_OK)
{
return HAL_ERROR;
}
/* Selects the Multiple Speed oscillator (MSI) clock range .*/
__HAL_RCC_MSI_RANGE_CONFIG(RCC_OscInitStruct->MSIClockRange);
/* Adjusts the Multiple Speed oscillator (MSI) calibration value.*/
__HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->MSICalibrationValue);
}
else
{
/* Else, keep current flash latency while decreasing applies */
/* Selects the Multiple Speed oscillator (MSI) clock range .*/
__HAL_RCC_MSI_RANGE_CONFIG(RCC_OscInitStruct->MSIClockRange);
/* Adjusts the Multiple Speed oscillator (MSI) calibration value.*/
__HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->MSICalibrationValue);
/* Decrease number of wait states update if necessary */
/* Only possible when MSI is the System clock source */
if(sysclk_source == RCC_CFGR_SWS_MSI)
{
if(RCC_SetFlashLatencyFromMSIRange(RCC_OscInitStruct->MSIClockRange) != HAL_OK)
{
return HAL_ERROR;
}
}
}
/* Update the SystemCoreClock global variable */
SystemCoreClock = HAL_RCC_GetSysClockFreq() >> (AHBPrescTable[READ_BIT(RCC->CFGR, RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos] & 0x1FU);
/* Configure the source of time base considering new system clocks settings*/
status = HAL_InitTick(uwTickPrio);
if(status != HAL_OK)
{
return status;
}
}
}
else
{
/* Check the MSI State */
if(RCC_OscInitStruct->MSIState != RCC_MSI_OFF)
{
/* Enable the Internal High Speed oscillator (MSI). */
__HAL_RCC_MSI_ENABLE();
/* Get timeout */
tickstart = HAL_GetTick();
/* Wait till MSI is ready */
while(READ_BIT(RCC->CR, RCC_CR_MSIRDY) == 0U)
{
if((HAL_GetTick() - tickstart) > MSI_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
/* Selects the Multiple Speed oscillator (MSI) clock range .*/
__HAL_RCC_MSI_RANGE_CONFIG(RCC_OscInitStruct->MSIClockRange);
/* Adjusts the Multiple Speed oscillator (MSI) calibration value.*/
__HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->MSICalibrationValue);
}
else
{
/* Disable the Internal High Speed oscillator (MSI). */
__HAL_RCC_MSI_DISABLE();
/* Get timeout */
tickstart = HAL_GetTick();
/* Wait till MSI is ready */
while(READ_BIT(RCC->CR, RCC_CR_MSIRDY) != 0U)
{
if((HAL_GetTick() - tickstart) > MSI_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
}
}
}
/*------------------------------- HSE Configuration ------------------------*/
if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSE) == RCC_OSCILLATORTYPE_HSE)
{
/* Check the parameters */
assert_param(IS_RCC_HSE(RCC_OscInitStruct->HSEState));
/* When the HSE is used as system clock or clock source for PLL in these cases it is not allowed to be disabled */
if((sysclk_source == RCC_CFGR_SWS_HSE) ||
((sysclk_source == RCC_CFGR_SWS_PLL) && (pll_config == RCC_PLLSOURCE_HSE)))
{
if((READ_BIT(RCC->CR, RCC_CR_HSERDY) != 0U) && (RCC_OscInitStruct->HSEState == RCC_HSE_OFF))
{
return HAL_ERROR;
}
}
else
{
/* Set the new HSE configuration ---------------------------------------*/
__HAL_RCC_HSE_CONFIG(RCC_OscInitStruct->HSEState);
/* Check the HSE State */
if(RCC_OscInitStruct->HSEState != RCC_HSE_OFF)
{
/* Get Start Tick*/
tickstart = HAL_GetTick();
/* Wait till HSE is ready */
while(READ_BIT(RCC->CR, RCC_CR_HSERDY) == 0U)
{
if((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
}
else
{
/* Get Start Tick*/
tickstart = HAL_GetTick();
/* Wait till HSE is disabled */
while(READ_BIT(RCC->CR, RCC_CR_HSERDY) != 0U)
{
if((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
}
}
}
/*----------------------------- HSI Configuration --------------------------*/
if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSI) == RCC_OSCILLATORTYPE_HSI)
{
/* Check the parameters */
assert_param(IS_RCC_HSI(RCC_OscInitStruct->HSIState));
assert_param(IS_RCC_HSI_CALIBRATION_VALUE(RCC_OscInitStruct->HSICalibrationValue));
/* Check if HSI is used as system clock or as PLL source when PLL is selected as system clock */
if((sysclk_source == RCC_CFGR_SWS_HSI) ||
((sysclk_source == RCC_CFGR_SWS_PLL) && (pll_config == RCC_PLLSOURCE_HSI)))
{
/* When HSI is used as system clock it will not be disabled */
if((READ_BIT(RCC->CR, RCC_CR_HSIRDY) != 0U) && (RCC_OscInitStruct->HSIState == RCC_HSI_OFF))
{
return HAL_ERROR;
}
/* Otherwise, just the calibration is allowed */
else
{
/* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/
__HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue);
}
}
else
{
/* Check the HSI State */
if(RCC_OscInitStruct->HSIState != RCC_HSI_OFF)
{
/* Enable the Internal High Speed oscillator (HSI). */
__HAL_RCC_HSI_ENABLE();
/* Get Start Tick*/
tickstart = HAL_GetTick();
/* Wait till HSI is ready */
while(READ_BIT(RCC->CR, RCC_CR_HSIRDY) == 0U)
{
if((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
/* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/
__HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue);
}
else
{
/* Disable the Internal High Speed oscillator (HSI). */
__HAL_RCC_HSI_DISABLE();
/* Get Start Tick*/
tickstart = HAL_GetTick();
/* Wait till HSI is disabled */
while(READ_BIT(RCC->CR, RCC_CR_HSIRDY) != 0U)
{
if((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
}
}
}
/*------------------------------ LSI Configuration -------------------------*/
if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSI) == RCC_OSCILLATORTYPE_LSI)
{
/* Check the parameters */
assert_param(IS_RCC_LSI(RCC_OscInitStruct->LSIState));
/* Check the LSI State */
if(RCC_OscInitStruct->LSIState != RCC_LSI_OFF)
{
#if defined(RCC_CSR_LSIPREDIV)
uint32_t csr_temp = RCC->CSR;
/* Check LSI division factor */
assert_param(IS_RCC_LSIDIV(RCC_OscInitStruct->LSIDiv));
if (RCC_OscInitStruct->LSIDiv != (csr_temp & RCC_CSR_LSIPREDIV))
{
if (((csr_temp & RCC_CSR_LSIRDY) == RCC_CSR_LSIRDY) && \
((csr_temp & RCC_CSR_LSION) != RCC_CSR_LSION))
{
/* If LSIRDY is set while LSION is not enabled,
LSIPREDIV can't be updated */
return HAL_ERROR;
}
/* Turn off LSI before changing RCC_CSR_LSIPREDIV */
if ((csr_temp & RCC_CSR_LSION) == RCC_CSR_LSION)
{
__HAL_RCC_LSI_DISABLE();
/* Get Start Tick*/
tickstart = HAL_GetTick();
/* Wait till LSI is disabled */
while(READ_BIT(RCC->CSR, RCC_CSR_LSIRDY) != 0U)
{
if((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
}
/* Set LSI division factor */
MODIFY_REG(RCC->CSR, RCC_CSR_LSIPREDIV, RCC_OscInitStruct->LSIDiv);
}
#endif /* RCC_CSR_LSIPREDIV */
/* Enable the Internal Low Speed oscillator (LSI). */
__HAL_RCC_LSI_ENABLE();
/* Get Start Tick*/
tickstart = HAL_GetTick();
/* Wait till LSI is ready */
while(READ_BIT(RCC->CSR, RCC_CSR_LSIRDY) == 0U)
{
if((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
}
else
{
/* Disable the Internal Low Speed oscillator (LSI). */
__HAL_RCC_LSI_DISABLE();
/* Get Start Tick*/
tickstart = HAL_GetTick();
/* Wait till LSI is disabled */
while(READ_BIT(RCC->CSR, RCC_CSR_LSIRDY) != 0U)
{
if((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
}
}
/*------------------------------ LSE Configuration -------------------------*/
if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE)
{
FlagStatus pwrclkchanged = RESET;
/* Check the parameters */
assert_param(IS_RCC_LSE(RCC_OscInitStruct->LSEState));
/* Update LSE configuration in Backup Domain control register */
/* Requires to enable write access to Backup Domain of necessary */
if(HAL_IS_BIT_CLR(RCC->APB1ENR1, RCC_APB1ENR1_PWREN))
{
__HAL_RCC_PWR_CLK_ENABLE();
pwrclkchanged = SET;
}
if(HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP))
{
/* Enable write access to Backup domain */
SET_BIT(PWR->CR1, PWR_CR1_DBP);
/* Wait for Backup domain Write protection disable */
tickstart = HAL_GetTick();
while(HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP))
{
if((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
}
/* Set the new LSE configuration -----------------------------------------*/
#if defined(RCC_BDCR_LSESYSDIS)
if((RCC_OscInitStruct->LSEState & RCC_BDCR_LSEON) != 0U)
{
/* Set LSESYSDIS bit according to LSE propagation option (enabled or disabled) */
MODIFY_REG(RCC->BDCR, RCC_BDCR_LSESYSDIS, (RCC_OscInitStruct->LSEState & RCC_BDCR_LSESYSDIS));
if((RCC_OscInitStruct->LSEState & RCC_BDCR_LSEBYP) != 0U)
{
/* LSE oscillator bypass enable */
SET_BIT(RCC->BDCR, RCC_BDCR_LSEBYP);
SET_BIT(RCC->BDCR, RCC_BDCR_LSEON);
}
else
{
/* LSE oscillator enable */
SET_BIT(RCC->BDCR, RCC_BDCR_LSEON);
}
}
else
{
CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEON);
CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSEBYP);
}
#else
__HAL_RCC_LSE_CONFIG(RCC_OscInitStruct->LSEState);
#endif /* RCC_BDCR_LSESYSDIS */
/* Check the LSE State */
if(RCC_OscInitStruct->LSEState != RCC_LSE_OFF)
{
/* Get Start Tick*/
tickstart = HAL_GetTick();
/* Wait till LSE is ready */
while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == 0U)
{
if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
}
else
{
/* Get Start Tick*/
tickstart = HAL_GetTick();
/* Wait till LSE is disabled */
while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) != 0U)
{
if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
#if defined(RCC_BDCR_LSESYSDIS)
/* By default, stop disabling LSE propagation */
CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSESYSDIS);
#endif /* RCC_BDCR_LSESYSDIS */
}
/* Restore clock configuration if changed */
if(pwrclkchanged == SET)
{
__HAL_RCC_PWR_CLK_DISABLE();
}
}
#if defined(RCC_HSI48_SUPPORT)
/*------------------------------ HSI48 Configuration -----------------------*/
if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSI48) == RCC_OSCILLATORTYPE_HSI48)
{
/* Check the parameters */
assert_param(IS_RCC_HSI48(RCC_OscInitStruct->HSI48State));
/* Check the LSI State */
if(RCC_OscInitStruct->HSI48State != RCC_HSI48_OFF)
{
/* Enable the Internal Low Speed oscillator (HSI48). */
__HAL_RCC_HSI48_ENABLE();
/* Get Start Tick*/
tickstart = HAL_GetTick();
/* Wait till HSI48 is ready */
while(READ_BIT(RCC->CRRCR, RCC_CRRCR_HSI48RDY) == 0U)
{
if((HAL_GetTick() - tickstart) > HSI48_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
}
else
{
/* Disable the Internal Low Speed oscillator (HSI48). */
__HAL_RCC_HSI48_DISABLE();
/* Get Start Tick*/
tickstart = HAL_GetTick();
/* Wait till HSI48 is disabled */
while(READ_BIT(RCC->CRRCR, RCC_CRRCR_HSI48RDY) != 0U)
{
if((HAL_GetTick() - tickstart) > HSI48_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
}
}
#endif /* RCC_HSI48_SUPPORT */
/*-------------------------------- PLL Configuration -----------------------*/
/* Check the parameters */
assert_param(IS_RCC_PLL(RCC_OscInitStruct->PLL.PLLState));
if(RCC_OscInitStruct->PLL.PLLState != RCC_PLL_NONE)
{
/* PLL On ? */
if(RCC_OscInitStruct->PLL.PLLState == RCC_PLL_ON)
{
/* Check the parameters */
assert_param(IS_RCC_PLLSOURCE(RCC_OscInitStruct->PLL.PLLSource));
assert_param(IS_RCC_PLLM_VALUE(RCC_OscInitStruct->PLL.PLLM));
assert_param(IS_RCC_PLLN_VALUE(RCC_OscInitStruct->PLL.PLLN));
#if defined(RCC_PLLP_SUPPORT)
assert_param(IS_RCC_PLLP_VALUE(RCC_OscInitStruct->PLL.PLLP));
#endif /* RCC_PLLP_SUPPORT */
assert_param(IS_RCC_PLLQ_VALUE(RCC_OscInitStruct->PLL.PLLQ));
assert_param(IS_RCC_PLLR_VALUE(RCC_OscInitStruct->PLL.PLLR));
/* Do nothing if PLL configuration is the unchanged */
pll_config = RCC->PLLCFGR;
if((READ_BIT(pll_config, RCC_PLLCFGR_PLLSRC) != RCC_OscInitStruct->PLL.PLLSource) ||
(READ_BIT(pll_config, RCC_PLLCFGR_PLLM) != ((RCC_OscInitStruct->PLL.PLLM - 1U) << RCC_PLLCFGR_PLLM_Pos)) ||
(READ_BIT(pll_config, RCC_PLLCFGR_PLLN) != (RCC_OscInitStruct->PLL.PLLN << RCC_PLLCFGR_PLLN_Pos)) ||
#if defined(RCC_PLLP_SUPPORT)
#if defined(RCC_PLLP_DIV_2_31_SUPPORT)
(READ_BIT(pll_config, RCC_PLLCFGR_PLLPDIV) != (RCC_OscInitStruct->PLL.PLLP << RCC_PLLCFGR_PLLPDIV_Pos)) ||
#else
(READ_BIT(pll_config, RCC_PLLCFGR_PLLP) != ((RCC_OscInitStruct->PLL.PLLP == RCC_PLLP_DIV7) ? 0U : 1U)) ||
#endif
#endif
(READ_BIT(pll_config, RCC_PLLCFGR_PLLQ) != ((((RCC_OscInitStruct->PLL.PLLQ) >> 1U) - 1U) << RCC_PLLCFGR_PLLQ_Pos)) ||
(READ_BIT(pll_config, RCC_PLLCFGR_PLLR) != ((((RCC_OscInitStruct->PLL.PLLR) >> 1U) - 1U) << RCC_PLLCFGR_PLLR_Pos)))
{
/* Check if the PLL is used as system clock or not */
if(sysclk_source != RCC_CFGR_SWS_PLL)
{
#if defined(RCC_PLLSAI1_SUPPORT) || defined(RCC_PLLSAI2_SUPPORT)
/* Check if main PLL can be updated */
/* Not possible if the source is shared by other enabled PLLSAIx */
if((READ_BIT(RCC->CR, RCC_CR_PLLSAI1ON) != 0U)
#if defined(RCC_PLLSAI2_SUPPORT)
|| (READ_BIT(RCC->CR, RCC_CR_PLLSAI2ON) != 0U)
#endif
)
{
return HAL_ERROR;
}
else
#endif /* RCC_PLLSAI1_SUPPORT || RCC_PLLSAI2_SUPPORT */
{
/* Disable the main PLL. */
__HAL_RCC_PLL_DISABLE();
/* Get Start Tick*/
tickstart = HAL_GetTick();
/* Wait till PLL is ready */
while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) != 0U)
{
if((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
/* Configure the main PLL clock source, multiplication and division factors. */
#if defined(RCC_PLLP_SUPPORT)
__HAL_RCC_PLL_CONFIG(RCC_OscInitStruct->PLL.PLLSource,
RCC_OscInitStruct->PLL.PLLM,
RCC_OscInitStruct->PLL.PLLN,
RCC_OscInitStruct->PLL.PLLP,
RCC_OscInitStruct->PLL.PLLQ,
RCC_OscInitStruct->PLL.PLLR);
#else
__HAL_RCC_PLL_CONFIG(RCC_OscInitStruct->PLL.PLLSource,
RCC_OscInitStruct->PLL.PLLM,
RCC_OscInitStruct->PLL.PLLN,
RCC_OscInitStruct->PLL.PLLQ,
RCC_OscInitStruct->PLL.PLLR);
#endif
/* Enable the main PLL. */
__HAL_RCC_PLL_ENABLE();
/* Enable PLL System Clock output. */
__HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SYSCLK);
/* Get Start Tick*/
tickstart = HAL_GetTick();
/* Wait till PLL is ready */
while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) == 0U)
{
if((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
}
}
else
{
/* PLL is already used as System core clock */
return HAL_ERROR;
}
}
else
{
/* PLL configuration is unchanged */
/* Re-enable PLL if it was disabled (ie. low power mode) */
if(READ_BIT(RCC->CR, RCC_CR_PLLRDY) == 0U)
{
/* Enable the main PLL. */
__HAL_RCC_PLL_ENABLE();
/* Enable PLL System Clock output. */
__HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SYSCLK);
/* Get Start Tick*/
tickstart = HAL_GetTick();
/* Wait till PLL is ready */
while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) == 0U)
{
if((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
}
}
}
else
{
/* Check that PLL is not used as system clock or not */
if(sysclk_source != RCC_CFGR_SWS_PLL)
{
/* Disable the main PLL. */
__HAL_RCC_PLL_DISABLE();
/* Disable all PLL outputs to save power if no PLLs on */
#if defined(RCC_PLLSAI1_SUPPORT) && defined(RCC_CR_PLLSAI2RDY)
if(READ_BIT(RCC->CR, (RCC_CR_PLLSAI1RDY | RCC_CR_PLLSAI2RDY)) == 0U)
{
MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, RCC_PLLSOURCE_NONE);
}
#elif defined(RCC_PLLSAI1_SUPPORT)
if(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == 0U)
{
MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, RCC_PLLSOURCE_NONE);
}
#else
MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, RCC_PLLSOURCE_NONE);
#endif /* RCC_PLLSAI1_SUPPORT && RCC_CR_PLLSAI2RDY */
#if defined(RCC_PLLSAI2_SUPPORT)
__HAL_RCC_PLLCLKOUT_DISABLE(RCC_PLL_SYSCLK | RCC_PLL_48M1CLK | RCC_PLL_SAI3CLK);
#elif defined(RCC_PLLSAI1_SUPPORT)
__HAL_RCC_PLLCLKOUT_DISABLE(RCC_PLL_SYSCLK | RCC_PLL_48M1CLK | RCC_PLL_SAI2CLK);
#else
__HAL_RCC_PLLCLKOUT_DISABLE(RCC_PLL_SYSCLK | RCC_PLL_48M1CLK);
#endif /* RCC_PLLSAI2_SUPPORT */
/* Get Start Tick*/
tickstart = HAL_GetTick();
/* Wait till PLL is disabled */
while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) != 0U)
{
if((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
}
else
{
/* PLL is already used as System core clock */
return HAL_ERROR;
}
}
}
return HAL_OK;
}
/**
* @brief Initialize the CPU, AHB and APB busses clocks according to the specified
* parameters in the RCC_ClkInitStruct.
* @param RCC_ClkInitStruct pointer to an RCC_OscInitTypeDef structure that
* contains the configuration information for the RCC peripheral.
* @param FLatency FLASH Latency
* This parameter can be one of the following values:
* @arg FLASH_LATENCY_0 FLASH 0 Latency cycle
* @arg FLASH_LATENCY_1 FLASH 1 Latency cycle
* @arg FLASH_LATENCY_2 FLASH 2 Latency cycles
* @arg FLASH_LATENCY_3 FLASH 3 Latency cycles
* @arg FLASH_LATENCY_4 FLASH 4 Latency cycles
@if STM32L4S9xx
* @arg FLASH_LATENCY_5 FLASH 5 Latency cycles
* @arg FLASH_LATENCY_6 FLASH 6 Latency cycles
* @arg FLASH_LATENCY_7 FLASH 7 Latency cycles
* @arg FLASH_LATENCY_8 FLASH 8 Latency cycles
* @arg FLASH_LATENCY_9 FLASH 9 Latency cycles
* @arg FLASH_LATENCY_10 FLASH 10 Latency cycles
* @arg FLASH_LATENCY_11 FLASH 11 Latency cycles
* @arg FLASH_LATENCY_12 FLASH 12 Latency cycles
* @arg FLASH_LATENCY_13 FLASH 13 Latency cycles
* @arg FLASH_LATENCY_14 FLASH 14 Latency cycles
* @arg FLASH_LATENCY_15 FLASH 15 Latency cycles
@endif
*
* @note The SystemCoreClock CMSIS variable is used to store System Clock Frequency
* and updated by HAL_RCC_GetHCLKFreq() function called within this function
*
* @note The MSI is used by default as system clock source after
* startup from Reset, wake-up from STANDBY mode. After restart from Reset,
* the MSI frequency is set to its default value 4 MHz.
*
* @note The HSI can be selected as system clock source after
* from STOP modes or in case of failure of the HSE used directly or indirectly
* as system clock (if the Clock Security System CSS is enabled).
*
* @note A switch from one clock source to another occurs only if the target
* clock source is ready (clock stable after startup delay or PLL locked).
* If a clock source which is not yet ready is selected, the switch will
* occur when the clock source is ready.
*
* @note You can use HAL_RCC_GetClockConfig() function to know which clock is
* currently used as system clock source.
*
* @note Depending on the device voltage range, the software has to set correctly
* HPRE[3:0] bits to ensure that HCLK not exceed the maximum allowed frequency
* (for more details refer to section above "Initialization/de-initialization functions")
* @retval None
*/
HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t FLatency)
{
uint32_t tickstart;
#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \
defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
uint32_t hpre = RCC_SYSCLK_DIV1;
#endif
HAL_StatusTypeDef status;
/* Check Null pointer */
if(RCC_ClkInitStruct == NULL)
{
return HAL_ERROR;
}
/* Check the parameters */
assert_param(IS_RCC_CLOCKTYPE(RCC_ClkInitStruct->ClockType));
assert_param(IS_FLASH_LATENCY(FLatency));
/* To correctly read data from FLASH memory, the number of wait states (LATENCY)
must be correctly programmed according to the frequency of the CPU clock
(HCLK) and the supply voltage of the device. */
/* Increasing the number of wait states because of higher CPU frequency */
if(FLatency > __HAL_FLASH_GET_LATENCY())
{
/* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
__HAL_FLASH_SET_LATENCY(FLatency);
/* Check that the new number of wait states is taken into account to access the Flash
memory by reading the FLASH_ACR register */
if(__HAL_FLASH_GET_LATENCY() != FLatency)
{
return HAL_ERROR;
}
}
/*------------------------- SYSCLK Configuration ---------------------------*/
if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_SYSCLK) == RCC_CLOCKTYPE_SYSCLK)
{
assert_param(IS_RCC_SYSCLKSOURCE(RCC_ClkInitStruct->SYSCLKSource));
/* PLL is selected as System Clock Source */
if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_PLLCLK)
{
/* Check the PLL ready flag */
if(READ_BIT(RCC->CR, RCC_CR_PLLRDY) == 0U)
{
return HAL_ERROR;
}
#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \
defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
/* Undershoot management when selection PLL as SYSCLK source and frequency above 80Mhz */
/* Compute target PLL output frequency */
if(RCC_GetSysClockFreqFromPLLSource() > 80000000U)
{
if(READ_BIT(RCC->CFGR, RCC_CFGR_HPRE) == RCC_SYSCLK_DIV1)
{
/* Intermediate step with HCLK prescaler 2 necessary before to go over 80Mhz */
MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_SYSCLK_DIV2);
hpre = RCC_SYSCLK_DIV2;
}
else if((((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_HCLK) == RCC_CLOCKTYPE_HCLK) && (RCC_ClkInitStruct->AHBCLKDivider == RCC_SYSCLK_DIV1))
{
/* Intermediate step with HCLK prescaler 2 necessary before to go over 80Mhz */
MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_SYSCLK_DIV2);
hpre = RCC_SYSCLK_DIV2;
}
else
{
/* nothing to do */
}
}
#endif
}
else
{
/* HSE is selected as System Clock Source */
if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE)
{
/* Check the HSE ready flag */
if(READ_BIT(RCC->CR, RCC_CR_HSERDY) == 0U)
{
return HAL_ERROR;
}
}
/* MSI is selected as System Clock Source */
else if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_MSI)
{
/* Check the MSI ready flag */
if(READ_BIT(RCC->CR, RCC_CR_MSIRDY) == 0U)
{
return HAL_ERROR;
}
}
/* HSI is selected as System Clock Source */
else
{
/* Check the HSI ready flag */
if(READ_BIT(RCC->CR, RCC_CR_HSIRDY) == 0U)
{
return HAL_ERROR;
}
}
#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \
defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
/* Overshoot management when going down from PLL as SYSCLK source and frequency above 80Mhz */
if(HAL_RCC_GetSysClockFreq() > 80000000U)
{
/* Intermediate step with HCLK prescaler 2 necessary before to go under 80Mhz */
MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_SYSCLK_DIV2);
hpre = RCC_SYSCLK_DIV2;
}
#endif
}
MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_ClkInitStruct->SYSCLKSource);
/* Get Start Tick*/
tickstart = HAL_GetTick();
while(__HAL_RCC_GET_SYSCLK_SOURCE() != (RCC_ClkInitStruct->SYSCLKSource << RCC_CFGR_SWS_Pos))
{
if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE)
{
return HAL_TIMEOUT;
}
}
}
/*-------------------------- HCLK Configuration --------------------------*/
if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_HCLK) == RCC_CLOCKTYPE_HCLK)
{
assert_param(IS_RCC_HCLK(RCC_ClkInitStruct->AHBCLKDivider));
MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_ClkInitStruct->AHBCLKDivider);
}
#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \
defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
else
{
/* Is intermediate HCLK prescaler 2 applied internally, complete with HCLK prescaler 1 */
if(hpre == RCC_SYSCLK_DIV2)
{
MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_SYSCLK_DIV1);
}
}
#endif
/* Decreasing the number of wait states because of lower CPU frequency */
if(FLatency < __HAL_FLASH_GET_LATENCY())
{
/* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
__HAL_FLASH_SET_LATENCY(FLatency);
/* Check that the new number of wait states is taken into account to access the Flash
memory by reading the FLASH_ACR register */
if(__HAL_FLASH_GET_LATENCY() != FLatency)
{
return HAL_ERROR;
}
}
/*-------------------------- PCLK1 Configuration ---------------------------*/
if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK1) == RCC_CLOCKTYPE_PCLK1)
{
assert_param(IS_RCC_PCLK(RCC_ClkInitStruct->APB1CLKDivider));
MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE1, RCC_ClkInitStruct->APB1CLKDivider);
}
/*-------------------------- PCLK2 Configuration ---------------------------*/
if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK2) == RCC_CLOCKTYPE_PCLK2)
{
assert_param(IS_RCC_PCLK(RCC_ClkInitStruct->APB2CLKDivider));
MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2, ((RCC_ClkInitStruct->APB2CLKDivider) << 3U));
}
/* Update the SystemCoreClock global variable */
SystemCoreClock = HAL_RCC_GetSysClockFreq() >> (AHBPrescTable[READ_BIT(RCC->CFGR, RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos] & 0x1FU);
/* Configure the source of time base considering new system clocks settings*/
status = HAL_InitTick(uwTickPrio);
return status;
}
/**
* @}
*/
/** @defgroup RCC_Exported_Functions_Group2 Peripheral Control functions
* @brief RCC clocks control functions
*
@verbatim
===============================================================================
##### Peripheral Control functions #####
===============================================================================
[..]
This subsection provides a set of functions allowing to:
(+) Output clock to MCO pin.
(+) Retrieve current clock frequencies.
(+) Enable the Clock Security System.
@endverbatim
* @{
*/
/**
* @brief Select the clock source to output on MCO pin(PA8).
* @note PA8 should be configured in alternate function mode.
* @param RCC_MCOx specifies the output direction for the clock source.
* For STM32L4xx family this parameter can have only one value:
* @arg @ref RCC_MCO1 Clock source to output on MCO1 pin(PA8).
* @param RCC_MCOSource specifies the clock source to output.
* This parameter can be one of the following values:
* @arg @ref RCC_MCO1SOURCE_NOCLOCK MCO output disabled, no clock on MCO
* @arg @ref RCC_MCO1SOURCE_SYSCLK system clock selected as MCO source
* @arg @ref RCC_MCO1SOURCE_MSI MSI clock selected as MCO source
* @arg @ref RCC_MCO1SOURCE_HSI HSI clock selected as MCO source
* @arg @ref RCC_MCO1SOURCE_HSE HSE clock selected as MCO sourcee
* @arg @ref RCC_MCO1SOURCE_PLLCLK main PLL clock selected as MCO source
* @arg @ref RCC_MCO1SOURCE_LSI LSI clock selected as MCO source
* @arg @ref RCC_MCO1SOURCE_LSE LSE clock selected as MCO source
@if STM32L443xx
* @arg @ref RCC_MCO1SOURCE_HSI48 HSI48 clock selected as MCO source for devices with HSI48
@endif
* @param RCC_MCODiv specifies the MCO prescaler.
* This parameter can be one of the following values:
* @arg @ref RCC_MCODIV_1 no division applied to MCO clock
* @arg @ref RCC_MCODIV_2 division by 2 applied to MCO clock
* @arg @ref RCC_MCODIV_4 division by 4 applied to MCO clock
* @arg @ref RCC_MCODIV_8 division by 8 applied to MCO clock
* @arg @ref RCC_MCODIV_16 division by 16 applied to MCO clock
* @retval None
*/
void HAL_RCC_MCOConfig( uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_MCODiv)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* Check the parameters */
assert_param(IS_RCC_MCO(RCC_MCOx));
assert_param(IS_RCC_MCODIV(RCC_MCODiv));
assert_param(IS_RCC_MCO1SOURCE(RCC_MCOSource));
/* Prevent unused argument(s) compilation warning if no assert_param check */
UNUSED(RCC_MCOx);
/* MCO Clock Enable */
__MCO1_CLK_ENABLE();
/* Configure the MCO1 pin in alternate function mode */
GPIO_InitStruct.Pin = MCO1_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Alternate = GPIO_AF0_MCO;
HAL_GPIO_Init(MCO1_GPIO_PORT, &GPIO_InitStruct);
/* Mask MCOSEL[] and MCOPRE[] bits then set MCO1 clock source and prescaler */
MODIFY_REG(RCC->CFGR, (RCC_CFGR_MCOSEL | RCC_CFGR_MCOPRE), (RCC_MCOSource | RCC_MCODiv ));
}
/**
* @brief Return the SYSCLK frequency.
*
* @note The system frequency computed by this function is not the real
* frequency in the chip. It is calculated based on the predefined
* constant and the selected clock source:
* @note If SYSCLK source is MSI, function returns values based on MSI
* Value as defined by the MSI range.
* @note If SYSCLK source is HSI, function returns values based on HSI_VALUE(*)
* @note If SYSCLK source is HSE, function returns values based on HSE_VALUE(**)
* @note If SYSCLK source is PLL, function returns values based on HSE_VALUE(**),
* HSI_VALUE(*) or MSI Value multiplied/divided by the PLL factors.
* @note (*) HSI_VALUE is a constant defined in stm32l4xx_hal_conf.h file (default value
* 16 MHz) but the real value may vary depending on the variations
* in voltage and temperature.
* @note (**) HSE_VALUE is a constant defined in stm32l4xx_hal_conf.h file (default value
* 8 MHz), user has to ensure that HSE_VALUE is same as the real
* frequency of the crystal used. Otherwise, this function may
* have wrong result.
*
* @note The result of this function could be not correct when using fractional
* value for HSE crystal.
*
* @note This function can be used by the user application to compute the
* baudrate for the communication peripherals or configure other parameters.
*
* @note Each time SYSCLK changes, this function must be called to update the
* right SYSCLK value. Otherwise, any configuration based on this function will be incorrect.
*
*
* @retval SYSCLK frequency
*/
uint32_t HAL_RCC_GetSysClockFreq(void)
{
uint32_t msirange = 0U, sysclockfreq = 0U;
uint32_t pllvco, pllsource, pllr, pllm; /* no init needed */
uint32_t sysclk_source, pll_oscsource;
sysclk_source = __HAL_RCC_GET_SYSCLK_SOURCE();
pll_oscsource = __HAL_RCC_GET_PLL_OSCSOURCE();
if((sysclk_source == RCC_CFGR_SWS_MSI) ||
((sysclk_source == RCC_CFGR_SWS_PLL) && (pll_oscsource == RCC_PLLSOURCE_MSI)))
{
/* MSI or PLL with MSI source used as system clock source */
/* Get SYSCLK source */
if(READ_BIT(RCC->CR, RCC_CR_MSIRGSEL) == 0U)
{ /* MSISRANGE from RCC_CSR applies */
msirange = READ_BIT(RCC->CSR, RCC_CSR_MSISRANGE) >> RCC_CSR_MSISRANGE_Pos;
}
else
{ /* MSIRANGE from RCC_CR applies */
msirange = READ_BIT(RCC->CR, RCC_CR_MSIRANGE) >> RCC_CR_MSIRANGE_Pos;
}
/*MSI frequency range in HZ*/
msirange = MSIRangeTable[msirange];
if(sysclk_source == RCC_CFGR_SWS_MSI)
{
/* MSI used as system clock source */
sysclockfreq = msirange;
}
}
else if(sysclk_source == RCC_CFGR_SWS_HSI)
{
/* HSI used as system clock source */
sysclockfreq = HSI_VALUE;
}
else if(sysclk_source == RCC_CFGR_SWS_HSE)
{
/* HSE used as system clock source */
sysclockfreq = HSE_VALUE;
}
else
{
/* unexpected case: sysclockfreq at 0 */
}
if(sysclk_source == RCC_CFGR_SWS_PLL)
{
/* PLL used as system clock source */
/* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE) * PLLN / PLLM
SYSCLK = PLL_VCO / PLLR
*/
pllsource = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC);
switch (pllsource)
{
case RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */
pllvco = HSI_VALUE;
break;
case RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */
pllvco = HSE_VALUE;
break;
case RCC_PLLSOURCE_MSI: /* MSI used as PLL clock source */
default:
pllvco = msirange;
break;
}
pllm = (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U ;
pllvco = (pllvco * (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos)) / pllm;
pllr = ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1U ) * 2U;
sysclockfreq = pllvco / pllr;
}
return sysclockfreq;
}
/**
* @brief Return the HCLK frequency.
* @note Each time HCLK changes, this function must be called to update the
* right HCLK value. Otherwise, any configuration based on this function will be incorrect.
*
* @note The SystemCoreClock CMSIS variable is used to store System Clock Frequency.
* @retval HCLK frequency in Hz
*/
uint32_t HAL_RCC_GetHCLKFreq(void)
{
return SystemCoreClock;
}
/**
* @brief Return the PCLK1 frequency.
* @note Each time PCLK1 changes, this function must be called to update the
* right PCLK1 value. Otherwise, any configuration based on this function will be incorrect.
* @retval PCLK1 frequency in Hz
*/
uint32_t HAL_RCC_GetPCLK1Freq(void)
{
/* Get HCLK source and Compute PCLK1 frequency ---------------------------*/
return (HAL_RCC_GetHCLKFreq() >> (APBPrescTable[READ_BIT(RCC->CFGR, RCC_CFGR_PPRE1) >> RCC_CFGR_PPRE1_Pos] & 0x1FU));
}
/**
* @brief Return the PCLK2 frequency.
* @note Each time PCLK2 changes, this function must be called to update the
* right PCLK2 value. Otherwise, any configuration based on this function will be incorrect.
* @retval PCLK2 frequency in Hz
*/
uint32_t HAL_RCC_GetPCLK2Freq(void)
{
/* Get HCLK source and Compute PCLK2 frequency ---------------------------*/
return (HAL_RCC_GetHCLKFreq()>> (APBPrescTable[READ_BIT(RCC->CFGR, RCC_CFGR_PPRE2) >> RCC_CFGR_PPRE2_Pos] & 0x1FU));
}
/**
* @brief Configure the RCC_OscInitStruct according to the internal
* RCC configuration registers.
* @param RCC_OscInitStruct pointer to an RCC_OscInitTypeDef structure that
* will be configured.
* @retval None
*/
void HAL_RCC_GetOscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct)
{
/* Check the parameters */
assert_param(RCC_OscInitStruct != (void *)NULL);
/* Set all possible values for the Oscillator type parameter ---------------*/
#if defined(RCC_HSI48_SUPPORT)
RCC_OscInitStruct->OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_MSI | \
RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_HSI48;
#else
RCC_OscInitStruct->OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_MSI | \
RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_LSI;
#endif /* RCC_HSI48_SUPPORT */
/* Get the HSE configuration -----------------------------------------------*/
if(READ_BIT(RCC->CR, RCC_CR_HSEBYP) == RCC_CR_HSEBYP)
{
RCC_OscInitStruct->HSEState = RCC_HSE_BYPASS;
}
else if(READ_BIT(RCC->CR, RCC_CR_HSEON) == RCC_CR_HSEON)
{
RCC_OscInitStruct->HSEState = RCC_HSE_ON;
}
else
{
RCC_OscInitStruct->HSEState = RCC_HSE_OFF;
}
/* Get the MSI configuration -----------------------------------------------*/
if(READ_BIT(RCC->CR, RCC_CR_MSION) == RCC_CR_MSION)
{
RCC_OscInitStruct->MSIState = RCC_MSI_ON;
}
else
{
RCC_OscInitStruct->MSIState = RCC_MSI_OFF;
}
RCC_OscInitStruct->MSICalibrationValue = READ_BIT(RCC->ICSCR, RCC_ICSCR_MSITRIM) >> RCC_ICSCR_MSITRIM_Pos;
RCC_OscInitStruct->MSIClockRange = READ_BIT(RCC->CR, RCC_CR_MSIRANGE);
/* Get the HSI configuration -----------------------------------------------*/
if(READ_BIT(RCC->CR, RCC_CR_HSION) == RCC_CR_HSION)
{
RCC_OscInitStruct->HSIState = RCC_HSI_ON;
}
else
{
RCC_OscInitStruct->HSIState = RCC_HSI_OFF;
}
RCC_OscInitStruct->HSICalibrationValue = READ_BIT(RCC->ICSCR, RCC_ICSCR_HSITRIM) >> RCC_ICSCR_HSITRIM_Pos;
/* Get the LSE configuration -----------------------------------------------*/
if(READ_BIT(RCC->BDCR, RCC_BDCR_LSEBYP) == RCC_BDCR_LSEBYP)
{
#if defined(RCC_BDCR_LSESYSDIS)
if((RCC->BDCR & RCC_BDCR_LSESYSDIS) == RCC_BDCR_LSESYSDIS)
{
RCC_OscInitStruct->LSEState = RCC_LSE_BYPASS_RTC_ONLY;
}
else
#endif /* RCC_BDCR_LSESYSDIS */
{
RCC_OscInitStruct->LSEState = RCC_LSE_BYPASS;
}
}
else if(READ_BIT(RCC->BDCR, RCC_BDCR_LSEON) == RCC_BDCR_LSEON)
{
#if defined(RCC_BDCR_LSESYSDIS)
if((RCC->BDCR & RCC_BDCR_LSESYSDIS) == RCC_BDCR_LSESYSDIS)
{
RCC_OscInitStruct->LSEState = RCC_LSE_ON_RTC_ONLY;
}
else
#endif /* RCC_BDCR_LSESYSDIS */
{
RCC_OscInitStruct->LSEState = RCC_LSE_ON;
}
}
else
{
RCC_OscInitStruct->LSEState = RCC_LSE_OFF;
}
/* Get the LSI configuration -----------------------------------------------*/
if(READ_BIT(RCC->CSR, RCC_CSR_LSION) == RCC_CSR_LSION)
{
RCC_OscInitStruct->LSIState = RCC_LSI_ON;
}
else
{
RCC_OscInitStruct->LSIState = RCC_LSI_OFF;
}
#if defined(RCC_CSR_LSIPREDIV)
/* Get the LSI configuration -----------------------------------------------*/
if((RCC->CSR & RCC_CSR_LSIPREDIV) == RCC_CSR_LSIPREDIV)
{
RCC_OscInitStruct->LSIDiv = RCC_LSI_DIV128;
}
else
{
RCC_OscInitStruct->LSIDiv = RCC_LSI_DIV1;
}
#endif /* RCC_CSR_LSIPREDIV */
#if defined(RCC_HSI48_SUPPORT)
/* Get the HSI48 configuration ---------------------------------------------*/
if(READ_BIT(RCC->CRRCR, RCC_CRRCR_HSI48ON) == RCC_CRRCR_HSI48ON)
{
RCC_OscInitStruct->HSI48State = RCC_HSI48_ON;
}
else
{
RCC_OscInitStruct->HSI48State = RCC_HSI48_OFF;
}
#else
RCC_OscInitStruct->HSI48State = RCC_HSI48_OFF;
#endif /* RCC_HSI48_SUPPORT */
/* Get the PLL configuration -----------------------------------------------*/
if(READ_BIT(RCC->CR, RCC_CR_PLLON) == RCC_CR_PLLON)
{
RCC_OscInitStruct->PLL.PLLState = RCC_PLL_ON;
}
else
{
RCC_OscInitStruct->PLL.PLLState = RCC_PLL_OFF;
}
RCC_OscInitStruct->PLL.PLLSource = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC);
RCC_OscInitStruct->PLL.PLLM = (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U;
RCC_OscInitStruct->PLL.PLLN = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos;
RCC_OscInitStruct->PLL.PLLQ = (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLQ) >> RCC_PLLCFGR_PLLQ_Pos) + 1U) << 1U);
RCC_OscInitStruct->PLL.PLLR = (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1U) << 1U);
#if defined(RCC_PLLP_SUPPORT)
#if defined(RCC_PLLP_DIV_2_31_SUPPORT)
RCC_OscInitStruct->PLL.PLLP = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLPDIV) >> RCC_PLLCFGR_PLLPDIV_Pos;
#else
if(READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLP) != 0U)
{
RCC_OscInitStruct->PLL.PLLP = RCC_PLLP_DIV17;
}
else
{
RCC_OscInitStruct->PLL.PLLP = RCC_PLLP_DIV7;
}
#endif /* RCC_PLLP_DIV_2_31_SUPPORT */
#endif /* RCC_PLLP_SUPPORT */
}
/**
* @brief Configure the RCC_ClkInitStruct according to the internal
* RCC configuration registers.
* @param RCC_ClkInitStruct pointer to an RCC_ClkInitTypeDef structure that
* will be configured.
* @param pFLatency Pointer on the Flash Latency.
* @retval None
*/
void HAL_RCC_GetClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t *pFLatency)
{
/* Check the parameters */
assert_param(RCC_ClkInitStruct != (void *)NULL);
assert_param(pFLatency != (void *)NULL);
/* Set all possible values for the Clock type parameter --------------------*/
RCC_ClkInitStruct->ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
/* Get the SYSCLK configuration --------------------------------------------*/
RCC_ClkInitStruct->SYSCLKSource = READ_BIT(RCC->CFGR, RCC_CFGR_SW);
/* Get the HCLK configuration ----------------------------------------------*/
RCC_ClkInitStruct->AHBCLKDivider = READ_BIT(RCC->CFGR, RCC_CFGR_HPRE);
/* Get the APB1 configuration ----------------------------------------------*/
RCC_ClkInitStruct->APB1CLKDivider = READ_BIT(RCC->CFGR, RCC_CFGR_PPRE1);
/* Get the APB2 configuration ----------------------------------------------*/
RCC_ClkInitStruct->APB2CLKDivider = (READ_BIT(RCC->CFGR, RCC_CFGR_PPRE2) >> 3U);
/* Get the Flash Wait State (Latency) configuration ------------------------*/
*pFLatency = __HAL_FLASH_GET_LATENCY();
}
/**
* @brief Enable the Clock Security System.
* @note If a failure is detected on the HSE oscillator clock, this oscillator
* is automatically disabled and an interrupt is generated to inform the
* software about the failure (Clock Security System Interrupt, CSSI),
* allowing the MCU to perform rescue operations. The CSSI is linked to
* the Cortex-M4 NMI (Non-Maskable Interrupt) exception vector.
* @note The Clock Security System can only be cleared by reset.
* @retval None
*/
void HAL_RCC_EnableCSS(void)
{
SET_BIT(RCC->CR, RCC_CR_CSSON) ;
}
/**
* @brief Handle the RCC Clock Security System interrupt request.
* @note This API should be called under the NMI_Handler().
* @retval None
*/
void HAL_RCC_NMI_IRQHandler(void)
{
/* Check RCC CSSF interrupt flag */
if(__HAL_RCC_GET_IT(RCC_IT_CSS))
{
/* RCC Clock Security System interrupt user callback */
HAL_RCC_CSSCallback();
/* Clear RCC CSS pending bit */
__HAL_RCC_CLEAR_IT(RCC_IT_CSS);
}
}
/**
* @brief RCC Clock Security System interrupt callback.
* @retval none
*/
__weak void HAL_RCC_CSSCallback(void)
{
/* NOTE : This function should not be modified, when the callback is needed,
the HAL_RCC_CSSCallback should be implemented in the user file
*/
}
/**
* @brief Get and clear reset flags
* @param None
* @note Once reset flags are retrieved, this API is clearing them in order
* to isolate next reset reason.
* @retval can be a combination of @ref RCC_Reset_Flag
*/
uint32_t HAL_RCC_GetResetSource(void)
{
uint32_t reset;
/* Get all reset flags */
reset = RCC->CSR & RCC_RESET_FLAG_ALL;
/* Clear Reset flags */
RCC->CSR |= RCC_CSR_RMVF;
return reset;
}
/** * @}
*/
/**
* @}
*/
/* Private function prototypes -----------------------------------------------*/
/** @addtogroup RCC_Private_Functions
* @{
*/
/**
* @brief Update number of Flash wait states in line with MSI range and current
voltage range.
* @param msirange MSI range value from RCC_MSIRANGE_0 to RCC_MSIRANGE_11
* @retval HAL status
*/
static HAL_StatusTypeDef RCC_SetFlashLatencyFromMSIRange(uint32_t msirange)
{
uint32_t vos;
uint32_t latency = FLASH_LATENCY_0; /* default value 0WS */
if(__HAL_RCC_PWR_IS_CLK_ENABLED())
{
vos = HAL_PWREx_GetVoltageRange();
}
else
{
__HAL_RCC_PWR_CLK_ENABLE();
vos = HAL_PWREx_GetVoltageRange();
__HAL_RCC_PWR_CLK_DISABLE();
}
if(vos == PWR_REGULATOR_VOLTAGE_SCALE1)
{
if(msirange > RCC_MSIRANGE_8)
{
/* MSI > 16Mhz */
if(msirange > RCC_MSIRANGE_10)
{
/* MSI 48Mhz */
latency = FLASH_LATENCY_2; /* 2WS */
}
else
{
/* MSI 24Mhz or 32Mhz */
latency = FLASH_LATENCY_1; /* 1WS */
}
}
/* else MSI <= 16Mhz default FLASH_LATENCY_0 0WS */
}
else
{
#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \
defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
if(msirange >= RCC_MSIRANGE_8)
{
/* MSI >= 16Mhz */
latency = FLASH_LATENCY_2; /* 2WS */
}
else
{
if(msirange == RCC_MSIRANGE_7)
{
/* MSI 8Mhz */
latency = FLASH_LATENCY_1; /* 1WS */
}
/* else MSI < 8Mhz default FLASH_LATENCY_0 0WS */
}
#else
if(msirange > RCC_MSIRANGE_8)
{
/* MSI > 16Mhz */
latency = FLASH_LATENCY_3; /* 3WS */
}
else
{
if(msirange == RCC_MSIRANGE_8)
{
/* MSI 16Mhz */
latency = FLASH_LATENCY_2; /* 2WS */
}
else if(msirange == RCC_MSIRANGE_7)
{
/* MSI 8Mhz */
latency = FLASH_LATENCY_1; /* 1WS */
}
/* else MSI < 8Mhz default FLASH_LATENCY_0 0WS */
}
#endif
}
__HAL_FLASH_SET_LATENCY(latency);
/* Check that the new number of wait states is taken into account to access the Flash
memory by reading the FLASH_ACR register */
if(__HAL_FLASH_GET_LATENCY() != latency)
{
return HAL_ERROR;
}
return HAL_OK;
}
#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \
defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
/**
* @brief Compute SYSCLK frequency based on PLL SYSCLK source.
* @retval SYSCLK frequency
*/
static uint32_t RCC_GetSysClockFreqFromPLLSource(void)
{
uint32_t msirange = 0U;
uint32_t pllvco, pllsource, pllr, pllm, sysclockfreq; /* no init needed */
if(__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_MSI)
{
/* Get MSI range source */
if(READ_BIT(RCC->CR, RCC_CR_MSIRGSEL) == 0U)
{ /* MSISRANGE from RCC_CSR applies */
msirange = READ_BIT(RCC->CSR, RCC_CSR_MSISRANGE) >> RCC_CSR_MSISRANGE_Pos;
}
else
{ /* MSIRANGE from RCC_CR applies */
msirange = READ_BIT(RCC->CR, RCC_CR_MSIRANGE) >> RCC_CR_MSIRANGE_Pos;
}
/*MSI frequency range in HZ*/
msirange = MSIRangeTable[msirange];
}
/* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE) * PLLN / PLLM
SYSCLK = PLL_VCO / PLLR
*/
pllsource = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC);
switch (pllsource)
{
case RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */
pllvco = HSI_VALUE;
break;
case RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */
pllvco = HSE_VALUE;
break;
case RCC_PLLSOURCE_MSI: /* MSI used as PLL clock source */
default:
pllvco = msirange;
break;
}
pllm = (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U ;
pllvco = (pllvco * (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos)) / pllm;
pllr = ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1U ) * 2U;
sysclockfreq = pllvco / pllr;
return sysclockfreq;
}
#endif
/**
* @}
*/
#endif /* HAL_RCC_MODULE_ENABLED */
/**
* @}
*/
/**
* @}
*/

View File

@@ -1,3552 +0,0 @@
/**
******************************************************************************
* @file stm32l4xx_hal_rcc_ex.c
* @author MCD Application Team
* @brief Extended RCC HAL module driver.
* This file provides firmware functions to manage the following
* functionalities RCC extended peripheral:
* + Extended Peripheral Control functions
* + Extended Clock management functions
* + Extended Clock Recovery System Control functions
*
******************************************************************************
* @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.
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32l4xx_hal.h"
/** @addtogroup STM32L4xx_HAL_Driver
* @{
*/
/** @defgroup RCCEx RCCEx
* @brief RCC Extended HAL module driver
* @{
*/
#ifdef HAL_RCC_MODULE_ENABLED
/* Private typedef -----------------------------------------------------------*/
/* Private defines -----------------------------------------------------------*/
/** @defgroup RCCEx_Private_Constants RCCEx Private Constants
* @{
*/
#define PLLSAI1_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */
#define PLLSAI2_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */
#define PLL_TIMEOUT_VALUE 2U /* 2 ms (minimum Tick + 1) */
#define DIVIDER_P_UPDATE 0U
#define DIVIDER_Q_UPDATE 1U
#define DIVIDER_R_UPDATE 2U
#define __LSCO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define LSCO_GPIO_PORT GPIOA
#define LSCO_PIN GPIO_PIN_2
/**
* @}
*/
/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/** @defgroup RCCEx_Private_Functions RCCEx Private Functions
* @{
*/
#if defined(RCC_PLLSAI1_SUPPORT)
static HAL_StatusTypeDef RCCEx_PLLSAI1_Config(RCC_PLLSAI1InitTypeDef *PllSai1, uint32_t Divider);
#endif /* RCC_PLLSAI1_SUPPORT */
#if defined(RCC_PLLSAI2_SUPPORT)
static HAL_StatusTypeDef RCCEx_PLLSAI2_Config(RCC_PLLSAI2InitTypeDef *PllSai2, uint32_t Divider);
#endif /* RCC_PLLSAI2_SUPPORT */
#if defined(SAI1)
static uint32_t RCCEx_GetSAIxPeriphCLKFreq(uint32_t PeriphClk, uint32_t InputFrequency);
#endif /* SAI1 */
/**
* @}
*/
/* Exported functions --------------------------------------------------------*/
/** @defgroup RCCEx_Exported_Functions RCCEx Exported Functions
* @{
*/
/** @defgroup RCCEx_Exported_Functions_Group1 Extended Peripheral Control functions
* @brief Extended Peripheral Control functions
*
@verbatim
===============================================================================
##### Extended Peripheral Control functions #####
===============================================================================
[..]
This subsection provides a set of functions allowing to control the RCC Clocks
frequencies.
[..]
(@) Important note: Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to
select the RTC clock source; in this case the Backup domain will be reset in
order to modify the RTC Clock source, as consequence RTC registers (including
the backup registers) are set to their reset values.
@endverbatim
* @{
*/
/**
* @brief Initialize the RCC extended peripherals clocks according to the specified
* parameters in the RCC_PeriphCLKInitTypeDef.
* @param PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
* contains a field PeriphClockSelection which can be a combination of the following values:
* @arg @ref RCC_PERIPHCLK_RTC RTC peripheral clock
* @arg @ref RCC_PERIPHCLK_ADC ADC peripheral clock
@if STM32L462xx
* @arg @ref RCC_PERIPHCLK_DFSDM1 DFSDM1 peripheral clock (only for devices with DFSDM1)
@endif
@if STM32L486xx
* @arg @ref RCC_PERIPHCLK_DFSDM1 DFSDM1 peripheral clock (only for devices with DFSDM1)
@endif
@if STM32L4A6xx
* @arg @ref RCC_PERIPHCLK_DFSDM1 DFSDM1 peripheral clock (only for devices with DFSDM1)
@endif
* @arg @ref RCC_PERIPHCLK_I2C1 I2C1 peripheral clock
* @arg @ref RCC_PERIPHCLK_I2C2 I2C2 peripheral clock
* @arg @ref RCC_PERIPHCLK_I2C3 I2C3 peripheral clock
@if STM32L462xx
* @arg @ref RCC_PERIPHCLK_I2C4 I2C4 peripheral clock (only for devices with I2C4)
@endif
@if STM32L4A6xx
* @arg @ref RCC_PERIPHCLK_I2C4 I2C4 peripheral clock (only for devices with I2C4)
@endif
@if STM32L4S9xx
* @arg @ref RCC_PERIPHCLK_I2C4 I2C4 peripheral clock (only for devices with I2C4)
@endif
* @arg @ref RCC_PERIPHCLK_LPTIM1 LPTIM1 peripheral clock
* @arg @ref RCC_PERIPHCLK_LPTIM2 LPTIM2 peripheral clock
* @arg @ref RCC_PERIPHCLK_LPUART1 LPUART1 peripheral clock
* @arg @ref RCC_PERIPHCLK_RNG RNG peripheral clock
* @arg @ref RCC_PERIPHCLK_SAI1 SAI1 peripheral clock (only for devices with SAI1)
@if STM32L486xx
* @arg @ref RCC_PERIPHCLK_SAI2 SAI2 peripheral clock (only for devices with SAI2)
@endif
@if STM32L4A6xx
* @arg @ref RCC_PERIPHCLK_SAI2 SAI2 peripheral clock (only for devices with SAI2)
@endif
@if STM32L4S9xx
* @arg @ref RCC_PERIPHCLK_SAI2 SAI2 peripheral clock (only for devices with SAI2)
@endif
* @arg @ref RCC_PERIPHCLK_SDMMC1 SDMMC1 peripheral clock
@if STM32L443xx
* @arg @ref RCC_PERIPHCLK_SWPMI1 SWPMI1 peripheral clock (only for devices with SWPMI1)
@endif
@if STM32L486xx
* @arg @ref RCC_PERIPHCLK_SWPMI1 SWPMI1 peripheral clock (only for devices with SWPMI1)
@endif
@if STM32L4A6xx
* @arg @ref RCC_PERIPHCLK_SWPMI1 SWPMI1 peripheral clock (only for devices with SWPMI1)
@endif
* @arg @ref RCC_PERIPHCLK_USART1 USART1 peripheral clock
* @arg @ref RCC_PERIPHCLK_USART2 USART1 peripheral clock
* @arg @ref RCC_PERIPHCLK_USART3 USART1 peripheral clock
@if STM32L462xx
* @arg @ref RCC_PERIPHCLK_UART4 USART1 peripheral clock (only for devices with UART4)
@endif
@if STM32L486xx
* @arg @ref RCC_PERIPHCLK_UART4 USART1 peripheral clock (only for devices with UART4)
* @arg @ref RCC_PERIPHCLK_UART5 USART1 peripheral clock (only for devices with UART5)
* @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB)
@endif
@if STM32L4A6xx
* @arg @ref RCC_PERIPHCLK_UART4 USART1 peripheral clock (only for devices with UART4)
* @arg @ref RCC_PERIPHCLK_UART5 USART1 peripheral clock (only for devices with UART5)
* @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB)
@endif
@if STM32L4S9xx
* @arg @ref RCC_PERIPHCLK_UART4 USART1 peripheral clock (only for devices with UART4)
* @arg @ref RCC_PERIPHCLK_UART5 USART1 peripheral clock (only for devices with UART5)
* @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB)
* @arg @ref RCC_PERIPHCLK_DFSDM1 DFSDM1 peripheral kernel clock (only for devices with DFSDM1)
* @arg @ref RCC_PERIPHCLK_DFSDM1AUDIO DFSDM1 peripheral audio clock (only for devices with DFSDM1)
* @arg @ref RCC_PERIPHCLK_LTDC LTDC peripheral clock (only for devices with LTDC)
* @arg @ref RCC_PERIPHCLK_DSI DSI peripheral clock (only for devices with DSI)
* @arg @ref RCC_PERIPHCLK_OSPI OctoSPI peripheral clock (only for devices with OctoSPI)
@endif
*
* @note Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to select
* the RTC clock source: in this case the access to Backup domain is enabled.
*
* @retval HAL status
*/
HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit)
{
uint32_t tmpregister, tickstart; /* no init needed */
HAL_StatusTypeDef ret = HAL_OK; /* Intermediate status */
HAL_StatusTypeDef status = HAL_OK; /* Final status */
/* Check the parameters */
assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));
#if defined(SAI1)
/*-------------------------- SAI1 clock source configuration ---------------------*/
if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1))
{
/* Check the parameters */
assert_param(IS_RCC_SAI1CLK(PeriphClkInit->Sai1ClockSelection));
switch(PeriphClkInit->Sai1ClockSelection)
{
case RCC_SAI1CLKSOURCE_PLL: /* PLL is used as clock source for SAI1*/
/* Enable SAI Clock output generated from System PLL . */
#if defined(RCC_PLLSAI2_SUPPORT)
__HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SAI3CLK);
#else
__HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SAI2CLK);
#endif /* RCC_PLLSAI2_SUPPORT */
/* SAI1 clock source config set later after clock selection check */
break;
case RCC_SAI1CLKSOURCE_PLLSAI1: /* PLLSAI1 is used as clock source for SAI1*/
/* PLLSAI1 input clock, parameters M, N & P configuration and clock output (PLLSAI1ClockOut) */
ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_P_UPDATE);
/* SAI1 clock source config set later after clock selection check */
break;
#if defined(RCC_PLLSAI2_SUPPORT)
case RCC_SAI1CLKSOURCE_PLLSAI2: /* PLLSAI2 is used as clock source for SAI1*/
/* PLLSAI2 input clock, parameters M, N & P configuration clock output (PLLSAI2ClockOut) */
ret = RCCEx_PLLSAI2_Config(&(PeriphClkInit->PLLSAI2), DIVIDER_P_UPDATE);
/* SAI1 clock source config set later after clock selection check */
break;
#endif /* RCC_PLLSAI2_SUPPORT */
case RCC_SAI1CLKSOURCE_PIN: /* External clock is used as source of SAI1 clock*/
#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
case RCC_SAI1CLKSOURCE_HSI: /* HSI is used as source of SAI1 clock*/
#endif /* STM32L4P5xx || STM32L4Q5xx || STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */
/* SAI1 clock source config set later after clock selection check */
break;
default:
ret = HAL_ERROR;
break;
}
if(ret == HAL_OK)
{
/* Set the source of SAI1 clock*/
__HAL_RCC_SAI1_CONFIG(PeriphClkInit->Sai1ClockSelection);
}
else
{
/* set overall return value */
status = ret;
}
}
#endif /* SAI1 */
#if defined(SAI2)
/*-------------------------- SAI2 clock source configuration ---------------------*/
if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2))
{
/* Check the parameters */
assert_param(IS_RCC_SAI2CLK(PeriphClkInit->Sai2ClockSelection));
switch(PeriphClkInit->Sai2ClockSelection)
{
case RCC_SAI2CLKSOURCE_PLL: /* PLL is used as clock source for SAI2*/
/* Enable SAI Clock output generated from System PLL . */
__HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SAI3CLK);
/* SAI2 clock source config set later after clock selection check */
break;
case RCC_SAI2CLKSOURCE_PLLSAI1: /* PLLSAI1 is used as clock source for SAI2*/
/* PLLSAI1 input clock, parameters M, N & P configuration and clock output (PLLSAI1ClockOut) */
ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_P_UPDATE);
/* SAI2 clock source config set later after clock selection check */
break;
case RCC_SAI2CLKSOURCE_PLLSAI2: /* PLLSAI2 is used as clock source for SAI2*/
/* PLLSAI2 input clock, parameters M, N & P configuration and clock output (PLLSAI2ClockOut) */
ret = RCCEx_PLLSAI2_Config(&(PeriphClkInit->PLLSAI2), DIVIDER_P_UPDATE);
/* SAI2 clock source config set later after clock selection check */
break;
case RCC_SAI2CLKSOURCE_PIN: /* External clock is used as source of SAI2 clock*/
#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
case RCC_SAI2CLKSOURCE_HSI: /* HSI is used as source of SAI2 clock*/
#endif /* STM32L4P5xx || STM32L4Q5xx || STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */
/* SAI2 clock source config set later after clock selection check */
break;
default:
ret = HAL_ERROR;
break;
}
if(ret == HAL_OK)
{
/* Set the source of SAI2 clock*/
__HAL_RCC_SAI2_CONFIG(PeriphClkInit->Sai2ClockSelection);
}
else
{
/* set overall return value */
status = ret;
}
}
#endif /* SAI2 */
/*-------------------------- RTC clock source configuration ----------------------*/
if((PeriphClkInit->PeriphClockSelection & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC)
{
FlagStatus pwrclkchanged = RESET;
/* Check for RTC Parameters used to output RTCCLK */
assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));
/* Enable Power Clock */
if(__HAL_RCC_PWR_IS_CLK_DISABLED() != 0U)
{
__HAL_RCC_PWR_CLK_ENABLE();
pwrclkchanged = SET;
}
/* Enable write access to Backup domain */
SET_BIT(PWR->CR1, PWR_CR1_DBP);
/* Wait for Backup domain Write protection disable */
tickstart = HAL_GetTick();
while(READ_BIT(PWR->CR1, PWR_CR1_DBP) == 0U)
{
if((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
{
ret = HAL_TIMEOUT;
break;
}
}
if(ret == HAL_OK)
{
/* Reset the Backup domain only if the RTC Clock source selection is modified from default */
tmpregister = READ_BIT(RCC->BDCR, RCC_BDCR_RTCSEL);
if((tmpregister != RCC_RTCCLKSOURCE_NONE) && (tmpregister != PeriphClkInit->RTCClockSelection))
{
/* Store the content of BDCR register before the reset of Backup Domain */
tmpregister = READ_BIT(RCC->BDCR, ~(RCC_BDCR_RTCSEL));
/* RTC Clock selection can be changed only if the Backup Domain is reset */
__HAL_RCC_BACKUPRESET_FORCE();
__HAL_RCC_BACKUPRESET_RELEASE();
/* Restore the Content of BDCR register */
RCC->BDCR = tmpregister;
}
/* Wait for LSE reactivation if LSE was enable prior to Backup Domain reset */
if (HAL_IS_BIT_SET(tmpregister, RCC_BDCR_LSEON))
{
/* Get Start Tick*/
tickstart = HAL_GetTick();
/* Wait till LSE is ready */
while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == 0U)
{
if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
{
ret = HAL_TIMEOUT;
break;
}
}
}
if(ret == HAL_OK)
{
/* Apply new RTC clock source selection */
__HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
}
else
{
/* set overall return value */
status = ret;
}
}
else
{
/* set overall return value */
status = ret;
}
/* Restore clock configuration if changed */
if(pwrclkchanged == SET)
{
__HAL_RCC_PWR_CLK_DISABLE();
}
}
/*-------------------------- USART1 clock source configuration -------------------*/
if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1)
{
/* Check the parameters */
assert_param(IS_RCC_USART1CLKSOURCE(PeriphClkInit->Usart1ClockSelection));
/* Configure the USART1 clock source */
__HAL_RCC_USART1_CONFIG(PeriphClkInit->Usart1ClockSelection);
}
/*-------------------------- USART2 clock source configuration -------------------*/
if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2)
{
/* Check the parameters */
assert_param(IS_RCC_USART2CLKSOURCE(PeriphClkInit->Usart2ClockSelection));
/* Configure the USART2 clock source */
__HAL_RCC_USART2_CONFIG(PeriphClkInit->Usart2ClockSelection);
}
#if defined(USART3)
/*-------------------------- USART3 clock source configuration -------------------*/
if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USART3) == RCC_PERIPHCLK_USART3)
{
/* Check the parameters */
assert_param(IS_RCC_USART3CLKSOURCE(PeriphClkInit->Usart3ClockSelection));
/* Configure the USART3 clock source */
__HAL_RCC_USART3_CONFIG(PeriphClkInit->Usart3ClockSelection);
}
#endif /* USART3 */
#if defined(UART4)
/*-------------------------- UART4 clock source configuration --------------------*/
if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_UART4) == RCC_PERIPHCLK_UART4)
{
/* Check the parameters */
assert_param(IS_RCC_UART4CLKSOURCE(PeriphClkInit->Uart4ClockSelection));
/* Configure the UART4 clock source */
__HAL_RCC_UART4_CONFIG(PeriphClkInit->Uart4ClockSelection);
}
#endif /* UART4 */
#if defined(UART5)
/*-------------------------- UART5 clock source configuration --------------------*/
if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_UART5) == RCC_PERIPHCLK_UART5)
{
/* Check the parameters */
assert_param(IS_RCC_UART5CLKSOURCE(PeriphClkInit->Uart5ClockSelection));
/* Configure the UART5 clock source */
__HAL_RCC_UART5_CONFIG(PeriphClkInit->Uart5ClockSelection);
}
#endif /* UART5 */
/*-------------------------- LPUART1 clock source configuration ------------------*/
if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1)
{
/* Check the parameters */
assert_param(IS_RCC_LPUART1CLKSOURCE(PeriphClkInit->Lpuart1ClockSelection));
/* Configure the LPUART1 clock source */
__HAL_RCC_LPUART1_CONFIG(PeriphClkInit->Lpuart1ClockSelection);
}
/*-------------------------- LPTIM1 clock source configuration -------------------*/
if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPTIM1) == (RCC_PERIPHCLK_LPTIM1))
{
assert_param(IS_RCC_LPTIM1CLK(PeriphClkInit->Lptim1ClockSelection));
__HAL_RCC_LPTIM1_CONFIG(PeriphClkInit->Lptim1ClockSelection);
}
/*-------------------------- LPTIM2 clock source configuration -------------------*/
if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPTIM2) == (RCC_PERIPHCLK_LPTIM2))
{
assert_param(IS_RCC_LPTIM2CLK(PeriphClkInit->Lptim2ClockSelection));
__HAL_RCC_LPTIM2_CONFIG(PeriphClkInit->Lptim2ClockSelection);
}
/*-------------------------- I2C1 clock source configuration ---------------------*/
if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1)
{
/* Check the parameters */
assert_param(IS_RCC_I2C1CLKSOURCE(PeriphClkInit->I2c1ClockSelection));
/* Configure the I2C1 clock source */
__HAL_RCC_I2C1_CONFIG(PeriphClkInit->I2c1ClockSelection);
}
#if defined(I2C2)
/*-------------------------- I2C2 clock source configuration ---------------------*/
if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2C2) == RCC_PERIPHCLK_I2C2)
{
/* Check the parameters */
assert_param(IS_RCC_I2C2CLKSOURCE(PeriphClkInit->I2c2ClockSelection));
/* Configure the I2C2 clock source */
__HAL_RCC_I2C2_CONFIG(PeriphClkInit->I2c2ClockSelection);
}
#endif /* I2C2 */
/*-------------------------- I2C3 clock source configuration ---------------------*/
if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2C3) == RCC_PERIPHCLK_I2C3)
{
/* Check the parameters */
assert_param(IS_RCC_I2C3CLKSOURCE(PeriphClkInit->I2c3ClockSelection));
/* Configure the I2C3 clock source */
__HAL_RCC_I2C3_CONFIG(PeriphClkInit->I2c3ClockSelection);
}
#if defined(I2C4)
/*-------------------------- I2C4 clock source configuration ---------------------*/
if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2C4) == RCC_PERIPHCLK_I2C4)
{
/* Check the parameters */
assert_param(IS_RCC_I2C4CLKSOURCE(PeriphClkInit->I2c4ClockSelection));
/* Configure the I2C4 clock source */
__HAL_RCC_I2C4_CONFIG(PeriphClkInit->I2c4ClockSelection);
}
#endif /* I2C4 */
#if defined(USB_OTG_FS) || defined(USB)
/*-------------------------- USB clock source configuration ----------------------*/
if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USB) == (RCC_PERIPHCLK_USB))
{
assert_param(IS_RCC_USBCLKSOURCE(PeriphClkInit->UsbClockSelection));
__HAL_RCC_USB_CONFIG(PeriphClkInit->UsbClockSelection);
if(PeriphClkInit->UsbClockSelection == RCC_USBCLKSOURCE_PLL)
{
/* Enable PLL48M1CLK output clock */
__HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_48M1CLK);
}
else
{
#if defined(RCC_PLLSAI1_SUPPORT)
if(PeriphClkInit->UsbClockSelection == RCC_USBCLKSOURCE_PLLSAI1)
{
/* PLLSAI1 input clock, parameters M, N & Q configuration and clock output (PLLSAI1ClockOut) */
ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_Q_UPDATE);
if(ret != HAL_OK)
{
/* set overall return value */
status = ret;
}
}
#endif /* RCC_PLLSAI1_SUPPORT */
}
}
#endif /* USB_OTG_FS || USB */
#if defined(SDMMC1)
/*-------------------------- SDMMC1 clock source configuration -------------------*/
if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SDMMC1) == (RCC_PERIPHCLK_SDMMC1))
{
assert_param(IS_RCC_SDMMC1CLKSOURCE(PeriphClkInit->Sdmmc1ClockSelection));
__HAL_RCC_SDMMC1_CONFIG(PeriphClkInit->Sdmmc1ClockSelection);
if(PeriphClkInit->Sdmmc1ClockSelection == RCC_SDMMC1CLKSOURCE_PLL) /* PLL "Q" ? */
{
/* Enable PLL48M1CLK output clock */
__HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_48M1CLK);
}
#if defined(RCC_CCIPR2_SDMMCSEL)
else if(PeriphClkInit->Sdmmc1ClockSelection == RCC_SDMMC1CLKSOURCE_PLLP) /* PLL "P" ? */
{
/* Enable PLLSAI3CLK output */
__HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SAI3CLK);
}
#endif
else if(PeriphClkInit->Sdmmc1ClockSelection == RCC_SDMMC1CLKSOURCE_PLLSAI1)
{
/* PLLSAI1 input clock, parameters M, N & Q configuration and clock output (PLLSAI1ClockOut) */
ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_Q_UPDATE);
if(ret != HAL_OK)
{
/* set overall return value */
status = ret;
}
}
else
{
/* nothing to do */
}
}
#endif /* SDMMC1 */
/*-------------------------- RNG clock source configuration ----------------------*/
if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RNG) == (RCC_PERIPHCLK_RNG))
{
assert_param(IS_RCC_RNGCLKSOURCE(PeriphClkInit->RngClockSelection));
__HAL_RCC_RNG_CONFIG(PeriphClkInit->RngClockSelection);
if(PeriphClkInit->RngClockSelection == RCC_RNGCLKSOURCE_PLL)
{
/* Enable PLL48M1CLK output clock */
__HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_48M1CLK);
}
#if defined(RCC_PLLSAI1_SUPPORT)
else if(PeriphClkInit->RngClockSelection == RCC_RNGCLKSOURCE_PLLSAI1)
{
/* PLLSAI1 input clock, parameters M, N & Q configuration and clock output (PLLSAI1ClockOut) */
ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_Q_UPDATE);
if(ret != HAL_OK)
{
/* set overall return value */
status = ret;
}
}
#endif /* RCC_PLLSAI1_SUPPORT */
else
{
/* nothing to do */
}
}
/*-------------------------- ADC clock source configuration ----------------------*/
#if !defined(STM32L412xx) && !defined(STM32L422xx)
if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC)
{
/* Check the parameters */
assert_param(IS_RCC_ADCCLKSOURCE(PeriphClkInit->AdcClockSelection));
/* Configure the ADC interface clock source */
__HAL_RCC_ADC_CONFIG(PeriphClkInit->AdcClockSelection);
#if defined(RCC_PLLSAI1_SUPPORT)
if(PeriphClkInit->AdcClockSelection == RCC_ADCCLKSOURCE_PLLSAI1)
{
/* PLLSAI1 input clock, parameters M, N & R configuration and clock output (PLLSAI1ClockOut) */
ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_R_UPDATE);
if(ret != HAL_OK)
{
/* set overall return value */
status = ret;
}
}
#endif /* RCC_PLLSAI1_SUPPORT */
#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || defined(STM32L496xx) || defined(STM32L4A6xx)
else if(PeriphClkInit->AdcClockSelection == RCC_ADCCLKSOURCE_PLLSAI2)
{
/* PLLSAI2 input clock, parameters M, N & R configuration and clock output (PLLSAI2ClockOut) */
ret = RCCEx_PLLSAI2_Config(&(PeriphClkInit->PLLSAI2), DIVIDER_R_UPDATE);
if(ret != HAL_OK)
{
/* set overall return value */
status = ret;
}
}
#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || STM32L496xx || STM32L4A6xx */
}
#endif /* !STM32L412xx && !STM32L422xx */
#if defined(SWPMI1)
/*-------------------------- SWPMI1 clock source configuration -------------------*/
if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SWPMI1) == RCC_PERIPHCLK_SWPMI1)
{
/* Check the parameters */
assert_param(IS_RCC_SWPMI1CLKSOURCE(PeriphClkInit->Swpmi1ClockSelection));
/* Configure the SWPMI1 clock source */
__HAL_RCC_SWPMI1_CONFIG(PeriphClkInit->Swpmi1ClockSelection);
}
#endif /* SWPMI1 */
#if defined(DFSDM1_Filter0)
/*-------------------------- DFSDM1 clock source configuration -------------------*/
if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DFSDM1) == RCC_PERIPHCLK_DFSDM1)
{
/* Check the parameters */
assert_param(IS_RCC_DFSDM1CLKSOURCE(PeriphClkInit->Dfsdm1ClockSelection));
/* Configure the DFSDM1 interface clock source */
__HAL_RCC_DFSDM1_CONFIG(PeriphClkInit->Dfsdm1ClockSelection);
}
#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
/*-------------------------- DFSDM1 audio clock source configuration -------------*/
if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DFSDM1AUDIO) == RCC_PERIPHCLK_DFSDM1AUDIO)
{
/* Check the parameters */
assert_param(IS_RCC_DFSDM1AUDIOCLKSOURCE(PeriphClkInit->Dfsdm1AudioClockSelection));
/* Configure the DFSDM1 interface audio clock source */
__HAL_RCC_DFSDM1AUDIO_CONFIG(PeriphClkInit->Dfsdm1AudioClockSelection);
}
#endif /* STM32L4P5xx || STM32L4Q5xx || STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */
#endif /* DFSDM1_Filter0 */
#if defined(LTDC)
/*-------------------------- LTDC clock source configuration --------------------*/
if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LTDC) == RCC_PERIPHCLK_LTDC)
{
/* Check the parameters */
assert_param(IS_RCC_LTDCCLKSOURCE(PeriphClkInit->LtdcClockSelection));
/* Disable the PLLSAI2 */
__HAL_RCC_PLLSAI2_DISABLE();
/* Get Start Tick*/
tickstart = HAL_GetTick();
/* Wait till PLLSAI2 is ready */
while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) != 0U)
{
if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE)
{
ret = HAL_TIMEOUT;
break;
}
}
if(ret == HAL_OK)
{
/* Configure the LTDC clock source */
__HAL_RCC_LTDC_CONFIG(PeriphClkInit->LtdcClockSelection);
/* PLLSAI2 input clock, parameters M, N & R configuration and clock output (PLLSAI2ClockOut) */
ret = RCCEx_PLLSAI2_Config(&(PeriphClkInit->PLLSAI2), DIVIDER_R_UPDATE);
}
if(ret != HAL_OK)
{
/* set overall return value */
status = ret;
}
}
#endif /* LTDC */
#if defined(DSI)
/*-------------------------- DSI clock source configuration ---------------------*/
if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DSI) == RCC_PERIPHCLK_DSI)
{
/* Check the parameters */
assert_param(IS_RCC_DSICLKSOURCE(PeriphClkInit->DsiClockSelection));
/* Configure the DSI clock source */
__HAL_RCC_DSI_CONFIG(PeriphClkInit->DsiClockSelection);
if(PeriphClkInit->DsiClockSelection == RCC_DSICLKSOURCE_PLLSAI2)
{
/* PLLSAI2 input clock, parameters M, N & Q configuration and clock output (PLLSAI2ClockOut) */
ret = RCCEx_PLLSAI2_Config(&(PeriphClkInit->PLLSAI2), DIVIDER_Q_UPDATE);
if(ret != HAL_OK)
{
/* set overall return value */
status = ret;
}
}
}
#endif /* DSI */
#if defined(OCTOSPI1) || defined(OCTOSPI2)
/*-------------------------- OctoSPIx clock source configuration ----------------*/
if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_OSPI) == RCC_PERIPHCLK_OSPI)
{
/* Check the parameters */
assert_param(IS_RCC_OSPICLKSOURCE(PeriphClkInit->OspiClockSelection));
/* Configure the OctoSPI clock source */
__HAL_RCC_OSPI_CONFIG(PeriphClkInit->OspiClockSelection);
if(PeriphClkInit->OspiClockSelection == RCC_OSPICLKSOURCE_PLL)
{
/* Enable PLL48M1CLK output */
__HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_48M1CLK);
}
}
#endif /* OCTOSPI1 || OCTOSPI2 */
return status;
}
/**
* @brief Get the RCC_ClkInitStruct according to the internal RCC configuration registers.
* @param PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
* returns the configuration information for the Extended Peripherals
* clocks(SAI1, SAI2, LPTIM1, LPTIM2, I2C1, I2C2, I2C3, I2C4, LPUART1,
* USART1, USART2, USART3, UART4, UART5, RTC, ADCx, DFSDMx, SWPMI1, USB, SDMMC1 and RNG).
* @retval None
*/
void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit)
{
/* Set all possible values for the extended clock type parameter------------*/
#if defined(STM32L412xx) || defined(STM32L422xx)
PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | \
RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | \
RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_USB | \
RCC_PERIPHCLK_RNG | \
RCC_PERIPHCLK_RTC ;
#elif defined(STM32L431xx)
PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | \
RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | \
RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | \
RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_SWPMI1 | \
RCC_PERIPHCLK_RTC ;
#elif defined(STM32L432xx) || defined(STM32L442xx)
PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | \
RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C3 | \
RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_USB | \
RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_SWPMI1 | \
RCC_PERIPHCLK_RTC ;
#elif defined(STM32L433xx) || defined(STM32L443xx)
PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | \
RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | \
RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_USB | \
RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_SWPMI1 | \
RCC_PERIPHCLK_RTC ;
#elif defined(STM32L451xx)
PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | \
RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | RCC_PERIPHCLK_I2C4 | \
RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | \
RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_DFSDM1 | \
RCC_PERIPHCLK_RTC ;
#elif defined(STM32L452xx) || defined(STM32L462xx)
PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | \
RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | RCC_PERIPHCLK_I2C4 | \
RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_USB | \
RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_DFSDM1 | \
RCC_PERIPHCLK_RTC ;
#elif defined(STM32L471xx)
PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | RCC_PERIPHCLK_UART5 | \
RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | \
RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_SAI2 | \
RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_SWPMI1 | RCC_PERIPHCLK_DFSDM1 | \
RCC_PERIPHCLK_RTC ;
#elif defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx)
PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | RCC_PERIPHCLK_UART5 | \
RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | \
RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_SAI2 | RCC_PERIPHCLK_USB | \
RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_SWPMI1 | RCC_PERIPHCLK_DFSDM1 | \
RCC_PERIPHCLK_RTC ;
#elif defined(STM32L496xx) || defined(STM32L4A6xx)
PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | RCC_PERIPHCLK_UART5 | \
RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | RCC_PERIPHCLK_I2C4 | \
RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_SAI2 | RCC_PERIPHCLK_USB | \
RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_SWPMI1 | RCC_PERIPHCLK_DFSDM1 | \
RCC_PERIPHCLK_RTC ;
#elif defined(STM32L4R5xx) || defined(STM32L4S5xx)
PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | RCC_PERIPHCLK_UART5 | \
RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | RCC_PERIPHCLK_I2C4 | \
RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_SAI2 | RCC_PERIPHCLK_USB | \
RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_DFSDM1 | \
RCC_PERIPHCLK_DFSDM1AUDIO | RCC_PERIPHCLK_RTC | RCC_PERIPHCLK_OSPI;
#elif defined(STM32L4R7xx) || defined(STM32L4S7xx) || defined(STM32L4Q5xx)
PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | RCC_PERIPHCLK_UART5 | \
RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | RCC_PERIPHCLK_I2C4 | \
RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_SAI2 | RCC_PERIPHCLK_USB | \
RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_DFSDM1 | \
RCC_PERIPHCLK_DFSDM1AUDIO | RCC_PERIPHCLK_RTC | RCC_PERIPHCLK_OSPI | RCC_PERIPHCLK_LTDC;
#elif defined(STM32L4R9xx) || defined(STM32L4S9xx)
PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1 | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4 | RCC_PERIPHCLK_UART5 | \
RCC_PERIPHCLK_LPUART1 | RCC_PERIPHCLK_I2C1 | RCC_PERIPHCLK_I2C2 | RCC_PERIPHCLK_I2C3 | RCC_PERIPHCLK_I2C4 | \
RCC_PERIPHCLK_LPTIM1 | RCC_PERIPHCLK_LPTIM2 | RCC_PERIPHCLK_SAI1 | RCC_PERIPHCLK_SAI2 | RCC_PERIPHCLK_USB | \
RCC_PERIPHCLK_SDMMC1 | RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_DFSDM1 | \
RCC_PERIPHCLK_DFSDM1AUDIO | RCC_PERIPHCLK_RTC | RCC_PERIPHCLK_OSPI | RCC_PERIPHCLK_LTDC | RCC_PERIPHCLK_DSI;
#endif /* STM32L431xx */
#if defined(RCC_PLLSAI1_SUPPORT)
/* Get the PLLSAI1 Clock configuration -----------------------------------------------*/
PeriphClkInit->PLLSAI1.PLLSAI1Source = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC) >> RCC_PLLCFGR_PLLSRC_Pos;
#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT)
PeriphClkInit->PLLSAI1.PLLSAI1M = (READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M) >> RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + 1U;
#else
PeriphClkInit->PLLSAI1.PLLSAI1M = (READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U;
#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */
PeriphClkInit->PLLSAI1.PLLSAI1N = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos;
PeriphClkInit->PLLSAI1.PLLSAI1P = ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1P) >> RCC_PLLSAI1CFGR_PLLSAI1P_Pos) << 4U) + 7U;
PeriphClkInit->PLLSAI1.PLLSAI1Q = ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1Q) >> RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) + 1U) * 2U;
PeriphClkInit->PLLSAI1.PLLSAI1R = ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1R) >> RCC_PLLSAI1CFGR_PLLSAI1R_Pos) + 1U) * 2U;
#endif /* RCC_PLLSAI1_SUPPORT */
#if defined(RCC_PLLSAI2_SUPPORT)
/* Get the PLLSAI2 Clock configuration -----------------------------------------------*/
PeriphClkInit->PLLSAI2.PLLSAI2Source = PeriphClkInit->PLLSAI1.PLLSAI1Source;
#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT)
PeriphClkInit->PLLSAI2.PLLSAI2M = (READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2M) >> RCC_PLLSAI2CFGR_PLLSAI2M_Pos) + 1U;
#else
PeriphClkInit->PLLSAI2.PLLSAI2M = PeriphClkInit->PLLSAI1.PLLSAI1M;
#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT */
PeriphClkInit->PLLSAI2.PLLSAI2N = READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N) >> RCC_PLLSAI2CFGR_PLLSAI2N_Pos;
PeriphClkInit->PLLSAI2.PLLSAI2P = ((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2P) >> RCC_PLLSAI2CFGR_PLLSAI2P_Pos) << 4U) + 7U;
#if defined(RCC_PLLSAI2Q_DIV_SUPPORT)
PeriphClkInit->PLLSAI2.PLLSAI2Q = ((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2Q) >> RCC_PLLSAI2CFGR_PLLSAI2Q_Pos) + 1U) * 2U;
#endif /* RCC_PLLSAI2Q_DIV_SUPPORT */
PeriphClkInit->PLLSAI2.PLLSAI2R = ((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2R)>> RCC_PLLSAI2CFGR_PLLSAI2R_Pos) + 1U) * 2U;
#endif /* RCC_PLLSAI2_SUPPORT */
/* Get the USART1 clock source ---------------------------------------------*/
PeriphClkInit->Usart1ClockSelection = __HAL_RCC_GET_USART1_SOURCE();
/* Get the USART2 clock source ---------------------------------------------*/
PeriphClkInit->Usart2ClockSelection = __HAL_RCC_GET_USART2_SOURCE();
#if defined(USART3)
/* Get the USART3 clock source ---------------------------------------------*/
PeriphClkInit->Usart3ClockSelection = __HAL_RCC_GET_USART3_SOURCE();
#endif /* USART3 */
#if defined(UART4)
/* Get the UART4 clock source ----------------------------------------------*/
PeriphClkInit->Uart4ClockSelection = __HAL_RCC_GET_UART4_SOURCE();
#endif /* UART4 */
#if defined(UART5)
/* Get the UART5 clock source ----------------------------------------------*/
PeriphClkInit->Uart5ClockSelection = __HAL_RCC_GET_UART5_SOURCE();
#endif /* UART5 */
/* Get the LPUART1 clock source --------------------------------------------*/
PeriphClkInit->Lpuart1ClockSelection = __HAL_RCC_GET_LPUART1_SOURCE();
/* Get the I2C1 clock source -----------------------------------------------*/
PeriphClkInit->I2c1ClockSelection = __HAL_RCC_GET_I2C1_SOURCE();
#if defined(I2C2)
/* Get the I2C2 clock source ----------------------------------------------*/
PeriphClkInit->I2c2ClockSelection = __HAL_RCC_GET_I2C2_SOURCE();
#endif /* I2C2 */
/* Get the I2C3 clock source -----------------------------------------------*/
PeriphClkInit->I2c3ClockSelection = __HAL_RCC_GET_I2C3_SOURCE();
#if defined(I2C4)
/* Get the I2C4 clock source -----------------------------------------------*/
PeriphClkInit->I2c4ClockSelection = __HAL_RCC_GET_I2C4_SOURCE();
#endif /* I2C4 */
/* Get the LPTIM1 clock source ---------------------------------------------*/
PeriphClkInit->Lptim1ClockSelection = __HAL_RCC_GET_LPTIM1_SOURCE();
/* Get the LPTIM2 clock source ---------------------------------------------*/
PeriphClkInit->Lptim2ClockSelection = __HAL_RCC_GET_LPTIM2_SOURCE();
#if defined(SAI1)
/* Get the SAI1 clock source -----------------------------------------------*/
PeriphClkInit->Sai1ClockSelection = __HAL_RCC_GET_SAI1_SOURCE();
#endif /* SAI1 */
#if defined(SAI2)
/* Get the SAI2 clock source -----------------------------------------------*/
PeriphClkInit->Sai2ClockSelection = __HAL_RCC_GET_SAI2_SOURCE();
#endif /* SAI2 */
/* Get the RTC clock source ------------------------------------------------*/
PeriphClkInit->RTCClockSelection = __HAL_RCC_GET_RTC_SOURCE();
#if defined(USB_OTG_FS) || defined(USB)
/* Get the USB clock source ------------------------------------------------*/
PeriphClkInit->UsbClockSelection = __HAL_RCC_GET_USB_SOURCE();
#endif /* USB_OTG_FS || USB */
#if defined(SDMMC1)
/* Get the SDMMC1 clock source ---------------------------------------------*/
PeriphClkInit->Sdmmc1ClockSelection = __HAL_RCC_GET_SDMMC1_SOURCE();
#endif /* SDMMC1 */
/* Get the RNG clock source ------------------------------------------------*/
PeriphClkInit->RngClockSelection = __HAL_RCC_GET_RNG_SOURCE();
#if !defined(STM32L412xx) && !defined(STM32L422xx)
/* Get the ADC clock source ------------------------------------------------*/
PeriphClkInit->AdcClockSelection = __HAL_RCC_GET_ADC_SOURCE();
#endif /* !STM32L412xx && !STM32L422xx */
#if defined(SWPMI1)
/* Get the SWPMI1 clock source ---------------------------------------------*/
PeriphClkInit->Swpmi1ClockSelection = __HAL_RCC_GET_SWPMI1_SOURCE();
#endif /* SWPMI1 */
#if defined(DFSDM1_Filter0)
/* Get the DFSDM1 clock source ---------------------------------------------*/
PeriphClkInit->Dfsdm1ClockSelection = __HAL_RCC_GET_DFSDM1_SOURCE();
#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
/* Get the DFSDM1 audio clock source ---------------------------------------*/
PeriphClkInit->Dfsdm1AudioClockSelection = __HAL_RCC_GET_DFSDM1AUDIO_SOURCE();
#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */
#endif /* DFSDM1_Filter0 */
#if defined(LTDC)
/* Get the LTDC clock source -----------------------------------------------*/
PeriphClkInit->LtdcClockSelection = __HAL_RCC_GET_LTDC_SOURCE();
#endif /* LTDC */
#if defined(DSI)
/* Get the DSI clock source ------------------------------------------------*/
PeriphClkInit->DsiClockSelection = __HAL_RCC_GET_DSI_SOURCE();
#endif /* DSI */
#if defined(OCTOSPI1) || defined(OCTOSPI2)
/* Get the OctoSPIclock source --------------------------------------------*/
PeriphClkInit->OspiClockSelection = __HAL_RCC_GET_OSPI_SOURCE();
#endif /* OCTOSPI1 || OCTOSPI2 */
}
/**
* @brief Return the peripheral clock frequency for peripherals with clock source from PLLSAIs
* @note Return 0 if peripheral clock identifier not managed by this API
* @param PeriphClk Peripheral clock identifier
* This parameter can be one of the following values:
* @arg @ref RCC_PERIPHCLK_RTC RTC peripheral clock
* @arg @ref RCC_PERIPHCLK_ADC ADC peripheral clock
@if STM32L462xx
* @arg @ref RCC_PERIPHCLK_DFSDM1 DFSDM1 peripheral clock (only for devices with DFSDM)
@endif
@if STM32L486xx
* @arg @ref RCC_PERIPHCLK_DFSDM1 DFSDM1 peripheral clock (only for devices with DFSDM)
@endif
@if STM32L4A6xx
* @arg @ref RCC_PERIPHCLK_DFSDM1 DFSDM1 peripheral clock (only for devices with DFSDM)
@endif
* @arg @ref RCC_PERIPHCLK_I2C1 I2C1 peripheral clock
* @arg @ref RCC_PERIPHCLK_I2C2 I2C2 peripheral clock
* @arg @ref RCC_PERIPHCLK_I2C3 I2C3 peripheral clock
@if STM32L462xx
* @arg @ref RCC_PERIPHCLK_I2C4 I2C4 peripheral clock (only for devices with I2C4)
@endif
@if STM32L4A6xx
* @arg @ref RCC_PERIPHCLK_I2C4 I2C4 peripheral clock (only for devices with I2C4)
@endif
@if STM32L4S9xx
* @arg @ref RCC_PERIPHCLK_I2C4 I2C4 peripheral clock (only for devices with I2C4)
@endif
* @arg @ref RCC_PERIPHCLK_LPTIM1 LPTIM1 peripheral clock
* @arg @ref RCC_PERIPHCLK_LPTIM2 LPTIM2 peripheral clock
* @arg @ref RCC_PERIPHCLK_LPUART1 LPUART1 peripheral clock
* @arg @ref RCC_PERIPHCLK_RNG RNG peripheral clock
* @arg @ref RCC_PERIPHCLK_SAI1 SAI1 peripheral clock (only for devices with SAI1)
@if STM32L486xx
* @arg @ref RCC_PERIPHCLK_SAI2 SAI2 peripheral clock (only for devices with SAI2)
@endif
@if STM32L4A6xx
* @arg @ref RCC_PERIPHCLK_SAI2 SAI2 peripheral clock (only for devices with SAI2)
@endif
@if STM32L4S9xx
* @arg @ref RCC_PERIPHCLK_SAI2 SAI2 peripheral clock (only for devices with SAI2)
@endif
* @arg @ref RCC_PERIPHCLK_SDMMC1 SDMMC1 peripheral clock
@if STM32L443xx
* @arg @ref RCC_PERIPHCLK_SWPMI1 SWPMI1 peripheral clock (only for devices with SWPMI1)
@endif
@if STM32L486xx
* @arg @ref RCC_PERIPHCLK_SWPMI1 SWPMI1 peripheral clock (only for devices with SWPMI1)
@endif
@if STM32L4A6xx
* @arg @ref RCC_PERIPHCLK_SWPMI1 SWPMI1 peripheral clock (only for devices with SWPMI1)
@endif
* @arg @ref RCC_PERIPHCLK_USART1 USART1 peripheral clock
* @arg @ref RCC_PERIPHCLK_USART2 USART1 peripheral clock
* @arg @ref RCC_PERIPHCLK_USART3 USART1 peripheral clock
@if STM32L462xx
* @arg @ref RCC_PERIPHCLK_UART4 UART4 peripheral clock (only for devices with UART4)
* @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB)
@endif
@if STM32L486xx
* @arg @ref RCC_PERIPHCLK_UART4 UART4 peripheral clock (only for devices with UART4)
* @arg @ref RCC_PERIPHCLK_UART5 UART5 peripheral clock (only for devices with UART5)
* @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB)
@endif
@if STM32L4A6xx
* @arg @ref RCC_PERIPHCLK_UART4 UART4 peripheral clock (only for devices with UART4)
* @arg @ref RCC_PERIPHCLK_UART5 UART5 peripheral clock (only for devices with UART5)
* @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB)
@endif
@if STM32L4S9xx
* @arg @ref RCC_PERIPHCLK_UART4 USART1 peripheral clock (only for devices with UART4)
* @arg @ref RCC_PERIPHCLK_UART5 USART1 peripheral clock (only for devices with UART5)
* @arg @ref RCC_PERIPHCLK_USB USB peripheral clock (only for devices with USB)
* @arg @ref RCC_PERIPHCLK_DFSDM1 DFSDM1 peripheral kernel clock (only for devices with DFSDM1)
* @arg @ref RCC_PERIPHCLK_DFSDM1AUDIO DFSDM1 peripheral audio clock (only for devices with DFSDM1)
* @arg @ref RCC_PERIPHCLK_LTDC LTDC peripheral clock (only for devices with LTDC)
* @arg @ref RCC_PERIPHCLK_DSI DSI peripheral clock (only for devices with DSI)
* @arg @ref RCC_PERIPHCLK_OSPI OctoSPI peripheral clock (only for devices with OctoSPI)
@endif
* @retval Frequency in Hz
*/
uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)
{
uint32_t frequency = 0U;
uint32_t srcclk, pll_oscsource, pllvco, plln; /* no init needed */
#if defined(SDMMC1) && defined(RCC_CCIPR2_SDMMCSEL)
uint32_t pllp; /* no init needed */
#endif
/* Check the parameters */
assert_param(IS_RCC_PERIPHCLOCK(PeriphClk));
if(PeriphClk == RCC_PERIPHCLK_RTC)
{
/* Get the current RTC source */
srcclk = __HAL_RCC_GET_RTC_SOURCE();
switch(srcclk)
{
case RCC_RTCCLKSOURCE_LSE:
/* Check if LSE is ready */
if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))
{
frequency = LSE_VALUE;
}
break;
case RCC_RTCCLKSOURCE_LSI:
/* Check if LSI is ready */
if(HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY))
{
#if defined(RCC_CSR_LSIPREDIV)
if(HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIPREDIV))
{
frequency = LSI_VALUE/128U;
}
else
#endif /* RCC_CSR_LSIPREDIV */
{
frequency = LSI_VALUE;
}
}
break;
case RCC_RTCCLKSOURCE_HSE_DIV32:
/* Check if HSE is ready */
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY))
{
frequency = HSE_VALUE / 32U;
}
break;
default:
/* No clock source, frequency default init at 0 */
break;
}
}
else
{
/* Other external peripheral clock source than RTC */
pll_oscsource = __HAL_RCC_GET_PLL_OSCSOURCE();
/* Compute PLL clock input */
switch(pll_oscsource)
{
case RCC_PLLSOURCE_MSI: /* MSI ? */
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_MSIRDY))
{
/*MSI frequency range in HZ*/
pllvco = MSIRangeTable[(__HAL_RCC_GET_MSI_RANGE() >> 4U)];
}
else
{
pllvco = 0U;
}
break;
case RCC_PLLSOURCE_HSI: /* HSI ? */
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))
{
pllvco = HSI_VALUE;
}
else
{
pllvco = 0U;
}
break;
case RCC_PLLSOURCE_HSE: /* HSE ? */
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY))
{
pllvco = HSE_VALUE;
}
else
{
pllvco = 0U;
}
break;
default:
/* No source */
pllvco = 0U;
break;
}
switch(PeriphClk)
{
#if defined(SAI1)
case RCC_PERIPHCLK_SAI1:
frequency = RCCEx_GetSAIxPeriphCLKFreq(RCC_PERIPHCLK_SAI1, pllvco);
break;
#endif
#if defined(SAI2)
case RCC_PERIPHCLK_SAI2:
frequency = RCCEx_GetSAIxPeriphCLKFreq(RCC_PERIPHCLK_SAI2, pllvco);
break;
#endif
#if defined(USB_OTG_FS) || defined(USB)
case RCC_PERIPHCLK_USB:
#endif /* USB_OTG_FS || USB */
case RCC_PERIPHCLK_RNG:
#if defined(SDMMC1) && !defined(RCC_CCIPR2_SDMMCSEL)
case RCC_PERIPHCLK_SDMMC1:
#endif /* SDMMC1 && !RCC_CCIPR2_SDMMCSEL */
{
srcclk = READ_BIT(RCC->CCIPR, RCC_CCIPR_CLK48SEL);
switch(srcclk)
{
case RCC_CCIPR_CLK48SEL: /* MSI ? */
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_MSIRDY))
{
/*MSI frequency range in HZ*/
frequency = MSIRangeTable[(__HAL_RCC_GET_MSI_RANGE() >> 4U)];
}
break;
case RCC_CCIPR_CLK48SEL_1: /* PLL ? */
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLRDY))
{
if(HAL_IS_BIT_SET(RCC->PLLCFGR, RCC_PLLCFGR_PLLQEN))
{
/* f(PLL Source) * PLLN / PLLM */
plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos;
pllvco = ((pllvco * plln) / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U));
/* f(PLL48M1CLK) = f(VCO input) / PLLQ */
frequency = (pllvco / (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLQ) >> RCC_PLLCFGR_PLLQ_Pos) + 1U) << 1U));
}
}
break;
#if defined(RCC_PLLSAI1_SUPPORT)
case RCC_CCIPR_CLK48SEL_0: /* PLLSAI1 ? */
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLSAI1RDY))
{
if(HAL_IS_BIT_SET(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1QEN))
{
plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos;
#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT)
/* PLLSAI1M exists: apply PLLSAI1M divider for PLLSAI1 output computation */
/* f(PLLSAI1 Source) * PLLSAI1N / PLLSAI1M */
pllvco = ((pllvco * plln) / ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M) >> RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + 1U));
#else
/* f(PLL Source) * PLLSAI1N / PLLM */
pllvco = ((pllvco * plln) / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U));
#endif
/* f(PLL48M2CLK) = f(VCOSAI1 input) / PLLSAI1Q */
frequency = (pllvco / (((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1Q) >> RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) + 1U) << 1U));
}
}
break;
#endif /* RCC_PLLSAI1_SUPPORT */
#if defined(RCC_HSI48_SUPPORT)
case 0U:
if(HAL_IS_BIT_SET(RCC->CRRCR, RCC_CRRCR_HSI48RDY)) /* HSI48 ? */
{
frequency = HSI48_VALUE;
}
break;
#endif /* RCC_HSI48_SUPPORT */
default:
/* No clock source, frequency default init at 0 */
break;
} /* switch(srcclk) */
break;
}
#if defined(SDMMC1) && defined(RCC_CCIPR2_SDMMCSEL)
case RCC_PERIPHCLK_SDMMC1:
if(HAL_IS_BIT_SET(RCC->CCIPR2, RCC_CCIPR2_SDMMCSEL)) /* PLL "P" ? */
{
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLRDY))
{
if(HAL_IS_BIT_SET(RCC->PLLCFGR, RCC_PLLCFGR_PLLPEN))
{
/* f(PLL Source) * PLLN / PLLM */
plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos;
pllvco = ((pllvco * plln) / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U));
/* f(PLLSAI3CLK) = f(VCO input) / PLLP */
pllp = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLPDIV) >> RCC_PLLCFGR_PLLPDIV_Pos;
if(pllp == 0U)
{
if(READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLP) != 0U)
{
pllp = 17U;
}
else
{
pllp = 7U;
}
}
frequency = (pllvco / pllp);
}
}
}
else /* 48MHz from PLL "Q" or MSI or PLLSAI1Q or HSI48 */
{
srcclk = READ_BIT(RCC->CCIPR, RCC_CCIPR_CLK48SEL);
switch(srcclk)
{
case RCC_CCIPR_CLK48SEL: /* MSI ? */
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_MSIRDY))
{
/*MSI frequency range in HZ*/
frequency = MSIRangeTable[(__HAL_RCC_GET_MSI_RANGE() >> 4U)];
}
break;
case RCC_CCIPR_CLK48SEL_1: /* PLL "Q" ? */
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLRDY))
{
if(HAL_IS_BIT_SET(RCC->PLLCFGR, RCC_PLLCFGR_PLLQEN))
{
/* f(PLL Source) * PLLN / PLLM */
plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos;
pllvco = ((pllvco * plln) / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U));
/* f(PLL48M1CLK) = f(VCO input) / PLLQ */
frequency = (pllvco / (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLQ) >> RCC_PLLCFGR_PLLQ_Pos) + 1U) << 1U));
}
}
break;
case RCC_CCIPR_CLK48SEL_0: /* PLLSAI1 ? */
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLSAI1RDY))
{
if(HAL_IS_BIT_SET(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1QEN))
{
/* f(PLLSAI1 Source) * PLLSAI1N / PLLSAI1M */
plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos;
pllvco = ((pllvco * plln) / ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M) >> RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + 1U));
/* f(PLL48M2CLK) = f(VCOSAI1 input) / PLLSAI1Q */
frequency = (pllvco / (((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1Q) >> RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) + 1U) << 1U));
}
}
break;
case 0U:
if(HAL_IS_BIT_SET(RCC->CRRCR, RCC_CRRCR_HSI48RDY)) /* HSI48 ? */
{
frequency = HSI48_VALUE;
}
break;
default:
/* No clock source, frequency default init at 0 */
break;
} /* switch(srcclk) */
}
break;
#endif /* SDMMC1 && RCC_CCIPR2_SDMMCSEL */
case RCC_PERIPHCLK_USART1:
{
/* Get the current USART1 source */
srcclk = __HAL_RCC_GET_USART1_SOURCE();
switch(srcclk)
{
case RCC_USART1CLKSOURCE_PCLK2:
frequency = HAL_RCC_GetPCLK2Freq();
break;
case RCC_USART1CLKSOURCE_SYSCLK:
frequency = HAL_RCC_GetSysClockFreq();
break;
case RCC_USART1CLKSOURCE_HSI:
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))
{
frequency = HSI_VALUE;
}
break;
case RCC_USART1CLKSOURCE_LSE:
if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))
{
frequency = LSE_VALUE;
}
break;
default:
/* No clock source, frequency default init at 0 */
break;
}
break;
}
case RCC_PERIPHCLK_USART2:
{
/* Get the current USART2 source */
srcclk = __HAL_RCC_GET_USART2_SOURCE();
switch(srcclk)
{
case RCC_USART2CLKSOURCE_PCLK1:
frequency = HAL_RCC_GetPCLK1Freq();
break;
case RCC_USART2CLKSOURCE_SYSCLK:
frequency = HAL_RCC_GetSysClockFreq();
break;
case RCC_USART2CLKSOURCE_HSI:
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))
{
frequency = HSI_VALUE;
}
break;
case RCC_USART2CLKSOURCE_LSE:
if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))
{
frequency = LSE_VALUE;
}
break;
default:
/* No clock source, frequency default init at 0 */
break;
}
break;
}
#if defined(USART3)
case RCC_PERIPHCLK_USART3:
{
/* Get the current USART3 source */
srcclk = __HAL_RCC_GET_USART3_SOURCE();
switch(srcclk)
{
case RCC_USART3CLKSOURCE_PCLK1:
frequency = HAL_RCC_GetPCLK1Freq();
break;
case RCC_USART3CLKSOURCE_SYSCLK:
frequency = HAL_RCC_GetSysClockFreq();
break;
case RCC_USART3CLKSOURCE_HSI:
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))
{
frequency = HSI_VALUE;
}
break;
case RCC_USART3CLKSOURCE_LSE:
if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))
{
frequency = LSE_VALUE;
}
break;
default:
/* No clock source, frequency default init at 0 */
break;
}
break;
}
#endif /* USART3 */
#if defined(UART4)
case RCC_PERIPHCLK_UART4:
{
/* Get the current UART4 source */
srcclk = __HAL_RCC_GET_UART4_SOURCE();
switch(srcclk)
{
case RCC_UART4CLKSOURCE_PCLK1:
frequency = HAL_RCC_GetPCLK1Freq();
break;
case RCC_UART4CLKSOURCE_SYSCLK:
frequency = HAL_RCC_GetSysClockFreq();
break;
case RCC_UART4CLKSOURCE_HSI:
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))
{
frequency = HSI_VALUE;
}
break;
case RCC_UART4CLKSOURCE_LSE:
if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))
{
frequency = LSE_VALUE;
}
break;
default:
/* No clock source, frequency default init at 0 */
break;
}
break;
}
#endif /* UART4 */
#if defined(UART5)
case RCC_PERIPHCLK_UART5:
{
/* Get the current UART5 source */
srcclk = __HAL_RCC_GET_UART5_SOURCE();
switch(srcclk)
{
case RCC_UART5CLKSOURCE_PCLK1:
frequency = HAL_RCC_GetPCLK1Freq();
break;
case RCC_UART5CLKSOURCE_SYSCLK:
frequency = HAL_RCC_GetSysClockFreq();
break;
case RCC_UART5CLKSOURCE_HSI:
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))
{
frequency = HSI_VALUE;
}
break;
case RCC_UART5CLKSOURCE_LSE:
if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))
{
frequency = LSE_VALUE;
}
break;
default:
/* No clock source, frequency default init at 0 */
break;
}
break;
}
#endif /* UART5 */
case RCC_PERIPHCLK_LPUART1:
{
/* Get the current LPUART1 source */
srcclk = __HAL_RCC_GET_LPUART1_SOURCE();
switch(srcclk)
{
case RCC_LPUART1CLKSOURCE_PCLK1:
frequency = HAL_RCC_GetPCLK1Freq();
break;
case RCC_LPUART1CLKSOURCE_SYSCLK:
frequency = HAL_RCC_GetSysClockFreq();
break;
case RCC_LPUART1CLKSOURCE_HSI:
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))
{
frequency = HSI_VALUE;
}
break;
case RCC_LPUART1CLKSOURCE_LSE:
if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))
{
frequency = LSE_VALUE;
}
break;
default:
/* No clock source, frequency default init at 0 */
break;
}
break;
}
case RCC_PERIPHCLK_ADC:
{
srcclk = __HAL_RCC_GET_ADC_SOURCE();
switch(srcclk)
{
case RCC_ADCCLKSOURCE_SYSCLK:
frequency = HAL_RCC_GetSysClockFreq();
break;
#if defined(RCC_PLLSAI1_SUPPORT)
case RCC_ADCCLKSOURCE_PLLSAI1:
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLSAI1RDY) && (__HAL_RCC_GET_PLLSAI1CLKOUT_CONFIG(RCC_PLLSAI1_ADC1CLK) != 0U))
{
plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos;
#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT)
/* PLLSAI1M exists: apply PLLSAI1M divider for PLLSAI1 output computation */
/* f(PLLSAI1 Source) * PLLSAI1N / PLLSAI1M */
pllvco = ((pllvco * plln) / ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M) >> RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + 1U));
#else
/* f(PLL Source) * PLLSAI1N / PLLM */
pllvco = ((pllvco * plln) / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U));
#endif
/* f(PLLADC1CLK) = f(VCOSAI1 input) / PLLSAI1R */
frequency = (pllvco / (((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1R) >> RCC_PLLSAI1CFGR_PLLSAI1R_Pos) + 1U) << 1U));
}
break;
#endif /* RCC_PLLSAI1_SUPPORT */
#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || defined(STM32L496xx) || defined(STM32L4A6xx)
case RCC_ADCCLKSOURCE_PLLSAI2:
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLSAI2RDY) && (__HAL_RCC_GET_PLLSAI2CLKOUT_CONFIG(RCC_PLLSAI2_ADC2CLK) != 0U))
{
plln = READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N) >> RCC_PLLSAI2CFGR_PLLSAI2N_Pos;
#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT)
/* PLLSAI2M exists: apply PLLSAI2M divider for PLLSAI2 output computation */
/* f(PLLSAI2 Source) * PLLSAI2N / PLLSAI2M */
pllvco = ((pllvco * plln) / ((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2M) >> RCC_PLLSAI2CFGR_PLLSAI2M_Pos) + 1U));
#else
/* f(PLL Source) * PLLSAI2N / PLLM */
pllvco = ((pllvco * plln) / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U));
#endif
/* f(PLLADC2CLK) = f(VCOSAI2 input) / PLLSAI2R */
frequency = (pllvco / (((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2R) >> RCC_PLLSAI2CFGR_PLLSAI2R_Pos) + 1U) << 1U));
}
break;
#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx || STM32L496xx || STM32L4A6xx */
default:
/* No clock source, frequency default init at 0 */
break;
}
break;
}
#if defined(DFSDM1_Filter0)
case RCC_PERIPHCLK_DFSDM1:
{
/* Get the current DFSDM1 source */
srcclk = __HAL_RCC_GET_DFSDM1_SOURCE();
if(srcclk == RCC_DFSDM1CLKSOURCE_PCLK2)
{
frequency = HAL_RCC_GetPCLK2Freq();
}
else
{
frequency = HAL_RCC_GetSysClockFreq();
}
break;
}
#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
case RCC_PERIPHCLK_DFSDM1AUDIO:
{
/* Get the current DFSDM1 audio source */
srcclk = __HAL_RCC_GET_DFSDM1AUDIO_SOURCE();
switch(srcclk)
{
case RCC_DFSDM1AUDIOCLKSOURCE_SAI1:
frequency = RCCEx_GetSAIxPeriphCLKFreq(RCC_PERIPHCLK_SAI1, pllvco);
break;
case RCC_DFSDM1AUDIOCLKSOURCE_MSI:
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_MSIRDY))
{
/*MSI frequency range in HZ*/
frequency = MSIRangeTable[(__HAL_RCC_GET_MSI_RANGE() >> 4U)];
}
break;
case RCC_DFSDM1AUDIOCLKSOURCE_HSI:
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))
{
frequency = HSI_VALUE;
}
break;
default:
/* No clock source, frequency default init at 0 */
break;
}
break;
}
#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */
#endif /* DFSDM1_Filter0 */
case RCC_PERIPHCLK_I2C1:
{
/* Get the current I2C1 source */
srcclk = __HAL_RCC_GET_I2C1_SOURCE();
switch(srcclk)
{
case RCC_I2C1CLKSOURCE_PCLK1:
frequency = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C1CLKSOURCE_SYSCLK:
frequency = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C1CLKSOURCE_HSI:
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))
{
frequency = HSI_VALUE;
}
break;
default:
/* No clock source, frequency default init at 0 */
break;
}
break;
}
#if defined(I2C2)
case RCC_PERIPHCLK_I2C2:
{
/* Get the current I2C2 source */
srcclk = __HAL_RCC_GET_I2C2_SOURCE();
switch(srcclk)
{
case RCC_I2C2CLKSOURCE_PCLK1:
frequency = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C2CLKSOURCE_SYSCLK:
frequency = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C2CLKSOURCE_HSI:
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))
{
frequency = HSI_VALUE;
}
break;
default:
/* No clock source, frequency default init at 0 */
break;
}
break;
}
#endif /* I2C2 */
case RCC_PERIPHCLK_I2C3:
{
/* Get the current I2C3 source */
srcclk = __HAL_RCC_GET_I2C3_SOURCE();
switch(srcclk)
{
case RCC_I2C3CLKSOURCE_PCLK1:
frequency = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C3CLKSOURCE_SYSCLK:
frequency = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C3CLKSOURCE_HSI:
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))
{
frequency = HSI_VALUE;
}
break;
default:
/* No clock source, frequency default init at 0 */
break;
}
break;
}
#if defined(I2C4)
case RCC_PERIPHCLK_I2C4:
{
/* Get the current I2C4 source */
srcclk = __HAL_RCC_GET_I2C4_SOURCE();
switch(srcclk)
{
case RCC_I2C4CLKSOURCE_PCLK1:
frequency = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C4CLKSOURCE_SYSCLK:
frequency = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C4CLKSOURCE_HSI:
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))
{
frequency = HSI_VALUE;
}
break;
default:
/* No clock source, frequency default init at 0 */
break;
}
break;
}
#endif /* I2C4 */
case RCC_PERIPHCLK_LPTIM1:
{
/* Get the current LPTIM1 source */
srcclk = __HAL_RCC_GET_LPTIM1_SOURCE();
switch(srcclk)
{
case RCC_LPTIM1CLKSOURCE_PCLK1:
frequency = HAL_RCC_GetPCLK1Freq();
break;
case RCC_LPTIM1CLKSOURCE_LSI:
if(HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY))
{
#if defined(RCC_CSR_LSIPREDIV)
if(HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIPREDIV))
{
frequency = LSI_VALUE/128U;
}
else
#endif /* RCC_CSR_LSIPREDIV */
{
frequency = LSI_VALUE;
}
}
break;
case RCC_LPTIM1CLKSOURCE_HSI:
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))
{
frequency = HSI_VALUE;
}
break;
case RCC_LPTIM1CLKSOURCE_LSE:
if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))
{
frequency = LSE_VALUE;
}
break;
default:
/* No clock source, frequency default init at 0 */
break;
}
break;
}
case RCC_PERIPHCLK_LPTIM2:
{
/* Get the current LPTIM2 source */
srcclk = __HAL_RCC_GET_LPTIM2_SOURCE();
switch(srcclk)
{
case RCC_LPTIM2CLKSOURCE_PCLK1:
frequency = HAL_RCC_GetPCLK1Freq();
break;
case RCC_LPTIM2CLKSOURCE_LSI:
if(HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY))
{
#if defined(RCC_CSR_LSIPREDIV)
if(HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIPREDIV))
{
frequency = LSI_VALUE/128U;
}
else
#endif /* RCC_CSR_LSIPREDIV */
{
frequency = LSI_VALUE;
}
}
break;
case RCC_LPTIM2CLKSOURCE_HSI:
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))
{
frequency = HSI_VALUE;
}
break;
case RCC_LPTIM2CLKSOURCE_LSE:
if(HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY))
{
frequency = LSE_VALUE;
}
break;
default:
/* No clock source, frequency default init at 0 */
break;
}
break;
}
#if defined(SWPMI1)
case RCC_PERIPHCLK_SWPMI1:
{
/* Get the current SWPMI1 source */
srcclk = __HAL_RCC_GET_SWPMI1_SOURCE();
switch(srcclk)
{
case RCC_SWPMI1CLKSOURCE_PCLK1:
frequency = HAL_RCC_GetPCLK1Freq();
break;
case RCC_SWPMI1CLKSOURCE_HSI:
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))
{
frequency = HSI_VALUE;
}
break;
default:
/* No clock source, frequency default init at 0 */
break;
}
break;
}
#endif /* SWPMI1 */
#if defined(OCTOSPI1) || defined(OCTOSPI2)
case RCC_PERIPHCLK_OSPI:
{
/* Get the current OctoSPI clock source */
srcclk = __HAL_RCC_GET_OSPI_SOURCE();
switch(srcclk)
{
case RCC_OSPICLKSOURCE_SYSCLK:
frequency = HAL_RCC_GetSysClockFreq();
break;
case RCC_OSPICLKSOURCE_MSI:
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_MSIRDY))
{
/*MSI frequency range in HZ*/
frequency = MSIRangeTable[(__HAL_RCC_GET_MSI_RANGE() >> 4U)];
}
break;
case RCC_OSPICLKSOURCE_PLL:
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLRDY))
{
if(HAL_IS_BIT_SET(RCC->PLLCFGR, RCC_PLLCFGR_PLLQEN))
{
/* f(PLL Source) * PLLN / PLLM */
plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos;
pllvco = ((pllvco * plln) / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U));
/* f(PLL48M1CLK) = f(VCO input) / PLLQ */
frequency = (pllvco / (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLQ) >> RCC_PLLCFGR_PLLQ_Pos) + 1U) << 1U));
}
}
break;
default:
/* No clock source, frequency default init at 0 */
break;
}
break;
}
#endif /* OCTOSPI1 || OCTOSPI2 */
default:
break;
}
}
return(frequency);
}
/**
* @}
*/
/** @defgroup RCCEx_Exported_Functions_Group2 Extended Clock management functions
* @brief Extended Clock management functions
*
@verbatim
===============================================================================
##### Extended clock management functions #####
===============================================================================
[..]
This subsection provides a set of functions allowing to control the
activation or deactivation of MSI PLL-mode, PLLSAI1, PLLSAI2, LSE CSS,
Low speed clock output and clock after wake-up from STOP mode.
@endverbatim
* @{
*/
#if defined(RCC_PLLSAI1_SUPPORT)
/**
* @brief Enable PLLSAI1.
* @param PLLSAI1Init pointer to an RCC_PLLSAI1InitTypeDef structure that
* contains the configuration information for the PLLSAI1
* @retval HAL status
*/
HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI1(RCC_PLLSAI1InitTypeDef *PLLSAI1Init)
{
uint32_t tickstart;
HAL_StatusTypeDef status = HAL_OK;
/* check for PLLSAI1 Parameters used to output PLLSAI1CLK */
assert_param(IS_RCC_PLLSAI1SOURCE(PLLSAI1Init->PLLSAI1Source));
assert_param(IS_RCC_PLLSAI1M_VALUE(PLLSAI1Init->PLLSAI1M));
assert_param(IS_RCC_PLLSAI1N_VALUE(PLLSAI1Init->PLLSAI1N));
assert_param(IS_RCC_PLLSAI1P_VALUE(PLLSAI1Init->PLLSAI1P));
assert_param(IS_RCC_PLLSAI1Q_VALUE(PLLSAI1Init->PLLSAI1Q));
assert_param(IS_RCC_PLLSAI1R_VALUE(PLLSAI1Init->PLLSAI1R));
assert_param(IS_RCC_PLLSAI1CLOCKOUT_VALUE(PLLSAI1Init->PLLSAI1ClockOut));
/* Disable the PLLSAI1 */
__HAL_RCC_PLLSAI1_DISABLE();
/* Get Start Tick*/
tickstart = HAL_GetTick();
/* Wait till PLLSAI1 is ready to be updated */
while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) != 0U)
{
if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE)
{
status = HAL_TIMEOUT;
break;
}
}
if(status == HAL_OK)
{
#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT)
/* Configure the PLLSAI1 Multiplication factor N */
/* Configure the PLLSAI1 Division factors M, P, Q and R */
__HAL_RCC_PLLSAI1_CONFIG(PLLSAI1Init->PLLSAI1M, PLLSAI1Init->PLLSAI1N, PLLSAI1Init->PLLSAI1P, PLLSAI1Init->PLLSAI1Q, PLLSAI1Init->PLLSAI1R);
#else
/* Configure the PLLSAI1 Multiplication factor N */
/* Configure the PLLSAI1 Division factors P, Q and R */
__HAL_RCC_PLLSAI1_CONFIG(PLLSAI1Init->PLLSAI1N, PLLSAI1Init->PLLSAI1P, PLLSAI1Init->PLLSAI1Q, PLLSAI1Init->PLLSAI1R);
#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */
/* Configure the PLLSAI1 Clock output(s) */
__HAL_RCC_PLLSAI1CLKOUT_ENABLE(PLLSAI1Init->PLLSAI1ClockOut);
/* Enable the PLLSAI1 again by setting PLLSAI1ON to 1*/
__HAL_RCC_PLLSAI1_ENABLE();
/* Get Start Tick*/
tickstart = HAL_GetTick();
/* Wait till PLLSAI1 is ready */
while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == 0U)
{
if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE)
{
status = HAL_TIMEOUT;
break;
}
}
}
return status;
}
/**
* @brief Disable PLLSAI1.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_RCCEx_DisablePLLSAI1(void)
{
uint32_t tickstart;
HAL_StatusTypeDef status = HAL_OK;
/* Disable the PLLSAI1 */
__HAL_RCC_PLLSAI1_DISABLE();
/* Get Start Tick*/
tickstart = HAL_GetTick();
/* Wait till PLLSAI1 is ready */
while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) != 0U)
{
if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE)
{
status = HAL_TIMEOUT;
break;
}
}
/* Disable the PLLSAI1 Clock outputs */
__HAL_RCC_PLLSAI1CLKOUT_DISABLE(RCC_PLLSAI1CFGR_PLLSAI1PEN|RCC_PLLSAI1CFGR_PLLSAI1QEN|RCC_PLLSAI1CFGR_PLLSAI1REN);
/* Reset PLL source to save power if no PLLs on */
#if defined(RCC_PLLSAI2_SUPPORT)
if(READ_BIT(RCC->CR, (RCC_CR_PLLRDY | RCC_CR_PLLSAI2RDY)) == 0U)
{
MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, RCC_PLLSOURCE_NONE);
}
#else
if(READ_BIT(RCC->CR, RCC_CR_PLLRDY) == 0U)
{
MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, RCC_PLLSOURCE_NONE);
}
#endif /* RCC_PLLSAI2_SUPPORT */
return status;
}
#endif /* RCC_PLLSAI1_SUPPORT */
#if defined(RCC_PLLSAI2_SUPPORT)
/**
* @brief Enable PLLSAI2.
* @param PLLSAI2Init pointer to an RCC_PLLSAI2InitTypeDef structure that
* contains the configuration information for the PLLSAI2
* @retval HAL status
*/
HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI2(RCC_PLLSAI2InitTypeDef *PLLSAI2Init)
{
uint32_t tickstart;
HAL_StatusTypeDef status = HAL_OK;
/* check for PLLSAI2 Parameters used to output PLLSAI2CLK */
assert_param(IS_RCC_PLLSAI2SOURCE(PLLSAI2Init->PLLSAI2Source));
assert_param(IS_RCC_PLLSAI2M_VALUE(PLLSAI2Init->PLLSAI2M));
assert_param(IS_RCC_PLLSAI2N_VALUE(PLLSAI2Init->PLLSAI2N));
assert_param(IS_RCC_PLLSAI2P_VALUE(PLLSAI2Init->PLLSAI2P));
#if defined(RCC_PLLSAI2Q_DIV_SUPPORT)
assert_param(IS_RCC_PLLSAI2Q_VALUE(PLLSAI2Init->PLLSAI2Q));
#endif /* RCC_PLLSAI2Q_DIV_SUPPORT */
assert_param(IS_RCC_PLLSAI2R_VALUE(PLLSAI2Init->PLLSAI2R));
assert_param(IS_RCC_PLLSAI2CLOCKOUT_VALUE(PLLSAI2Init->PLLSAI2ClockOut));
/* Disable the PLLSAI2 */
__HAL_RCC_PLLSAI2_DISABLE();
/* Get Start Tick*/
tickstart = HAL_GetTick();
/* Wait till PLLSAI2 is ready to be updated */
while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) != 0U)
{
if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE)
{
status = HAL_TIMEOUT;
break;
}
}
if(status == HAL_OK)
{
#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT) && defined(RCC_PLLSAI2Q_DIV_SUPPORT)
/* Configure the PLLSAI2 Multiplication factor N */
/* Configure the PLLSAI2 Division factors M, P, Q and R */
__HAL_RCC_PLLSAI2_CONFIG(PLLSAI2Init->PLLSAI2M, PLLSAI2Init->PLLSAI2N, PLLSAI2Init->PLLSAI2P, PLLSAI2Init->PLLSAI2Q, PLLSAI2Init->PLLSAI2R);
#elif defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT)
/* Configure the PLLSAI2 Multiplication factor N */
/* Configure the PLLSAI2 Division factors M, P and R */
__HAL_RCC_PLLSAI2_CONFIG(PLLSAI2Init->PLLSAI2M, PLLSAI2Init->PLLSAI2N, PLLSAI2Init->PLLSAI2P, PLLSAI2Init->PLLSAI2R);
#elif defined(RCC_PLLSAI2Q_DIV_SUPPORT)
/* Configure the PLLSAI2 Multiplication factor N */
/* Configure the PLLSAI2 Division factors P, Q and R */
__HAL_RCC_PLLSAI2_CONFIG(PLLSAI2Init->PLLSAI2N, PLLSAI2Init->PLLSAI2P, PLLSAI2Init->PLLSAI2Q, PLLSAI2Init->PLLSAI2R);
#else
/* Configure the PLLSAI2 Multiplication factor N */
/* Configure the PLLSAI2 Division factors P and R */
__HAL_RCC_PLLSAI2_CONFIG(PLLSAI2Init->PLLSAI2N, PLLSAI2Init->PLLSAI2P, PLLSAI2Init->PLLSAI2R);
#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT && RCC_PLLSAI2Q_DIV_SUPPORT */
/* Configure the PLLSAI2 Clock output(s) */
__HAL_RCC_PLLSAI2CLKOUT_ENABLE(PLLSAI2Init->PLLSAI2ClockOut);
/* Enable the PLLSAI2 again by setting PLLSAI2ON to 1*/
__HAL_RCC_PLLSAI2_ENABLE();
/* Get Start Tick*/
tickstart = HAL_GetTick();
/* Wait till PLLSAI2 is ready */
while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) == 0U)
{
if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE)
{
status = HAL_TIMEOUT;
break;
}
}
}
return status;
}
/**
* @brief Disable PLLISAI2.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_RCCEx_DisablePLLSAI2(void)
{
uint32_t tickstart;
HAL_StatusTypeDef status = HAL_OK;
/* Disable the PLLSAI2 */
__HAL_RCC_PLLSAI2_DISABLE();
/* Get Start Tick*/
tickstart = HAL_GetTick();
/* Wait till PLLSAI2 is ready */
while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) != 0U)
{
if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE)
{
status = HAL_TIMEOUT;
break;
}
}
/* Disable the PLLSAI2 Clock outputs */
#if defined(RCC_PLLSAI2Q_DIV_SUPPORT)
__HAL_RCC_PLLSAI2CLKOUT_DISABLE(RCC_PLLSAI2CFGR_PLLSAI2PEN|RCC_PLLSAI2CFGR_PLLSAI2QEN|RCC_PLLSAI2CFGR_PLLSAI2REN);
#else
__HAL_RCC_PLLSAI2CLKOUT_DISABLE(RCC_PLLSAI2CFGR_PLLSAI2PEN|RCC_PLLSAI2CFGR_PLLSAI2REN);
#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT && RCC_PLLSAI2Q_DIV_SUPPORT */
/* Reset PLL source to save power if no PLLs on */
if(READ_BIT(RCC->CR, (RCC_CR_PLLRDY | RCC_CR_PLLSAI1RDY)) == 0U)
{
MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, RCC_PLLSOURCE_NONE);
}
return status;
}
#endif /* RCC_PLLSAI2_SUPPORT */
/**
* @brief Configure the oscillator clock source for wakeup from Stop and CSS backup clock.
* @param WakeUpClk Wakeup clock
* This parameter can be one of the following values:
* @arg @ref RCC_STOP_WAKEUPCLOCK_MSI MSI oscillator selection
* @arg @ref RCC_STOP_WAKEUPCLOCK_HSI HSI oscillator selection
* @note This function shall not be called after the Clock Security System on HSE has been
* enabled.
* @retval None
*/
void HAL_RCCEx_WakeUpStopCLKConfig(uint32_t WakeUpClk)
{
assert_param(IS_RCC_STOP_WAKEUPCLOCK(WakeUpClk));
__HAL_RCC_WAKEUPSTOP_CLK_CONFIG(WakeUpClk);
}
/**
* @brief Configure the MSI range after standby mode.
* @note After Standby its frequency can be selected between 4 possible values (1, 2, 4 or 8 MHz).
* @param MSIRange MSI range
* This parameter can be one of the following values:
* @arg @ref RCC_MSIRANGE_4 Range 4 around 1 MHz
* @arg @ref RCC_MSIRANGE_5 Range 5 around 2 MHz
* @arg @ref RCC_MSIRANGE_6 Range 6 around 4 MHz (reset value)
* @arg @ref RCC_MSIRANGE_7 Range 7 around 8 MHz
* @retval None
*/
void HAL_RCCEx_StandbyMSIRangeConfig(uint32_t MSIRange)
{
assert_param(IS_RCC_MSI_STANDBY_CLOCK_RANGE(MSIRange));
__HAL_RCC_MSI_STANDBY_RANGE_CONFIG(MSIRange);
}
/**
* @brief Enable the LSE Clock Security System.
* @note Prior to enable the LSE Clock Security System, LSE oscillator is to be enabled
* with HAL_RCC_OscConfig() and the LSE oscillator clock is to be selected as RTC
* clock with HAL_RCCEx_PeriphCLKConfig().
* @retval None
*/
void HAL_RCCEx_EnableLSECSS(void)
{
SET_BIT(RCC->BDCR, RCC_BDCR_LSECSSON);
}
/**
* @brief Disable the LSE Clock Security System.
* @note LSE Clock Security System can only be disabled after a LSE failure detection.
* @retval None
*/
void HAL_RCCEx_DisableLSECSS(void)
{
CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSECSSON) ;
/* Disable LSE CSS IT if any */
__HAL_RCC_DISABLE_IT(RCC_IT_LSECSS);
}
/**
* @brief Enable the LSE Clock Security System Interrupt & corresponding EXTI line.
* @note LSE Clock Security System Interrupt is mapped on RTC EXTI line 19
* @retval None
*/
void HAL_RCCEx_EnableLSECSS_IT(void)
{
/* Enable LSE CSS */
SET_BIT(RCC->BDCR, RCC_BDCR_LSECSSON) ;
/* Enable LSE CSS IT */
__HAL_RCC_ENABLE_IT(RCC_IT_LSECSS);
/* Enable IT on EXTI Line 19 */
__HAL_RCC_LSECSS_EXTI_ENABLE_IT();
__HAL_RCC_LSECSS_EXTI_ENABLE_RISING_EDGE();
}
/**
* @brief Handle the RCC LSE Clock Security System interrupt request.
* @retval None
*/
void HAL_RCCEx_LSECSS_IRQHandler(void)
{
/* Check RCC LSE CSSF flag */
if(__HAL_RCC_GET_IT(RCC_IT_LSECSS))
{
/* RCC LSE Clock Security System interrupt user callback */
HAL_RCCEx_LSECSS_Callback();
/* Clear RCC LSE CSS pending bit */
__HAL_RCC_CLEAR_IT(RCC_IT_LSECSS);
}
}
/**
* @brief RCCEx LSE Clock Security System interrupt callback.
* @retval none
*/
__weak void HAL_RCCEx_LSECSS_Callback(void)
{
/* NOTE : This function should not be modified, when the callback is needed,
the @ref HAL_RCCEx_LSECSS_Callback should be implemented in the user file
*/
}
/**
* @brief Select the Low Speed clock source to output on LSCO pin (PA2).
* @param LSCOSource specifies the Low Speed clock source to output.
* This parameter can be one of the following values:
* @arg @ref RCC_LSCOSOURCE_LSI LSI clock selected as LSCO source
* @arg @ref RCC_LSCOSOURCE_LSE LSE clock selected as LSCO source
* @retval None
*/
void HAL_RCCEx_EnableLSCO(uint32_t LSCOSource)
{
GPIO_InitTypeDef GPIO_InitStruct;
FlagStatus pwrclkchanged = RESET;
FlagStatus backupchanged = RESET;
/* Check the parameters */
assert_param(IS_RCC_LSCOSOURCE(LSCOSource));
/* LSCO Pin Clock Enable */
__LSCO_CLK_ENABLE();
/* Configure the LSCO pin in analog mode */
GPIO_InitStruct.Pin = LSCO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(LSCO_GPIO_PORT, &GPIO_InitStruct);
/* Update LSCOSEL clock source in Backup Domain control register */
if(__HAL_RCC_PWR_IS_CLK_DISABLED())
{
__HAL_RCC_PWR_CLK_ENABLE();
pwrclkchanged = SET;
}
if(HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP))
{
HAL_PWR_EnableBkUpAccess();
backupchanged = SET;
}
MODIFY_REG(RCC->BDCR, RCC_BDCR_LSCOSEL | RCC_BDCR_LSCOEN, LSCOSource | RCC_BDCR_LSCOEN);
if(backupchanged == SET)
{
HAL_PWR_DisableBkUpAccess();
}
if(pwrclkchanged == SET)
{
__HAL_RCC_PWR_CLK_DISABLE();
}
}
/**
* @brief Disable the Low Speed clock output.
* @retval None
*/
void HAL_RCCEx_DisableLSCO(void)
{
FlagStatus pwrclkchanged = RESET;
FlagStatus backupchanged = RESET;
/* Update LSCOEN bit in Backup Domain control register */
if(__HAL_RCC_PWR_IS_CLK_DISABLED())
{
__HAL_RCC_PWR_CLK_ENABLE();
pwrclkchanged = SET;
}
if(HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP))
{
/* Enable access to the backup domain */
HAL_PWR_EnableBkUpAccess();
backupchanged = SET;
}
CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSCOEN);
/* Restore previous configuration */
if(backupchanged == SET)
{
/* Disable access to the backup domain */
HAL_PWR_DisableBkUpAccess();
}
if(pwrclkchanged == SET)
{
__HAL_RCC_PWR_CLK_DISABLE();
}
}
/**
* @brief Enable the PLL-mode of the MSI.
* @note Prior to enable the PLL-mode of the MSI for automatic hardware
* calibration LSE oscillator is to be enabled with HAL_RCC_OscConfig().
* @retval None
*/
void HAL_RCCEx_EnableMSIPLLMode(void)
{
SET_BIT(RCC->CR, RCC_CR_MSIPLLEN) ;
}
/**
* @brief Disable the PLL-mode of the MSI.
* @note PLL-mode of the MSI is automatically reset when LSE oscillator is disabled.
* @retval None
*/
void HAL_RCCEx_DisableMSIPLLMode(void)
{
CLEAR_BIT(RCC->CR, RCC_CR_MSIPLLEN) ;
}
#if defined (OCTOSPI1) && defined (OCTOSPI2)
/**
* @brief Configure OCTOSPI instances DQS delays.
* @param Delay1 OCTOSPI1 DQS delay
* @param Delay2 OCTOSPI2 DQS delay
* @note Delay parameters stand for unitary delays from 0 to 15. Actual delay is Delay1 or Delay2 + 1.
* @retval None
*/
void HAL_RCCEx_OCTOSPIDelayConfig(uint32_t Delay1, uint32_t Delay2)
{
assert_param(IS_RCC_OCTOSPIDELAY(Delay1));
assert_param(IS_RCC_OCTOSPIDELAY(Delay2));
MODIFY_REG(RCC->DLYCFGR, RCC_DLYCFGR_OCTOSPI1_DLY|RCC_DLYCFGR_OCTOSPI2_DLY, (Delay1 | (Delay2 << RCC_DLYCFGR_OCTOSPI2_DLY_Pos))) ;
}
#endif /* OCTOSPI1 && OCTOSPI2 */
/**
* @}
*/
#if defined(CRS)
/** @defgroup RCCEx_Exported_Functions_Group3 Extended Clock Recovery System Control functions
* @brief Extended Clock Recovery System Control functions
*
@verbatim
===============================================================================
##### Extended Clock Recovery System Control functions #####
===============================================================================
[..]
For devices with Clock Recovery System feature (CRS), RCC Extension HAL driver can be used as follows:
(#) In System clock config, HSI48 needs to be enabled
(#) Enable CRS clock in IP MSP init which will use CRS functions
(#) Call CRS functions as follows:
(##) Prepare synchronization configuration necessary for HSI48 calibration
(+++) Default values can be set for frequency Error Measurement (reload and error limit)
and also HSI48 oscillator smooth trimming.
(+++) Macro __HAL_RCC_CRS_RELOADVALUE_CALCULATE can be also used to calculate
directly reload value with target and sychronization frequencies values
(##) Call function HAL_RCCEx_CRSConfig which
(+++) Resets CRS registers to their default values.
(+++) Configures CRS registers with synchronization configuration
(+++) Enables automatic calibration and frequency error counter feature
Note: When using USB LPM (Link Power Management) and the device is in Sleep mode, the
periodic USB SOF will not be generated by the host. No SYNC signal will therefore be
provided to the CRS to calibrate the HSI48 on the run. To guarantee the required clock
precision after waking up from Sleep mode, the LSE or reference clock on the GPIOs
should be used as SYNC signal.
(##) A polling function is provided to wait for complete synchronization
(+++) Call function HAL_RCCEx_CRSWaitSynchronization()
(+++) According to CRS status, user can decide to adjust again the calibration or continue
application if synchronization is OK
(#) User can retrieve information related to synchronization in calling function
HAL_RCCEx_CRSGetSynchronizationInfo()
(#) Regarding synchronization status and synchronization information, user can try a new calibration
in changing synchronization configuration and call again HAL_RCCEx_CRSConfig.
Note: When the SYNC event is detected during the downcounting phase (before reaching the zero value),
it means that the actual frequency is lower than the target (and so, that the TRIM value should be
incremented), while when it is detected during the upcounting phase it means that the actual frequency
is higher (and that the TRIM value should be decremented).
(#) In interrupt mode, user can resort to the available macros (__HAL_RCC_CRS_XXX_IT). Interrupts will go
through CRS Handler (CRS_IRQn/CRS_IRQHandler)
(++) Call function HAL_RCCEx_CRSConfig()
(++) Enable CRS_IRQn (thanks to NVIC functions)
(++) Enable CRS interrupt (__HAL_RCC_CRS_ENABLE_IT)
(++) Implement CRS status management in the following user callbacks called from
HAL_RCCEx_CRS_IRQHandler():
(+++) HAL_RCCEx_CRS_SyncOkCallback()
(+++) HAL_RCCEx_CRS_SyncWarnCallback()
(+++) HAL_RCCEx_CRS_ExpectedSyncCallback()
(+++) HAL_RCCEx_CRS_ErrorCallback()
(#) To force a SYNC EVENT, user can use the function HAL_RCCEx_CRSSoftwareSynchronizationGenerate().
This function can be called before calling HAL_RCCEx_CRSConfig (for instance in Systick handler)
@endverbatim
* @{
*/
/**
* @brief Start automatic synchronization for polling mode
* @param pInit Pointer on RCC_CRSInitTypeDef structure
* @retval None
*/
void HAL_RCCEx_CRSConfig(RCC_CRSInitTypeDef *pInit)
{
uint32_t value; /* no init needed */
/* Check the parameters */
assert_param(IS_RCC_CRS_SYNC_DIV(pInit->Prescaler));
assert_param(IS_RCC_CRS_SYNC_SOURCE(pInit->Source));
assert_param(IS_RCC_CRS_SYNC_POLARITY(pInit->Polarity));
assert_param(IS_RCC_CRS_RELOADVALUE(pInit->ReloadValue));
assert_param(IS_RCC_CRS_ERRORLIMIT(pInit->ErrorLimitValue));
assert_param(IS_RCC_CRS_HSI48CALIBRATION(pInit->HSI48CalibrationValue));
/* CONFIGURATION */
/* Before configuration, reset CRS registers to their default values*/
__HAL_RCC_CRS_FORCE_RESET();
__HAL_RCC_CRS_RELEASE_RESET();
/* Set the SYNCDIV[2:0] bits according to Prescaler value */
/* Set the SYNCSRC[1:0] bits according to Source value */
/* Set the SYNCSPOL bit according to Polarity value */
value = (pInit->Prescaler | pInit->Source | pInit->Polarity);
/* Set the RELOAD[15:0] bits according to ReloadValue value */
value |= pInit->ReloadValue;
/* Set the FELIM[7:0] bits according to ErrorLimitValue value */
value |= (pInit->ErrorLimitValue << CRS_CFGR_FELIM_Pos);
WRITE_REG(CRS->CFGR, value);
/* Adjust HSI48 oscillator smooth trimming */
/* Set the TRIM[6:0] bits for STM32L412xx/L422xx or TRIM[5:0] bits otherwise
according to RCC_CRS_HSI48CalibrationValue value */
MODIFY_REG(CRS->CR, CRS_CR_TRIM, (pInit->HSI48CalibrationValue << CRS_CR_TRIM_Pos));
/* START AUTOMATIC SYNCHRONIZATION*/
/* Enable Automatic trimming & Frequency error counter */
SET_BIT(CRS->CR, CRS_CR_AUTOTRIMEN | CRS_CR_CEN);
}
/**
* @brief Generate the software synchronization event
* @retval None
*/
void HAL_RCCEx_CRSSoftwareSynchronizationGenerate(void)
{
SET_BIT(CRS->CR, CRS_CR_SWSYNC);
}
/**
* @brief Return synchronization info
* @param pSynchroInfo Pointer on RCC_CRSSynchroInfoTypeDef structure
* @retval None
*/
void HAL_RCCEx_CRSGetSynchronizationInfo(RCC_CRSSynchroInfoTypeDef *pSynchroInfo)
{
/* Check the parameter */
assert_param(pSynchroInfo != (void *)NULL);
/* Get the reload value */
pSynchroInfo->ReloadValue = (READ_BIT(CRS->CFGR, CRS_CFGR_RELOAD));
/* Get HSI48 oscillator smooth trimming */
pSynchroInfo->HSI48CalibrationValue = (READ_BIT(CRS->CR, CRS_CR_TRIM) >> CRS_CR_TRIM_Pos);
/* Get Frequency error capture */
pSynchroInfo->FreqErrorCapture = (READ_BIT(CRS->ISR, CRS_ISR_FECAP) >> CRS_ISR_FECAP_Pos);
/* Get Frequency error direction */
pSynchroInfo->FreqErrorDirection = (READ_BIT(CRS->ISR, CRS_ISR_FEDIR));
}
/**
* @brief Wait for CRS Synchronization status.
* @param Timeout Duration of the timeout
* @note Timeout is based on the maximum time to receive a SYNC event based on synchronization
* frequency.
* @note If Timeout set to HAL_MAX_DELAY, HAL_TIMEOUT will be never returned.
* @retval Combination of Synchronization status
* This parameter can be a combination of the following values:
* @arg @ref RCC_CRS_TIMEOUT
* @arg @ref RCC_CRS_SYNCOK
* @arg @ref RCC_CRS_SYNCWARN
* @arg @ref RCC_CRS_SYNCERR
* @arg @ref RCC_CRS_SYNCMISS
* @arg @ref RCC_CRS_TRIMOVF
*/
uint32_t HAL_RCCEx_CRSWaitSynchronization(uint32_t Timeout)
{
uint32_t crsstatus = RCC_CRS_NONE;
uint32_t tickstart;
/* Get timeout */
tickstart = HAL_GetTick();
/* Wait for CRS flag or timeout detection */
do
{
if(Timeout != HAL_MAX_DELAY)
{
if(((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
{
crsstatus = RCC_CRS_TIMEOUT;
}
}
/* Check CRS SYNCOK flag */
if(__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_SYNCOK))
{
/* CRS SYNC event OK */
crsstatus |= RCC_CRS_SYNCOK;
/* Clear CRS SYNC event OK bit */
__HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_SYNCOK);
}
/* Check CRS SYNCWARN flag */
if(__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_SYNCWARN))
{
/* CRS SYNC warning */
crsstatus |= RCC_CRS_SYNCWARN;
/* Clear CRS SYNCWARN bit */
__HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_SYNCWARN);
}
/* Check CRS TRIM overflow flag */
if(__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_TRIMOVF))
{
/* CRS SYNC Error */
crsstatus |= RCC_CRS_TRIMOVF;
/* Clear CRS Error bit */
__HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_TRIMOVF);
}
/* Check CRS Error flag */
if(__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_SYNCERR))
{
/* CRS SYNC Error */
crsstatus |= RCC_CRS_SYNCERR;
/* Clear CRS Error bit */
__HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_SYNCERR);
}
/* Check CRS SYNC Missed flag */
if(__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_SYNCMISS))
{
/* CRS SYNC Missed */
crsstatus |= RCC_CRS_SYNCMISS;
/* Clear CRS SYNC Missed bit */
__HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_SYNCMISS);
}
/* Check CRS Expected SYNC flag */
if(__HAL_RCC_CRS_GET_FLAG(RCC_CRS_FLAG_ESYNC))
{
/* frequency error counter reached a zero value */
__HAL_RCC_CRS_CLEAR_FLAG(RCC_CRS_FLAG_ESYNC);
}
} while(RCC_CRS_NONE == crsstatus);
return crsstatus;
}
/**
* @brief Handle the Clock Recovery System interrupt request.
* @retval None
*/
void HAL_RCCEx_CRS_IRQHandler(void)
{
uint32_t crserror = RCC_CRS_NONE;
/* Get current IT flags and IT sources values */
uint32_t itflags = READ_REG(CRS->ISR);
uint32_t itsources = READ_REG(CRS->CR);
/* Check CRS SYNCOK flag */
if(((itflags & RCC_CRS_FLAG_SYNCOK) != 0U) && ((itsources & RCC_CRS_IT_SYNCOK) != 0U))
{
/* Clear CRS SYNC event OK flag */
WRITE_REG(CRS->ICR, CRS_ICR_SYNCOKC);
/* user callback */
HAL_RCCEx_CRS_SyncOkCallback();
}
/* Check CRS SYNCWARN flag */
else if(((itflags & RCC_CRS_FLAG_SYNCWARN) != 0U) && ((itsources & RCC_CRS_IT_SYNCWARN) != 0U))
{
/* Clear CRS SYNCWARN flag */
WRITE_REG(CRS->ICR, CRS_ICR_SYNCWARNC);
/* user callback */
HAL_RCCEx_CRS_SyncWarnCallback();
}
/* Check CRS Expected SYNC flag */
else if(((itflags & RCC_CRS_FLAG_ESYNC) != 0U) && ((itsources & RCC_CRS_IT_ESYNC) != 0U))
{
/* frequency error counter reached a zero value */
WRITE_REG(CRS->ICR, CRS_ICR_ESYNCC);
/* user callback */
HAL_RCCEx_CRS_ExpectedSyncCallback();
}
/* Check CRS Error flags */
else
{
if(((itflags & RCC_CRS_FLAG_ERR) != 0U) && ((itsources & RCC_CRS_IT_ERR) != 0U))
{
if((itflags & RCC_CRS_FLAG_SYNCERR) != 0U)
{
crserror |= RCC_CRS_SYNCERR;
}
if((itflags & RCC_CRS_FLAG_SYNCMISS) != 0U)
{
crserror |= RCC_CRS_SYNCMISS;
}
if((itflags & RCC_CRS_FLAG_TRIMOVF) != 0U)
{
crserror |= RCC_CRS_TRIMOVF;
}
/* Clear CRS Error flags */
WRITE_REG(CRS->ICR, CRS_ICR_ERRC);
/* user error callback */
HAL_RCCEx_CRS_ErrorCallback(crserror);
}
}
}
/**
* @brief RCCEx Clock Recovery System SYNCOK interrupt callback.
* @retval none
*/
__weak void HAL_RCCEx_CRS_SyncOkCallback(void)
{
/* NOTE : This function should not be modified, when the callback is needed,
the @ref HAL_RCCEx_CRS_SyncOkCallback should be implemented in the user file
*/
}
/**
* @brief RCCEx Clock Recovery System SYNCWARN interrupt callback.
* @retval none
*/
__weak void HAL_RCCEx_CRS_SyncWarnCallback(void)
{
/* NOTE : This function should not be modified, when the callback is needed,
the @ref HAL_RCCEx_CRS_SyncWarnCallback should be implemented in the user file
*/
}
/**
* @brief RCCEx Clock Recovery System Expected SYNC interrupt callback.
* @retval none
*/
__weak void HAL_RCCEx_CRS_ExpectedSyncCallback(void)
{
/* NOTE : This function should not be modified, when the callback is needed,
the @ref HAL_RCCEx_CRS_ExpectedSyncCallback should be implemented in the user file
*/
}
/**
* @brief RCCEx Clock Recovery System Error interrupt callback.
* @param Error Combination of Error status.
* This parameter can be a combination of the following values:
* @arg @ref RCC_CRS_SYNCERR
* @arg @ref RCC_CRS_SYNCMISS
* @arg @ref RCC_CRS_TRIMOVF
* @retval none
*/
__weak void HAL_RCCEx_CRS_ErrorCallback(uint32_t Error)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(Error);
/* NOTE : This function should not be modified, when the callback is needed,
the @ref HAL_RCCEx_CRS_ErrorCallback should be implemented in the user file
*/
}
/**
* @}
*/
#endif /* CRS */
/**
* @}
*/
/** @addtogroup RCCEx_Private_Functions
* @{
*/
#if defined(RCC_PLLSAI1_SUPPORT)
/**
* @brief Configure the parameters N & P & optionally M of PLLSAI1 and enable PLLSAI1 output clock(s).
* @param PllSai1 pointer to an RCC_PLLSAI1InitTypeDef structure that
* contains the configuration parameters N & P & optionally M as well as PLLSAI1 output clock(s)
* @param Divider divider parameter to be updated
*
* @note PLLSAI1 is temporary disable to apply new parameters
*
* @retval HAL status
*/
static HAL_StatusTypeDef RCCEx_PLLSAI1_Config(RCC_PLLSAI1InitTypeDef *PllSai1, uint32_t Divider)
{
uint32_t tickstart;
HAL_StatusTypeDef status = HAL_OK;
/* check for PLLSAI1 Parameters used to output PLLSAI1CLK */
/* P, Q and R dividers are verified in each specific divider case below */
assert_param(IS_RCC_PLLSAI1SOURCE(PllSai1->PLLSAI1Source));
assert_param(IS_RCC_PLLSAI1M_VALUE(PllSai1->PLLSAI1M));
assert_param(IS_RCC_PLLSAI1N_VALUE(PllSai1->PLLSAI1N));
assert_param(IS_RCC_PLLSAI1CLOCKOUT_VALUE(PllSai1->PLLSAI1ClockOut));
/* Check that PLLSAI1 clock source and divider M can be applied */
if(__HAL_RCC_GET_PLL_OSCSOURCE() != RCC_PLLSOURCE_NONE)
{
/* PLL clock source and divider M already set, check that no request for change */
if((__HAL_RCC_GET_PLL_OSCSOURCE() != PllSai1->PLLSAI1Source)
||
(PllSai1->PLLSAI1Source == RCC_PLLSOURCE_NONE)
#if !defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT)
||
(((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U) != PllSai1->PLLSAI1M)
#endif
)
{
status = HAL_ERROR;
}
}
else
{
/* Check PLLSAI1 clock source availability */
switch(PllSai1->PLLSAI1Source)
{
case RCC_PLLSOURCE_MSI:
if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_MSIRDY))
{
status = HAL_ERROR;
}
break;
case RCC_PLLSOURCE_HSI:
if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSIRDY))
{
status = HAL_ERROR;
}
break;
case RCC_PLLSOURCE_HSE:
if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSERDY))
{
if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSEBYP))
{
status = HAL_ERROR;
}
}
break;
default:
status = HAL_ERROR;
break;
}
if(status == HAL_OK)
{
#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT)
/* Set PLLSAI1 clock source */
MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, PllSai1->PLLSAI1Source);
#else
/* Set PLLSAI1 clock source and divider M */
MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLM, PllSai1->PLLSAI1Source | (PllSai1->PLLSAI1M - 1U) << RCC_PLLCFGR_PLLM_Pos);
#endif
}
}
if(status == HAL_OK)
{
/* Disable the PLLSAI1 */
__HAL_RCC_PLLSAI1_DISABLE();
/* Get Start Tick*/
tickstart = HAL_GetTick();
/* Wait till PLLSAI1 is ready to be updated */
while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) != 0U)
{
if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE)
{
status = HAL_TIMEOUT;
break;
}
}
if(status == HAL_OK)
{
if(Divider == DIVIDER_P_UPDATE)
{
assert_param(IS_RCC_PLLSAI1P_VALUE(PllSai1->PLLSAI1P));
#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT)
/* Configure the PLLSAI1 Division factor M, P and Multiplication factor N*/
#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT)
MODIFY_REG(RCC->PLLSAI1CFGR,
RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1PDIV | RCC_PLLSAI1CFGR_PLLSAI1M,
(PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) |
(PllSai1->PLLSAI1P << RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos) |
((PllSai1->PLLSAI1M - 1U) << RCC_PLLSAI1CFGR_PLLSAI1M_Pos));
#else
MODIFY_REG(RCC->PLLSAI1CFGR,
RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1P | RCC_PLLSAI1CFGR_PLLSAI1M,
(PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) |
((PllSai1->PLLSAI1P >> 4U) << RCC_PLLSAI1CFGR_PLLSAI1P_Pos) |
((PllSai1->PLLSAI1M - 1U) << RCC_PLLSAI1CFGR_PLLSAI1M_Pos));
#endif /* RCC_PLLSAI1P_DIV_2_31_SUPPORT */
#else
/* Configure the PLLSAI1 Division factor P and Multiplication factor N*/
#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT)
MODIFY_REG(RCC->PLLSAI1CFGR,
RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1PDIV,
(PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) |
(PllSai1->PLLSAI1P << RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos));
#else
MODIFY_REG(RCC->PLLSAI1CFGR,
RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1P,
(PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) |
((PllSai1->PLLSAI1P >> 4U) << RCC_PLLSAI1CFGR_PLLSAI1P_Pos));
#endif /* RCC_PLLSAI1P_DIV_2_31_SUPPORT */
#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */
}
else if(Divider == DIVIDER_Q_UPDATE)
{
assert_param(IS_RCC_PLLSAI1Q_VALUE(PllSai1->PLLSAI1Q));
#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT)
/* Configure the PLLSAI1 Division factor M, Q and Multiplication factor N*/
MODIFY_REG(RCC->PLLSAI1CFGR,
RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1Q | RCC_PLLSAI1CFGR_PLLSAI1M,
(PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) |
(((PllSai1->PLLSAI1Q >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) |
((PllSai1->PLLSAI1M - 1U) << RCC_PLLSAI1CFGR_PLLSAI1M_Pos));
#else
/* Configure the PLLSAI1 Division factor Q and Multiplication factor N*/
MODIFY_REG(RCC->PLLSAI1CFGR,
RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1Q,
(PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) |
(((PllSai1->PLLSAI1Q >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1Q_Pos));
#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */
}
else
{
assert_param(IS_RCC_PLLSAI1R_VALUE(PllSai1->PLLSAI1R));
#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT)
/* Configure the PLLSAI1 Division factor M, R and Multiplication factor N*/
MODIFY_REG(RCC->PLLSAI1CFGR,
RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1R | RCC_PLLSAI1CFGR_PLLSAI1M,
(PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) |
(((PllSai1->PLLSAI1R >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1R_Pos) |
((PllSai1->PLLSAI1M - 1U) << RCC_PLLSAI1CFGR_PLLSAI1M_Pos));
#else
/* Configure the PLLSAI1 Division factor R and Multiplication factor N*/
MODIFY_REG(RCC->PLLSAI1CFGR,
RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1R,
(PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) |
(((PllSai1->PLLSAI1R >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1R_Pos));
#endif /* RCC_PLLSAI1M_DIV_1_16_SUPPORT */
}
/* Enable the PLLSAI1 again by setting PLLSAI1ON to 1*/
__HAL_RCC_PLLSAI1_ENABLE();
/* Get Start Tick*/
tickstart = HAL_GetTick();
/* Wait till PLLSAI1 is ready */
while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == 0U)
{
if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE)
{
status = HAL_TIMEOUT;
break;
}
}
if(status == HAL_OK)
{
/* Configure the PLLSAI1 Clock output(s) */
__HAL_RCC_PLLSAI1CLKOUT_ENABLE(PllSai1->PLLSAI1ClockOut);
}
}
}
return status;
}
#endif /* RCC_PLLSAI1_SUPPORT */
#if defined(RCC_PLLSAI2_SUPPORT)
/**
* @brief Configure the parameters N & P & optionally M of PLLSAI2 and enable PLLSAI2 output clock(s).
* @param PllSai2 pointer to an RCC_PLLSAI2InitTypeDef structure that
* contains the configuration parameters N & P & optionally M as well as PLLSAI2 output clock(s)
* @param Divider divider parameter to be updated
*
* @note PLLSAI2 is temporary disable to apply new parameters
*
* @retval HAL status
*/
static HAL_StatusTypeDef RCCEx_PLLSAI2_Config(RCC_PLLSAI2InitTypeDef *PllSai2, uint32_t Divider)
{
uint32_t tickstart;
HAL_StatusTypeDef status = HAL_OK;
/* check for PLLSAI2 Parameters used to output PLLSAI2CLK */
/* P, Q and R dividers are verified in each specific divider case below */
assert_param(IS_RCC_PLLSAI2SOURCE(PllSai2->PLLSAI2Source));
assert_param(IS_RCC_PLLSAI2M_VALUE(PllSai2->PLLSAI2M));
assert_param(IS_RCC_PLLSAI2N_VALUE(PllSai2->PLLSAI2N));
assert_param(IS_RCC_PLLSAI2CLOCKOUT_VALUE(PllSai2->PLLSAI2ClockOut));
/* Check that PLLSAI2 clock source and divider M can be applied */
if(__HAL_RCC_GET_PLL_OSCSOURCE() != RCC_PLLSOURCE_NONE)
{
/* PLL clock source and divider M already set, check that no request for change */
if((__HAL_RCC_GET_PLL_OSCSOURCE() != PllSai2->PLLSAI2Source)
||
(PllSai2->PLLSAI2Source == RCC_PLLSOURCE_NONE)
#if !defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT)
||
(((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U) != PllSai2->PLLSAI2M)
#endif
)
{
status = HAL_ERROR;
}
}
else
{
/* Check PLLSAI2 clock source availability */
switch(PllSai2->PLLSAI2Source)
{
case RCC_PLLSOURCE_MSI:
if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_MSIRDY))
{
status = HAL_ERROR;
}
break;
case RCC_PLLSOURCE_HSI:
if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSIRDY))
{
status = HAL_ERROR;
}
break;
case RCC_PLLSOURCE_HSE:
if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSERDY))
{
if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSEBYP))
{
status = HAL_ERROR;
}
}
break;
default:
status = HAL_ERROR;
break;
}
if(status == HAL_OK)
{
#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT)
/* Set PLLSAI2 clock source */
MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, PllSai2->PLLSAI2Source);
#else
/* Set PLLSAI2 clock source and divider M */
MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLM, PllSai2->PLLSAI2Source | (PllSai2->PLLSAI2M - 1U) << RCC_PLLCFGR_PLLM_Pos);
#endif
}
}
if(status == HAL_OK)
{
/* Disable the PLLSAI2 */
__HAL_RCC_PLLSAI2_DISABLE();
/* Get Start Tick*/
tickstart = HAL_GetTick();
/* Wait till PLLSAI2 is ready to be updated */
while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) != 0U)
{
if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE)
{
status = HAL_TIMEOUT;
break;
}
}
if(status == HAL_OK)
{
if(Divider == DIVIDER_P_UPDATE)
{
assert_param(IS_RCC_PLLSAI2P_VALUE(PllSai2->PLLSAI2P));
#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT)
/* Configure the PLLSAI2 Division factor M, P and Multiplication factor N*/
#if defined(RCC_PLLSAI2P_DIV_2_31_SUPPORT)
MODIFY_REG(RCC->PLLSAI2CFGR,
RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2PDIV | RCC_PLLSAI2CFGR_PLLSAI2M,
(PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) |
(PllSai2->PLLSAI2P << RCC_PLLSAI2CFGR_PLLSAI2PDIV_Pos) |
((PllSai2->PLLSAI2M - 1U) << RCC_PLLSAI2CFGR_PLLSAI2M_Pos));
#else
MODIFY_REG(RCC->PLLSAI2CFGR,
RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2P | RCC_PLLSAI2CFGR_PLLSAI2M,
(PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) |
((PllSai2->PLLSAI2P >> 4U) << RCC_PLLSAI2CFGR_PLLSAI2P_Pos) |
((PllSai2->PLLSAI2M - 1U) << RCC_PLLSAI2CFGR_PLLSAI2M_Pos));
#endif /* RCC_PLLSAI2P_DIV_2_31_SUPPORT */
#else
/* Configure the PLLSAI2 Division factor P and Multiplication factor N*/
#if defined(RCC_PLLSAI2P_DIV_2_31_SUPPORT)
MODIFY_REG(RCC->PLLSAI2CFGR,
RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2PDIV,
(PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) |
(PllSai2->PLLSAI2P << RCC_PLLSAI2CFGR_PLLSAI2PDIV_Pos));
#else
MODIFY_REG(RCC->PLLSAI2CFGR,
RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2P,
(PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) |
((PllSai2->PLLSAI2P >> 4U) << RCC_PLLSAI2CFGR_PLLSAI2P_Pos));
#endif /* RCC_PLLSAI2P_DIV_2_31_SUPPORT */
#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT */
}
#if defined(RCC_PLLSAI2Q_DIV_SUPPORT)
else if(Divider == DIVIDER_Q_UPDATE)
{
assert_param(IS_RCC_PLLSAI2Q_VALUE(PllSai2->PLLSAI2Q));
#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT)
/* Configure the PLLSAI2 Division factor M, Q and Multiplication factor N*/
MODIFY_REG(RCC->PLLSAI2CFGR,
RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2Q | RCC_PLLSAI2CFGR_PLLSAI2M,
(PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) |
(((PllSai2->PLLSAI2Q >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2Q_Pos) |
((PllSai2->PLLSAI2M - 1U) << RCC_PLLSAI2CFGR_PLLSAI2M_Pos));
#else
/* Configure the PLLSAI2 Division factor Q and Multiplication factor N*/
MODIFY_REG(RCC->PLLSAI2CFGR,
RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2Q,
(PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) |
(((PllSai2->PLLSAI2Q >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2Q_Pos));
#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT */
}
#endif /* RCC_PLLSAI2Q_DIV_SUPPORT */
else
{
assert_param(IS_RCC_PLLSAI2R_VALUE(PllSai2->PLLSAI2R));
#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT)
/* Configure the PLLSAI2 Division factor M, R and Multiplication factor N*/
MODIFY_REG(RCC->PLLSAI2CFGR,
RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2R | RCC_PLLSAI2CFGR_PLLSAI2M,
(PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) |
(((PllSai2->PLLSAI2R >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2R_Pos) |
((PllSai2->PLLSAI2M - 1U) << RCC_PLLSAI2CFGR_PLLSAI2M_Pos));
#else
/* Configure the PLLSAI2 Division factor R and Multiplication factor N*/
MODIFY_REG(RCC->PLLSAI2CFGR,
RCC_PLLSAI2CFGR_PLLSAI2N | RCC_PLLSAI2CFGR_PLLSAI2R,
(PllSai2->PLLSAI2N << RCC_PLLSAI2CFGR_PLLSAI2N_Pos) |
(((PllSai2->PLLSAI2R >> 1U) - 1U) << RCC_PLLSAI2CFGR_PLLSAI2R_Pos));
#endif /* RCC_PLLSAI2M_DIV_1_16_SUPPORT */
}
/* Enable the PLLSAI2 again by setting PLLSAI2ON to 1*/
__HAL_RCC_PLLSAI2_ENABLE();
/* Get Start Tick*/
tickstart = HAL_GetTick();
/* Wait till PLLSAI2 is ready */
while(READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) == 0U)
{
if((HAL_GetTick() - tickstart) > PLLSAI2_TIMEOUT_VALUE)
{
status = HAL_TIMEOUT;
break;
}
}
if(status == HAL_OK)
{
/* Configure the PLLSAI2 Clock output(s) */
__HAL_RCC_PLLSAI2CLKOUT_ENABLE(PllSai2->PLLSAI2ClockOut);
}
}
}
return status;
}
#endif /* RCC_PLLSAI2_SUPPORT */
#if defined(SAI1)
static uint32_t RCCEx_GetSAIxPeriphCLKFreq(uint32_t PeriphClk, uint32_t InputFrequency)
{
uint32_t frequency = 0U;
uint32_t srcclk = 0U;
uint32_t pllvco, plln; /* no init needed */
#if defined(RCC_PLLP_SUPPORT)
uint32_t pllp = 0U;
#endif /* RCC_PLLP_SUPPORT */
/* Handle SAIx */
if(PeriphClk == RCC_PERIPHCLK_SAI1)
{
srcclk = __HAL_RCC_GET_SAI1_SOURCE();
if(srcclk == RCC_SAI1CLKSOURCE_PIN)
{
frequency = EXTERNAL_SAI1_CLOCK_VALUE;
}
/* Else, PLL clock output to check below */
}
#if defined(SAI2)
else
{
if(PeriphClk == RCC_PERIPHCLK_SAI2)
{
srcclk = __HAL_RCC_GET_SAI2_SOURCE();
if(srcclk == RCC_SAI2CLKSOURCE_PIN)
{
frequency = EXTERNAL_SAI2_CLOCK_VALUE;
}
/* Else, PLL clock output to check below */
}
}
#endif /* SAI2 */
if(frequency == 0U)
{
pllvco = InputFrequency;
#if defined(SAI2)
if((srcclk == RCC_SAI1CLKSOURCE_PLL) || (srcclk == RCC_SAI2CLKSOURCE_PLL))
{
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLRDY) && (__HAL_RCC_GET_PLLCLKOUT_CONFIG(RCC_PLL_SAI3CLK) != 0U))
{
/* f(PLL Source) / PLLM */
pllvco = (pllvco / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U));
/* f(PLLSAI3CLK) = f(VCO input) * PLLN / PLLP */
plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos;
#if defined(RCC_PLLP_DIV_2_31_SUPPORT)
pllp = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLPDIV) >> RCC_PLLCFGR_PLLPDIV_Pos;
#endif
if(pllp == 0U)
{
if(READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLP) != 0U)
{
pllp = 17U;
}
else
{
pllp = 7U;
}
}
frequency = (pllvco * plln) / pllp;
}
}
else if(srcclk == 0U) /* RCC_SAI1CLKSOURCE_PLLSAI1 || RCC_SAI2CLKSOURCE_PLLSAI1 */
{
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLSAI1RDY) && (__HAL_RCC_GET_PLLSAI1CLKOUT_CONFIG(RCC_PLLSAI1_SAI1CLK) != 0U))
{
#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT)
/* PLLSAI1M exists: apply PLLSAI1M divider for PLLSAI1 output computation */
/* f(PLLSAI1 Source) / PLLSAI1M */
pllvco = (pllvco / ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M) >> RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + 1U));
#else
/* f(PLL Source) / PLLM */
pllvco = (pllvco / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U));
#endif
/* f(PLLSAI1CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1P */
plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos;
#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT)
pllp = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1PDIV) >> RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos;
#endif
if(pllp == 0U)
{
if(READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1P) != 0U)
{
pllp = 17U;
}
else
{
pllp = 7U;
}
}
frequency = (pllvco * plln) / pllp;
}
}
#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
else if((srcclk == RCC_SAI1CLKSOURCE_HSI) || (srcclk == RCC_SAI2CLKSOURCE_HSI))
{
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))
{
frequency = HSI_VALUE;
}
}
#endif /* STM32L4P5xx || STM32L4Q5xx || STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */
#else
if(srcclk == RCC_SAI1CLKSOURCE_PLL)
{
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLRDY) && (__HAL_RCC_GET_PLLCLKOUT_CONFIG(RCC_PLL_SAI2CLK) != 0U))
{
/* f(PLL Source) / PLLM */
pllvco = (pllvco / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U));
/* f(PLLSAI2CLK) = f(VCO input) * PLLN / PLLP */
plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos;
#if defined(RCC_PLLP_DIV_2_31_SUPPORT)
pllp = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLPDIV) >> RCC_PLLCFGR_PLLPDIV_Pos;
#endif
if(pllp == 0U)
{
if(READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLP) != 0U)
{
pllp = 17U;
}
else
{
pllp = 7U;
}
}
frequency = (pllvco * plln) / pllp;
}
else if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))
{
/* HSI automatically selected as clock source if PLLs not enabled */
frequency = HSI_VALUE;
}
else
{
/* No clock source, frequency default init at 0 */
}
}
else if(srcclk == RCC_SAI1CLKSOURCE_PLLSAI1)
{
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLSAI1RDY) && (__HAL_RCC_GET_PLLSAI1CLKOUT_CONFIG(RCC_PLLSAI1_SAI1CLK) != 0U))
{
#if defined(RCC_PLLSAI1M_DIV_1_16_SUPPORT)
/* PLLSAI1M exists: apply PLLSAI1M divider for PLLSAI1 output computation */
/* f(PLLSAI1 Source) / PLLSAI1M */
pllvco = (pllvco / ((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1M) >> RCC_PLLSAI1CFGR_PLLSAI1M_Pos) + 1U));
#else
/* f(PLL Source) / PLLM */
pllvco = (pllvco / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U));
#endif
/* f(PLLSAI1CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1P */
plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos;
#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT)
pllp = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1PDIV) >> RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos;
#endif
if(pllp == 0U)
{
if(READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1P) != 0U)
{
pllp = 17U;
}
else
{
pllp = 7U;
}
}
frequency = (pllvco * plln) / pllp;
}
else if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))
{
/* HSI automatically selected as clock source if PLLs not enabled */
frequency = HSI_VALUE;
}
else
{
/* No clock source, frequency default init at 0 */
}
}
#endif /* SAI2 */
#if defined(RCC_PLLSAI2_SUPPORT)
else if((srcclk == RCC_SAI1CLKSOURCE_PLLSAI2) || (srcclk == RCC_SAI2CLKSOURCE_PLLSAI2))
{
if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLSAI2RDY) && (__HAL_RCC_GET_PLLSAI2CLKOUT_CONFIG(RCC_PLLSAI2_SAI2CLK) != 0U))
{
#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT)
/* PLLSAI2M exists: apply PLLSAI2M divider for PLLSAI2 output computation */
/* f(PLLSAI2 Source) / PLLSAI2M */
pllvco = (pllvco / ((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2M) >> RCC_PLLSAI2CFGR_PLLSAI2M_Pos) + 1U));
#else
/* f(PLL Source) / PLLM */
pllvco = (pllvco / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U));
#endif
/* f(PLLSAI2CLK) = f(VCOSAI2 input) * PLLSAI2N / PLLSAI2P */
plln = READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N) >> RCC_PLLSAI2CFGR_PLLSAI2N_Pos;
#if defined(RCC_PLLSAI2P_DIV_2_31_SUPPORT)
pllp = READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2PDIV) >> RCC_PLLSAI2CFGR_PLLSAI2PDIV_Pos;
#endif
if(pllp == 0U)
{
if(READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2P) != 0U)
{
pllp = 17U;
}
else
{
pllp = 7U;
}
}
frequency = (pllvco * plln) / pllp;
}
}
#endif /* RCC_PLLSAI2_SUPPORT */
else
{
/* No clock source, frequency default init at 0 */
}
}
return frequency;
}
#endif /* SAI1 */
/**
* @}
*/
/**
* @}
*/
#endif /* HAL_RCC_MODULE_ENABLED */
/**
* @}
*/
/**
* @}
*/

File diff suppressed because it is too large Load Diff

View File

@@ -1,2838 +0,0 @@
/**
******************************************************************************
* @file stm32l4xx_hal_tim_ex.c
* @author MCD Application Team
* @brief TIM HAL module driver.
* This file provides firmware functions to manage the following
* functionalities of the Timer Extended peripheral:
* + Time Hall Sensor Interface Initialization
* + Time Hall Sensor Interface Start
* + Time Complementary signal break and dead time configuration
* + Time Master and Slave synchronization configuration
* + Time Output Compare/PWM Channel Configuration (for channels 5 and 6)
* + Time OCRef clear configuration
* + Timer remapping capabilities configuration
******************************************************************************
* @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.
*
******************************************************************************
@verbatim
==============================================================================
##### TIMER Extended features #####
==============================================================================
[..]
The Timer Extended features include:
(#) Complementary outputs with programmable dead-time for :
(++) Output Compare
(++) PWM generation (Edge and Center-aligned Mode)
(++) One-pulse mode output
(#) Synchronization circuit to control the timer with external signals and to
interconnect several timers together.
(#) Break input to put the timer output signals in reset state or in a known state.
(#) Supports incremental (quadrature) encoder and hall-sensor circuitry for
positioning purposes
##### How to use this driver #####
==============================================================================
[..]
(#) Initialize the TIM low level resources by implementing the following functions
depending on the selected feature:
(++) Hall Sensor output : HAL_TIMEx_HallSensor_MspInit()
(#) Initialize the TIM low level resources :
(##) Enable the TIM interface clock using __HAL_RCC_TIMx_CLK_ENABLE();
(##) TIM pins configuration
(+++) Enable the clock for the TIM GPIOs using the following function:
__HAL_RCC_GPIOx_CLK_ENABLE();
(+++) Configure these TIM pins in Alternate function mode using HAL_GPIO_Init();
(#) The external Clock can be configured, if needed (the default clock is the
internal clock from the APBx), using the following function:
HAL_TIM_ConfigClockSource, the clock configuration should be done before
any start function.
(#) Configure the TIM in the desired functioning mode using one of the
initialization function of this driver:
(++) HAL_TIMEx_HallSensor_Init() and HAL_TIMEx_ConfigCommutEvent(): to use the
Timer Hall Sensor Interface and the commutation event with the corresponding
Interrupt and DMA request if needed (Note that One Timer is used to interface
with the Hall sensor Interface and another Timer should be used to use
the commutation event).
(#) Activate the TIM peripheral using one of the start functions:
(++) Complementary Output Compare : HAL_TIMEx_OCN_Start(), HAL_TIMEx_OCN_Start_DMA(),
HAL_TIMEx_OCN_Start_IT()
(++) Complementary PWM generation : HAL_TIMEx_PWMN_Start(), HAL_TIMEx_PWMN_Start_DMA(),
HAL_TIMEx_PWMN_Start_IT()
(++) Complementary One-pulse mode output : HAL_TIMEx_OnePulseN_Start(), HAL_TIMEx_OnePulseN_Start_IT()
(++) Hall Sensor output : HAL_TIMEx_HallSensor_Start(), HAL_TIMEx_HallSensor_Start_DMA(),
HAL_TIMEx_HallSensor_Start_IT().
@endverbatim
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32l4xx_hal.h"
/** @addtogroup STM32L4xx_HAL_Driver
* @{
*/
/** @defgroup TIMEx TIMEx
* @brief TIM Extended HAL module driver
* @{
*/
#ifdef HAL_TIM_MODULE_ENABLED
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
static void TIM_DMADelayPulseNCplt(DMA_HandleTypeDef *hdma);
static void TIM_DMAErrorCCxN(DMA_HandleTypeDef *hdma);
static void TIM_CCxNChannelCmd(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t ChannelNState);
/* Exported functions --------------------------------------------------------*/
/** @defgroup TIMEx_Exported_Functions TIM Extended Exported Functions
* @{
*/
/** @defgroup TIMEx_Exported_Functions_Group1 Extended Timer Hall Sensor functions
* @brief Timer Hall Sensor functions
*
@verbatim
==============================================================================
##### Timer Hall Sensor functions #####
==============================================================================
[..]
This section provides functions allowing to:
(+) Initialize and configure TIM HAL Sensor.
(+) De-initialize TIM HAL Sensor.
(+) Start the Hall Sensor Interface.
(+) Stop the Hall Sensor Interface.
(+) Start the Hall Sensor Interface and enable interrupts.
(+) Stop the Hall Sensor Interface and disable interrupts.
(+) Start the Hall Sensor Interface and enable DMA transfers.
(+) Stop the Hall Sensor Interface and disable DMA transfers.
@endverbatim
* @{
*/
/**
* @brief Initializes the TIM Hall Sensor Interface and initialize the associated handle.
* @note When the timer instance is initialized in Hall Sensor Interface mode,
* timer channels 1 and channel 2 are reserved and cannot be used for
* other purpose.
* @param htim TIM Hall Sensor Interface handle
* @param sConfig TIM Hall Sensor configuration structure
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_HallSensor_Init(TIM_HandleTypeDef *htim, TIM_HallSensor_InitTypeDef *sConfig)
{
TIM_OC_InitTypeDef OC_Config;
/* Check the TIM handle allocation */
if (htim == NULL)
{
return HAL_ERROR;
}
/* Check the parameters */
assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode));
assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision));
assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload));
assert_param(IS_TIM_IC_POLARITY(sConfig->IC1Polarity));
assert_param(IS_TIM_IC_PRESCALER(sConfig->IC1Prescaler));
assert_param(IS_TIM_IC_FILTER(sConfig->IC1Filter));
if (htim->State == HAL_TIM_STATE_RESET)
{
/* Allocate lock resource and initialize it */
htim->Lock = HAL_UNLOCKED;
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
/* Reset interrupt callbacks to legacy week callbacks */
TIM_ResetCallback(htim);
if (htim->HallSensor_MspInitCallback == NULL)
{
htim->HallSensor_MspInitCallback = HAL_TIMEx_HallSensor_MspInit;
}
/* Init the low level hardware : GPIO, CLOCK, NVIC */
htim->HallSensor_MspInitCallback(htim);
#else
/* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
HAL_TIMEx_HallSensor_MspInit(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
}
/* Set the TIM state */
htim->State = HAL_TIM_STATE_BUSY;
/* Configure the Time base in the Encoder Mode */
TIM_Base_SetConfig(htim->Instance, &htim->Init);
/* Configure the Channel 1 as Input Channel to interface with the three Outputs of the Hall sensor */
TIM_TI1_SetConfig(htim->Instance, sConfig->IC1Polarity, TIM_ICSELECTION_TRC, sConfig->IC1Filter);
/* Reset the IC1PSC Bits */
htim->Instance->CCMR1 &= ~TIM_CCMR1_IC1PSC;
/* Set the IC1PSC value */
htim->Instance->CCMR1 |= sConfig->IC1Prescaler;
/* Enable the Hall sensor interface (XOR function of the three inputs) */
htim->Instance->CR2 |= TIM_CR2_TI1S;
/* Select the TIM_TS_TI1F_ED signal as Input trigger for the TIM */
htim->Instance->SMCR &= ~TIM_SMCR_TS;
htim->Instance->SMCR |= TIM_TS_TI1F_ED;
/* Use the TIM_TS_TI1F_ED signal to reset the TIM counter each edge detection */
htim->Instance->SMCR &= ~TIM_SMCR_SMS;
htim->Instance->SMCR |= TIM_SLAVEMODE_RESET;
/* Program channel 2 in PWM 2 mode with the desired Commutation_Delay*/
OC_Config.OCFastMode = TIM_OCFAST_DISABLE;
OC_Config.OCIdleState = TIM_OCIDLESTATE_RESET;
OC_Config.OCMode = TIM_OCMODE_PWM2;
OC_Config.OCNIdleState = TIM_OCNIDLESTATE_RESET;
OC_Config.OCNPolarity = TIM_OCNPOLARITY_HIGH;
OC_Config.OCPolarity = TIM_OCPOLARITY_HIGH;
OC_Config.Pulse = sConfig->Commutation_Delay;
TIM_OC2_SetConfig(htim->Instance, &OC_Config);
/* Select OC2REF as trigger output on TRGO: write the MMS bits in the TIMx_CR2
register to 101 */
htim->Instance->CR2 &= ~TIM_CR2_MMS;
htim->Instance->CR2 |= TIM_TRGO_OC2REF;
/* Initialize the DMA burst operation state */
htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
/* Initialize the TIM channels state */
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
/* Initialize the TIM state*/
htim->State = HAL_TIM_STATE_READY;
return HAL_OK;
}
/**
* @brief DeInitializes the TIM Hall Sensor interface
* @param htim TIM Hall Sensor Interface handle
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_HallSensor_DeInit(TIM_HandleTypeDef *htim)
{
/* Check the parameters */
assert_param(IS_TIM_INSTANCE(htim->Instance));
htim->State = HAL_TIM_STATE_BUSY;
/* Disable the TIM Peripheral Clock */
__HAL_TIM_DISABLE(htim);
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
if (htim->HallSensor_MspDeInitCallback == NULL)
{
htim->HallSensor_MspDeInitCallback = HAL_TIMEx_HallSensor_MspDeInit;
}
/* DeInit the low level hardware */
htim->HallSensor_MspDeInitCallback(htim);
#else
/* DeInit the low level hardware: GPIO, CLOCK, NVIC */
HAL_TIMEx_HallSensor_MspDeInit(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
/* Change the DMA burst operation state */
htim->DMABurstState = HAL_DMA_BURST_STATE_RESET;
/* Change the TIM channels state */
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_RESET);
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_RESET);
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_RESET);
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_RESET);
/* Change TIM state */
htim->State = HAL_TIM_STATE_RESET;
/* Release Lock */
__HAL_UNLOCK(htim);
return HAL_OK;
}
/**
* @brief Initializes the TIM Hall Sensor MSP.
* @param htim TIM Hall Sensor Interface handle
* @retval None
*/
__weak void HAL_TIMEx_HallSensor_MspInit(TIM_HandleTypeDef *htim)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(htim);
/* NOTE : This function should not be modified, when the callback is needed,
the HAL_TIMEx_HallSensor_MspInit could be implemented in the user file
*/
}
/**
* @brief DeInitializes TIM Hall Sensor MSP.
* @param htim TIM Hall Sensor Interface handle
* @retval None
*/
__weak void HAL_TIMEx_HallSensor_MspDeInit(TIM_HandleTypeDef *htim)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(htim);
/* NOTE : This function should not be modified, when the callback is needed,
the HAL_TIMEx_HallSensor_MspDeInit could be implemented in the user file
*/
}
/**
* @brief Starts the TIM Hall Sensor Interface.
* @param htim TIM Hall Sensor Interface handle
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start(TIM_HandleTypeDef *htim)
{
uint32_t tmpsmcr;
HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
/* Check the parameters */
assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
/* Check the TIM channels state */
if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
|| (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
|| (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
|| (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
{
return HAL_ERROR;
}
/* Set the TIM channels state */
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
/* Enable the Input Capture channel 1
(in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
TIM_CHANNEL_2 and TIM_CHANNEL_3) */
TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
/* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
{
tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
{
__HAL_TIM_ENABLE(htim);
}
}
else
{
__HAL_TIM_ENABLE(htim);
}
/* Return function status */
return HAL_OK;
}
/**
* @brief Stops the TIM Hall sensor Interface.
* @param htim TIM Hall Sensor Interface handle
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop(TIM_HandleTypeDef *htim)
{
/* Check the parameters */
assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
/* Disable the Input Capture channels 1, 2 and 3
(in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
TIM_CHANNEL_2 and TIM_CHANNEL_3) */
TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
/* Disable the Peripheral */
__HAL_TIM_DISABLE(htim);
/* Set the TIM channels state */
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
/* Return function status */
return HAL_OK;
}
/**
* @brief Starts the TIM Hall Sensor Interface in interrupt mode.
* @param htim TIM Hall Sensor Interface handle
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start_IT(TIM_HandleTypeDef *htim)
{
uint32_t tmpsmcr;
HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
/* Check the parameters */
assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
/* Check the TIM channels state */
if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
|| (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
|| (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
|| (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
{
return HAL_ERROR;
}
/* Set the TIM channels state */
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
/* Enable the capture compare Interrupts 1 event */
__HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
/* Enable the Input Capture channel 1
(in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
TIM_CHANNEL_2 and TIM_CHANNEL_3) */
TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
/* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
{
tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
{
__HAL_TIM_ENABLE(htim);
}
}
else
{
__HAL_TIM_ENABLE(htim);
}
/* Return function status */
return HAL_OK;
}
/**
* @brief Stops the TIM Hall Sensor Interface in interrupt mode.
* @param htim TIM Hall Sensor Interface handle
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop_IT(TIM_HandleTypeDef *htim)
{
/* Check the parameters */
assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
/* Disable the Input Capture channel 1
(in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
TIM_CHANNEL_2 and TIM_CHANNEL_3) */
TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
/* Disable the capture compare Interrupts event */
__HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
/* Disable the Peripheral */
__HAL_TIM_DISABLE(htim);
/* Set the TIM channels state */
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
/* Return function status */
return HAL_OK;
}
/**
* @brief Starts the TIM Hall Sensor Interface in DMA mode.
* @param htim TIM Hall Sensor Interface handle
* @param pData The destination Buffer address.
* @param Length The length of data to be transferred from TIM peripheral to memory.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start_DMA(TIM_HandleTypeDef *htim, uint32_t *pData, uint16_t Length)
{
uint32_t tmpsmcr;
HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
/* Check the parameters */
assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
/* Set the TIM channel state */
if ((channel_1_state == HAL_TIM_CHANNEL_STATE_BUSY)
|| (complementary_channel_1_state == HAL_TIM_CHANNEL_STATE_BUSY))
{
return HAL_BUSY;
}
else if ((channel_1_state == HAL_TIM_CHANNEL_STATE_READY)
&& (complementary_channel_1_state == HAL_TIM_CHANNEL_STATE_READY))
{
if ((pData == NULL) && (Length > 0U))
{
return HAL_ERROR;
}
else
{
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
}
}
else
{
return HAL_ERROR;
}
/* Enable the Input Capture channel 1
(in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
TIM_CHANNEL_2 and TIM_CHANNEL_3) */
TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
/* Set the DMA Input Capture 1 Callbacks */
htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt;
htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
/* Set the DMA error callback */
htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
/* Enable the DMA channel for Capture 1*/
if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->CCR1, (uint32_t)pData, Length) != HAL_OK)
{
/* Return error status */
return HAL_ERROR;
}
/* Enable the capture compare 1 Interrupt */
__HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
/* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
{
tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
{
__HAL_TIM_ENABLE(htim);
}
}
else
{
__HAL_TIM_ENABLE(htim);
}
/* Return function status */
return HAL_OK;
}
/**
* @brief Stops the TIM Hall Sensor Interface in DMA mode.
* @param htim TIM Hall Sensor Interface handle
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop_DMA(TIM_HandleTypeDef *htim)
{
/* Check the parameters */
assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
/* Disable the Input Capture channel 1
(in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
TIM_CHANNEL_2 and TIM_CHANNEL_3) */
TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
/* Disable the capture compare Interrupts 1 event */
__HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
(void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
/* Disable the Peripheral */
__HAL_TIM_DISABLE(htim);
/* Set the TIM channel state */
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
/* Return function status */
return HAL_OK;
}
/**
* @}
*/
/** @defgroup TIMEx_Exported_Functions_Group2 Extended Timer Complementary Output Compare functions
* @brief Timer Complementary Output Compare functions
*
@verbatim
==============================================================================
##### Timer Complementary Output Compare functions #####
==============================================================================
[..]
This section provides functions allowing to:
(+) Start the Complementary Output Compare/PWM.
(+) Stop the Complementary Output Compare/PWM.
(+) Start the Complementary Output Compare/PWM and enable interrupts.
(+) Stop the Complementary Output Compare/PWM and disable interrupts.
(+) Start the Complementary Output Compare/PWM and enable DMA transfers.
(+) Stop the Complementary Output Compare/PWM and disable DMA transfers.
@endverbatim
* @{
*/
/**
* @brief Starts the TIM Output Compare signal generation on the complementary
* output.
* @param htim TIM Output Compare handle
* @param Channel TIM Channel to be enabled
* This parameter can be one of the following values:
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_OCN_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
{
uint32_t tmpsmcr;
/* Check the parameters */
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
/* Check the TIM complementary channel state */
if (TIM_CHANNEL_N_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
{
return HAL_ERROR;
}
/* Set the TIM complementary channel state */
TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
/* Enable the Capture compare channel N */
TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
/* Enable the Main Output */
__HAL_TIM_MOE_ENABLE(htim);
/* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
{
tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
{
__HAL_TIM_ENABLE(htim);
}
}
else
{
__HAL_TIM_ENABLE(htim);
}
/* Return function status */
return HAL_OK;
}
/**
* @brief Stops the TIM Output Compare signal generation on the complementary
* output.
* @param htim TIM handle
* @param Channel TIM Channel to be disabled
* This parameter can be one of the following values:
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_OCN_Stop(TIM_HandleTypeDef *htim, uint32_t Channel)
{
/* Check the parameters */
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
/* Disable the Capture compare channel N */
TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
/* Disable the Main Output */
__HAL_TIM_MOE_DISABLE(htim);
/* Disable the Peripheral */
__HAL_TIM_DISABLE(htim);
/* Set the TIM complementary channel state */
TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
/* Return function status */
return HAL_OK;
}
/**
* @brief Starts the TIM Output Compare signal generation in interrupt mode
* on the complementary output.
* @param htim TIM OC handle
* @param Channel TIM Channel to be enabled
* This parameter can be one of the following values:
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_OCN_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
{
HAL_StatusTypeDef status = HAL_OK;
uint32_t tmpsmcr;
/* Check the parameters */
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
/* Check the TIM complementary channel state */
if (TIM_CHANNEL_N_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
{
return HAL_ERROR;
}
/* Set the TIM complementary channel state */
TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
switch (Channel)
{
case TIM_CHANNEL_1:
{
/* Enable the TIM Output Compare interrupt */
__HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
break;
}
case TIM_CHANNEL_2:
{
/* Enable the TIM Output Compare interrupt */
__HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
break;
}
case TIM_CHANNEL_3:
{
/* Enable the TIM Output Compare interrupt */
__HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3);
break;
}
default:
status = HAL_ERROR;
break;
}
if (status == HAL_OK)
{
/* Enable the TIM Break interrupt */
__HAL_TIM_ENABLE_IT(htim, TIM_IT_BREAK);
/* Enable the Capture compare channel N */
TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
/* Enable the Main Output */
__HAL_TIM_MOE_ENABLE(htim);
/* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
{
tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
{
__HAL_TIM_ENABLE(htim);
}
}
else
{
__HAL_TIM_ENABLE(htim);
}
}
/* Return function status */
return status;
}
/**
* @brief Stops the TIM Output Compare signal generation in interrupt mode
* on the complementary output.
* @param htim TIM Output Compare handle
* @param Channel TIM Channel to be disabled
* This parameter can be one of the following values:
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_OCN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
{
HAL_StatusTypeDef status = HAL_OK;
uint32_t tmpccer;
/* Check the parameters */
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
switch (Channel)
{
case TIM_CHANNEL_1:
{
/* Disable the TIM Output Compare interrupt */
__HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
break;
}
case TIM_CHANNEL_2:
{
/* Disable the TIM Output Compare interrupt */
__HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
break;
}
case TIM_CHANNEL_3:
{
/* Disable the TIM Output Compare interrupt */
__HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3);
break;
}
default:
status = HAL_ERROR;
break;
}
if (status == HAL_OK)
{
/* Disable the Capture compare channel N */
TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
/* Disable the TIM Break interrupt (only if no more channel is active) */
tmpccer = htim->Instance->CCER;
if ((tmpccer & (TIM_CCER_CC1NE | TIM_CCER_CC2NE | TIM_CCER_CC3NE)) == (uint32_t)RESET)
{
__HAL_TIM_DISABLE_IT(htim, TIM_IT_BREAK);
}
/* Disable the Main Output */
__HAL_TIM_MOE_DISABLE(htim);
/* Disable the Peripheral */
__HAL_TIM_DISABLE(htim);
/* Set the TIM complementary channel state */
TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
}
/* Return function status */
return status;
}
/**
* @brief Starts the TIM Output Compare signal generation in DMA mode
* on the complementary output.
* @param htim TIM Output Compare handle
* @param Channel TIM Channel to be enabled
* This parameter can be one of the following values:
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
* @param pData The source Buffer address.
* @param Length The length of data to be transferred from memory to TIM peripheral
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_OCN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length)
{
HAL_StatusTypeDef status = HAL_OK;
uint32_t tmpsmcr;
/* Check the parameters */
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
/* Set the TIM complementary channel state */
if (TIM_CHANNEL_N_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_BUSY)
{
return HAL_BUSY;
}
else if (TIM_CHANNEL_N_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_READY)
{
if ((pData == NULL) && (Length > 0U))
{
return HAL_ERROR;
}
else
{
TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
}
}
else
{
return HAL_ERROR;
}
switch (Channel)
{
case TIM_CHANNEL_1:
{
/* Set the DMA compare callbacks */
htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseNCplt;
htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
/* Set the DMA error callback */
htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAErrorCCxN ;
/* Enable the DMA channel */
if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->CCR1,
Length) != HAL_OK)
{
/* Return error status */
return HAL_ERROR;
}
/* Enable the TIM Output Compare DMA request */
__HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
break;
}
case TIM_CHANNEL_2:
{
/* Set the DMA compare callbacks */
htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseNCplt;
htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
/* Set the DMA error callback */
htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAErrorCCxN ;
/* Enable the DMA channel */
if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)pData, (uint32_t)&htim->Instance->CCR2,
Length) != HAL_OK)
{
/* Return error status */
return HAL_ERROR;
}
/* Enable the TIM Output Compare DMA request */
__HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
break;
}
case TIM_CHANNEL_3:
{
/* Set the DMA compare callbacks */
htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseNCplt;
htim->hdma[TIM_DMA_ID_CC3]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
/* Set the DMA error callback */
htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAErrorCCxN ;
/* Enable the DMA channel */
if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)pData, (uint32_t)&htim->Instance->CCR3,
Length) != HAL_OK)
{
/* Return error status */
return HAL_ERROR;
}
/* Enable the TIM Output Compare DMA request */
__HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3);
break;
}
default:
status = HAL_ERROR;
break;
}
if (status == HAL_OK)
{
/* Enable the Capture compare channel N */
TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
/* Enable the Main Output */
__HAL_TIM_MOE_ENABLE(htim);
/* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
{
tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
{
__HAL_TIM_ENABLE(htim);
}
}
else
{
__HAL_TIM_ENABLE(htim);
}
}
/* Return function status */
return status;
}
/**
* @brief Stops the TIM Output Compare signal generation in DMA mode
* on the complementary output.
* @param htim TIM Output Compare handle
* @param Channel TIM Channel to be disabled
* This parameter can be one of the following values:
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_OCN_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check the parameters */
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
switch (Channel)
{
case TIM_CHANNEL_1:
{
/* Disable the TIM Output Compare DMA request */
__HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
(void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
break;
}
case TIM_CHANNEL_2:
{
/* Disable the TIM Output Compare DMA request */
__HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
(void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
break;
}
case TIM_CHANNEL_3:
{
/* Disable the TIM Output Compare DMA request */
__HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3);
(void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC3]);
break;
}
default:
status = HAL_ERROR;
break;
}
if (status == HAL_OK)
{
/* Disable the Capture compare channel N */
TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
/* Disable the Main Output */
__HAL_TIM_MOE_DISABLE(htim);
/* Disable the Peripheral */
__HAL_TIM_DISABLE(htim);
/* Set the TIM complementary channel state */
TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
}
/* Return function status */
return status;
}
/**
* @}
*/
/** @defgroup TIMEx_Exported_Functions_Group3 Extended Timer Complementary PWM functions
* @brief Timer Complementary PWM functions
*
@verbatim
==============================================================================
##### Timer Complementary PWM functions #####
==============================================================================
[..]
This section provides functions allowing to:
(+) Start the Complementary PWM.
(+) Stop the Complementary PWM.
(+) Start the Complementary PWM and enable interrupts.
(+) Stop the Complementary PWM and disable interrupts.
(+) Start the Complementary PWM and enable DMA transfers.
(+) Stop the Complementary PWM and disable DMA transfers.
(+) Start the Complementary Input Capture measurement.
(+) Stop the Complementary Input Capture.
(+) Start the Complementary Input Capture and enable interrupts.
(+) Stop the Complementary Input Capture and disable interrupts.
(+) Start the Complementary Input Capture and enable DMA transfers.
(+) Stop the Complementary Input Capture and disable DMA transfers.
(+) Start the Complementary One Pulse generation.
(+) Stop the Complementary One Pulse.
(+) Start the Complementary One Pulse and enable interrupts.
(+) Stop the Complementary One Pulse and disable interrupts.
@endverbatim
* @{
*/
/**
* @brief Starts the PWM signal generation on the complementary output.
* @param htim TIM handle
* @param Channel TIM Channel to be enabled
* This parameter can be one of the following values:
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_PWMN_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
{
uint32_t tmpsmcr;
/* Check the parameters */
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
/* Check the TIM complementary channel state */
if (TIM_CHANNEL_N_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
{
return HAL_ERROR;
}
/* Set the TIM complementary channel state */
TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
/* Enable the complementary PWM output */
TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
/* Enable the Main Output */
__HAL_TIM_MOE_ENABLE(htim);
/* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
{
tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
{
__HAL_TIM_ENABLE(htim);
}
}
else
{
__HAL_TIM_ENABLE(htim);
}
/* Return function status */
return HAL_OK;
}
/**
* @brief Stops the PWM signal generation on the complementary output.
* @param htim TIM handle
* @param Channel TIM Channel to be disabled
* This parameter can be one of the following values:
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop(TIM_HandleTypeDef *htim, uint32_t Channel)
{
/* Check the parameters */
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
/* Disable the complementary PWM output */
TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
/* Disable the Main Output */
__HAL_TIM_MOE_DISABLE(htim);
/* Disable the Peripheral */
__HAL_TIM_DISABLE(htim);
/* Set the TIM complementary channel state */
TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
/* Return function status */
return HAL_OK;
}
/**
* @brief Starts the PWM signal generation in interrupt mode on the
* complementary output.
* @param htim TIM handle
* @param Channel TIM Channel to be disabled
* This parameter can be one of the following values:
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
{
HAL_StatusTypeDef status = HAL_OK;
uint32_t tmpsmcr;
/* Check the parameters */
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
/* Check the TIM complementary channel state */
if (TIM_CHANNEL_N_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
{
return HAL_ERROR;
}
/* Set the TIM complementary channel state */
TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
switch (Channel)
{
case TIM_CHANNEL_1:
{
/* Enable the TIM Capture/Compare 1 interrupt */
__HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
break;
}
case TIM_CHANNEL_2:
{
/* Enable the TIM Capture/Compare 2 interrupt */
__HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
break;
}
case TIM_CHANNEL_3:
{
/* Enable the TIM Capture/Compare 3 interrupt */
__HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3);
break;
}
default:
status = HAL_ERROR;
break;
}
if (status == HAL_OK)
{
/* Enable the TIM Break interrupt */
__HAL_TIM_ENABLE_IT(htim, TIM_IT_BREAK);
/* Enable the complementary PWM output */
TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
/* Enable the Main Output */
__HAL_TIM_MOE_ENABLE(htim);
/* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
{
tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
{
__HAL_TIM_ENABLE(htim);
}
}
else
{
__HAL_TIM_ENABLE(htim);
}
}
/* Return function status */
return status;
}
/**
* @brief Stops the PWM signal generation in interrupt mode on the
* complementary output.
* @param htim TIM handle
* @param Channel TIM Channel to be disabled
* This parameter can be one of the following values:
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
{
HAL_StatusTypeDef status = HAL_OK;
uint32_t tmpccer;
/* Check the parameters */
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
switch (Channel)
{
case TIM_CHANNEL_1:
{
/* Disable the TIM Capture/Compare 1 interrupt */
__HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
break;
}
case TIM_CHANNEL_2:
{
/* Disable the TIM Capture/Compare 2 interrupt */
__HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
break;
}
case TIM_CHANNEL_3:
{
/* Disable the TIM Capture/Compare 3 interrupt */
__HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3);
break;
}
default:
status = HAL_ERROR;
break;
}
if (status == HAL_OK)
{
/* Disable the complementary PWM output */
TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
/* Disable the TIM Break interrupt (only if no more channel is active) */
tmpccer = htim->Instance->CCER;
if ((tmpccer & (TIM_CCER_CC1NE | TIM_CCER_CC2NE | TIM_CCER_CC3NE)) == (uint32_t)RESET)
{
__HAL_TIM_DISABLE_IT(htim, TIM_IT_BREAK);
}
/* Disable the Main Output */
__HAL_TIM_MOE_DISABLE(htim);
/* Disable the Peripheral */
__HAL_TIM_DISABLE(htim);
/* Set the TIM complementary channel state */
TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
}
/* Return function status */
return status;
}
/**
* @brief Starts the TIM PWM signal generation in DMA mode on the
* complementary output
* @param htim TIM handle
* @param Channel TIM Channel to be enabled
* This parameter can be one of the following values:
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
* @param pData The source Buffer address.
* @param Length The length of data to be transferred from memory to TIM peripheral
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length)
{
HAL_StatusTypeDef status = HAL_OK;
uint32_t tmpsmcr;
/* Check the parameters */
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
/* Set the TIM complementary channel state */
if (TIM_CHANNEL_N_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_BUSY)
{
return HAL_BUSY;
}
else if (TIM_CHANNEL_N_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_READY)
{
if ((pData == NULL) && (Length > 0U))
{
return HAL_ERROR;
}
else
{
TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
}
}
else
{
return HAL_ERROR;
}
switch (Channel)
{
case TIM_CHANNEL_1:
{
/* Set the DMA compare callbacks */
htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseNCplt;
htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
/* Set the DMA error callback */
htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAErrorCCxN ;
/* Enable the DMA channel */
if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->CCR1,
Length) != HAL_OK)
{
/* Return error status */
return HAL_ERROR;
}
/* Enable the TIM Capture/Compare 1 DMA request */
__HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
break;
}
case TIM_CHANNEL_2:
{
/* Set the DMA compare callbacks */
htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseNCplt;
htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
/* Set the DMA error callback */
htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAErrorCCxN ;
/* Enable the DMA channel */
if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)pData, (uint32_t)&htim->Instance->CCR2,
Length) != HAL_OK)
{
/* Return error status */
return HAL_ERROR;
}
/* Enable the TIM Capture/Compare 2 DMA request */
__HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
break;
}
case TIM_CHANNEL_3:
{
/* Set the DMA compare callbacks */
htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseNCplt;
htim->hdma[TIM_DMA_ID_CC3]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
/* Set the DMA error callback */
htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAErrorCCxN ;
/* Enable the DMA channel */
if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)pData, (uint32_t)&htim->Instance->CCR3,
Length) != HAL_OK)
{
/* Return error status */
return HAL_ERROR;
}
/* Enable the TIM Capture/Compare 3 DMA request */
__HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3);
break;
}
default:
status = HAL_ERROR;
break;
}
if (status == HAL_OK)
{
/* Enable the complementary PWM output */
TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
/* Enable the Main Output */
__HAL_TIM_MOE_ENABLE(htim);
/* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
{
tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
{
__HAL_TIM_ENABLE(htim);
}
}
else
{
__HAL_TIM_ENABLE(htim);
}
}
/* Return function status */
return status;
}
/**
* @brief Stops the TIM PWM signal generation in DMA mode on the complementary
* output
* @param htim TIM handle
* @param Channel TIM Channel to be disabled
* This parameter can be one of the following values:
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
{
HAL_StatusTypeDef status = HAL_OK;
/* Check the parameters */
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
switch (Channel)
{
case TIM_CHANNEL_1:
{
/* Disable the TIM Capture/Compare 1 DMA request */
__HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
(void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
break;
}
case TIM_CHANNEL_2:
{
/* Disable the TIM Capture/Compare 2 DMA request */
__HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
(void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
break;
}
case TIM_CHANNEL_3:
{
/* Disable the TIM Capture/Compare 3 DMA request */
__HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3);
(void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC3]);
break;
}
default:
status = HAL_ERROR;
break;
}
if (status == HAL_OK)
{
/* Disable the complementary PWM output */
TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
/* Disable the Main Output */
__HAL_TIM_MOE_DISABLE(htim);
/* Disable the Peripheral */
__HAL_TIM_DISABLE(htim);
/* Set the TIM complementary channel state */
TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
}
/* Return function status */
return status;
}
/**
* @}
*/
/** @defgroup TIMEx_Exported_Functions_Group4 Extended Timer Complementary One Pulse functions
* @brief Timer Complementary One Pulse functions
*
@verbatim
==============================================================================
##### Timer Complementary One Pulse functions #####
==============================================================================
[..]
This section provides functions allowing to:
(+) Start the Complementary One Pulse generation.
(+) Stop the Complementary One Pulse.
(+) Start the Complementary One Pulse and enable interrupts.
(+) Stop the Complementary One Pulse and disable interrupts.
@endverbatim
* @{
*/
/**
* @brief Starts the TIM One Pulse signal generation on the complementary
* output.
* @note OutputChannel must match the pulse output channel chosen when calling
* @ref HAL_TIM_OnePulse_ConfigChannel().
* @param htim TIM One Pulse handle
* @param OutputChannel pulse output channel to enable
* This parameter can be one of the following values:
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Start(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
{
uint32_t input_channel = (OutputChannel == TIM_CHANNEL_1) ? TIM_CHANNEL_2 : TIM_CHANNEL_1;
HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
/* Check the parameters */
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel));
/* Check the TIM channels state */
if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
|| (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
|| (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
|| (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
{
return HAL_ERROR;
}
/* Set the TIM channels state */
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
/* Enable the complementary One Pulse output channel and the Input Capture channel */
TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_ENABLE);
TIM_CCxChannelCmd(htim->Instance, input_channel, TIM_CCx_ENABLE);
/* Enable the Main Output */
__HAL_TIM_MOE_ENABLE(htim);
/* Return function status */
return HAL_OK;
}
/**
* @brief Stops the TIM One Pulse signal generation on the complementary
* output.
* @note OutputChannel must match the pulse output channel chosen when calling
* @ref HAL_TIM_OnePulse_ConfigChannel().
* @param htim TIM One Pulse handle
* @param OutputChannel pulse output channel to disable
* This parameter can be one of the following values:
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Stop(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
{
uint32_t input_channel = (OutputChannel == TIM_CHANNEL_1) ? TIM_CHANNEL_2 : TIM_CHANNEL_1;
/* Check the parameters */
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel));
/* Disable the complementary One Pulse output channel and the Input Capture channel */
TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_DISABLE);
TIM_CCxChannelCmd(htim->Instance, input_channel, TIM_CCx_DISABLE);
/* Disable the Main Output */
__HAL_TIM_MOE_DISABLE(htim);
/* Disable the Peripheral */
__HAL_TIM_DISABLE(htim);
/* Set the TIM channels state */
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
/* Return function status */
return HAL_OK;
}
/**
* @brief Starts the TIM One Pulse signal generation in interrupt mode on the
* complementary channel.
* @note OutputChannel must match the pulse output channel chosen when calling
* @ref HAL_TIM_OnePulse_ConfigChannel().
* @param htim TIM One Pulse handle
* @param OutputChannel pulse output channel to enable
* This parameter can be one of the following values:
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Start_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
{
uint32_t input_channel = (OutputChannel == TIM_CHANNEL_1) ? TIM_CHANNEL_2 : TIM_CHANNEL_1;
HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
/* Check the parameters */
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel));
/* Check the TIM channels state */
if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
|| (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
|| (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
|| (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
{
return HAL_ERROR;
}
/* Set the TIM channels state */
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
/* Enable the TIM Capture/Compare 1 interrupt */
__HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
/* Enable the TIM Capture/Compare 2 interrupt */
__HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
/* Enable the complementary One Pulse output channel and the Input Capture channel */
TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_ENABLE);
TIM_CCxChannelCmd(htim->Instance, input_channel, TIM_CCx_ENABLE);
/* Enable the Main Output */
__HAL_TIM_MOE_ENABLE(htim);
/* Return function status */
return HAL_OK;
}
/**
* @brief Stops the TIM One Pulse signal generation in interrupt mode on the
* complementary channel.
* @note OutputChannel must match the pulse output channel chosen when calling
* @ref HAL_TIM_OnePulse_ConfigChannel().
* @param htim TIM One Pulse handle
* @param OutputChannel pulse output channel to disable
* This parameter can be one of the following values:
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
{
uint32_t input_channel = (OutputChannel == TIM_CHANNEL_1) ? TIM_CHANNEL_2 : TIM_CHANNEL_1;
/* Check the parameters */
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel));
/* Disable the TIM Capture/Compare 1 interrupt */
__HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
/* Disable the TIM Capture/Compare 2 interrupt */
__HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
/* Disable the complementary One Pulse output channel and the Input Capture channel */
TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_DISABLE);
TIM_CCxChannelCmd(htim->Instance, input_channel, TIM_CCx_DISABLE);
/* Disable the Main Output */
__HAL_TIM_MOE_DISABLE(htim);
/* Disable the Peripheral */
__HAL_TIM_DISABLE(htim);
/* Set the TIM channels state */
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
/* Return function status */
return HAL_OK;
}
/**
* @}
*/
/** @defgroup TIMEx_Exported_Functions_Group5 Extended Peripheral Control functions
* @brief Peripheral Control functions
*
@verbatim
==============================================================================
##### Peripheral Control functions #####
==============================================================================
[..]
This section provides functions allowing to:
(+) Configure the commutation event in case of use of the Hall sensor interface.
(+) Configure Output channels for OC and PWM mode.
(+) Configure Complementary channels, break features and dead time.
(+) Configure Master synchronization.
(+) Configure timer remapping capabilities.
(+) Enable or disable channel grouping.
@endverbatim
* @{
*/
/**
* @brief Configure the TIM commutation event sequence.
* @note This function is mandatory to use the commutation event in order to
* update the configuration at each commutation detection on the TRGI input of the Timer,
* the typical use of this feature is with the use of another Timer(interface Timer)
* configured in Hall sensor interface, this interface Timer will generate the
* commutation at its TRGO output (connected to Timer used in this function) each time
* the TI1 of the Interface Timer detect a commutation at its input TI1.
* @param htim TIM handle
* @param InputTrigger the Internal trigger corresponding to the Timer Interfacing with the Hall sensor
* This parameter can be one of the following values:
* @arg TIM_TS_ITR0: Internal trigger 0 selected
* @arg TIM_TS_ITR1: Internal trigger 1 selected
* @arg TIM_TS_ITR2: Internal trigger 2 selected
* @arg TIM_TS_ITR3: Internal trigger 3 selected
* @arg TIM_TS_NONE: No trigger is needed
* @param CommutationSource the Commutation Event source
* This parameter can be one of the following values:
* @arg TIM_COMMUTATION_TRGI: Commutation source is the TRGI of the Interface Timer
* @arg TIM_COMMUTATION_SOFTWARE: Commutation source is set by software using the COMG bit
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_ConfigCommutEvent(TIM_HandleTypeDef *htim, uint32_t InputTrigger,
uint32_t CommutationSource)
{
/* Check the parameters */
assert_param(IS_TIM_COMMUTATION_EVENT_INSTANCE(htim->Instance));
assert_param(IS_TIM_INTERNAL_TRIGGEREVENT_SELECTION(InputTrigger));
__HAL_LOCK(htim);
if ((InputTrigger == TIM_TS_ITR0) || (InputTrigger == TIM_TS_ITR1) ||
(InputTrigger == TIM_TS_ITR2) || (InputTrigger == TIM_TS_ITR3))
{
/* Select the Input trigger */
htim->Instance->SMCR &= ~TIM_SMCR_TS;
htim->Instance->SMCR |= InputTrigger;
}
/* Select the Capture Compare preload feature */
htim->Instance->CR2 |= TIM_CR2_CCPC;
/* Select the Commutation event source */
htim->Instance->CR2 &= ~TIM_CR2_CCUS;
htim->Instance->CR2 |= CommutationSource;
/* Disable Commutation Interrupt */
__HAL_TIM_DISABLE_IT(htim, TIM_IT_COM);
/* Disable Commutation DMA request */
__HAL_TIM_DISABLE_DMA(htim, TIM_DMA_COM);
__HAL_UNLOCK(htim);
return HAL_OK;
}
/**
* @brief Configure the TIM commutation event sequence with interrupt.
* @note This function is mandatory to use the commutation event in order to
* update the configuration at each commutation detection on the TRGI input of the Timer,
* the typical use of this feature is with the use of another Timer(interface Timer)
* configured in Hall sensor interface, this interface Timer will generate the
* commutation at its TRGO output (connected to Timer used in this function) each time
* the TI1 of the Interface Timer detect a commutation at its input TI1.
* @param htim TIM handle
* @param InputTrigger the Internal trigger corresponding to the Timer Interfacing with the Hall sensor
* This parameter can be one of the following values:
* @arg TIM_TS_ITR0: Internal trigger 0 selected
* @arg TIM_TS_ITR1: Internal trigger 1 selected
* @arg TIM_TS_ITR2: Internal trigger 2 selected
* @arg TIM_TS_ITR3: Internal trigger 3 selected
* @arg TIM_TS_NONE: No trigger is needed
* @param CommutationSource the Commutation Event source
* This parameter can be one of the following values:
* @arg TIM_COMMUTATION_TRGI: Commutation source is the TRGI of the Interface Timer
* @arg TIM_COMMUTATION_SOFTWARE: Commutation source is set by software using the COMG bit
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_ConfigCommutEvent_IT(TIM_HandleTypeDef *htim, uint32_t InputTrigger,
uint32_t CommutationSource)
{
/* Check the parameters */
assert_param(IS_TIM_COMMUTATION_EVENT_INSTANCE(htim->Instance));
assert_param(IS_TIM_INTERNAL_TRIGGEREVENT_SELECTION(InputTrigger));
__HAL_LOCK(htim);
if ((InputTrigger == TIM_TS_ITR0) || (InputTrigger == TIM_TS_ITR1) ||
(InputTrigger == TIM_TS_ITR2) || (InputTrigger == TIM_TS_ITR3))
{
/* Select the Input trigger */
htim->Instance->SMCR &= ~TIM_SMCR_TS;
htim->Instance->SMCR |= InputTrigger;
}
/* Select the Capture Compare preload feature */
htim->Instance->CR2 |= TIM_CR2_CCPC;
/* Select the Commutation event source */
htim->Instance->CR2 &= ~TIM_CR2_CCUS;
htim->Instance->CR2 |= CommutationSource;
/* Disable Commutation DMA request */
__HAL_TIM_DISABLE_DMA(htim, TIM_DMA_COM);
/* Enable the Commutation Interrupt */
__HAL_TIM_ENABLE_IT(htim, TIM_IT_COM);
__HAL_UNLOCK(htim);
return HAL_OK;
}
/**
* @brief Configure the TIM commutation event sequence with DMA.
* @note This function is mandatory to use the commutation event in order to
* update the configuration at each commutation detection on the TRGI input of the Timer,
* the typical use of this feature is with the use of another Timer(interface Timer)
* configured in Hall sensor interface, this interface Timer will generate the
* commutation at its TRGO output (connected to Timer used in this function) each time
* the TI1 of the Interface Timer detect a commutation at its input TI1.
* @note The user should configure the DMA in his own software, in This function only the COMDE bit is set
* @param htim TIM handle
* @param InputTrigger the Internal trigger corresponding to the Timer Interfacing with the Hall sensor
* This parameter can be one of the following values:
* @arg TIM_TS_ITR0: Internal trigger 0 selected
* @arg TIM_TS_ITR1: Internal trigger 1 selected
* @arg TIM_TS_ITR2: Internal trigger 2 selected
* @arg TIM_TS_ITR3: Internal trigger 3 selected
* @arg TIM_TS_NONE: No trigger is needed
* @param CommutationSource the Commutation Event source
* This parameter can be one of the following values:
* @arg TIM_COMMUTATION_TRGI: Commutation source is the TRGI of the Interface Timer
* @arg TIM_COMMUTATION_SOFTWARE: Commutation source is set by software using the COMG bit
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_ConfigCommutEvent_DMA(TIM_HandleTypeDef *htim, uint32_t InputTrigger,
uint32_t CommutationSource)
{
/* Check the parameters */
assert_param(IS_TIM_COMMUTATION_EVENT_INSTANCE(htim->Instance));
assert_param(IS_TIM_INTERNAL_TRIGGEREVENT_SELECTION(InputTrigger));
__HAL_LOCK(htim);
if ((InputTrigger == TIM_TS_ITR0) || (InputTrigger == TIM_TS_ITR1) ||
(InputTrigger == TIM_TS_ITR2) || (InputTrigger == TIM_TS_ITR3))
{
/* Select the Input trigger */
htim->Instance->SMCR &= ~TIM_SMCR_TS;
htim->Instance->SMCR |= InputTrigger;
}
/* Select the Capture Compare preload feature */
htim->Instance->CR2 |= TIM_CR2_CCPC;
/* Select the Commutation event source */
htim->Instance->CR2 &= ~TIM_CR2_CCUS;
htim->Instance->CR2 |= CommutationSource;
/* Enable the Commutation DMA Request */
/* Set the DMA Commutation Callback */
htim->hdma[TIM_DMA_ID_COMMUTATION]->XferCpltCallback = TIMEx_DMACommutationCplt;
htim->hdma[TIM_DMA_ID_COMMUTATION]->XferHalfCpltCallback = TIMEx_DMACommutationHalfCplt;
/* Set the DMA error callback */
htim->hdma[TIM_DMA_ID_COMMUTATION]->XferErrorCallback = TIM_DMAError;
/* Disable Commutation Interrupt */
__HAL_TIM_DISABLE_IT(htim, TIM_IT_COM);
/* Enable the Commutation DMA Request */
__HAL_TIM_ENABLE_DMA(htim, TIM_DMA_COM);
__HAL_UNLOCK(htim);
return HAL_OK;
}
/**
* @brief Configures the TIM in master mode.
* @param htim TIM handle.
* @param sMasterConfig pointer to a TIM_MasterConfigTypeDef structure that
* contains the selected trigger output (TRGO) and the Master/Slave
* mode.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_MasterConfigSynchronization(TIM_HandleTypeDef *htim,
TIM_MasterConfigTypeDef *sMasterConfig)
{
uint32_t tmpcr2;
uint32_t tmpsmcr;
/* Check the parameters */
assert_param(IS_TIM_MASTER_INSTANCE(htim->Instance));
assert_param(IS_TIM_TRGO_SOURCE(sMasterConfig->MasterOutputTrigger));
assert_param(IS_TIM_MSM_STATE(sMasterConfig->MasterSlaveMode));
/* Check input state */
__HAL_LOCK(htim);
/* Change the handler state */
htim->State = HAL_TIM_STATE_BUSY;
/* Get the TIMx CR2 register value */
tmpcr2 = htim->Instance->CR2;
/* Get the TIMx SMCR register value */
tmpsmcr = htim->Instance->SMCR;
/* If the timer supports ADC synchronization through TRGO2, set the master mode selection 2 */
if (IS_TIM_TRGO2_INSTANCE(htim->Instance))
{
/* Check the parameters */
assert_param(IS_TIM_TRGO2_SOURCE(sMasterConfig->MasterOutputTrigger2));
/* Clear the MMS2 bits */
tmpcr2 &= ~TIM_CR2_MMS2;
/* Select the TRGO2 source*/
tmpcr2 |= sMasterConfig->MasterOutputTrigger2;
}
/* Reset the MMS Bits */
tmpcr2 &= ~TIM_CR2_MMS;
/* Select the TRGO source */
tmpcr2 |= sMasterConfig->MasterOutputTrigger;
/* Update TIMx CR2 */
htim->Instance->CR2 = tmpcr2;
if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
{
/* Reset the MSM Bit */
tmpsmcr &= ~TIM_SMCR_MSM;
/* Set master mode */
tmpsmcr |= sMasterConfig->MasterSlaveMode;
/* Update TIMx SMCR */
htim->Instance->SMCR = tmpsmcr;
}
/* Change the htim state */
htim->State = HAL_TIM_STATE_READY;
__HAL_UNLOCK(htim);
return HAL_OK;
}
/**
* @brief Configures the Break feature, dead time, Lock level, OSSI/OSSR State
* and the AOE(automatic output enable).
* @param htim TIM handle
* @param sBreakDeadTimeConfig pointer to a TIM_ConfigBreakDeadConfigTypeDef structure that
* contains the BDTR Register configuration information for the TIM peripheral.
* @note Interrupts can be generated when an active level is detected on the
* break input, the break 2 input or the system break input. Break
* interrupt can be enabled by calling the @ref __HAL_TIM_ENABLE_IT macro.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_ConfigBreakDeadTime(TIM_HandleTypeDef *htim,
TIM_BreakDeadTimeConfigTypeDef *sBreakDeadTimeConfig)
{
/* Keep this variable initialized to 0 as it is used to configure BDTR register */
uint32_t tmpbdtr = 0U;
/* Check the parameters */
assert_param(IS_TIM_BREAK_INSTANCE(htim->Instance));
assert_param(IS_TIM_OSSR_STATE(sBreakDeadTimeConfig->OffStateRunMode));
assert_param(IS_TIM_OSSI_STATE(sBreakDeadTimeConfig->OffStateIDLEMode));
assert_param(IS_TIM_LOCK_LEVEL(sBreakDeadTimeConfig->LockLevel));
assert_param(IS_TIM_DEADTIME(sBreakDeadTimeConfig->DeadTime));
assert_param(IS_TIM_BREAK_STATE(sBreakDeadTimeConfig->BreakState));
assert_param(IS_TIM_BREAK_POLARITY(sBreakDeadTimeConfig->BreakPolarity));
assert_param(IS_TIM_BREAK_FILTER(sBreakDeadTimeConfig->BreakFilter));
assert_param(IS_TIM_AUTOMATIC_OUTPUT_STATE(sBreakDeadTimeConfig->AutomaticOutput));
/* Check input state */
__HAL_LOCK(htim);
/* Set the Lock level, the Break enable Bit and the Polarity, the OSSR State,
the OSSI State, the dead time value and the Automatic Output Enable Bit */
/* Set the BDTR bits */
MODIFY_REG(tmpbdtr, TIM_BDTR_DTG, sBreakDeadTimeConfig->DeadTime);
MODIFY_REG(tmpbdtr, TIM_BDTR_LOCK, sBreakDeadTimeConfig->LockLevel);
MODIFY_REG(tmpbdtr, TIM_BDTR_OSSI, sBreakDeadTimeConfig->OffStateIDLEMode);
MODIFY_REG(tmpbdtr, TIM_BDTR_OSSR, sBreakDeadTimeConfig->OffStateRunMode);
MODIFY_REG(tmpbdtr, TIM_BDTR_BKE, sBreakDeadTimeConfig->BreakState);
MODIFY_REG(tmpbdtr, TIM_BDTR_BKP, sBreakDeadTimeConfig->BreakPolarity);
MODIFY_REG(tmpbdtr, TIM_BDTR_AOE, sBreakDeadTimeConfig->AutomaticOutput);
MODIFY_REG(tmpbdtr, TIM_BDTR_BKF, (sBreakDeadTimeConfig->BreakFilter << TIM_BDTR_BKF_Pos));
if (IS_TIM_BKIN2_INSTANCE(htim->Instance))
{
/* Check the parameters */
assert_param(IS_TIM_BREAK2_STATE(sBreakDeadTimeConfig->Break2State));
assert_param(IS_TIM_BREAK2_POLARITY(sBreakDeadTimeConfig->Break2Polarity));
assert_param(IS_TIM_BREAK_FILTER(sBreakDeadTimeConfig->Break2Filter));
/* Set the BREAK2 input related BDTR bits */
MODIFY_REG(tmpbdtr, TIM_BDTR_BK2F, (sBreakDeadTimeConfig->Break2Filter << TIM_BDTR_BK2F_Pos));
MODIFY_REG(tmpbdtr, TIM_BDTR_BK2E, sBreakDeadTimeConfig->Break2State);
MODIFY_REG(tmpbdtr, TIM_BDTR_BK2P, sBreakDeadTimeConfig->Break2Polarity);
}
/* Set TIMx_BDTR */
htim->Instance->BDTR = tmpbdtr;
__HAL_UNLOCK(htim);
return HAL_OK;
}
/**
* @brief Configures the break input source.
* @param htim TIM handle.
* @param BreakInput Break input to configure
* This parameter can be one of the following values:
* @arg TIM_BREAKINPUT_BRK: Timer break input
* @arg TIM_BREAKINPUT_BRK2: Timer break 2 input
* @param sBreakInputConfig Break input source configuration
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_ConfigBreakInput(TIM_HandleTypeDef *htim,
uint32_t BreakInput,
TIMEx_BreakInputConfigTypeDef *sBreakInputConfig)
{
HAL_StatusTypeDef status = HAL_OK;
uint32_t tmporx;
uint32_t bkin_enable_mask;
uint32_t bkin_polarity_mask;
uint32_t bkin_enable_bitpos;
uint32_t bkin_polarity_bitpos;
/* Check the parameters */
assert_param(IS_TIM_BREAK_INSTANCE(htim->Instance));
assert_param(IS_TIM_BREAKINPUT(BreakInput));
assert_param(IS_TIM_BREAKINPUTSOURCE(sBreakInputConfig->Source));
assert_param(IS_TIM_BREAKINPUTSOURCE_STATE(sBreakInputConfig->Enable));
#if defined(DFSDM1_Channel0)
if (sBreakInputConfig->Source != TIM_BREAKINPUTSOURCE_DFSDM1)
{
assert_param(IS_TIM_BREAKINPUTSOURCE_POLARITY(sBreakInputConfig->Polarity));
}
#else
assert_param(IS_TIM_BREAKINPUTSOURCE_POLARITY(sBreakInputConfig->Polarity));
#endif /* DFSDM1_Channel0 */
/* Check input state */
__HAL_LOCK(htim);
switch (sBreakInputConfig->Source)
{
case TIM_BREAKINPUTSOURCE_BKIN:
{
bkin_enable_mask = TIM1_OR2_BKINE;
bkin_enable_bitpos = TIM1_OR2_BKINE_Pos;
bkin_polarity_mask = TIM1_OR2_BKINP;
bkin_polarity_bitpos = TIM1_OR2_BKINP_Pos;
break;
}
case TIM_BREAKINPUTSOURCE_COMP1:
{
bkin_enable_mask = TIM1_OR2_BKCMP1E;
bkin_enable_bitpos = TIM1_OR2_BKCMP1E_Pos;
bkin_polarity_mask = TIM1_OR2_BKCMP1P;
bkin_polarity_bitpos = TIM1_OR2_BKCMP1P_Pos;
break;
}
case TIM_BREAKINPUTSOURCE_COMP2:
{
bkin_enable_mask = TIM1_OR2_BKCMP2E;
bkin_enable_bitpos = TIM1_OR2_BKCMP2E_Pos;
bkin_polarity_mask = TIM1_OR2_BKCMP2P;
bkin_polarity_bitpos = TIM1_OR2_BKCMP2P_Pos;
break;
}
#if defined(DFSDM1_Channel0)
case TIM_BREAKINPUTSOURCE_DFSDM1:
{
bkin_enable_mask = TIM1_OR2_BKDF1BK0E;
bkin_enable_bitpos = TIM1_OR2_BKDF1BK0E_Pos;
bkin_polarity_mask = 0U;
bkin_polarity_bitpos = 0U;
break;
}
#endif /* DFSDM1_Channel0 */
default:
{
bkin_enable_mask = 0U;
bkin_polarity_mask = 0U;
bkin_enable_bitpos = 0U;
bkin_polarity_bitpos = 0U;
break;
}
}
switch (BreakInput)
{
case TIM_BREAKINPUT_BRK:
{
/* Get the TIMx_OR2 register value */
tmporx = htim->Instance->OR2;
/* Enable the break input */
tmporx &= ~bkin_enable_mask;
tmporx |= (sBreakInputConfig->Enable << bkin_enable_bitpos) & bkin_enable_mask;
/* Set the break input polarity */
#if defined(DFSDM1_Channel0)
if (sBreakInputConfig->Source != TIM_BREAKINPUTSOURCE_DFSDM1)
#endif /* DFSDM1_Channel0 */
{
tmporx &= ~bkin_polarity_mask;
tmporx |= (sBreakInputConfig->Polarity << bkin_polarity_bitpos) & bkin_polarity_mask;
}
/* Set TIMx_OR2 */
htim->Instance->OR2 = tmporx;
break;
}
case TIM_BREAKINPUT_BRK2:
{
/* Get the TIMx_OR3 register value */
tmporx = htim->Instance->OR3;
/* Enable the break input */
tmporx &= ~bkin_enable_mask;
tmporx |= (sBreakInputConfig->Enable << bkin_enable_bitpos) & bkin_enable_mask;
/* Set the break input polarity */
#if defined(DFSDM1_Channel0)
if (sBreakInputConfig->Source != TIM_BREAKINPUTSOURCE_DFSDM1)
#endif /* DFSDM1_Channel0 */
{
tmporx &= ~bkin_polarity_mask;
tmporx |= (sBreakInputConfig->Polarity << bkin_polarity_bitpos) & bkin_polarity_mask;
}
/* Set TIMx_OR3 */
htim->Instance->OR3 = tmporx;
break;
}
default:
status = HAL_ERROR;
break;
}
__HAL_UNLOCK(htim);
return status;
}
/**
* @brief Configures the TIMx Remapping input capabilities.
* @param htim TIM handle.
* @param Remap specifies the TIM remapping source.
@if STM32L422xx
* For TIM1, the parameter is a combination of 2 fields (field1 | field2):
*
* field1 can have the following values:
* @arg TIM_TIM1_ETR_ADC1_NONE: TIM1_ETR is not connected to any ADC1 AWD (analog watchdog)
* @arg TIM_TIM1_ETR_ADC1_AWD1: TIM1_ETR is connected to ADC1 AWD1
* @arg TIM_TIM1_ETR_ADC1_AWD2: TIM1_ETR is connected to ADC1 AWD2
* @arg TIM_TIM1_ETR_ADC1_AWD3: TIM1_ETR is connected to ADC1 AWD3
*
* field2 can have the following values:
* @arg TIM_TIM1_TI1_GPIO: TIM1 TI1 is connected to GPIO
* @arg TIM_TIM1_TI1_COMP1: TIM1 TI1 is connected to COMP1 output
*
@endif
@if STM32L486xx
* For TIM1, the parameter is a combination of 4 fields (field1 | field2 | field3 | field4):
*
* field1 can have the following values:
* @arg TIM_TIM1_ETR_ADC1_NONE: TIM1_ETR is not connected to any ADC1 AWD (analog watchdog)
* @arg TIM_TIM1_ETR_ADC1_AWD1: TIM1_ETR is connected to ADC1 AWD1
* @arg TIM_TIM1_ETR_ADC1_AWD2: TIM1_ETR is connected to ADC1 AWD2
* @arg TIM_TIM1_ETR_ADC1_AWD3: TIM1_ETR is connected to ADC1 AWD3
*
* field2 can have the following values:
* @arg TIM_TIM1_ETR_ADC3_NONE: TIM1_ETR is not connected to any ADC3 AWD (analog watchdog)
* @arg TIM_TIM1_ETR_ADC3_AWD1: TIM1_ETR is connected to ADC3 AWD1
* @arg TIM_TIM1_ETR_ADC3_AWD2: TIM1_ETR is connected to ADC3 AWD2
* @arg TIM_TIM1_ETR_ADC3_AWD3: TIM1_ETR is connected to ADC3 AWD3
*
* field3 can have the following values:
* @arg TIM_TIM1_TI1_GPIO: TIM1 TI1 is connected to GPIO
* @arg TIM_TIM1_TI1_COMP1: TIM1 TI1 is connected to COMP1 output
*
* field4 can have the following values:
* @arg TIM_TIM1_ETR_COMP1: TIM1_ETR is connected to COMP1 output
* @arg TIM_TIM1_ETR_COMP2: TIM1_ETR is connected to COMP2 output
* @note When field4 is set to TIM_TIM1_ETR_COMP1 or TIM_TIM1_ETR_COMP2 field1 and field2 values are not significant
@endif
@if STM32L443xx
* For TIM1, the parameter is a combination of 3 fields (field1 | field2 | field3):
*
* field1 can have the following values:
* @arg TIM_TIM1_ETR_ADC1_NONE: TIM1_ETR is not connected to any ADC1 AWD (analog watchdog)
* @arg TIM_TIM1_ETR_ADC1_AWD1: TIM1_ETR is connected to ADC1 AWD1
* @arg TIM_TIM1_ETR_ADC1_AWD2: TIM1_ETR is connected to ADC1 AWD2
* @arg TIM_TIM1_ETR_ADC1_AWD3: TIM1_ETR is connected to ADC1 AWD3
*
* field2 can have the following values:
* @arg TIM_TIM1_TI1_GPIO: TIM1 TI1 is connected to GPIO
* @arg TIM_TIM1_TI1_COMP1: TIM1 TI1 is connected to COMP1 output
*
* field3 can have the following values:
* @arg TIM_TIM1_ETR_COMP1: TIM1_ETR is connected to COMP1 output
* @arg TIM_TIM1_ETR_COMP2: TIM1_ETR is connected to COMP2 output
*
* @note When field3 is set to TIM_TIM1_ETR_COMP1 or TIM_TIM1_ETR_COMP2 field1 values is not significant
*
@endif
@if STM32L486xx
* For TIM2, the parameter is a combination of 3 fields (field1 | field2 | field3):
*
* field1 can have the following values:
* @arg TIM_TIM2_ITR1_TIM8_TRGO: TIM2_ITR1 is connected to TIM8_TRGO
* @arg TIM_TIM2_ITR1_OTG_FS_SOF: TIM2_ITR1 is connected to OTG_FS SOF
*
* field2 can have the following values:
* @arg TIM_TIM2_ETR_GPIO: TIM2_ETR is connected to GPIO
* @arg TIM_TIM2_ETR_LSE: TIM2_ETR is connected to LSE
* @arg TIM_TIM2_ETR_COMP1: TIM2_ETR is connected to COMP1 output
* @arg TIM_TIM2_ETR_COMP2: TIM2_ETR is connected to COMP2 output
*
* field3 can have the following values:
* @arg TIM_TIM2_TI4_GPIO: TIM2 TI4 is connected to GPIO
* @arg TIM_TIM2_TI4_COMP1: TIM2 TI4 is connected to COMP1 output
* @arg TIM_TIM2_TI4_COMP2: TIM2 TI4 is connected to COMP2 output
* @arg TIM_TIM2_TI4_COMP1_COMP2: TIM2 TI4 is connected to logical OR between COMP1 and COMP2 output
@endif
@if STM32L422xx
* For TIM2, the parameter is a combination of 3 fields (field1 | field2 | field3):
*
* field1 can have the following values:
* @arg TIM_TIM2_ITR1_NONE: No internal trigger on TIM2_ITR1
* @arg TIM_TIM2_ITR1_USB_SOF: TIM2_ITR1 is connected to USB SOF
*
* field2 can have the following values:
* @arg TIM_TIM2_ETR_GPIO: TIM2_ETR is connected to GPIO
* @arg TIM_TIM2_ETR_LSE: TIM2_ETR is connected to LSE
* @arg TIM_TIM2_ETR_COMP1: TIM2_ETR is connected to COMP1 output
*
* field3 can have the following values:
* @arg TIM_TIM2_TI4_GPIO: TIM2 TI4 is connected to GPIO
* @arg TIM_TIM2_TI4_COMP1: TIM2 TI4 is connected to COMP1 output
*
@endif
@if STM32L443xx
* For TIM2, the parameter is a combination of 3 fields (field1 | field2 | field3):
*
* field1 can have the following values:
* @arg TIM_TIM2_ITR1_NONE: No internal trigger on TIM2_ITR1
* @arg TIM_TIM2_ITR1_USB_SOF: TIM2_ITR1 is connected to USB SOF
*
* field2 can have the following values:
* @arg TIM_TIM2_ETR_GPIO: TIM2_ETR is connected to GPIO
* @arg TIM_TIM2_ETR_LSE: TIM2_ETR is connected to LSE
* @arg TIM_TIM2_ETR_COMP1: TIM2_ETR is connected to COMP1 output
* @arg TIM_TIM2_ETR_COMP2: TIM2_ETR is connected to COMP2 output
*
* field3 can have the following values:
* @arg TIM_TIM2_TI4_GPIO: TIM2 TI4 is connected to GPIO
* @arg TIM_TIM2_TI4_COMP1: TIM2 TI4 is connected to COMP1 output
* @arg TIM_TIM2_TI4_COMP2: TIM2 TI4 is connected to COMP2 output
* @arg TIM_TIM2_TI4_COMP1_COMP2: TIM2 TI4 is connected to logical OR between COMP1 and COMP2 output
*
@endif
@if STM32L486xx
* For TIM3, the parameter is a combination 2 fields(field1 | field2):
*
* field1 can have the following values:
* @arg TIM_TIM3_TI1_GPIO: TIM3 TI1 is connected to GPIO
* @arg TIM_TIM3_TI1_COMP1: TIM3 TI1 is connected to COMP1 output
* @arg TIM_TIM3_TI1_COMP2: TIM3 TI1 is connected to COMP2 output
* @arg TIM_TIM3_TI1_COMP1_COMP2: TIM3 TI1 is connected to logical OR between COMP1 and COMP2 output
*
* field2 can have the following values:
* @arg TIM_TIM3_ETR_GPIO: TIM3_ETR is connected to GPIO
* @arg TIM_TIM3_ETR_COMP1: TIM3_ETR is connected to COMP1 output
*
@endif
@if STM32L486xx
* For TIM8, the parameter is a combination of 3 fields (field1 | field2 | field3):
*
* field1 can have the following values:
* @arg TIM_TIM8_ETR_ADC2_NONE: TIM8_ETR is not connected to any ADC2 AWD (analog watchdog)
* @arg TIM_TIM8_ETR_ADC2_AWD1: TIM8_ETR is connected to ADC2 AWD1
* @arg TIM_TIM8_ETR_ADC2_AWD2: TIM8_ETR is connected to ADC2 AWD2
* @arg TIM_TIM8_ETR_ADC2_AWD3: TIM8_ETR is connected to ADC2 AWD3
*
* field2 can have the following values:
* @arg TIM_TIM8_ETR_ADC3_NONE: TIM8_ETR is not connected to any ADC3 AWD (analog watchdog)
* @arg TIM_TIM8_ETR_ADC3_AWD1: TIM8_ETR is connected to ADC3 AWD1
* @arg TIM_TIM8_ETR_ADC3_AWD2: TIM8_ETR is connected to ADC3 AWD2
* @arg TIM_TIM8_ETR_ADC3_AWD3: TIM8_ETR is connected to ADC3 AWD3
*
* field3 can have the following values:
* @arg TIM_TIM8_TI1_GPIO: TIM8 TI1 is connected to GPIO
* @arg TIM_TIM8_TI1_COMP2: TIM8 TI1 is connected to COMP2 output
*
* field4 can have the following values:
* @arg TIM_TIM8_ETR_COMP1: TIM8_ETR is connected to COMP1 output
* @arg TIM_TIM8_ETR_COMP2: TIM8_ETR is connected to COMP2 output
* @note When field4 is set to TIM_TIM8_ETR_COMP1 or TIM_TIM8_ETR_COMP2 field1 and field2 values are not significant
*
@endif
@if STM32L422xx
* For TIM15, the parameter is a combination of 2 fields (field1 | field2):
*
* field1 can have the following values:
* @arg TIM_TIM15_TI1_GPIO: TIM15 TI1 is connected to GPIO
* @arg TIM_TIM15_TI1_LSE: TIM15 TI1 is connected to LSE
*
* field2 can have the following values:
* @arg TIM_TIM15_ENCODERMODE_NONE: No redirection
* @arg TIM_TIM15_ENCODERMODE_TIM2: TIM2 IC1 and TIM2 IC2 are connected to TIM15 IC1 and TIM15 IC2 respectively
*
@endif
@if STM32L443xx
* For TIM15, the parameter is a combination of 2 fields (field1 | field2):
*
* field1 can have the following values:
* @arg TIM_TIM15_TI1_GPIO: TIM15 TI1 is connected to GPIO
* @arg TIM_TIM15_TI1_LSE: TIM15 TI1 is connected to LSE
*
* field2 can have the following values:
* @arg TIM_TIM15_ENCODERMODE_NONE: No redirection
* @arg TIM_TIM15_ENCODERMODE_TIM2: TIM2 IC1 and TIM2 IC2 are connected to TIM15 IC1 and TIM15 IC2 respectively
* @arg TIM_TIM15_ENCODERMODE_TIM3: TIM3 IC1 and TIM3 IC2 are connected to TIM15 IC1 and TIM15 IC2 respectively
* @arg TIM_TIM15_ENCODERMODE_TIM4: TIM4 IC1 and TIM4 IC2 are connected to TIM15 IC1 and TIM15 IC2 respectively
*
@endif
@if STM32L486xx
* @arg TIM_TIM16_TI1_GPIO: TIM16 TI1 is connected to GPIO
* @arg TIM_TIM16_TI1_LSI: TIM16 TI1 is connected to LSI
* @arg TIM_TIM16_TI1_LSE: TIM16 TI1 is connected to LSE
* @arg TIM_TIM16_TI1_RTC: TIM16 TI1 is connected to RTC wakeup interrupt
*
@endif
@if STM32L422xx
* For TIM16, the parameter can have the following values:
* @arg TIM_TIM16_TI1_GPIO: TIM16 TI1 is connected to GPIO
* @arg TIM_TIM16_TI1_LSI: TIM16 TI1 is connected to LSI
* @arg TIM_TIM16_TI1_LSE: TIM16 TI1 is connected to LSE
* @arg TIM_TIM16_TI1_RTC: TIM16 TI1 is connected to RTC wakeup interrupt
* @arg TIM_TIM16_TI1_MSI: TIM16 TI1 is connected to MSI (constraints: MSI clock < 1/4 TIM APB clock)
* @arg TIM_TIM16_TI1_HSE_32: TIM16 TI1 is connected to HSE div 32 (note that HSE div 32 must be selected as RTC clock source)
* @arg TIM_TIM16_TI1_MCO: TIM16 TI1 is connected to MCO
*
@endif
@if STM32L443xx
* For TIM16, the parameter can have the following values:
* @arg TIM_TIM16_TI1_GPIO: TIM16 TI1 is connected to GPIO
* @arg TIM_TIM16_TI1_LSI: TIM16 TI1 is connected to LSI
* @arg TIM_TIM16_TI1_LSE: TIM16 TI1 is connected to LSE
* @arg TIM_TIM16_TI1_RTC: TIM16 TI1 is connected to RTC wakeup interrupt
* @arg TIM_TIM16_TI1_MSI: TIM16 TI1 is connected to MSI (constraints: MSI clock < 1/4 TIM APB clock)
* @arg TIM_TIM16_TI1_HSE_32: TIM16 TI1 is connected to HSE div 32 (note that HSE div 32 must be selected as RTC clock source)
* @arg TIM_TIM16_TI1_MCO: TIM16 TI1 is connected to MCO
*
@endif
@if STM32L486xx
* For TIM17, the parameter can have the following values:
* @arg TIM_TIM17_TI1_GPIO: TIM17 TI1 is connected to GPIO
* @arg TIM_TIM17_TI1_MSI: TIM17 TI1 is connected to MSI (constraints: MSI clock < 1/4 TIM APB clock)
* @arg TIM_TIM17_TI1_HSE_32: TIM17 TI1 is connected to HSE div 32
* @arg TIM_TIM17_TI1_MCO: TIM17 TI1 is connected to MCO
@endif
*
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_RemapConfig(TIM_HandleTypeDef *htim, uint32_t Remap)
{
uint32_t tmpor1;
uint32_t tmpor2;
/* Check parameters */
assert_param(IS_TIM_REMAP_INSTANCE(htim->Instance));
assert_param(IS_TIM_REMAP(Remap));
__HAL_LOCK(htim);
/* Set ETR_SEL bit field (if required) */
if (IS_TIM_ETRSEL_INSTANCE(htim->Instance))
{
tmpor2 = htim->Instance->OR2;
tmpor2 &= ~TIM1_OR2_ETRSEL_Msk;
tmpor2 |= (Remap & TIM1_OR2_ETRSEL_Msk);
/* Set TIMx_OR2 */
htim->Instance->OR2 = tmpor2;
}
/* Set other remapping capabilities */
tmpor1 = Remap;
tmpor1 &= ~TIM1_OR2_ETRSEL_Msk;
/* Set TIMx_OR1 */
htim->Instance->OR1 = tmpor1;
__HAL_UNLOCK(htim);
return HAL_OK;
}
/**
* @brief Group channel 5 and channel 1, 2 or 3
* @param htim TIM handle.
* @param Channels specifies the reference signal(s) the OC5REF is combined with.
* This parameter can be any combination of the following values:
* TIM_GROUPCH5_NONE: No effect of OC5REF on OC1REFC, OC2REFC and OC3REFC
* TIM_GROUPCH5_OC1REFC: OC1REFC is the logical AND of OC1REFC and OC5REF
* TIM_GROUPCH5_OC2REFC: OC2REFC is the logical AND of OC2REFC and OC5REF
* TIM_GROUPCH5_OC3REFC: OC3REFC is the logical AND of OC3REFC and OC5REF
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIMEx_GroupChannel5(TIM_HandleTypeDef *htim, uint32_t Channels)
{
/* Check parameters */
assert_param(IS_TIM_COMBINED3PHASEPWM_INSTANCE(htim->Instance));
assert_param(IS_TIM_GROUPCH5(Channels));
/* Process Locked */
__HAL_LOCK(htim);
htim->State = HAL_TIM_STATE_BUSY;
/* Clear GC5Cx bit fields */
htim->Instance->CCR5 &= ~(TIM_CCR5_GC5C3 | TIM_CCR5_GC5C2 | TIM_CCR5_GC5C1);
/* Set GC5Cx bit fields */
htim->Instance->CCR5 |= Channels;
/* Change the htim state */
htim->State = HAL_TIM_STATE_READY;
__HAL_UNLOCK(htim);
return HAL_OK;
}
/**
* @}
*/
/** @defgroup TIMEx_Exported_Functions_Group6 Extended Callbacks functions
* @brief Extended Callbacks functions
*
@verbatim
==============================================================================
##### Extended Callbacks functions #####
==============================================================================
[..]
This section provides Extended TIM callback functions:
(+) Timer Commutation callback
(+) Timer Break callback
@endverbatim
* @{
*/
/**
* @brief Hall commutation changed callback in non-blocking mode
* @param htim TIM handle
* @retval None
*/
__weak void HAL_TIMEx_CommutCallback(TIM_HandleTypeDef *htim)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(htim);
/* NOTE : This function should not be modified, when the callback is needed,
the HAL_TIMEx_CommutCallback could be implemented in the user file
*/
}
/**
* @brief Hall commutation changed half complete callback in non-blocking mode
* @param htim TIM handle
* @retval None
*/
__weak void HAL_TIMEx_CommutHalfCpltCallback(TIM_HandleTypeDef *htim)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(htim);
/* NOTE : This function should not be modified, when the callback is needed,
the HAL_TIMEx_CommutHalfCpltCallback could be implemented in the user file
*/
}
/**
* @brief Hall Break detection callback in non-blocking mode
* @param htim TIM handle
* @retval None
*/
__weak void HAL_TIMEx_BreakCallback(TIM_HandleTypeDef *htim)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(htim);
/* NOTE : This function should not be modified, when the callback is needed,
the HAL_TIMEx_BreakCallback could be implemented in the user file
*/
}
/**
* @brief Hall Break2 detection callback in non blocking mode
* @param htim: TIM handle
* @retval None
*/
__weak void HAL_TIMEx_Break2Callback(TIM_HandleTypeDef *htim)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(htim);
/* NOTE : This function Should not be modified, when the callback is needed,
the HAL_TIMEx_Break2Callback could be implemented in the user file
*/
}
/**
* @}
*/
/** @defgroup TIMEx_Exported_Functions_Group7 Extended Peripheral State functions
* @brief Extended Peripheral State functions
*
@verbatim
==============================================================================
##### Extended Peripheral State functions #####
==============================================================================
[..]
This subsection permits to get in run-time the status of the peripheral
and the data flow.
@endverbatim
* @{
*/
/**
* @brief Return the TIM Hall Sensor interface handle state.
* @param htim TIM Hall Sensor handle
* @retval HAL state
*/
HAL_TIM_StateTypeDef HAL_TIMEx_HallSensor_GetState(TIM_HandleTypeDef *htim)
{
return htim->State;
}
/**
* @brief Return actual state of the TIM complementary channel.
* @param htim TIM handle
* @param ChannelN TIM Complementary channel
* This parameter can be one of the following values:
* @arg TIM_CHANNEL_1: TIM Channel 1
* @arg TIM_CHANNEL_2: TIM Channel 2
* @arg TIM_CHANNEL_3: TIM Channel 3
* @retval TIM Complementary channel state
*/
HAL_TIM_ChannelStateTypeDef HAL_TIMEx_GetChannelNState(TIM_HandleTypeDef *htim, uint32_t ChannelN)
{
HAL_TIM_ChannelStateTypeDef channel_state;
/* Check the parameters */
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, ChannelN));
channel_state = TIM_CHANNEL_N_STATE_GET(htim, ChannelN);
return channel_state;
}
/**
* @}
*/
/**
* @}
*/
/* Private functions ---------------------------------------------------------*/
/** @defgroup TIMEx_Private_Functions TIM Extended Private Functions
* @{
*/
/**
* @brief TIM DMA Commutation callback.
* @param hdma pointer to DMA handle.
* @retval None
*/
void TIMEx_DMACommutationCplt(DMA_HandleTypeDef *hdma)
{
TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
/* Change the htim state */
htim->State = HAL_TIM_STATE_READY;
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
htim->CommutationCallback(htim);
#else
HAL_TIMEx_CommutCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
}
/**
* @brief TIM DMA Commutation half complete callback.
* @param hdma pointer to DMA handle.
* @retval None
*/
void TIMEx_DMACommutationHalfCplt(DMA_HandleTypeDef *hdma)
{
TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
/* Change the htim state */
htim->State = HAL_TIM_STATE_READY;
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
htim->CommutationHalfCpltCallback(htim);
#else
HAL_TIMEx_CommutHalfCpltCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
}
/**
* @brief TIM DMA Delay Pulse complete callback (complementary channel).
* @param hdma pointer to DMA handle.
* @retval None
*/
static void TIM_DMADelayPulseNCplt(DMA_HandleTypeDef *hdma)
{
TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
if (hdma == htim->hdma[TIM_DMA_ID_CC1])
{
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
if (hdma->Init.Mode == DMA_NORMAL)
{
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
}
}
else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
{
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
if (hdma->Init.Mode == DMA_NORMAL)
{
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
}
}
else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
{
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
if (hdma->Init.Mode == DMA_NORMAL)
{
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_3, HAL_TIM_CHANNEL_STATE_READY);
}
}
else if (hdma == htim->hdma[TIM_DMA_ID_CC4])
{
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_4;
if (hdma->Init.Mode == DMA_NORMAL)
{
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_4, HAL_TIM_CHANNEL_STATE_READY);
}
}
else
{
/* nothing to do */
}
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
htim->PWM_PulseFinishedCallback(htim);
#else
HAL_TIM_PWM_PulseFinishedCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
}
/**
* @brief TIM DMA error callback (complementary channel)
* @param hdma pointer to DMA handle.
* @retval None
*/
static void TIM_DMAErrorCCxN(DMA_HandleTypeDef *hdma)
{
TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
if (hdma == htim->hdma[TIM_DMA_ID_CC1])
{
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
}
else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
{
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
}
else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
{
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_3, HAL_TIM_CHANNEL_STATE_READY);
}
else
{
/* nothing to do */
}
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
htim->ErrorCallback(htim);
#else
HAL_TIM_ErrorCallback(htim);
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
}
/**
* @brief Enables or disables the TIM Capture Compare Channel xN.
* @param TIMx to select the TIM peripheral
* @param Channel specifies the TIM Channel
* This parameter can be one of the following values:
* @arg TIM_CHANNEL_1: TIM Channel 1
* @arg TIM_CHANNEL_2: TIM Channel 2
* @arg TIM_CHANNEL_3: TIM Channel 3
* @param ChannelNState specifies the TIM Channel CCxNE bit new state.
* This parameter can be: TIM_CCxN_ENABLE or TIM_CCxN_Disable.
* @retval None
*/
static void TIM_CCxNChannelCmd(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t ChannelNState)
{
uint32_t tmp;
tmp = TIM_CCER_CC1NE << (Channel & 0x1FU); /* 0x1FU = 31 bits max shift */
/* Reset the CCxNE Bit */
TIMx->CCER &= ~tmp;
/* Set or reset the CCxNE Bit */
TIMx->CCER |= (uint32_t)(ChannelNState << (Channel & 0x1FU)); /* 0x1FU = 31 bits max shift */
}
/**
* @}
*/
#endif /* HAL_TIM_MODULE_ENABLED */
/**
* @}
*/
/**
* @}
*/

View File

@@ -0,0 +1,400 @@
/**
******************************************************************************
* @file stm32l4xx_ll_dma.c
* @author MCD Application Team
* @brief DMA 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 "stm32l4xx_ll_dma.h"
#include "stm32l4xx_ll_bus.h"
#ifdef USE_FULL_ASSERT
#include "stm32_assert.h"
#else
#define assert_param(expr) ((void)0U)
#endif
/** @addtogroup STM32L4xx_LL_Driver
* @{
*/
#if defined (DMA1) || defined (DMA2)
/** @defgroup DMA_LL DMA
* @{
*/
/* Private types -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private constants ---------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/
/** @addtogroup DMA_LL_Private_Macros
* @{
*/
#define IS_LL_DMA_DIRECTION(__VALUE__) (((__VALUE__) == LL_DMA_DIRECTION_PERIPH_TO_MEMORY) || \
((__VALUE__) == LL_DMA_DIRECTION_MEMORY_TO_PERIPH) || \
((__VALUE__) == LL_DMA_DIRECTION_MEMORY_TO_MEMORY))
#define IS_LL_DMA_MODE(__VALUE__) (((__VALUE__) == LL_DMA_MODE_NORMAL) || \
((__VALUE__) == LL_DMA_MODE_CIRCULAR))
#define IS_LL_DMA_PERIPHINCMODE(__VALUE__) (((__VALUE__) == LL_DMA_PERIPH_INCREMENT) || \
((__VALUE__) == LL_DMA_PERIPH_NOINCREMENT))
#define IS_LL_DMA_MEMORYINCMODE(__VALUE__) (((__VALUE__) == LL_DMA_MEMORY_INCREMENT) || \
((__VALUE__) == LL_DMA_MEMORY_NOINCREMENT))
#define IS_LL_DMA_PERIPHDATASIZE(__VALUE__) (((__VALUE__) == LL_DMA_PDATAALIGN_BYTE) || \
((__VALUE__) == LL_DMA_PDATAALIGN_HALFWORD) || \
((__VALUE__) == LL_DMA_PDATAALIGN_WORD))
#define IS_LL_DMA_MEMORYDATASIZE(__VALUE__) (((__VALUE__) == LL_DMA_MDATAALIGN_BYTE) || \
((__VALUE__) == LL_DMA_MDATAALIGN_HALFWORD) || \
((__VALUE__) == LL_DMA_MDATAALIGN_WORD))
#define IS_LL_DMA_NBDATA(__VALUE__) ((__VALUE__) <= 0x0000FFFFU)
#if defined(DMAMUX1)
#define IS_LL_DMA_PERIPHREQUEST(__VALUE__) ((__VALUE__) <= 93U)
#else
#define IS_LL_DMA_PERIPHREQUEST(__VALUE__) (((__VALUE__) == LL_DMA_REQUEST_0) || \
((__VALUE__) == LL_DMA_REQUEST_1) || \
((__VALUE__) == LL_DMA_REQUEST_2) || \
((__VALUE__) == LL_DMA_REQUEST_3) || \
((__VALUE__) == LL_DMA_REQUEST_4) || \
((__VALUE__) == LL_DMA_REQUEST_5) || \
((__VALUE__) == LL_DMA_REQUEST_6) || \
((__VALUE__) == LL_DMA_REQUEST_7))
#endif /* DMAMUX1 */
#define IS_LL_DMA_PRIORITY(__VALUE__) (((__VALUE__) == LL_DMA_PRIORITY_LOW) || \
((__VALUE__) == LL_DMA_PRIORITY_MEDIUM) || \
((__VALUE__) == LL_DMA_PRIORITY_HIGH) || \
((__VALUE__) == LL_DMA_PRIORITY_VERYHIGH))
#if defined (DMA2)
#if defined (DMA2_Channel6) && defined (DMA2_Channel7)
#define IS_LL_DMA_ALL_CHANNEL_INSTANCE(INSTANCE, CHANNEL) ((((INSTANCE) == DMA1) && \
(((CHANNEL) == LL_DMA_CHANNEL_1) || \
((CHANNEL) == LL_DMA_CHANNEL_2) || \
((CHANNEL) == LL_DMA_CHANNEL_3) || \
((CHANNEL) == LL_DMA_CHANNEL_4) || \
((CHANNEL) == LL_DMA_CHANNEL_5) || \
((CHANNEL) == LL_DMA_CHANNEL_6) || \
((CHANNEL) == LL_DMA_CHANNEL_7))) || \
(((INSTANCE) == DMA2) && \
(((CHANNEL) == LL_DMA_CHANNEL_1) || \
((CHANNEL) == LL_DMA_CHANNEL_2) || \
((CHANNEL) == LL_DMA_CHANNEL_3) || \
((CHANNEL) == LL_DMA_CHANNEL_4) || \
((CHANNEL) == LL_DMA_CHANNEL_5) || \
((CHANNEL) == LL_DMA_CHANNEL_6) || \
((CHANNEL) == LL_DMA_CHANNEL_7))))
#else
#define IS_LL_DMA_ALL_CHANNEL_INSTANCE(INSTANCE, CHANNEL) ((((INSTANCE) == DMA1) && \
(((CHANNEL) == LL_DMA_CHANNEL_1) || \
((CHANNEL) == LL_DMA_CHANNEL_2) || \
((CHANNEL) == LL_DMA_CHANNEL_3) || \
((CHANNEL) == LL_DMA_CHANNEL_4) || \
((CHANNEL) == LL_DMA_CHANNEL_5) || \
((CHANNEL) == LL_DMA_CHANNEL_6) || \
((CHANNEL) == LL_DMA_CHANNEL_7))) || \
(((INSTANCE) == DMA2) && \
(((CHANNEL) == LL_DMA_CHANNEL_1) || \
((CHANNEL) == LL_DMA_CHANNEL_2) || \
((CHANNEL) == LL_DMA_CHANNEL_3) || \
((CHANNEL) == LL_DMA_CHANNEL_4) || \
((CHANNEL) == LL_DMA_CHANNEL_5))))
#endif
#else
#define IS_LL_DMA_ALL_CHANNEL_INSTANCE(INSTANCE, CHANNEL) ((((INSTANCE) == DMA1) && \
(((CHANNEL) == LL_DMA_CHANNEL_1)|| \
((CHANNEL) == LL_DMA_CHANNEL_2) || \
((CHANNEL) == LL_DMA_CHANNEL_3) || \
((CHANNEL) == LL_DMA_CHANNEL_4) || \
((CHANNEL) == LL_DMA_CHANNEL_5) || \
((CHANNEL) == LL_DMA_CHANNEL_6) || \
((CHANNEL) == LL_DMA_CHANNEL_7))))
#endif
/**
* @}
*/
/* Private function prototypes -----------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/** @addtogroup DMA_LL_Exported_Functions
* @{
*/
/** @addtogroup DMA_LL_EF_Init
* @{
*/
/**
* @brief De-initialize the DMA registers to their default reset values.
* @param DMAx DMAx Instance
* @param Channel This parameter can be one of the following values:
* @arg @ref LL_DMA_CHANNEL_1
* @arg @ref LL_DMA_CHANNEL_2
* @arg @ref LL_DMA_CHANNEL_3
* @arg @ref LL_DMA_CHANNEL_4
* @arg @ref LL_DMA_CHANNEL_5
* @arg @ref LL_DMA_CHANNEL_6
* @arg @ref LL_DMA_CHANNEL_7
* @arg @ref LL_DMA_CHANNEL_ALL
* @retval An ErrorStatus enumeration value:
* - SUCCESS: DMA registers are de-initialized
* - ERROR: DMA registers are not de-initialized
*/
ErrorStatus LL_DMA_DeInit(DMA_TypeDef *DMAx, uint32_t Channel)
{
ErrorStatus status = SUCCESS;
DMA_Channel_TypeDef *tmp;
/* Check the DMA Instance DMAx and Channel parameters*/
assert_param(IS_LL_DMA_ALL_CHANNEL_INSTANCE(DMAx, Channel) || (Channel == LL_DMA_CHANNEL_ALL));
if (Channel == LL_DMA_CHANNEL_ALL)
{
if (DMAx == DMA1)
{
/* Force reset of DMA clock */
LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_DMA1);
/* Release reset of DMA clock */
LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_DMA1);
}
#if defined(DMA2)
else if (DMAx == DMA2)
{
/* Force reset of DMA clock */
LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_DMA2);
/* Release reset of DMA clock */
LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_DMA2);
}
#endif
else
{
status = ERROR;
}
}
else
{
tmp = (DMA_Channel_TypeDef *)(__LL_DMA_GET_CHANNEL_INSTANCE(DMAx, Channel));
/* Disable the selected DMAx_Channely */
CLEAR_BIT(tmp->CCR, DMA_CCR_EN);
/* Reset DMAx_Channely control register */
WRITE_REG(tmp->CCR, 0U);
/* Reset DMAx_Channely remaining bytes register */
WRITE_REG(tmp->CNDTR, 0U);
/* Reset DMAx_Channely peripheral address register */
WRITE_REG(tmp->CPAR, 0U);
/* Reset DMAx_Channely memory 0 address register */
WRITE_REG(tmp->CMAR, 0U);
#if defined(DMAMUX1)
/* Reset Request register field for DMAx Channel */
LL_DMA_SetPeriphRequest(DMAx, Channel, LL_DMAMUX_REQ_MEM2MEM);
#else
/* Reset Request register field for DMAx Channel */
LL_DMA_SetPeriphRequest(DMAx, Channel, LL_DMA_REQUEST_0);
#endif /* DMAMUX1 */
if (Channel == LL_DMA_CHANNEL_1)
{
/* Reset interrupt pending bits for DMAx Channel1 */
LL_DMA_ClearFlag_GI1(DMAx);
}
else if (Channel == LL_DMA_CHANNEL_2)
{
/* Reset interrupt pending bits for DMAx Channel2 */
LL_DMA_ClearFlag_GI2(DMAx);
}
else if (Channel == LL_DMA_CHANNEL_3)
{
/* Reset interrupt pending bits for DMAx Channel3 */
LL_DMA_ClearFlag_GI3(DMAx);
}
else if (Channel == LL_DMA_CHANNEL_4)
{
/* Reset interrupt pending bits for DMAx Channel4 */
LL_DMA_ClearFlag_GI4(DMAx);
}
else if (Channel == LL_DMA_CHANNEL_5)
{
/* Reset interrupt pending bits for DMAx Channel5 */
LL_DMA_ClearFlag_GI5(DMAx);
}
else if (Channel == LL_DMA_CHANNEL_6)
{
/* Reset interrupt pending bits for DMAx Channel6 */
LL_DMA_ClearFlag_GI6(DMAx);
}
else if (Channel == LL_DMA_CHANNEL_7)
{
/* Reset interrupt pending bits for DMAx Channel7 */
LL_DMA_ClearFlag_GI7(DMAx);
}
else
{
status = ERROR;
}
}
return status;
}
/**
* @brief Initialize the DMA registers according to the specified parameters in DMA_InitStruct.
* @note To convert DMAx_Channely Instance to DMAx Instance and Channely, use helper macros :
* @arg @ref __LL_DMA_GET_INSTANCE
* @arg @ref __LL_DMA_GET_CHANNEL
* @param DMAx DMAx Instance
* @param Channel This parameter can be one of the following values:
* @arg @ref LL_DMA_CHANNEL_1
* @arg @ref LL_DMA_CHANNEL_2
* @arg @ref LL_DMA_CHANNEL_3
* @arg @ref LL_DMA_CHANNEL_4
* @arg @ref LL_DMA_CHANNEL_5
* @arg @ref LL_DMA_CHANNEL_6
* @arg @ref LL_DMA_CHANNEL_7
* @param DMA_InitStruct pointer to a @ref LL_DMA_InitTypeDef structure.
* @retval An ErrorStatus enumeration value:
* - SUCCESS: DMA registers are initialized
* - ERROR: Not applicable
*/
ErrorStatus LL_DMA_Init(DMA_TypeDef *DMAx, uint32_t Channel, LL_DMA_InitTypeDef *DMA_InitStruct)
{
/* Check the DMA Instance DMAx and Channel parameters*/
assert_param(IS_LL_DMA_ALL_CHANNEL_INSTANCE(DMAx, Channel));
/* Check the DMA parameters from DMA_InitStruct */
assert_param(IS_LL_DMA_DIRECTION(DMA_InitStruct->Direction));
assert_param(IS_LL_DMA_MODE(DMA_InitStruct->Mode));
assert_param(IS_LL_DMA_PERIPHINCMODE(DMA_InitStruct->PeriphOrM2MSrcIncMode));
assert_param(IS_LL_DMA_MEMORYINCMODE(DMA_InitStruct->MemoryOrM2MDstIncMode));
assert_param(IS_LL_DMA_PERIPHDATASIZE(DMA_InitStruct->PeriphOrM2MSrcDataSize));
assert_param(IS_LL_DMA_MEMORYDATASIZE(DMA_InitStruct->MemoryOrM2MDstDataSize));
assert_param(IS_LL_DMA_NBDATA(DMA_InitStruct->NbData));
assert_param(IS_LL_DMA_PERIPHREQUEST(DMA_InitStruct->PeriphRequest));
assert_param(IS_LL_DMA_PRIORITY(DMA_InitStruct->Priority));
/*---------------------------- DMAx CCR Configuration ------------------------
* Configure DMAx_Channely: data transfer direction, data transfer mode,
* peripheral and memory increment mode,
* data size alignment and priority level with parameters :
* - Direction: DMA_CCR_DIR and DMA_CCR_MEM2MEM bits
* - Mode: DMA_CCR_CIRC bit
* - PeriphOrM2MSrcIncMode: DMA_CCR_PINC bit
* - MemoryOrM2MDstIncMode: DMA_CCR_MINC bit
* - PeriphOrM2MSrcDataSize: DMA_CCR_PSIZE[1:0] bits
* - MemoryOrM2MDstDataSize: DMA_CCR_MSIZE[1:0] bits
* - Priority: DMA_CCR_PL[1:0] bits
*/
LL_DMA_ConfigTransfer(DMAx, Channel, DMA_InitStruct->Direction | \
DMA_InitStruct->Mode | \
DMA_InitStruct->PeriphOrM2MSrcIncMode | \
DMA_InitStruct->MemoryOrM2MDstIncMode | \
DMA_InitStruct->PeriphOrM2MSrcDataSize | \
DMA_InitStruct->MemoryOrM2MDstDataSize | \
DMA_InitStruct->Priority);
/*-------------------------- DMAx CMAR Configuration -------------------------
* Configure the memory or destination base address with parameter :
* - MemoryOrM2MDstAddress: DMA_CMAR_MA[31:0] bits
*/
LL_DMA_SetMemoryAddress(DMAx, Channel, DMA_InitStruct->MemoryOrM2MDstAddress);
/*-------------------------- DMAx CPAR Configuration -------------------------
* Configure the peripheral or source base address with parameter :
* - PeriphOrM2MSrcAddress: DMA_CPAR_PA[31:0] bits
*/
LL_DMA_SetPeriphAddress(DMAx, Channel, DMA_InitStruct->PeriphOrM2MSrcAddress);
/*--------------------------- DMAx CNDTR Configuration -----------------------
* Configure the peripheral base address with parameter :
* - NbData: DMA_CNDTR_NDT[15:0] bits
*/
LL_DMA_SetDataLength(DMAx, Channel, DMA_InitStruct->NbData);
#if defined(DMAMUX1)
/*--------------------------- DMAMUXx CCR Configuration ----------------------
* Configure the DMA request for DMA Channels on DMAMUX Channel x with parameter :
* - PeriphRequest: DMA_CxCR[7:0] bits
*/
LL_DMA_SetPeriphRequest(DMAx, Channel, DMA_InitStruct->PeriphRequest);
#else
/*--------------------------- DMAx CSELR Configuration -----------------------
* Configure the DMA request for DMA instance on Channel x with parameter :
* - PeriphRequest: DMA_CSELR[31:0] bits
*/
LL_DMA_SetPeriphRequest(DMAx, Channel, DMA_InitStruct->PeriphRequest);
#endif /* DMAMUX1 */
return SUCCESS;
}
/**
* @brief Set each @ref LL_DMA_InitTypeDef field to default value.
* @param DMA_InitStruct Pointer to a @ref LL_DMA_InitTypeDef structure.
* @retval None
*/
void LL_DMA_StructInit(LL_DMA_InitTypeDef *DMA_InitStruct)
{
/* Set DMA_InitStruct fields to default values */
DMA_InitStruct->PeriphOrM2MSrcAddress = 0x00000000U;
DMA_InitStruct->MemoryOrM2MDstAddress = 0x00000000U;
DMA_InitStruct->Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY;
DMA_InitStruct->Mode = LL_DMA_MODE_NORMAL;
DMA_InitStruct->PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
DMA_InitStruct->MemoryOrM2MDstIncMode = LL_DMA_MEMORY_NOINCREMENT;
DMA_InitStruct->PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_BYTE;
DMA_InitStruct->MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_BYTE;
DMA_InitStruct->NbData = 0x00000000U;
#if defined(DMAMUX1)
DMA_InitStruct->PeriphRequest = LL_DMAMUX_REQ_MEM2MEM;
#else
DMA_InitStruct->PeriphRequest = LL_DMA_REQUEST_0;
#endif /* DMAMUX1 */
DMA_InitStruct->Priority = LL_DMA_PRIORITY_LOW;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#endif /* DMA1 || DMA2 */
/**
* @}
*/
#endif /* USE_FULL_LL_DRIVER */

View File

@@ -0,0 +1,288 @@
/**
******************************************************************************
* @file stm32l4xx_ll_exti.c
* @author MCD Application Team
* @brief EXTI 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 "stm32l4xx_ll_exti.h"
#ifdef USE_FULL_ASSERT
#include "stm32_assert.h"
#else
#define assert_param(expr) ((void)0U)
#endif
/** @addtogroup STM32L4xx_LL_Driver
* @{
*/
#if defined (EXTI)
/** @defgroup EXTI_LL EXTI
* @{
*/
/* Private types -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private constants ---------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/
/** @addtogroup EXTI_LL_Private_Macros
* @{
*/
#define IS_LL_EXTI_LINE_0_31(__VALUE__) (((__VALUE__) & ~LL_EXTI_LINE_ALL_0_31) == 0x00000000U)
#define IS_LL_EXTI_LINE_32_63(__VALUE__) (((__VALUE__) & ~LL_EXTI_LINE_ALL_32_63) == 0x00000000U)
#define IS_LL_EXTI_MODE(__VALUE__) (((__VALUE__) == LL_EXTI_MODE_IT) \
|| ((__VALUE__) == LL_EXTI_MODE_EVENT) \
|| ((__VALUE__) == LL_EXTI_MODE_IT_EVENT))
#define IS_LL_EXTI_TRIGGER(__VALUE__) (((__VALUE__) == LL_EXTI_TRIGGER_NONE) \
|| ((__VALUE__) == LL_EXTI_TRIGGER_RISING) \
|| ((__VALUE__) == LL_EXTI_TRIGGER_FALLING) \
|| ((__VALUE__) == LL_EXTI_TRIGGER_RISING_FALLING))
/**
* @}
*/
/* Private function prototypes -----------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/** @addtogroup EXTI_LL_Exported_Functions
* @{
*/
/** @addtogroup EXTI_LL_EF_Init
* @{
*/
/**
* @brief De-initialize the EXTI registers to their default reset values.
* @retval An ErrorStatus enumeration value:
* - 0x00: EXTI registers are de-initialized
*/
uint32_t LL_EXTI_DeInit(void)
{
/* Interrupt mask register set to default reset values */
LL_EXTI_WriteReg(IMR1, 0xFF820000U);
/* Event mask register set to default reset values */
LL_EXTI_WriteReg(EMR1, 0x00000000U);
/* Rising Trigger selection register set to default reset values */
LL_EXTI_WriteReg(RTSR1, 0x00000000U);
/* Falling Trigger selection register set to default reset values */
LL_EXTI_WriteReg(FTSR1, 0x00000000U);
/* Software interrupt event register set to default reset values */
LL_EXTI_WriteReg(SWIER1, 0x00000000U);
/* Pending register clear */
LL_EXTI_WriteReg(PR1, 0x007DFFFFU);
/* Interrupt mask register 2 set to default reset values */
#if defined(LL_EXTI_LINE_40)
LL_EXTI_WriteReg(IMR2, 0x00000187U);
#else
LL_EXTI_WriteReg(IMR2, 0x00000087U);
#endif
/* Event mask register 2 set to default reset values */
LL_EXTI_WriteReg(EMR2, 0x00000000U);
/* Rising Trigger selection register 2 set to default reset values */
LL_EXTI_WriteReg(RTSR2, 0x00000000U);
/* Falling Trigger selection register 2 set to default reset values */
LL_EXTI_WriteReg(FTSR2, 0x00000000U);
/* Software interrupt event register 2 set to default reset values */
LL_EXTI_WriteReg(SWIER2, 0x00000000U);
/* Pending register 2 clear */
LL_EXTI_WriteReg(PR2, 0x00000078U);
return 0x00u;
}
/**
* @brief Initialize the EXTI registers according to the specified parameters in EXTI_InitStruct.
* @param EXTI_InitStruct pointer to a @ref LL_EXTI_InitTypeDef structure.
* @retval An ErrorStatus enumeration value:
* - 0x00: EXTI registers are initialized
* - any other value : wrong configuration
*/
uint32_t LL_EXTI_Init(LL_EXTI_InitTypeDef *EXTI_InitStruct)
{
uint32_t status = 0x00u;
/* Check the parameters */
assert_param(IS_LL_EXTI_LINE_0_31(EXTI_InitStruct->Line_0_31));
assert_param(IS_LL_EXTI_LINE_32_63(EXTI_InitStruct->Line_32_63));
assert_param(IS_FUNCTIONAL_STATE(EXTI_InitStruct->LineCommand));
assert_param(IS_LL_EXTI_MODE(EXTI_InitStruct->Mode));
/* ENABLE LineCommand */
if (EXTI_InitStruct->LineCommand != DISABLE)
{
assert_param(IS_LL_EXTI_TRIGGER(EXTI_InitStruct->Trigger));
/* Configure EXTI Lines in range from 0 to 31 */
if (EXTI_InitStruct->Line_0_31 != LL_EXTI_LINE_NONE)
{
switch (EXTI_InitStruct->Mode)
{
case LL_EXTI_MODE_IT:
/* First Disable Event on provided Lines */
LL_EXTI_DisableEvent_0_31(EXTI_InitStruct->Line_0_31);
/* Then Enable IT on provided Lines */
LL_EXTI_EnableIT_0_31(EXTI_InitStruct->Line_0_31);
break;
case LL_EXTI_MODE_EVENT:
/* First Disable IT on provided Lines */
LL_EXTI_DisableIT_0_31(EXTI_InitStruct->Line_0_31);
/* Then Enable Event on provided Lines */
LL_EXTI_EnableEvent_0_31(EXTI_InitStruct->Line_0_31);
break;
case LL_EXTI_MODE_IT_EVENT:
/* Directly Enable IT & Event on provided Lines */
LL_EXTI_EnableIT_0_31(EXTI_InitStruct->Line_0_31);
LL_EXTI_EnableEvent_0_31(EXTI_InitStruct->Line_0_31);
break;
default:
status = 0x01u;
break;
}
if (EXTI_InitStruct->Trigger != LL_EXTI_TRIGGER_NONE)
{
switch (EXTI_InitStruct->Trigger)
{
case LL_EXTI_TRIGGER_RISING:
/* First Disable Falling Trigger on provided Lines */
LL_EXTI_DisableFallingTrig_0_31(EXTI_InitStruct->Line_0_31);
/* Then Enable Rising Trigger on provided Lines */
LL_EXTI_EnableRisingTrig_0_31(EXTI_InitStruct->Line_0_31);
break;
case LL_EXTI_TRIGGER_FALLING:
/* First Disable Rising Trigger on provided Lines */
LL_EXTI_DisableRisingTrig_0_31(EXTI_InitStruct->Line_0_31);
/* Then Enable Falling Trigger on provided Lines */
LL_EXTI_EnableFallingTrig_0_31(EXTI_InitStruct->Line_0_31);
break;
case LL_EXTI_TRIGGER_RISING_FALLING:
LL_EXTI_EnableRisingTrig_0_31(EXTI_InitStruct->Line_0_31);
LL_EXTI_EnableFallingTrig_0_31(EXTI_InitStruct->Line_0_31);
break;
default:
status |= 0x02u;
break;
}
}
}
/* Configure EXTI Lines in range from 32 to 63 */
if (EXTI_InitStruct->Line_32_63 != LL_EXTI_LINE_NONE)
{
switch (EXTI_InitStruct->Mode)
{
case LL_EXTI_MODE_IT:
/* First Disable Event on provided Lines */
LL_EXTI_DisableEvent_32_63(EXTI_InitStruct->Line_32_63);
/* Then Enable IT on provided Lines */
LL_EXTI_EnableIT_32_63(EXTI_InitStruct->Line_32_63);
break;
case LL_EXTI_MODE_EVENT:
/* First Disable IT on provided Lines */
LL_EXTI_DisableIT_32_63(EXTI_InitStruct->Line_32_63);
/* Then Enable Event on provided Lines */
LL_EXTI_EnableEvent_32_63(EXTI_InitStruct->Line_32_63);
break;
case LL_EXTI_MODE_IT_EVENT:
/* Directly Enable IT & Event on provided Lines */
LL_EXTI_EnableIT_32_63(EXTI_InitStruct->Line_32_63);
LL_EXTI_EnableEvent_32_63(EXTI_InitStruct->Line_32_63);
break;
default:
status |= 0x04u;
break;
}
if (EXTI_InitStruct->Trigger != LL_EXTI_TRIGGER_NONE)
{
switch (EXTI_InitStruct->Trigger)
{
case LL_EXTI_TRIGGER_RISING:
/* First Disable Falling Trigger on provided Lines */
LL_EXTI_DisableFallingTrig_32_63(EXTI_InitStruct->Line_32_63);
/* Then Enable IT on provided Lines */
LL_EXTI_EnableRisingTrig_32_63(EXTI_InitStruct->Line_32_63);
break;
case LL_EXTI_TRIGGER_FALLING:
/* First Disable Rising Trigger on provided Lines */
LL_EXTI_DisableRisingTrig_32_63(EXTI_InitStruct->Line_32_63);
/* Then Enable Falling Trigger on provided Lines */
LL_EXTI_EnableFallingTrig_32_63(EXTI_InitStruct->Line_32_63);
break;
case LL_EXTI_TRIGGER_RISING_FALLING:
LL_EXTI_EnableRisingTrig_32_63(EXTI_InitStruct->Line_32_63);
LL_EXTI_EnableFallingTrig_32_63(EXTI_InitStruct->Line_32_63);
break;
default:
status = ERROR;
break;
}
}
}
}
/* DISABLE LineCommand */
else
{
/* De-configure EXTI Lines in range from 0 to 31 */
LL_EXTI_DisableIT_0_31(EXTI_InitStruct->Line_0_31);
LL_EXTI_DisableEvent_0_31(EXTI_InitStruct->Line_0_31);
/* De-configure EXTI Lines in range from 32 to 63 */
LL_EXTI_DisableIT_32_63(EXTI_InitStruct->Line_32_63);
LL_EXTI_DisableEvent_32_63(EXTI_InitStruct->Line_32_63);
}
return status;
}
/**
* @brief Set each @ref LL_EXTI_InitTypeDef field to default value.
* @param EXTI_InitStruct Pointer to a @ref LL_EXTI_InitTypeDef structure.
* @retval None
*/
void LL_EXTI_StructInit(LL_EXTI_InitTypeDef *EXTI_InitStruct)
{
EXTI_InitStruct->Line_0_31 = LL_EXTI_LINE_NONE;
EXTI_InitStruct->Line_32_63 = LL_EXTI_LINE_NONE;
EXTI_InitStruct->LineCommand = DISABLE;
EXTI_InitStruct->Mode = LL_EXTI_MODE_IT;
EXTI_InitStruct->Trigger = LL_EXTI_TRIGGER_FALLING;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#endif /* defined (EXTI) */
/**
* @}
*/
#endif /* USE_FULL_LL_DRIVER */

View File

@@ -0,0 +1,293 @@
/**
******************************************************************************
* @file stm32l4xx_ll_gpio.c
* @author MCD Application Team
* @brief GPIO 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 "stm32l4xx_ll_gpio.h"
#include "stm32l4xx_ll_bus.h"
#ifdef USE_FULL_ASSERT
#include "stm32_assert.h"
#else
#define assert_param(expr) ((void)0U)
#endif
/** @addtogroup STM32L4xx_LL_Driver
* @{
*/
#if defined (GPIOA) || defined (GPIOB) || defined (GPIOC) || defined (GPIOD) || defined (GPIOE) || defined (GPIOF) || defined (GPIOG) || defined (GPIOH) || defined (GPIOI)
/** @addtogroup GPIO_LL
* @{
*/
/** MISRA C:2012 deviation rule has been granted for following rules:
* Rule-12.2 - Medium: RHS argument is in interval [0,INF] which is out of
* range of the shift operator in following API :
* LL_GPIO_Init
*/
/* Private types -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private constants ---------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/
/** @addtogroup GPIO_LL_Private_Macros
* @{
*/
#define IS_LL_GPIO_PIN(__VALUE__) (((0x00u) < (__VALUE__)) && ((__VALUE__) <= (LL_GPIO_PIN_ALL)))
#define IS_LL_GPIO_MODE(__VALUE__) (((__VALUE__) == LL_GPIO_MODE_INPUT) ||\
((__VALUE__) == LL_GPIO_MODE_OUTPUT) ||\
((__VALUE__) == LL_GPIO_MODE_ALTERNATE) ||\
((__VALUE__) == LL_GPIO_MODE_ANALOG))
#define IS_LL_GPIO_OUTPUT_TYPE(__VALUE__) (((__VALUE__) == LL_GPIO_OUTPUT_PUSHPULL) ||\
((__VALUE__) == LL_GPIO_OUTPUT_OPENDRAIN))
#define IS_LL_GPIO_SPEED(__VALUE__) (((__VALUE__) == LL_GPIO_SPEED_FREQ_LOW) ||\
((__VALUE__) == LL_GPIO_SPEED_FREQ_MEDIUM) ||\
((__VALUE__) == LL_GPIO_SPEED_FREQ_HIGH) ||\
((__VALUE__) == LL_GPIO_SPEED_FREQ_VERY_HIGH))
#define IS_LL_GPIO_PULL(__VALUE__) (((__VALUE__) == LL_GPIO_PULL_NO) ||\
((__VALUE__) == LL_GPIO_PULL_UP) ||\
((__VALUE__) == LL_GPIO_PULL_DOWN))
#define IS_LL_GPIO_ALTERNATE(__VALUE__) (((__VALUE__) == LL_GPIO_AF_0 ) ||\
((__VALUE__) == LL_GPIO_AF_1 ) ||\
((__VALUE__) == LL_GPIO_AF_2 ) ||\
((__VALUE__) == LL_GPIO_AF_3 ) ||\
((__VALUE__) == LL_GPIO_AF_4 ) ||\
((__VALUE__) == LL_GPIO_AF_5 ) ||\
((__VALUE__) == LL_GPIO_AF_6 ) ||\
((__VALUE__) == LL_GPIO_AF_7 ) ||\
((__VALUE__) == LL_GPIO_AF_8 ) ||\
((__VALUE__) == LL_GPIO_AF_9 ) ||\
((__VALUE__) == LL_GPIO_AF_10 ) ||\
((__VALUE__) == LL_GPIO_AF_11 ) ||\
((__VALUE__) == LL_GPIO_AF_12 ) ||\
((__VALUE__) == LL_GPIO_AF_13 ) ||\
((__VALUE__) == LL_GPIO_AF_14 ) ||\
((__VALUE__) == LL_GPIO_AF_15 ))
/**
* @}
*/
/* Private function prototypes -----------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/** @addtogroup GPIO_LL_Exported_Functions
* @{
*/
/** @addtogroup GPIO_LL_EF_Init
* @{
*/
/**
* @brief De-initialize GPIO registers (Registers restored to their default values).
* @param GPIOx GPIO Port
* @retval An ErrorStatus enumeration value:
* - SUCCESS: GPIO registers are de-initialized
* - ERROR: Wrong GPIO Port
*/
ErrorStatus LL_GPIO_DeInit(GPIO_TypeDef *GPIOx)
{
ErrorStatus status = SUCCESS;
/* Check the parameters */
assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
/* Force and Release reset on clock of GPIOx Port */
if (GPIOx == GPIOA)
{
LL_AHB2_GRP1_ForceReset(LL_AHB2_GRP1_PERIPH_GPIOA);
LL_AHB2_GRP1_ReleaseReset(LL_AHB2_GRP1_PERIPH_GPIOA);
}
else if (GPIOx == GPIOB)
{
LL_AHB2_GRP1_ForceReset(LL_AHB2_GRP1_PERIPH_GPIOB);
LL_AHB2_GRP1_ReleaseReset(LL_AHB2_GRP1_PERIPH_GPIOB);
}
else if (GPIOx == GPIOC)
{
LL_AHB2_GRP1_ForceReset(LL_AHB2_GRP1_PERIPH_GPIOC);
LL_AHB2_GRP1_ReleaseReset(LL_AHB2_GRP1_PERIPH_GPIOC);
}
#if defined(GPIOD)
else if (GPIOx == GPIOD)
{
LL_AHB2_GRP1_ForceReset(LL_AHB2_GRP1_PERIPH_GPIOD);
LL_AHB2_GRP1_ReleaseReset(LL_AHB2_GRP1_PERIPH_GPIOD);
}
#endif /* GPIOD */
#if defined(GPIOE)
else if (GPIOx == GPIOE)
{
LL_AHB2_GRP1_ForceReset(LL_AHB2_GRP1_PERIPH_GPIOE);
LL_AHB2_GRP1_ReleaseReset(LL_AHB2_GRP1_PERIPH_GPIOE);
}
#endif /* GPIOE */
#if defined(GPIOF)
else if (GPIOx == GPIOF)
{
LL_AHB2_GRP1_ForceReset(LL_AHB2_GRP1_PERIPH_GPIOF);
LL_AHB2_GRP1_ReleaseReset(LL_AHB2_GRP1_PERIPH_GPIOF);
}
#endif /* GPIOF */
#if defined(GPIOG)
else if (GPIOx == GPIOG)
{
LL_AHB2_GRP1_ForceReset(LL_AHB2_GRP1_PERIPH_GPIOG);
LL_AHB2_GRP1_ReleaseReset(LL_AHB2_GRP1_PERIPH_GPIOG);
}
#endif /* GPIOG */
#if defined(GPIOH)
else if (GPIOx == GPIOH)
{
LL_AHB2_GRP1_ForceReset(LL_AHB2_GRP1_PERIPH_GPIOH);
LL_AHB2_GRP1_ReleaseReset(LL_AHB2_GRP1_PERIPH_GPIOH);
}
#endif /* GPIOH */
#if defined(GPIOI)
else if (GPIOx == GPIOI)
{
LL_AHB2_GRP1_ForceReset(LL_AHB2_GRP1_PERIPH_GPIOI);
LL_AHB2_GRP1_ReleaseReset(LL_AHB2_GRP1_PERIPH_GPIOI);
}
#endif /* GPIOI */
else
{
status = ERROR;
}
return (status);
}
/**
* @brief Initialize GPIO registers according to the specified parameters in GPIO_InitStruct.
* @param GPIOx GPIO Port
* @param GPIO_InitStruct pointer to a @ref LL_GPIO_InitTypeDef structure
* that contains the configuration information for the specified GPIO peripheral.
* @retval An ErrorStatus enumeration value:
* - SUCCESS: GPIO registers are initialized according to GPIO_InitStruct content
* - ERROR: Not applicable
*/
ErrorStatus LL_GPIO_Init(GPIO_TypeDef *GPIOx, LL_GPIO_InitTypeDef *GPIO_InitStruct)
{
uint32_t pinpos;
uint32_t currentpin;
/* Check the parameters */
assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
assert_param(IS_LL_GPIO_PIN(GPIO_InitStruct->Pin));
assert_param(IS_LL_GPIO_MODE(GPIO_InitStruct->Mode));
assert_param(IS_LL_GPIO_PULL(GPIO_InitStruct->Pull));
/* ------------------------- Configure the port pins ---------------- */
/* Initialize pinpos on first pin set */
pinpos = POSITION_VAL(GPIO_InitStruct->Pin);
/* Configure the port pins */
while (((GPIO_InitStruct->Pin) >> pinpos) != 0x00u)
{
/* Get current io position */
currentpin = (GPIO_InitStruct->Pin) & (0x00000001uL << pinpos);
if (currentpin != 0x00u)
{
if ((GPIO_InitStruct->Mode == LL_GPIO_MODE_OUTPUT) || (GPIO_InitStruct->Mode == LL_GPIO_MODE_ALTERNATE))
{
/* Check Speed mode parameters */
assert_param(IS_LL_GPIO_SPEED(GPIO_InitStruct->Speed));
/* Speed mode configuration */
LL_GPIO_SetPinSpeed(GPIOx, currentpin, GPIO_InitStruct->Speed);
/* Check Output mode parameters */
assert_param(IS_LL_GPIO_OUTPUT_TYPE(GPIO_InitStruct->OutputType));
/* Output mode configuration*/
LL_GPIO_SetPinOutputType(GPIOx, GPIO_InitStruct->Pin, GPIO_InitStruct->OutputType);
}
/* Pull-up Pull down resistor configuration*/
LL_GPIO_SetPinPull(GPIOx, currentpin, GPIO_InitStruct->Pull);
if (GPIO_InitStruct->Mode == LL_GPIO_MODE_ALTERNATE)
{
/* Check Alternate parameter */
assert_param(IS_LL_GPIO_ALTERNATE(GPIO_InitStruct->Alternate));
/* Speed mode configuration */
if (currentpin < LL_GPIO_PIN_8)
{
LL_GPIO_SetAFPin_0_7(GPIOx, currentpin, GPIO_InitStruct->Alternate);
}
else
{
LL_GPIO_SetAFPin_8_15(GPIOx, currentpin, GPIO_InitStruct->Alternate);
}
}
/* Pin Mode configuration */
LL_GPIO_SetPinMode(GPIOx, currentpin, GPIO_InitStruct->Mode);
}
pinpos++;
}
return (SUCCESS);
}
/**
* @brief Set each @ref LL_GPIO_InitTypeDef field to default value.
* @param GPIO_InitStruct pointer to a @ref LL_GPIO_InitTypeDef structure
* whose fields will be set to default values.
* @retval None
*/
void LL_GPIO_StructInit(LL_GPIO_InitTypeDef *GPIO_InitStruct)
{
/* Reset GPIO init structure parameters values */
GPIO_InitStruct->Pin = LL_GPIO_PIN_ALL;
GPIO_InitStruct->Mode = LL_GPIO_MODE_ANALOG;
GPIO_InitStruct->Speed = LL_GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct->OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct->Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct->Alternate = LL_GPIO_AF_0;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#endif /* defined (GPIOA) || defined (GPIOB) || defined (GPIOC) || defined (GPIOD) || defined (GPIOE) || defined (GPIOF) || defined (GPIOG) || defined (GPIOH) || defined (GPIOI) */
/**
* @}
*/
#endif /* USE_FULL_LL_DRIVER */

View File

@@ -0,0 +1,82 @@
/**
******************************************************************************
* @file stm32l4xx_ll_pwr.c
* @author MCD Application Team
* @brief PWR 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 "stm32l4xx_ll_pwr.h"
#include "stm32l4xx_ll_bus.h"
/** @addtogroup STM32L4xx_LL_Driver
* @{
*/
#if defined(PWR)
/** @defgroup PWR_LL PWR
* @{
*/
/* Private types -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private constants ---------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/** @addtogroup PWR_LL_Exported_Functions
* @{
*/
/** @addtogroup PWR_LL_EF_Init
* @{
*/
/**
* @brief De-initialize the PWR registers to their default reset values.
* @retval An ErrorStatus enumeration value:
* - SUCCESS: PWR registers are de-initialized
* - ERROR: not applicable
*/
ErrorStatus LL_PWR_DeInit(void)
{
/* Force reset of PWR clock */
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_PWR);
/* Release reset of PWR clock */
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_PWR);
return SUCCESS;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#endif /* defined(PWR) */
/**
* @}
*/
#endif /* USE_FULL_LL_DRIVER */

View File

@@ -0,0 +1,2039 @@
/**
******************************************************************************
* @file stm32l4xx_ll_rcc.c
* @author MCD Application Team
* @brief RCC 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 "stm32l4xx_ll_rcc.h"
#ifdef USE_FULL_ASSERT
#include "stm32_assert.h"
#else
#define assert_param(expr) ((void)0U)
#endif
/** @addtogroup STM32L4xx_LL_Driver
* @{
*/
#if defined(RCC)
/** @addtogroup RCC_LL
* @{
*/
/* Private types -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private constants ---------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/
/** @addtogroup RCC_LL_Private_Macros
* @{
*/
#if defined(RCC_CCIPR_USART3SEL)
#define IS_LL_RCC_USART_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_USART1_CLKSOURCE) \
|| ((__VALUE__) == LL_RCC_USART2_CLKSOURCE) \
|| ((__VALUE__) == LL_RCC_USART3_CLKSOURCE))
#else
#define IS_LL_RCC_USART_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_USART1_CLKSOURCE) \
|| ((__VALUE__) == LL_RCC_USART2_CLKSOURCE))
#endif /* RCC_CCIPR_USART3SEL */
#if defined(RCC_CCIPR_UART4SEL) && defined(RCC_CCIPR_UART5SEL)
#define IS_LL_RCC_UART_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_UART4_CLKSOURCE) \
|| ((__VALUE__) == LL_RCC_UART5_CLKSOURCE))
#elif defined(RCC_CCIPR_UART4SEL)
#define IS_LL_RCC_UART_CLKSOURCE(__VALUE__) ((__VALUE__) == LL_RCC_UART4_CLKSOURCE)
#elif defined(RCC_CCIPR_UART5SEL)
#define IS_LL_RCC_UART_CLKSOURCE(__VALUE__) ((__VALUE__) == LL_RCC_UART5_CLKSOURCE)
#endif /* RCC_CCIPR_UART4SEL && RCC_CCIPR_UART5SEL*/
#define IS_LL_RCC_LPUART_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_LPUART1_CLKSOURCE))
#if defined(RCC_CCIPR_I2C2SEL) && defined(RCC_CCIPR_I2C3SEL) && defined(RCC_CCIPR2_I2C4SEL)
#define IS_LL_RCC_I2C_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_I2C1_CLKSOURCE) \
|| ((__VALUE__) == LL_RCC_I2C2_CLKSOURCE) \
|| ((__VALUE__) == LL_RCC_I2C3_CLKSOURCE) \
|| ((__VALUE__) == LL_RCC_I2C4_CLKSOURCE))
#elif defined(RCC_CCIPR_I2C2SEL) && defined(RCC_CCIPR_I2C3SEL)
#define IS_LL_RCC_I2C_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_I2C1_CLKSOURCE) \
|| ((__VALUE__) == LL_RCC_I2C2_CLKSOURCE) \
|| ((__VALUE__) == LL_RCC_I2C3_CLKSOURCE))
#elif !defined(RCC_CCIPR_I2C2SEL) && defined(RCC_CCIPR_I2C3SEL)
#define IS_LL_RCC_I2C_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_I2C1_CLKSOURCE) \
|| ((__VALUE__) == LL_RCC_I2C3_CLKSOURCE))
#else
#define IS_LL_RCC_I2C_CLKSOURCE(__VALUE__) ((__VALUE__) == LL_RCC_I2C1_CLKSOURCE)
#endif /* RCC_CCIPR_I2C2SEL && RCC_CCIPR_I2C3SEL && RCC_CCIPR2_I2C4SEL */
#define IS_LL_RCC_LPTIM_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_LPTIM1_CLKSOURCE) \
|| ((__VALUE__) == LL_RCC_LPTIM2_CLKSOURCE))
#if defined(RCC_CCIPR_SAI2SEL) || defined(RCC_CCIPR2_SAI2SEL)
#define IS_LL_RCC_SAI_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_SAI1_CLKSOURCE) \
|| ((__VALUE__) == LL_RCC_SAI2_CLKSOURCE))
#elif defined(RCC_CCIPR_SAI1SEL) || defined(RCC_CCIPR2_SAI1SEL)
#define IS_LL_RCC_SAI_CLKSOURCE(__VALUE__) ((__VALUE__) == LL_RCC_SAI1_CLKSOURCE)
#endif /* RCC_CCIPR_SAI2SEL RCC_CCIPR2_SAI2SEL ||*/
#if defined(SDMMC1)
#if defined(RCC_CCIPR2_SDMMCSEL)
#define IS_LL_RCC_SDMMC_KERNELCLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_SDMMC1_KERNELCLKSOURCE))
#endif /* RCC_CCIPR2_SDMMCSEL */
#define IS_LL_RCC_SDMMC_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_SDMMC1_CLKSOURCE))
#endif /* SDMMC1 */
#define IS_LL_RCC_RNG_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_RNG_CLKSOURCE))
#if defined(USB_OTG_FS) || defined(USB)
#define IS_LL_RCC_USB_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_USB_CLKSOURCE))
#endif /* USB_OTG_FS || USB */
#define IS_LL_RCC_ADC_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_ADC_CLKSOURCE))
#if defined(SWPMI1)
#define IS_LL_RCC_SWPMI_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_SWPMI1_CLKSOURCE))
#endif /* SWPMI1 */
#if defined(DFSDM1_Channel0)
#define IS_LL_RCC_DFSDM_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_DFSDM1_CLKSOURCE))
#if defined(RCC_CCIPR2_DFSDM1SEL)
#define IS_LL_RCC_DFSDM_AUDIO_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_DFSDM1_AUDIO_CLKSOURCE))
#endif /* RCC_CCIPR2_DFSDM1SEL */
#endif /* DFSDM1_Channel0 */
#if defined(DSI)
#define IS_LL_RCC_DSI_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_DSI_CLKSOURCE))
#endif /* DSI */
#if defined(LTDC)
#define IS_LL_RCC_LTDC_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_LTDC_CLKSOURCE))
#endif /* LTDC */
#if defined(OCTOSPI1)
#define IS_LL_RCC_OCTOSPI_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_OCTOSPI_CLKSOURCE))
#endif /* OCTOSPI */
/**
* @}
*/
/* Private function prototypes -----------------------------------------------*/
/** @defgroup RCC_LL_Private_Functions RCC Private functions
* @{
*/
static uint32_t RCC_GetSystemClockFreq(void);
static uint32_t RCC_GetHCLKClockFreq(uint32_t SYSCLK_Frequency);
static uint32_t RCC_GetPCLK1ClockFreq(uint32_t HCLK_Frequency);
static uint32_t RCC_GetPCLK2ClockFreq(uint32_t HCLK_Frequency);
static uint32_t RCC_PLL_GetFreqDomain_SYS(void);
#if defined(RCC_CCIPR_SAI1SEL) || defined(RCC_CCIPR_SAI2SEL) || defined(RCC_CCIPR2_SAI1SEL) || defined(RCC_CCIPR2_SAI2SEL)
static uint32_t RCC_PLL_GetFreqDomain_SAI(void);
#endif
static uint32_t RCC_PLL_GetFreqDomain_48M(void);
#if defined(RCC_PLLSAI1_SUPPORT)
static uint32_t RCC_PLLSAI1_GetFreqDomain_SAI(void);
static uint32_t RCC_PLLSAI1_GetFreqDomain_48M(void);
static uint32_t RCC_PLLSAI1_GetFreqDomain_ADC(void);
#endif /* RCC_PLLSAI1_SUPPORT */
#if defined(RCC_PLLSAI2_SUPPORT)
static uint32_t RCC_PLLSAI2_GetFreqDomain_SAI(void);
#if defined(LTDC)
static uint32_t RCC_PLLSAI2_GetFreqDomain_LTDC(void);
#else
static uint32_t RCC_PLLSAI2_GetFreqDomain_ADC(void);
#endif /* LTDC */
#if defined(DSI)
static uint32_t RCC_PLLSAI2_GetFreqDomain_DSI(void);
#endif /* DSI */
#endif /*RCC_PLLSAI2_SUPPORT*/
/**
* @}
*/
/* Exported functions --------------------------------------------------------*/
/** @addtogroup RCC_LL_Exported_Functions
* @{
*/
/** @addtogroup RCC_LL_EF_Init
* @{
*/
/**
* @brief Reset the RCC clock configuration to the default reset state.
* @note The default reset state of the clock configuration is given below:
* - MSI ON and used as system clock source
* - HSE, HSI, PLL, PLLSAI1 and PLLSAI2 OFF
* - AHB, APB1 and APB2 prescaler set to 1.
* - CSS, MCO OFF
* - All interrupts disabled
* @note This function doesn't modify the configuration of the
* - Peripheral clocks
* - LSI, LSE and RTC clocks
* @retval An ErrorStatus enumeration value:
* - SUCCESS: RCC registers are de-initialized
* - ERROR: not applicable
*/
ErrorStatus LL_RCC_DeInit(void)
{
__IO uint32_t vl_mask;
/* Set MSION bit */
LL_RCC_MSI_Enable();
/* Insure MSIRDY bit is set before writing default MSIRANGE value */
while (LL_RCC_MSI_IsReady() == 0U)
{
}
/* Set MSIRANGE default value */
LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_6);
/* Set MSITRIM bits to the reset value*/
LL_RCC_MSI_SetCalibTrimming(0);
/* Set HSITRIM bits to the reset value*/
#if defined(RCC_ICSCR_HSITRIM_6)
LL_RCC_HSI_SetCalibTrimming(0x40U);
#else
LL_RCC_HSI_SetCalibTrimming(0x10U);
#endif /* RCC_ICSCR_HSITRIM_6 */
/* Reset CFGR register */
LL_RCC_WriteReg(CFGR, 0x00000000U);
/* Read CR register */
vl_mask = LL_RCC_ReadReg(CR);
/* Reset HSION, HSIKERON, HSIASFS, HSEON, PLLON bits */
CLEAR_BIT(vl_mask,
(RCC_CR_HSION | RCC_CR_HSIASFS | RCC_CR_HSIKERON | RCC_CR_HSEON | RCC_CR_PLLON));
#if defined(RCC_PLLSAI1_SUPPORT)
/* Reset PLLSAI1ON bit */
CLEAR_BIT(vl_mask, RCC_CR_PLLSAI1ON);
#endif /*RCC_PLLSAI1_SUPPORT*/
#if defined(RCC_PLLSAI2_SUPPORT)
/* Reset PLLSAI2ON bit */
CLEAR_BIT(vl_mask, RCC_CR_PLLSAI2ON);
#endif /*RCC_PLLSAI2_SUPPORT*/
/* Write new value in CR register */
LL_RCC_WriteReg(CR, vl_mask);
#if defined(RCC_PLLSAI2_SUPPORT)
/* Wait for PLLRDY, PLLSAI1RDY and PLLSAI2RDY bits to be reset */
while(READ_BIT(RCC->CR, RCC_CR_PLLRDY | RCC_CR_PLLSAI1RDY | RCC_CR_PLLSAI2RDY) != 0U)
{
}
#elif defined(RCC_PLLSAI1_SUPPORT)
/* Wait for PLLRDY and PLLSAI1RDY to be reset */
while(READ_BIT(RCC->CR, RCC_CR_PLLRDY | RCC_CR_PLLSAI1RDY) != 0U)
{
}
#else
/* Wait for PLLRDY bit to be reset */
while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) != 0U)
{
}
#endif
/* Reset PLLCFGR register */
LL_RCC_WriteReg(PLLCFGR, 16U << RCC_PLLCFGR_PLLN_Pos);
#if defined(RCC_PLLSAI1_SUPPORT)
/* Reset PLLSAI1CFGR register */
LL_RCC_WriteReg(PLLSAI1CFGR, 16U << RCC_PLLSAI1CFGR_PLLSAI1N_Pos);
#endif /*RCC_PLLSAI1_SUPPORT*/
#if defined(RCC_PLLSAI2_SUPPORT)
/* Reset PLLSAI2CFGR register */
LL_RCC_WriteReg(PLLSAI2CFGR, 16U << RCC_PLLSAI2CFGR_PLLSAI2N_Pos);
#endif /*RCC_PLLSAI2_SUPPORT*/
/* Reset HSEBYP bit */
LL_RCC_HSE_DisableBypass();
/* Disable all interrupts */
LL_RCC_WriteReg(CIER, 0x00000000U);
/* Clear all interrupt flags */
vl_mask = RCC_CICR_LSIRDYC | RCC_CICR_LSERDYC | RCC_CICR_MSIRDYC | RCC_CICR_HSIRDYC | RCC_CICR_HSERDYC | RCC_CICR_PLLRDYC | \
RCC_CICR_CSSC | RCC_CICR_LSECSSC;
#if defined(RCC_HSI48_SUPPORT)
vl_mask |= RCC_CICR_HSI48RDYC;
#endif
#if defined(RCC_PLLSAI1_SUPPORT)
vl_mask |= RCC_CICR_PLLSAI1RDYC;
#endif
#if defined(RCC_PLLSAI2_SUPPORT)
vl_mask |= RCC_CICR_PLLSAI2RDYC;
#endif
LL_RCC_WriteReg(CICR, vl_mask);
/* Clear reset flags */
LL_RCC_ClearResetFlags();
return SUCCESS;
}
/**
* @}
*/
/** @addtogroup RCC_LL_EF_Get_Freq
* @brief Return the frequencies of different on chip clocks; System, AHB, APB1 and APB2 buses clocks
* and different peripheral clocks available on the device.
* @note If SYSCLK source is MSI, function returns values based on MSI_VALUE(*)
* @note If SYSCLK source is HSI, function returns values based on HSI_VALUE(**)
* @note If SYSCLK source is HSE, function returns values based on HSE_VALUE(***)
* @note If SYSCLK source is PLL, function returns values based on HSE_VALUE(***)
* or HSI_VALUE(**) or MSI_VALUE(*) multiplied/divided by the PLL factors.
* @note (*) MSI_VALUE is a constant defined in this file (default value
* 4 MHz) but the real value may vary depending on the variations
* in voltage and temperature.
* @note (**) HSI_VALUE is a constant defined in this file (default value
* 16 MHz) but the real value may vary depending on the variations
* in voltage and temperature.
* @note (***) HSE_VALUE is a constant defined in this file (default value
* 8 MHz), user has to ensure that HSE_VALUE is same as the real
* frequency of the crystal used. Otherwise, this function may
* have wrong result.
* @note The result of this function could be incorrect when using fractional
* value for HSE crystal.
* @note This function can be used by the user application to compute the
* baud-rate for the communication peripherals or configure other parameters.
* @{
*/
/**
* @brief Return the frequencies of different on chip clocks; System, AHB, APB1 and APB2 buses clocks
* @note Each time SYSCLK, HCLK, PCLK1 and/or PCLK2 clock changes, this function
* must be called to update structure fields. Otherwise, any
* configuration based on this function will be incorrect.
* @param RCC_Clocks pointer to a @ref LL_RCC_ClocksTypeDef structure which will hold the clocks frequencies
* @retval None
*/
void LL_RCC_GetSystemClocksFreq(LL_RCC_ClocksTypeDef *RCC_Clocks)
{
/* Get SYSCLK frequency */
RCC_Clocks->SYSCLK_Frequency = RCC_GetSystemClockFreq();
/* HCLK clock frequency */
RCC_Clocks->HCLK_Frequency = RCC_GetHCLKClockFreq(RCC_Clocks->SYSCLK_Frequency);
/* PCLK1 clock frequency */
RCC_Clocks->PCLK1_Frequency = RCC_GetPCLK1ClockFreq(RCC_Clocks->HCLK_Frequency);
/* PCLK2 clock frequency */
RCC_Clocks->PCLK2_Frequency = RCC_GetPCLK2ClockFreq(RCC_Clocks->HCLK_Frequency);
}
/**
* @brief Return USARTx clock frequency
* @param USARTxSource This parameter can be one of the following values:
* @arg @ref LL_RCC_USART1_CLKSOURCE
* @arg @ref LL_RCC_USART2_CLKSOURCE
* @arg @ref LL_RCC_USART3_CLKSOURCE (*)
*
* (*) value not defined in all devices.
* @retval USART clock frequency (in Hz)
* - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (HSI or LSE) is not ready
*/
uint32_t LL_RCC_GetUSARTClockFreq(uint32_t USARTxSource)
{
uint32_t usart_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
/* Check parameter */
assert_param(IS_LL_RCC_USART_CLKSOURCE(USARTxSource));
if (USARTxSource == LL_RCC_USART1_CLKSOURCE)
{
/* USART1CLK clock frequency */
switch (LL_RCC_GetUSARTClockSource(USARTxSource))
{
case LL_RCC_USART1_CLKSOURCE_SYSCLK: /* USART1 Clock is System Clock */
usart_frequency = RCC_GetSystemClockFreq();
break;
case LL_RCC_USART1_CLKSOURCE_HSI: /* USART1 Clock is HSI Osc. */
if (LL_RCC_HSI_IsReady() != 0U)
{
usart_frequency = HSI_VALUE;
}
break;
case LL_RCC_USART1_CLKSOURCE_LSE: /* USART1 Clock is LSE Osc. */
if (LL_RCC_LSE_IsReady() != 0U)
{
usart_frequency = LSE_VALUE;
}
break;
case LL_RCC_USART1_CLKSOURCE_PCLK2: /* USART1 Clock is PCLK2 */
usart_frequency = RCC_GetPCLK2ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq()));
break;
default:
break;
}
}
else if (USARTxSource == LL_RCC_USART2_CLKSOURCE)
{
/* USART2CLK clock frequency */
switch (LL_RCC_GetUSARTClockSource(USARTxSource))
{
case LL_RCC_USART2_CLKSOURCE_SYSCLK: /* USART2 Clock is System Clock */
usart_frequency = RCC_GetSystemClockFreq();
break;
case LL_RCC_USART2_CLKSOURCE_HSI: /* USART2 Clock is HSI Osc. */
if (LL_RCC_HSI_IsReady() != 0U)
{
usart_frequency = HSI_VALUE;
}
break;
case LL_RCC_USART2_CLKSOURCE_LSE: /* USART2 Clock is LSE Osc. */
if (LL_RCC_LSE_IsReady() != 0U)
{
usart_frequency = LSE_VALUE;
}
break;
case LL_RCC_USART2_CLKSOURCE_PCLK1: /* USART2 Clock is PCLK1 */
usart_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq()));
break;
default:
break;
}
}
else
{
#if defined(RCC_CCIPR_USART3SEL)
if (USARTxSource == LL_RCC_USART3_CLKSOURCE)
{
/* USART3CLK clock frequency */
switch (LL_RCC_GetUSARTClockSource(USARTxSource))
{
case LL_RCC_USART3_CLKSOURCE_SYSCLK: /* USART3 Clock is System Clock */
usart_frequency = RCC_GetSystemClockFreq();
break;
case LL_RCC_USART3_CLKSOURCE_HSI: /* USART3 Clock is HSI Osc. */
if (LL_RCC_HSI_IsReady() != 0U)
{
usart_frequency = HSI_VALUE;
}
break;
case LL_RCC_USART3_CLKSOURCE_LSE: /* USART3 Clock is LSE Osc. */
if (LL_RCC_LSE_IsReady() != 0U)
{
usart_frequency = LSE_VALUE;
}
break;
case LL_RCC_USART3_CLKSOURCE_PCLK1: /* USART3 Clock is PCLK1 */
usart_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq()));
break;
default:
break;
}
}
#endif /* RCC_CCIPR_USART3SEL */
}
return usart_frequency;
}
#if defined(RCC_CCIPR_UART4SEL) || defined(RCC_CCIPR_UART5SEL)
/**
* @brief Return UARTx clock frequency
* @param UARTxSource This parameter can be one of the following values:
* @arg @ref LL_RCC_UART4_CLKSOURCE
* @arg @ref LL_RCC_UART5_CLKSOURCE
* @retval UART clock frequency (in Hz)
* - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (HSI or LSE) is not ready
*/
uint32_t LL_RCC_GetUARTClockFreq(uint32_t UARTxSource)
{
uint32_t uart_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
/* Check parameter */
assert_param(IS_LL_RCC_UART_CLKSOURCE(UARTxSource));
#if defined(RCC_CCIPR_UART4SEL)
if (UARTxSource == LL_RCC_UART4_CLKSOURCE)
{
/* UART4CLK clock frequency */
switch (LL_RCC_GetUARTClockSource(UARTxSource))
{
case LL_RCC_UART4_CLKSOURCE_SYSCLK: /* UART4 Clock is System Clock */
uart_frequency = RCC_GetSystemClockFreq();
break;
case LL_RCC_UART4_CLKSOURCE_HSI: /* UART4 Clock is HSI Osc. */
if (LL_RCC_HSI_IsReady() != 0U)
{
uart_frequency = HSI_VALUE;
}
break;
case LL_RCC_UART4_CLKSOURCE_LSE: /* UART4 Clock is LSE Osc. */
if (LL_RCC_LSE_IsReady() != 0U)
{
uart_frequency = LSE_VALUE;
}
break;
case LL_RCC_UART4_CLKSOURCE_PCLK1: /* UART4 Clock is PCLK1 */
uart_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq()));
break;
default:
break;
}
}
#endif /* RCC_CCIPR_UART4SEL */
#if defined(RCC_CCIPR_UART5SEL)
if (UARTxSource == LL_RCC_UART5_CLKSOURCE)
{
/* UART5CLK clock frequency */
switch (LL_RCC_GetUARTClockSource(UARTxSource))
{
case LL_RCC_UART5_CLKSOURCE_SYSCLK: /* UART5 Clock is System Clock */
uart_frequency = RCC_GetSystemClockFreq();
break;
case LL_RCC_UART5_CLKSOURCE_HSI: /* UART5 Clock is HSI Osc. */
if (LL_RCC_HSI_IsReady() != 0U)
{
uart_frequency = HSI_VALUE;
}
break;
case LL_RCC_UART5_CLKSOURCE_LSE: /* UART5 Clock is LSE Osc. */
if (LL_RCC_LSE_IsReady() != 0U)
{
uart_frequency = LSE_VALUE;
}
break;
case LL_RCC_UART5_CLKSOURCE_PCLK1: /* UART5 Clock is PCLK1 */
uart_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq()));
break;
default:
break;
}
}
#endif /* RCC_CCIPR_UART5SEL */
return uart_frequency;
}
#endif /* RCC_CCIPR_UART4SEL || RCC_CCIPR_UART5SEL */
/**
* @brief Return I2Cx clock frequency
* @param I2CxSource This parameter can be one of the following values:
* @arg @ref LL_RCC_I2C1_CLKSOURCE
* @arg @ref LL_RCC_I2C2_CLKSOURCE (*)
* @arg @ref LL_RCC_I2C3_CLKSOURCE
* @arg @ref LL_RCC_I2C4_CLKSOURCE (*)
*
* (*) value not defined in all devices.
* @retval I2C clock frequency (in Hz)
* - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that HSI oscillator is not ready
*/
uint32_t LL_RCC_GetI2CClockFreq(uint32_t I2CxSource)
{
uint32_t i2c_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
/* Check parameter */
assert_param(IS_LL_RCC_I2C_CLKSOURCE(I2CxSource));
if (I2CxSource == LL_RCC_I2C1_CLKSOURCE)
{
/* I2C1 CLK clock frequency */
switch (LL_RCC_GetI2CClockSource(I2CxSource))
{
case LL_RCC_I2C1_CLKSOURCE_SYSCLK: /* I2C1 Clock is System Clock */
i2c_frequency = RCC_GetSystemClockFreq();
break;
case LL_RCC_I2C1_CLKSOURCE_HSI: /* I2C1 Clock is HSI Osc. */
if (LL_RCC_HSI_IsReady() != 0U)
{
i2c_frequency = HSI_VALUE;
}
break;
case LL_RCC_I2C1_CLKSOURCE_PCLK1: /* I2C1 Clock is PCLK1 */
i2c_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq()));
break;
default:
break;
}
}
#if defined(RCC_CCIPR_I2C2SEL)
else if (I2CxSource == LL_RCC_I2C2_CLKSOURCE)
{
/* I2C2 CLK clock frequency */
switch (LL_RCC_GetI2CClockSource(I2CxSource))
{
case LL_RCC_I2C2_CLKSOURCE_SYSCLK: /* I2C2 Clock is System Clock */
i2c_frequency = RCC_GetSystemClockFreq();
break;
case LL_RCC_I2C2_CLKSOURCE_HSI: /* I2C2 Clock is HSI Osc. */
if (LL_RCC_HSI_IsReady() != 0U)
{
i2c_frequency = HSI_VALUE;
}
break;
case LL_RCC_I2C2_CLKSOURCE_PCLK1: /* I2C2 Clock is PCLK1 */
i2c_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq()));
break;
default:
break;
}
}
#endif /*RCC_CCIPR_I2C2SEL*/
else
{
if (I2CxSource == LL_RCC_I2C3_CLKSOURCE)
{
/* I2C3 CLK clock frequency */
switch (LL_RCC_GetI2CClockSource(I2CxSource))
{
case LL_RCC_I2C3_CLKSOURCE_SYSCLK: /* I2C3 Clock is System Clock */
i2c_frequency = RCC_GetSystemClockFreq();
break;
case LL_RCC_I2C3_CLKSOURCE_HSI: /* I2C3 Clock is HSI Osc. */
if (LL_RCC_HSI_IsReady() != 0U)
{
i2c_frequency = HSI_VALUE;
}
break;
case LL_RCC_I2C3_CLKSOURCE_PCLK1: /* I2C3 Clock is PCLK1 */
i2c_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq()));
break;
default:
break;
}
}
#if defined(RCC_CCIPR2_I2C4SEL)
else
{
if (I2CxSource == LL_RCC_I2C4_CLKSOURCE)
{
/* I2C4 CLK clock frequency */
switch (LL_RCC_GetI2CClockSource(I2CxSource))
{
case LL_RCC_I2C4_CLKSOURCE_SYSCLK: /* I2C4 Clock is System Clock */
i2c_frequency = RCC_GetSystemClockFreq();
break;
case LL_RCC_I2C4_CLKSOURCE_HSI: /* I2C4 Clock is HSI Osc. */
if (LL_RCC_HSI_IsReady() != 0U)
{
i2c_frequency = HSI_VALUE;
}
break;
case LL_RCC_I2C4_CLKSOURCE_PCLK1: /* I2C4 Clock is PCLK1 */
i2c_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq()));
break;
default:
break;
}
}
}
#endif /*RCC_CCIPR2_I2C4SEL*/
}
return i2c_frequency;
}
/**
* @brief Return LPUARTx clock frequency
* @param LPUARTxSource This parameter can be one of the following values:
* @arg @ref LL_RCC_LPUART1_CLKSOURCE
* @retval LPUART clock frequency (in Hz)
* - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (HSI or LSE) is not ready
*/
uint32_t LL_RCC_GetLPUARTClockFreq(uint32_t LPUARTxSource)
{
uint32_t lpuart_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
/* Check parameter */
assert_param(IS_LL_RCC_LPUART_CLKSOURCE(LPUARTxSource));
/* LPUART1CLK clock frequency */
switch (LL_RCC_GetLPUARTClockSource(LPUARTxSource))
{
case LL_RCC_LPUART1_CLKSOURCE_SYSCLK: /* LPUART1 Clock is System Clock */
lpuart_frequency = RCC_GetSystemClockFreq();
break;
case LL_RCC_LPUART1_CLKSOURCE_HSI: /* LPUART1 Clock is HSI Osc. */
if (LL_RCC_HSI_IsReady() != 0U)
{
lpuart_frequency = HSI_VALUE;
}
break;
case LL_RCC_LPUART1_CLKSOURCE_LSE: /* LPUART1 Clock is LSE Osc. */
if (LL_RCC_LSE_IsReady() != 0U)
{
lpuart_frequency = LSE_VALUE;
}
break;
case LL_RCC_LPUART1_CLKSOURCE_PCLK1: /* LPUART1 Clock is PCLK1 */
lpuart_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq()));
break;
default:
break;
}
return lpuart_frequency;
}
/**
* @brief Return LPTIMx clock frequency
* @param LPTIMxSource This parameter can be one of the following values:
* @arg @ref LL_RCC_LPTIM1_CLKSOURCE
* @arg @ref LL_RCC_LPTIM2_CLKSOURCE
* @retval LPTIM clock frequency (in Hz)
* - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (HSI, LSI or LSE) is not ready
*/
uint32_t LL_RCC_GetLPTIMClockFreq(uint32_t LPTIMxSource)
{
uint32_t lptim_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
/* Check parameter */
assert_param(IS_LL_RCC_LPTIM_CLKSOURCE(LPTIMxSource));
if (LPTIMxSource == LL_RCC_LPTIM1_CLKSOURCE)
{
/* LPTIM1CLK clock frequency */
switch (LL_RCC_GetLPTIMClockSource(LPTIMxSource))
{
case LL_RCC_LPTIM1_CLKSOURCE_LSI: /* LPTIM1 Clock is LSI Osc. */
if (LL_RCC_LSI_IsReady() != 0U)
{
#if defined(RCC_CSR_LSIPREDIV)
if (LL_RCC_LSI_GetPrediv() == LL_RCC_LSI_PREDIV_128)
{
lptim_frequency = LSI_VALUE / 128U;
}
else
#endif /* RCC_CSR_LSIPREDIV */
{
lptim_frequency = LSI_VALUE;
}
}
break;
case LL_RCC_LPTIM1_CLKSOURCE_HSI: /* LPTIM1 Clock is HSI Osc. */
if (LL_RCC_HSI_IsReady() != 0U)
{
lptim_frequency = HSI_VALUE;
}
break;
case LL_RCC_LPTIM1_CLKSOURCE_LSE: /* LPTIM1 Clock is LSE Osc. */
if (LL_RCC_LSE_IsReady() != 0U)
{
lptim_frequency = LSE_VALUE;
}
break;
case LL_RCC_LPTIM1_CLKSOURCE_PCLK1: /* LPTIM1 Clock is PCLK1 */
lptim_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq()));
break;
default:
break;
}
}
else
{
if (LPTIMxSource == LL_RCC_LPTIM2_CLKSOURCE)
{
/* LPTIM2CLK clock frequency */
switch (LL_RCC_GetLPTIMClockSource(LPTIMxSource))
{
case LL_RCC_LPTIM2_CLKSOURCE_LSI: /* LPTIM2 Clock is LSI Osc. */
if (LL_RCC_LSI_IsReady() != 0U)
{
#if defined(RCC_CSR_LSIPREDIV)
if (LL_RCC_LSI_GetPrediv() == LL_RCC_LSI_PREDIV_128)
{
lptim_frequency = LSI_VALUE / 128U;
}
else
#endif /* RCC_CSR_LSIPREDIV */
{
lptim_frequency = LSI_VALUE;
}
}
break;
case LL_RCC_LPTIM2_CLKSOURCE_HSI: /* LPTIM2 Clock is HSI Osc. */
if (LL_RCC_HSI_IsReady() != 0U)
{
lptim_frequency = HSI_VALUE;
}
break;
case LL_RCC_LPTIM2_CLKSOURCE_LSE: /* LPTIM2 Clock is LSE Osc. */
if (LL_RCC_LSE_IsReady() != 0U)
{
lptim_frequency = LSE_VALUE;
}
break;
case LL_RCC_LPTIM2_CLKSOURCE_PCLK1: /* LPTIM2 Clock is PCLK1 */
lptim_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq()));
break;
default:
break;
}
}
}
return lptim_frequency;
}
#if defined(RCC_CCIPR_SAI1SEL) || defined(RCC_CCIPR_SAI2SEL) || defined(RCC_CCIPR2_SAI1SEL) || defined(RCC_CCIPR2_SAI2SEL)
/**
* @brief Return SAIx clock frequency
* @param SAIxSource This parameter can be one of the following values:
* @arg @ref LL_RCC_SAI1_CLKSOURCE
* @arg @ref LL_RCC_SAI2_CLKSOURCE (*)
*
* (*) value not defined in all devices.
* @retval SAI clock frequency (in Hz)
* - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that PLL is not ready
*/
uint32_t LL_RCC_GetSAIClockFreq(uint32_t SAIxSource)
{
uint32_t sai_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
/* Check parameter */
assert_param(IS_LL_RCC_SAI_CLKSOURCE(SAIxSource));
if (SAIxSource == LL_RCC_SAI1_CLKSOURCE)
{
/* SAI1CLK clock frequency */
switch (LL_RCC_GetSAIClockSource(SAIxSource))
{
case LL_RCC_SAI1_CLKSOURCE_PLLSAI1: /* PLLSAI1 clock used as SAI1 clock source */
if (LL_RCC_PLLSAI1_IsReady() != 0U)
{
if (LL_RCC_PLLSAI1_IsEnabledDomain_SAI() != 0U)
{
sai_frequency = RCC_PLLSAI1_GetFreqDomain_SAI();
}
}
break;
#if defined(RCC_PLLSAI2_SUPPORT)
case LL_RCC_SAI1_CLKSOURCE_PLLSAI2: /* PLLSAI2 clock used as SAI1 clock source */
if (LL_RCC_PLLSAI2_IsReady() != 0U)
{
if (LL_RCC_PLLSAI2_IsEnabledDomain_SAI() != 0U)
{
sai_frequency = RCC_PLLSAI2_GetFreqDomain_SAI();
}
}
break;
#endif /* RCC_PLLSAI2_SUPPORT */
case LL_RCC_SAI1_CLKSOURCE_PLL: /* PLL clock used as SAI1 clock source */
if (LL_RCC_PLL_IsReady() != 0U)
{
if (LL_RCC_PLL_IsEnabledDomain_SAI() != 0U)
{
sai_frequency = RCC_PLL_GetFreqDomain_SAI();
}
}
break;
case LL_RCC_SAI1_CLKSOURCE_PIN: /* External input clock used as SAI1 clock source */
sai_frequency = EXTERNAL_SAI1_CLOCK_VALUE;
break;
default:
break;
}
}
else
{
#if defined(RCC_CCIPR_SAI2SEL) || defined(RCC_CCIPR2_SAI2SEL)
if (SAIxSource == LL_RCC_SAI2_CLKSOURCE)
{
/* SAI2CLK clock frequency */
switch (LL_RCC_GetSAIClockSource(SAIxSource))
{
case LL_RCC_SAI2_CLKSOURCE_PLLSAI1: /* PLLSAI1 clock used as SAI2 clock source */
if (LL_RCC_PLLSAI1_IsReady() != 0U)
{
if (LL_RCC_PLLSAI1_IsEnabledDomain_SAI() != 0U)
{
sai_frequency = RCC_PLLSAI1_GetFreqDomain_SAI();
}
}
break;
#if defined(RCC_PLLSAI2_SUPPORT)
case LL_RCC_SAI2_CLKSOURCE_PLLSAI2: /* PLLSAI2 clock used as SAI2 clock source */
if (LL_RCC_PLLSAI2_IsReady() != 0U)
{
if (LL_RCC_PLLSAI2_IsEnabledDomain_SAI() != 0U)
{
sai_frequency = RCC_PLLSAI2_GetFreqDomain_SAI();
}
}
break;
#endif /* RCC_PLLSAI2_SUPPORT */
case LL_RCC_SAI2_CLKSOURCE_PLL: /* PLL clock used as SAI2 clock source */
if (LL_RCC_PLL_IsReady() != 0U)
{
if (LL_RCC_PLL_IsEnabledDomain_SAI() != 0U)
{
sai_frequency = RCC_PLL_GetFreqDomain_SAI();
}
}
break;
case LL_RCC_SAI2_CLKSOURCE_PIN: /* External input clock used as SAI2 clock source */
sai_frequency = EXTERNAL_SAI2_CLOCK_VALUE;
break;
default:
break;
}
}
#endif /* RCC_CCIPR_SAI2SEL || RCC_CCIPR2_SAI2SEL */
}
return sai_frequency;
}
#endif /* RCC_CCIPR_SAI1SEL || RCC_CCIPR_SAI2SEL || RCC_CCIPR2_SAI1SEL || RCC_CCIPR2_SAI2SEL*/
#if defined(SDMMC1)
#if defined(RCC_CCIPR2_SDMMCSEL)
/**
* @brief Return SDMMCx kernel clock frequency
* @param SDMMCxSource This parameter can be one of the following values:
* @arg @ref LL_RCC_SDMMC1_KERNELCLKSOURCE
* @retval SDMMC clock frequency (in Hz)
* - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (MSI) or PLL is not ready
* - @ref LL_RCC_PERIPH_FREQUENCY_NA indicates that no clock source selected
*/
uint32_t LL_RCC_GetSDMMCKernelClockFreq(uint32_t SDMMCxSource)
{
uint32_t sdmmc_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
/* Check parameter */
assert_param(IS_LL_RCC_SDMMC_KERNELCLKSOURCE(SDMMCxSource));
/* SDMMC1CLK kernel clock frequency */
switch (LL_RCC_GetSDMMCKernelClockSource(SDMMCxSource))
{
case LL_RCC_SDMMC1_KERNELCLKSOURCE_48CLK: /* 48MHz clock from internal multiplexor used as SDMMC1 clock source */
sdmmc_frequency = LL_RCC_GetSDMMCClockFreq(LL_RCC_SDMMC1_CLKSOURCE);
break;
case LL_RCC_SDMMC1_KERNELCLKSOURCE_PLLP: /* PLL "P" output (PLLSAI3CLK) clock used as SDMMC1 clock source */
if (LL_RCC_PLL_IsReady() != 0U)
{
if (LL_RCC_PLL_IsEnabledDomain_SAI() != 0U)
{
sdmmc_frequency = RCC_PLL_GetFreqDomain_SAI();
}
}
break;
default:
sdmmc_frequency = LL_RCC_PERIPH_FREQUENCY_NA;
break;
}
return sdmmc_frequency;
}
#endif
/**
* @brief Return SDMMCx clock frequency
* @param SDMMCxSource This parameter can be one of the following values:
* @arg @ref LL_RCC_SDMMC1_CLKSOURCE
* @retval SDMMC clock frequency (in Hz)
* - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (MSI) or PLL is not ready
* - @ref LL_RCC_PERIPH_FREQUENCY_NA indicates that no clock source selected
*/
uint32_t LL_RCC_GetSDMMCClockFreq(uint32_t SDMMCxSource)
{
uint32_t sdmmc_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
/* Check parameter */
assert_param(IS_LL_RCC_SDMMC_CLKSOURCE(SDMMCxSource));
/* SDMMC1CLK clock frequency */
switch (LL_RCC_GetSDMMCClockSource(SDMMCxSource))
{
#if defined(LL_RCC_SDMMC1_CLKSOURCE_PLLSAI1)
case LL_RCC_SDMMC1_CLKSOURCE_PLLSAI1: /* PLLSAI1 clock used as SDMMC1 clock source */
if (LL_RCC_PLLSAI1_IsReady() != 0U)
{
if (LL_RCC_PLLSAI1_IsEnabledDomain_48M() != 0U)
{
sdmmc_frequency = RCC_PLLSAI1_GetFreqDomain_48M();
}
}
break;
#endif
case LL_RCC_SDMMC1_CLKSOURCE_PLL: /* PLL clock used as SDMMC1 clock source */
if (LL_RCC_PLL_IsReady() != 0U)
{
if (LL_RCC_PLL_IsEnabledDomain_48M() != 0U)
{
sdmmc_frequency = RCC_PLL_GetFreqDomain_48M();
}
}
break;
#if defined(LL_RCC_SDMMC1_CLKSOURCE_MSI)
case LL_RCC_SDMMC1_CLKSOURCE_MSI: /* MSI clock used as SDMMC1 clock source */
if (LL_RCC_MSI_IsReady() != 0U)
{
sdmmc_frequency = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(),
((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ?
LL_RCC_MSI_GetRange() :
LL_RCC_MSI_GetRangeAfterStandby()));
}
break;
#endif
#if defined(RCC_HSI48_SUPPORT)
case LL_RCC_SDMMC1_CLKSOURCE_HSI48: /* HSI48 used as SDMMC1 clock source */
if (LL_RCC_HSI48_IsReady() != 0U)
{
sdmmc_frequency = HSI48_VALUE;
}
break;
#else
case LL_RCC_SDMMC1_CLKSOURCE_NONE: /* No clock used as SDMMC1 clock source */
#endif
default:
sdmmc_frequency = LL_RCC_PERIPH_FREQUENCY_NA;
break;
}
return sdmmc_frequency;
}
#endif /* SDMMC1 */
/**
* @brief Return RNGx clock frequency
* @param RNGxSource This parameter can be one of the following values:
* @arg @ref LL_RCC_RNG_CLKSOURCE
* @retval RNG clock frequency (in Hz)
* - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (MSI) or PLL is not ready
* - @ref LL_RCC_PERIPH_FREQUENCY_NA indicates that no clock source selected
*/
uint32_t LL_RCC_GetRNGClockFreq(uint32_t RNGxSource)
{
uint32_t rng_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
/* Check parameter */
assert_param(IS_LL_RCC_RNG_CLKSOURCE(RNGxSource));
/* RNGCLK clock frequency */
switch (LL_RCC_GetRNGClockSource(RNGxSource))
{
#if defined(RCC_PLLSAI1_SUPPORT)
case LL_RCC_RNG_CLKSOURCE_PLLSAI1: /* PLLSAI1 clock used as RNG clock source */
if (LL_RCC_PLLSAI1_IsReady() != 0U)
{
if (LL_RCC_PLLSAI1_IsEnabledDomain_48M() !=0U)
{
rng_frequency = RCC_PLLSAI1_GetFreqDomain_48M();
}
}
break;
#endif /* RCC_PLLSAI1_SUPPORT */
case LL_RCC_RNG_CLKSOURCE_PLL: /* PLL clock used as RNG clock source */
if (LL_RCC_PLL_IsReady() != 0U)
{
if (LL_RCC_PLL_IsEnabledDomain_48M() != 0U)
{
rng_frequency = RCC_PLL_GetFreqDomain_48M();
}
}
break;
case LL_RCC_RNG_CLKSOURCE_MSI: /* MSI clock used as RNG clock source */
if (LL_RCC_MSI_IsReady() != 0U)
{
rng_frequency = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(),
((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ?
LL_RCC_MSI_GetRange() :
LL_RCC_MSI_GetRangeAfterStandby()));
}
break;
#if defined(RCC_HSI48_SUPPORT)
case LL_RCC_RNG_CLKSOURCE_HSI48: /* HSI48 used as RNG clock source */
if (LL_RCC_HSI48_IsReady() != 0U)
{
rng_frequency = HSI48_VALUE;
}
break;
#else
case LL_RCC_RNG_CLKSOURCE_NONE: /* No clock used as RNG clock source */
#endif
default:
rng_frequency = LL_RCC_PERIPH_FREQUENCY_NA;
break;
}
return rng_frequency;
}
#if defined(USB_OTG_FS)||defined(USB)
/**
* @brief Return USBx clock frequency
* @param USBxSource This parameter can be one of the following values:
* @arg @ref LL_RCC_USB_CLKSOURCE
* @retval USB clock frequency (in Hz)
* - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (MSI) or PLL is not ready
* - @ref LL_RCC_PERIPH_FREQUENCY_NA indicates that no clock source selected
*/
uint32_t LL_RCC_GetUSBClockFreq(uint32_t USBxSource)
{
uint32_t usb_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
/* Check parameter */
assert_param(IS_LL_RCC_USB_CLKSOURCE(USBxSource));
/* USBCLK clock frequency */
switch (LL_RCC_GetUSBClockSource(USBxSource))
{
#if defined(RCC_PLLSAI1_SUPPORT)
case LL_RCC_USB_CLKSOURCE_PLLSAI1: /* PLLSAI1 clock used as USB clock source */
if (LL_RCC_PLLSAI1_IsReady() != 0U)
{
if (LL_RCC_PLLSAI1_IsEnabledDomain_48M() != 0U)
{
usb_frequency = RCC_PLLSAI1_GetFreqDomain_48M();
}
}
break;
#endif /* RCC_PLLSAI1_SUPPORT */
case LL_RCC_USB_CLKSOURCE_PLL: /* PLL clock used as USB clock source */
if (LL_RCC_PLL_IsReady() != 0U)
{
if (LL_RCC_PLL_IsEnabledDomain_48M() != 0U)
{
usb_frequency = RCC_PLL_GetFreqDomain_48M();
}
}
break;
case LL_RCC_USB_CLKSOURCE_MSI: /* MSI clock used as USB clock source */
if (LL_RCC_MSI_IsReady() != 0U)
{
usb_frequency = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(),
((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ?
LL_RCC_MSI_GetRange() :
LL_RCC_MSI_GetRangeAfterStandby()));
}
break;
#if defined(RCC_HSI48_SUPPORT)
case LL_RCC_USB_CLKSOURCE_HSI48: /* HSI48 used as USB clock source */
if (LL_RCC_HSI48_IsReady() != 0U)
{
usb_frequency = HSI48_VALUE;
}
break;
#else
case LL_RCC_USB_CLKSOURCE_NONE: /* No clock used as USB clock source */
#endif
default:
usb_frequency = LL_RCC_PERIPH_FREQUENCY_NA;
break;
}
return usb_frequency;
}
#endif /* USB_OTG_FS || USB */
/**
* @brief Return ADCx clock frequency
* @param ADCxSource This parameter can be one of the following values:
* @arg @ref LL_RCC_ADC_CLKSOURCE
* @retval ADC clock frequency (in Hz)
* - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (MSI) or PLL is not ready
* - @ref LL_RCC_PERIPH_FREQUENCY_NA indicates that no clock source selected
*/
uint32_t LL_RCC_GetADCClockFreq(uint32_t ADCxSource)
{
uint32_t adc_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
/* Check parameter */
assert_param(IS_LL_RCC_ADC_CLKSOURCE(ADCxSource));
/* ADCCLK clock frequency */
switch (LL_RCC_GetADCClockSource(ADCxSource))
{
#if defined(RCC_PLLSAI1_SUPPORT)
case LL_RCC_ADC_CLKSOURCE_PLLSAI1: /* PLLSAI1 clock used as ADC clock source */
if (LL_RCC_PLLSAI1_IsReady() != 0U)
{
if (LL_RCC_PLLSAI1_IsEnabledDomain_ADC() != 0U)
{
adc_frequency = RCC_PLLSAI1_GetFreqDomain_ADC();
}
}
break;
#endif /* RCC_PLLSAI1_SUPPORT */
#if defined(RCC_PLLSAI2_SUPPORT) && defined(LL_RCC_ADC_CLKSOURCE_PLLSAI2)
case LL_RCC_ADC_CLKSOURCE_PLLSAI2: /* PLLSAI2 clock used as ADC clock source */
if (LL_RCC_PLLSAI2_IsReady() != 0U)
{
if (LL_RCC_PLLSAI2_IsEnabledDomain_ADC() != 0U)
{
adc_frequency = RCC_PLLSAI2_GetFreqDomain_ADC();
}
}
break;
#endif /* RCC_PLLSAI2_SUPPORT && LL_RCC_ADC_CLKSOURCE_PLLSAI2 */
case LL_RCC_ADC_CLKSOURCE_SYSCLK: /* SYSCLK clock used as ADC clock source */
adc_frequency = RCC_GetSystemClockFreq();
break;
case LL_RCC_ADC_CLKSOURCE_NONE: /* No clock used as ADC clock source */
default:
adc_frequency = LL_RCC_PERIPH_FREQUENCY_NA;
break;
}
return adc_frequency;
}
#if defined(SWPMI1)
/**
* @brief Return SWPMIx clock frequency
* @param SWPMIxSource This parameter can be one of the following values:
* @arg @ref LL_RCC_SWPMI1_CLKSOURCE
* @retval SWPMI clock frequency (in Hz)
* - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (HSI) is not ready
*/
uint32_t LL_RCC_GetSWPMIClockFreq(uint32_t SWPMIxSource)
{
uint32_t swpmi_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
/* Check parameter */
assert_param(IS_LL_RCC_SWPMI_CLKSOURCE(SWPMIxSource));
/* SWPMI1CLK clock frequency */
switch (LL_RCC_GetSWPMIClockSource(SWPMIxSource))
{
case LL_RCC_SWPMI1_CLKSOURCE_HSI: /* SWPMI1 Clock is HSI Osc. */
if (LL_RCC_HSI_IsReady())
{
swpmi_frequency = HSI_VALUE;
}
break;
case LL_RCC_SWPMI1_CLKSOURCE_PCLK1: /* SWPMI1 Clock is PCLK1 */
swpmi_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq()));
break;
default:
break;
}
return swpmi_frequency;
}
#endif /* SWPMI1 */
#if defined(DFSDM1_Channel0)
/**
* @brief Return DFSDMx clock frequency
* @param DFSDMxSource This parameter can be one of the following values:
* @arg @ref LL_RCC_DFSDM1_CLKSOURCE
* @retval DFSDM clock frequency (in Hz)
*/
uint32_t LL_RCC_GetDFSDMClockFreq(uint32_t DFSDMxSource)
{
uint32_t dfsdm_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
/* Check parameter */
assert_param(IS_LL_RCC_DFSDM_CLKSOURCE(DFSDMxSource));
/* DFSDM1CLK clock frequency */
switch (LL_RCC_GetDFSDMClockSource(DFSDMxSource))
{
case LL_RCC_DFSDM1_CLKSOURCE_SYSCLK: /* DFSDM1 Clock is SYSCLK */
dfsdm_frequency = RCC_GetSystemClockFreq();
break;
case LL_RCC_DFSDM1_CLKSOURCE_PCLK2: /* DFSDM1 Clock is PCLK2 */
dfsdm_frequency = RCC_GetPCLK2ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq()));
break;
default:
break;
}
return dfsdm_frequency;
}
#if defined(RCC_CCIPR2_DFSDM1SEL)
/**
* @brief Return DFSDMx Audio clock frequency
* @param DFSDMxSource This parameter can be one of the following values:
* @arg @ref LL_RCC_DFSDM1_AUDIO_CLKSOURCE
* @retval DFSDM clock frequency (in Hz)
* - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready
*/
uint32_t LL_RCC_GetDFSDMAudioClockFreq(uint32_t DFSDMxSource)
{
uint32_t dfsdm_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
/* Check parameter */
assert_param(IS_LL_RCC_DFSDM_AUDIO_CLKSOURCE(DFSDMxSource));
/* DFSDM1CLK clock frequency */
switch (LL_RCC_GetDFSDMAudioClockSource(DFSDMxSource))
{
case LL_RCC_DFSDM1_AUDIO_CLKSOURCE_SAI1: /* SAI1 clock used as DFSDM1 audio clock */
dfsdm_frequency = LL_RCC_GetSAIClockFreq(LL_RCC_SAI1_CLKSOURCE);
break;
case LL_RCC_DFSDM1_AUDIO_CLKSOURCE_MSI: /* MSI clock used as DFSDM1 audio clock */
if (LL_RCC_MSI_IsReady() != 0U)
{
dfsdm_frequency = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(),
((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ?
LL_RCC_MSI_GetRange() :
LL_RCC_MSI_GetRangeAfterStandby()));
}
break;
case LL_RCC_DFSDM1_AUDIO_CLKSOURCE_HSI: /* HSI clock used as DFSDM1 audio clock */
default:
if (LL_RCC_HSI_IsReady() != 0U)
{
dfsdm_frequency = HSI_VALUE;
}
break;
}
return dfsdm_frequency;
}
#endif /* RCC_CCIPR2_DFSDM1SEL */
#endif /* DFSDM1_Channel0 */
#if defined(DSI)
/**
* @brief Return DSI clock frequency
* @param DSIxSource This parameter can be one of the following values:
* @arg @ref LL_RCC_DSI_CLKSOURCE
* @retval DSI clock frequency (in Hz)
* - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready
* - @ref LL_RCC_PERIPH_FREQUENCY_NA indicates that external clock is used
*/
uint32_t LL_RCC_GetDSIClockFreq(uint32_t DSIxSource)
{
uint32_t dsi_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
/* Check parameter */
assert_param(IS_LL_RCC_DSI_CLKSOURCE(DSIxSource));
/* DSICLK clock frequency */
switch (LL_RCC_GetDSIClockSource(DSIxSource))
{
case LL_RCC_DSI_CLKSOURCE_PLL: /* DSI Clock is PLLSAI2 Osc. */
if (LL_RCC_PLLSAI2_IsReady() != 0U)
{
if (LL_RCC_PLLSAI2_IsEnabledDomain_DSI() != 0U)
{
dsi_frequency = RCC_PLLSAI2_GetFreqDomain_DSI();
}
}
break;
case LL_RCC_DSI_CLKSOURCE_PHY: /* DSI Clock is DSI physical clock. */
default:
dsi_frequency = LL_RCC_PERIPH_FREQUENCY_NA;
break;
}
return dsi_frequency;
}
#endif /* DSI */
#if defined(LTDC)
/**
* @brief Return LTDC clock frequency
* @param LTDCxSource This parameter can be one of the following values:
* @arg @ref LL_RCC_LTDC_CLKSOURCE
* @retval LTDC clock frequency (in Hz)
* - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator PLLSAI is not ready
*/
uint32_t LL_RCC_GetLTDCClockFreq(uint32_t LTDCxSource)
{
uint32_t ltdc_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
/* Check parameter */
assert_param(IS_LL_RCC_LTDC_CLKSOURCE(LTDCxSource));
if (LL_RCC_PLLSAI2_IsReady() != 0U)
{
if (LL_RCC_PLLSAI2_IsEnabledDomain_LTDC() != 0U)
{
ltdc_frequency = RCC_PLLSAI2_GetFreqDomain_LTDC();
}
}
return ltdc_frequency;
}
#endif /* LTDC */
#if defined(OCTOSPI1)
/**
* @brief Return OCTOSPI clock frequency
* @param OCTOSPIxSource This parameter can be one of the following values:
* @arg @ref LL_RCC_OCTOSPI_CLKSOURCE
* @retval OCTOSPI clock frequency (in Hz)
* - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator PLLSAI is not ready
*/
uint32_t LL_RCC_GetOCTOSPIClockFreq(uint32_t OCTOSPIxSource)
{
uint32_t octospi_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
/* Check parameter */
assert_param(IS_LL_RCC_OCTOSPI_CLKSOURCE(OCTOSPIxSource));
/* OCTOSPI clock frequency */
switch (LL_RCC_GetOCTOSPIClockSource(OCTOSPIxSource))
{
case LL_RCC_OCTOSPI_CLKSOURCE_SYSCLK: /* OCTOSPI clock is SYSCLK */
octospi_frequency = RCC_GetSystemClockFreq();
break;
case LL_RCC_OCTOSPI_CLKSOURCE_MSI: /* MSI clock used as OCTOSPI clock */
if (LL_RCC_MSI_IsReady() != 0U)
{
octospi_frequency = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(),
((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ?
LL_RCC_MSI_GetRange() :
LL_RCC_MSI_GetRangeAfterStandby()));
}
break;
case LL_RCC_OCTOSPI_CLKSOURCE_PLL: /* PLL clock used as OCTOSPI source */
if (LL_RCC_PLL_IsReady() != 0U)
{
if (LL_RCC_PLL_IsEnabledDomain_48M() != 0U)
{
octospi_frequency = RCC_PLL_GetFreqDomain_48M();
}
}
break;
default:
octospi_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
break;
}
return octospi_frequency;
}
#endif /* OCTOSPI1 */
/**
* @}
*/
/**
* @}
*/
/** @addtogroup RCC_LL_Private_Functions
* @{
*/
/**
* @brief Return SYSTEM clock frequency
* @retval SYSTEM clock frequency (in Hz)
*/
static uint32_t RCC_GetSystemClockFreq(void)
{
uint32_t frequency;
/* Get SYSCLK source -------------------------------------------------------*/
switch (LL_RCC_GetSysClkSource())
{
case LL_RCC_SYS_CLKSOURCE_STATUS_MSI: /* MSI used as system clock source */
frequency = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(),
((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ?
LL_RCC_MSI_GetRange() :
LL_RCC_MSI_GetRangeAfterStandby()));
break;
case LL_RCC_SYS_CLKSOURCE_STATUS_HSI: /* HSI used as system clock source */
frequency = HSI_VALUE;
break;
case LL_RCC_SYS_CLKSOURCE_STATUS_HSE: /* HSE used as system clock source */
frequency = HSE_VALUE;
break;
case LL_RCC_SYS_CLKSOURCE_STATUS_PLL: /* PLL used as system clock source */
frequency = RCC_PLL_GetFreqDomain_SYS();
break;
default:
frequency = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(),
((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ?
LL_RCC_MSI_GetRange() :
LL_RCC_MSI_GetRangeAfterStandby()));
break;
}
return frequency;
}
/**
* @brief Return HCLK clock frequency
* @param SYSCLK_Frequency SYSCLK clock frequency
* @retval HCLK clock frequency (in Hz)
*/
static uint32_t RCC_GetHCLKClockFreq(uint32_t SYSCLK_Frequency)
{
/* HCLK clock frequency */
return __LL_RCC_CALC_HCLK_FREQ(SYSCLK_Frequency, LL_RCC_GetAHBPrescaler());
}
/**
* @brief Return PCLK1 clock frequency
* @param HCLK_Frequency HCLK clock frequency
* @retval PCLK1 clock frequency (in Hz)
*/
static uint32_t RCC_GetPCLK1ClockFreq(uint32_t HCLK_Frequency)
{
/* PCLK1 clock frequency */
return __LL_RCC_CALC_PCLK1_FREQ(HCLK_Frequency, LL_RCC_GetAPB1Prescaler());
}
/**
* @brief Return PCLK2 clock frequency
* @param HCLK_Frequency HCLK clock frequency
* @retval PCLK2 clock frequency (in Hz)
*/
static uint32_t RCC_GetPCLK2ClockFreq(uint32_t HCLK_Frequency)
{
/* PCLK2 clock frequency */
return __LL_RCC_CALC_PCLK2_FREQ(HCLK_Frequency, LL_RCC_GetAPB2Prescaler());
}
/**
* @brief Return PLL clock frequency used for system domain
* @retval PLL clock frequency (in Hz)
*/
static uint32_t RCC_PLL_GetFreqDomain_SYS(void)
{
uint32_t pllinputfreq, pllsource;
/* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN
SYSCLK = PLL_VCO / PLLR
*/
pllsource = LL_RCC_PLL_GetMainSource();
switch (pllsource)
{
case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLL clock source */
pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(),
((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ?
LL_RCC_MSI_GetRange() :
LL_RCC_MSI_GetRangeAfterStandby()));
break;
case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */
pllinputfreq = HSI_VALUE;
break;
case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */
pllinputfreq = HSE_VALUE;
break;
default:
pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(),
((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ?
LL_RCC_MSI_GetRange() :
LL_RCC_MSI_GetRangeAfterStandby()));
break;
}
return __LL_RCC_CALC_PLLCLK_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(),
LL_RCC_PLL_GetN(), LL_RCC_PLL_GetR());
}
#if defined(SAI1)
/**
* @brief Return PLL clock frequency used for SAI domain
* @retval PLL clock frequency (in Hz)
*/
static uint32_t RCC_PLL_GetFreqDomain_SAI(void)
{
uint32_t pllinputfreq, pllsource;
/* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE / PLLM) * PLLN
SAI Domain clock = PLL_VCO / PLLP
*/
pllsource = LL_RCC_PLL_GetMainSource();
switch (pllsource)
{
case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLL clock source */
pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(),
((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ?
LL_RCC_MSI_GetRange() :
LL_RCC_MSI_GetRangeAfterStandby()));
break;
case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */
pllinputfreq = HSI_VALUE;
break;
case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */
pllinputfreq = HSE_VALUE;
break;
default:
pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(),
((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ?
LL_RCC_MSI_GetRange() :
LL_RCC_MSI_GetRangeAfterStandby()));
break;
}
return __LL_RCC_CALC_PLLCLK_SAI_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(),
LL_RCC_PLL_GetN(), LL_RCC_PLL_GetP());
}
#endif /* SAI1 */
/**
* @brief Return PLL clock frequency used for 48 MHz domain
* @retval PLL clock frequency (in Hz)
*/
static uint32_t RCC_PLL_GetFreqDomain_48M(void)
{
uint32_t pllinputfreq, pllsource;
/* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN
48M Domain clock = PLL_VCO / PLLQ
*/
pllsource = LL_RCC_PLL_GetMainSource();
switch (pllsource)
{
case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLL clock source */
pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(),
((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ?
LL_RCC_MSI_GetRange() :
LL_RCC_MSI_GetRangeAfterStandby()));
break;
case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */
pllinputfreq = HSI_VALUE;
break;
case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */
pllinputfreq = HSE_VALUE;
break;
default:
pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(),
((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ?
LL_RCC_MSI_GetRange() :
LL_RCC_MSI_GetRangeAfterStandby()));
break;
}
return __LL_RCC_CALC_PLLCLK_48M_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(),
LL_RCC_PLL_GetN(), LL_RCC_PLL_GetQ());
}
#if defined(DSI)
/**
* @brief Return PLL clock frequency used for DSI clock
* @retval PLL clock frequency (in Hz)
*/
static uint32_t RCC_PLLSAI2_GetFreqDomain_DSI(void)
{
uint32_t pllinputfreq, pllsource;
/* PLLSAI2_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLSAI2M) * PLLSAI2N */
/* DSICLK = PLLSAI2_VCO / PLLSAI2R */
pllsource = LL_RCC_PLL_GetMainSource();
switch (pllsource)
{
case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLLSAI2 clock source */
pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(),
((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ?
LL_RCC_MSI_GetRange() :
LL_RCC_MSI_GetRangeAfterStandby()));
break;
case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLLSAI2 clock source */
pllinputfreq = HSI_VALUE;
break;
case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLLSAI2 clock source */
pllinputfreq = HSE_VALUE;
break;
default:
pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(),
((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ?
LL_RCC_MSI_GetRange() :
LL_RCC_MSI_GetRangeAfterStandby()));
break;
}
return __LL_RCC_CALC_PLLSAI2_DSI_FREQ(pllinputfreq, LL_RCC_PLLSAI2_GetDivider(),
LL_RCC_PLLSAI2_GetN(), LL_RCC_PLLSAI2_GetR());
}
#endif /* DSI */
#if defined(RCC_PLLSAI1_SUPPORT)
/**
* @brief Return PLLSAI1 clock frequency used for SAI domain
* @retval PLLSAI1 clock frequency (in Hz)
*/
static uint32_t RCC_PLLSAI1_GetFreqDomain_SAI(void)
{
uint32_t pllinputfreq, pllsource;
#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT)
/* PLLSAI1_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLSAI1M) * PLLSAI1N */
#else
/* PLLSAI1_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLSAI1N */
#endif
/* SAI Domain clock = PLLSAI1_VCO / PLLSAI1P */
pllsource = LL_RCC_PLL_GetMainSource();
switch (pllsource)
{
case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLLSAI1 clock source */
pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(),
((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ?
LL_RCC_MSI_GetRange() :
LL_RCC_MSI_GetRangeAfterStandby()));
break;
case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLLSAI1 clock source */
pllinputfreq = HSI_VALUE;
break;
case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLLSAI1 clock source */
pllinputfreq = HSE_VALUE;
break;
default:
pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(),
((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ?
LL_RCC_MSI_GetRange() :
LL_RCC_MSI_GetRangeAfterStandby()));
break;
}
return __LL_RCC_CALC_PLLSAI1_SAI_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(),
LL_RCC_PLLSAI1_GetN(), LL_RCC_PLLSAI1_GetP());
}
/**
* @brief Return PLLSAI1 clock frequency used for 48Mhz domain
* @retval PLLSAI1 clock frequency (in Hz)
*/
static uint32_t RCC_PLLSAI1_GetFreqDomain_48M(void)
{
uint32_t pllinputfreq, pllsource;
#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT)
/* PLLSAI1_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLSAI1M) * PLLSAI1N */
#else
/* PLLSAI1_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLSAI1N */
#endif
/* 48M Domain clock = PLLSAI1_VCO / PLLSAI1Q */
pllsource = LL_RCC_PLL_GetMainSource();
switch (pllsource)
{
case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLLSAI1 clock source */
pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(),
((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ?
LL_RCC_MSI_GetRange() :
LL_RCC_MSI_GetRangeAfterStandby()));
break;
case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLLSAI1 clock source */
pllinputfreq = HSI_VALUE;
break;
case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLLSAI1 clock source */
pllinputfreq = HSE_VALUE;
break;
default:
pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(),
((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ?
LL_RCC_MSI_GetRange() :
LL_RCC_MSI_GetRangeAfterStandby()));
break;
}
return __LL_RCC_CALC_PLLSAI1_48M_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(),
LL_RCC_PLLSAI1_GetN(), LL_RCC_PLLSAI1_GetQ());
}
/**
* @brief Return PLLSAI1 clock frequency used for ADC domain
* @retval PLLSAI1 clock frequency (in Hz)
*/
static uint32_t RCC_PLLSAI1_GetFreqDomain_ADC(void)
{
uint32_t pllinputfreq, pllsource;
#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT)
/* PLLSAI1_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLSAI1M) * PLLSAI1N */
#else
/* PLLSAI1_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLSAI1N */
#endif
/* 48M Domain clock = PLLSAI1_VCO / PLLSAI1R */
pllsource = LL_RCC_PLL_GetMainSource();
switch (pllsource)
{
case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLLSAI1 clock source */
pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(),
((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ?
LL_RCC_MSI_GetRange() :
LL_RCC_MSI_GetRangeAfterStandby()));
break;
case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLLSAI1 clock source */
pllinputfreq = HSI_VALUE;
break;
case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLLSAI1 clock source */
pllinputfreq = HSE_VALUE;
break;
default:
pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(),
((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ?
LL_RCC_MSI_GetRange() :
LL_RCC_MSI_GetRangeAfterStandby()));
break;
}
return __LL_RCC_CALC_PLLSAI1_ADC_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(),
LL_RCC_PLLSAI1_GetN(), LL_RCC_PLLSAI1_GetR());
}
#endif /* RCC_PLLSAI1_SUPPORT */
#if defined(RCC_PLLSAI2_SUPPORT)
/**
* @brief Return PLLSAI2 clock frequency used for SAI domain
* @retval PLLSAI2 clock frequency (in Hz)
*/
static uint32_t RCC_PLLSAI2_GetFreqDomain_SAI(void)
{
uint32_t pllinputfreq, pllsource;
#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT)
/* PLLSAI2_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLSAI2M) * PLLSAI2N */
#else
/* PLLSAI2_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLSAI2N */
#endif
/* SAI Domain clock = PLLSAI2_VCO / PLLSAI2P */
pllsource = LL_RCC_PLL_GetMainSource();
switch (pllsource)
{
case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLLSAI2 clock source */
pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(),
((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ?
LL_RCC_MSI_GetRange() :
LL_RCC_MSI_GetRangeAfterStandby()));
break;
case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLLSAI2 clock source */
pllinputfreq = HSI_VALUE;
break;
case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLLSAI2 clock source */
pllinputfreq = HSE_VALUE;
break;
default:
pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(),
((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ?
LL_RCC_MSI_GetRange() :
LL_RCC_MSI_GetRangeAfterStandby()));
break;
}
#if defined(RCC_PLLSAI2M_DIV_1_16_SUPPORT)
return __LL_RCC_CALC_PLLSAI2_SAI_FREQ(pllinputfreq, LL_RCC_PLLSAI2_GetDivider(),
LL_RCC_PLLSAI2_GetN(), LL_RCC_PLLSAI2_GetP());
#else
return __LL_RCC_CALC_PLLSAI2_SAI_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(),
LL_RCC_PLLSAI2_GetN(), LL_RCC_PLLSAI2_GetP());
#endif
}
#if defined(LTDC)
/**
* @brief Return PLLSAI2 clock frequency used for LTDC domain
* @retval PLLSAI2 clock frequency (in Hz)
*/
static uint32_t RCC_PLLSAI2_GetFreqDomain_LTDC(void)
{
uint32_t pllinputfreq, pllsource;
/* PLLSAI2_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLSAI2M) * PLLSAI2N */
/* LTDC Domain clock = (PLLSAI2_VCO / PLLSAI2R) / PLLSAI2DIVR */
pllsource = LL_RCC_PLL_GetMainSource();
switch (pllsource)
{
case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLLSAI2 clock source */
pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(),
((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ?
LL_RCC_MSI_GetRange() :
LL_RCC_MSI_GetRangeAfterStandby()));
break;
case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLLSAI2 clock source */
pllinputfreq = HSI_VALUE;
break;
case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLLSAI2 clock source */
pllinputfreq = HSE_VALUE;
break;
default:
pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(),
((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ?
LL_RCC_MSI_GetRange() :
LL_RCC_MSI_GetRangeAfterStandby()));
break;
}
return __LL_RCC_CALC_PLLSAI2_LTDC_FREQ(pllinputfreq, LL_RCC_PLLSAI2_GetDivider(),
LL_RCC_PLLSAI2_GetN(), LL_RCC_PLLSAI2_GetR(), LL_RCC_PLLSAI2_GetDIVR());
}
#else
/**
* @brief Return PLLSAI2 clock frequency used for ADC domain
* @retval PLLSAI2 clock frequency (in Hz)
*/
static uint32_t RCC_PLLSAI2_GetFreqDomain_ADC(void)
{
uint32_t pllinputfreq = 0U, pllsource = 0U;
/* PLLSAI2_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLSAI2N */
/* 48M Domain clock = PLLSAI2_VCO / PLLSAI2R */
pllsource = LL_RCC_PLL_GetMainSource();
switch (pllsource)
{
case LL_RCC_PLLSOURCE_MSI: /* MSI used as PLLSAI2 clock source */
pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(),
((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ?
LL_RCC_MSI_GetRange() :
LL_RCC_MSI_GetRangeAfterStandby()));
break;
case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLLSAI2 clock source */
pllinputfreq = HSI_VALUE;
break;
case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLLSAI2 clock source */
pllinputfreq = HSE_VALUE;
break;
default:
pllinputfreq = __LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(),
((LL_RCC_MSI_IsEnabledRangeSelect() != 0U) ?
LL_RCC_MSI_GetRange() :
LL_RCC_MSI_GetRangeAfterStandby()));
break;
}
return __LL_RCC_CALC_PLLSAI2_ADC_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(),
LL_RCC_PLLSAI2_GetN(), LL_RCC_PLLSAI2_GetR());
}
#endif /* LTDC */
#endif /*RCC_PLLSAI2_SUPPORT*/
/**
* @}
*/
/**
* @}
*/
#endif /* defined(RCC) */
/**
* @}
*/
#endif /* USE_FULL_LL_DRIVER */

View File

@@ -0,0 +1,295 @@
/**
******************************************************************************
* @file stm32l4xx_ll_spi.c
* @author MCD Application Team
* @brief SPI 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 "stm32l4xx_ll_spi.h"
#include "stm32l4xx_ll_bus.h"
#ifdef USE_FULL_ASSERT
#include "stm32_assert.h"
#else
#define assert_param(expr) ((void)0U)
#endif /* USE_FULL_ASSERT */
/** @addtogroup STM32L4xx_LL_Driver
* @{
*/
#if defined (SPI1) || defined (SPI2) || defined (SPI3)
/** @addtogroup SPI_LL
* @{
*/
/* Private types -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private constants ---------------------------------------------------------*/
/** @defgroup SPI_LL_Private_Constants SPI Private Constants
* @{
*/
/* SPI registers Masks */
#define SPI_CR1_CLEAR_MASK (SPI_CR1_CPHA | SPI_CR1_CPOL | SPI_CR1_MSTR | \
SPI_CR1_BR | SPI_CR1_LSBFIRST | SPI_CR1_SSI | \
SPI_CR1_SSM | SPI_CR1_RXONLY | SPI_CR1_CRCL | \
SPI_CR1_CRCNEXT | SPI_CR1_CRCEN | SPI_CR1_BIDIOE | \
SPI_CR1_BIDIMODE)
/**
* @}
*/
/* Private macros ------------------------------------------------------------*/
/** @defgroup SPI_LL_Private_Macros SPI Private Macros
* @{
*/
#define IS_LL_SPI_TRANSFER_DIRECTION(__VALUE__) (((__VALUE__) == LL_SPI_FULL_DUPLEX) \
|| ((__VALUE__) == LL_SPI_SIMPLEX_RX) \
|| ((__VALUE__) == LL_SPI_HALF_DUPLEX_RX) \
|| ((__VALUE__) == LL_SPI_HALF_DUPLEX_TX))
#define IS_LL_SPI_MODE(__VALUE__) (((__VALUE__) == LL_SPI_MODE_MASTER) \
|| ((__VALUE__) == LL_SPI_MODE_SLAVE))
#define IS_LL_SPI_DATAWIDTH(__VALUE__) (((__VALUE__) == LL_SPI_DATAWIDTH_4BIT) \
|| ((__VALUE__) == LL_SPI_DATAWIDTH_5BIT) \
|| ((__VALUE__) == LL_SPI_DATAWIDTH_6BIT) \
|| ((__VALUE__) == LL_SPI_DATAWIDTH_7BIT) \
|| ((__VALUE__) == LL_SPI_DATAWIDTH_8BIT) \
|| ((__VALUE__) == LL_SPI_DATAWIDTH_9BIT) \
|| ((__VALUE__) == LL_SPI_DATAWIDTH_10BIT) \
|| ((__VALUE__) == LL_SPI_DATAWIDTH_11BIT) \
|| ((__VALUE__) == LL_SPI_DATAWIDTH_12BIT) \
|| ((__VALUE__) == LL_SPI_DATAWIDTH_13BIT) \
|| ((__VALUE__) == LL_SPI_DATAWIDTH_14BIT) \
|| ((__VALUE__) == LL_SPI_DATAWIDTH_15BIT) \
|| ((__VALUE__) == LL_SPI_DATAWIDTH_16BIT))
#define IS_LL_SPI_POLARITY(__VALUE__) (((__VALUE__) == LL_SPI_POLARITY_LOW) \
|| ((__VALUE__) == LL_SPI_POLARITY_HIGH))
#define IS_LL_SPI_PHASE(__VALUE__) (((__VALUE__) == LL_SPI_PHASE_1EDGE) \
|| ((__VALUE__) == LL_SPI_PHASE_2EDGE))
#define IS_LL_SPI_NSS(__VALUE__) (((__VALUE__) == LL_SPI_NSS_SOFT) \
|| ((__VALUE__) == LL_SPI_NSS_HARD_INPUT) \
|| ((__VALUE__) == LL_SPI_NSS_HARD_OUTPUT))
#define IS_LL_SPI_BAUDRATE(__VALUE__) (((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV2) \
|| ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV4) \
|| ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV8) \
|| ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV16) \
|| ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV32) \
|| ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV64) \
|| ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV128) \
|| ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV256))
#define IS_LL_SPI_BITORDER(__VALUE__) (((__VALUE__) == LL_SPI_LSB_FIRST) \
|| ((__VALUE__) == LL_SPI_MSB_FIRST))
#define IS_LL_SPI_CRCCALCULATION(__VALUE__) (((__VALUE__) == LL_SPI_CRCCALCULATION_ENABLE) \
|| ((__VALUE__) == LL_SPI_CRCCALCULATION_DISABLE))
#define IS_LL_SPI_CRC_POLYNOMIAL(__VALUE__) ((__VALUE__) >= 0x1U)
/**
* @}
*/
/* Private function prototypes -----------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/** @addtogroup SPI_LL_Exported_Functions
* @{
*/
/** @addtogroup SPI_LL_EF_Init
* @{
*/
/**
* @brief De-initialize the SPI registers to their default reset values.
* @param SPIx SPI Instance
* @retval An ErrorStatus enumeration value:
* - SUCCESS: SPI registers are de-initialized
* - ERROR: SPI registers are not de-initialized
*/
ErrorStatus LL_SPI_DeInit(SPI_TypeDef *SPIx)
{
ErrorStatus status = ERROR;
/* Check the parameters */
assert_param(IS_SPI_ALL_INSTANCE(SPIx));
#if defined(SPI1)
if (SPIx == SPI1)
{
/* Force reset of SPI clock */
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1);
/* Release reset of SPI clock */
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI1);
status = SUCCESS;
}
#endif /* SPI1 */
#if defined(SPI2)
if (SPIx == SPI2)
{
/* Force reset of SPI clock */
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2);
/* Release reset of SPI clock */
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI2);
status = SUCCESS;
}
#endif /* SPI2 */
#if defined(SPI3)
if (SPIx == SPI3)
{
/* Force reset of SPI clock */
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI3);
/* Release reset of SPI clock */
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI3);
status = SUCCESS;
}
#endif /* SPI3 */
return status;
}
/**
* @brief Initialize the SPI registers according to the specified parameters in SPI_InitStruct.
* @note As some bits in SPI configuration registers can only be written when the SPI is disabled (SPI_CR1_SPE bit =0),
* SPI peripheral should be in disabled state prior calling this function. Otherwise, ERROR result will be returned.
* @param SPIx SPI Instance
* @param SPI_InitStruct pointer to a @ref LL_SPI_InitTypeDef structure
* @retval An ErrorStatus enumeration value. (Return always SUCCESS)
*/
ErrorStatus LL_SPI_Init(SPI_TypeDef *SPIx, LL_SPI_InitTypeDef *SPI_InitStruct)
{
ErrorStatus status = ERROR;
/* Check the SPI Instance SPIx*/
assert_param(IS_SPI_ALL_INSTANCE(SPIx));
/* Check the SPI parameters from SPI_InitStruct*/
assert_param(IS_LL_SPI_TRANSFER_DIRECTION(SPI_InitStruct->TransferDirection));
assert_param(IS_LL_SPI_MODE(SPI_InitStruct->Mode));
assert_param(IS_LL_SPI_DATAWIDTH(SPI_InitStruct->DataWidth));
assert_param(IS_LL_SPI_POLARITY(SPI_InitStruct->ClockPolarity));
assert_param(IS_LL_SPI_PHASE(SPI_InitStruct->ClockPhase));
assert_param(IS_LL_SPI_NSS(SPI_InitStruct->NSS));
assert_param(IS_LL_SPI_BAUDRATE(SPI_InitStruct->BaudRate));
assert_param(IS_LL_SPI_BITORDER(SPI_InitStruct->BitOrder));
assert_param(IS_LL_SPI_CRCCALCULATION(SPI_InitStruct->CRCCalculation));
if (LL_SPI_IsEnabled(SPIx) == 0x00000000U)
{
/*---------------------------- SPIx CR1 Configuration ------------------------
* Configure SPIx CR1 with parameters:
* - TransferDirection: SPI_CR1_BIDIMODE, SPI_CR1_BIDIOE and SPI_CR1_RXONLY bits
* - Master/Slave Mode: SPI_CR1_MSTR bit
* - ClockPolarity: SPI_CR1_CPOL bit
* - ClockPhase: SPI_CR1_CPHA bit
* - NSS management: SPI_CR1_SSM bit
* - BaudRate prescaler: SPI_CR1_BR[2:0] bits
* - BitOrder: SPI_CR1_LSBFIRST bit
* - CRCCalculation: SPI_CR1_CRCEN bit
*/
MODIFY_REG(SPIx->CR1,
SPI_CR1_CLEAR_MASK,
SPI_InitStruct->TransferDirection | SPI_InitStruct->Mode |
SPI_InitStruct->ClockPolarity | SPI_InitStruct->ClockPhase |
SPI_InitStruct->NSS | SPI_InitStruct->BaudRate |
SPI_InitStruct->BitOrder | SPI_InitStruct->CRCCalculation);
/*---------------------------- SPIx CR2 Configuration ------------------------
* Configure SPIx CR2 with parameters:
* - DataWidth: DS[3:0] bits
* - NSS management: SSOE bit
*/
MODIFY_REG(SPIx->CR2,
SPI_CR2_DS | SPI_CR2_SSOE,
SPI_InitStruct->DataWidth | (SPI_InitStruct->NSS >> 16U));
/* Set Rx FIFO to Quarter (1 Byte) in case of 8 Bits mode. No DataPacking by default */
if (SPI_InitStruct->DataWidth < LL_SPI_DATAWIDTH_9BIT)
{
LL_SPI_SetRxFIFOThreshold(SPIx, LL_SPI_RX_FIFO_TH_QUARTER);
}
/*---------------------------- SPIx CRCPR Configuration ----------------------
* Configure SPIx CRCPR with parameters:
* - CRCPoly: CRCPOLY[15:0] bits
*/
if (SPI_InitStruct->CRCCalculation == LL_SPI_CRCCALCULATION_ENABLE)
{
assert_param(IS_LL_SPI_CRC_POLYNOMIAL(SPI_InitStruct->CRCPoly));
LL_SPI_SetCRCPolynomial(SPIx, SPI_InitStruct->CRCPoly);
}
status = SUCCESS;
}
return status;
}
/**
* @brief Set each @ref LL_SPI_InitTypeDef field to default value.
* @param SPI_InitStruct pointer to a @ref LL_SPI_InitTypeDef structure
* whose fields will be set to default values.
* @retval None
*/
void LL_SPI_StructInit(LL_SPI_InitTypeDef *SPI_InitStruct)
{
/* Set SPI_InitStruct fields to default values */
SPI_InitStruct->TransferDirection = LL_SPI_FULL_DUPLEX;
SPI_InitStruct->Mode = LL_SPI_MODE_SLAVE;
SPI_InitStruct->DataWidth = LL_SPI_DATAWIDTH_8BIT;
SPI_InitStruct->ClockPolarity = LL_SPI_POLARITY_LOW;
SPI_InitStruct->ClockPhase = LL_SPI_PHASE_1EDGE;
SPI_InitStruct->NSS = LL_SPI_NSS_HARD_INPUT;
SPI_InitStruct->BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2;
SPI_InitStruct->BitOrder = LL_SPI_MSB_FIRST;
SPI_InitStruct->CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
SPI_InitStruct->CRCPoly = 7U;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#endif /* defined (SPI1) || defined (SPI2) || defined (SPI3) */
/**
* @}
*/
#endif /* USE_FULL_LL_DRIVER */

View File

@@ -0,0 +1,1360 @@
/**
******************************************************************************
* @file stm32l4xx_ll_tim.c
* @author MCD Application Team
* @brief TIM 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 "stm32l4xx_ll_tim.h"
#include "stm32l4xx_ll_bus.h"
#ifdef USE_FULL_ASSERT
#include "stm32_assert.h"
#else
#define assert_param(expr) ((void)0U)
#endif /* USE_FULL_ASSERT */
/** @addtogroup STM32L4xx_LL_Driver
* @{
*/
#if defined (TIM1) || defined (TIM8) || defined (TIM2) || defined (TIM3) || defined (TIM4) || defined (TIM5) || defined (TIM15) || defined (TIM16) || defined (TIM17) || defined (TIM6) || defined (TIM7)
/** @addtogroup TIM_LL
* @{
*/
/* Private types -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private constants ---------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/
/** @addtogroup TIM_LL_Private_Macros
* @{
*/
#define IS_LL_TIM_COUNTERMODE(__VALUE__) (((__VALUE__) == LL_TIM_COUNTERMODE_UP) \
|| ((__VALUE__) == LL_TIM_COUNTERMODE_DOWN) \
|| ((__VALUE__) == LL_TIM_COUNTERMODE_CENTER_UP) \
|| ((__VALUE__) == LL_TIM_COUNTERMODE_CENTER_DOWN) \
|| ((__VALUE__) == LL_TIM_COUNTERMODE_CENTER_UP_DOWN))
#define IS_LL_TIM_CLOCKDIVISION(__VALUE__) (((__VALUE__) == LL_TIM_CLOCKDIVISION_DIV1) \
|| ((__VALUE__) == LL_TIM_CLOCKDIVISION_DIV2) \
|| ((__VALUE__) == LL_TIM_CLOCKDIVISION_DIV4))
#define IS_LL_TIM_OCMODE(__VALUE__) (((__VALUE__) == LL_TIM_OCMODE_FROZEN) \
|| ((__VALUE__) == LL_TIM_OCMODE_ACTIVE) \
|| ((__VALUE__) == LL_TIM_OCMODE_INACTIVE) \
|| ((__VALUE__) == LL_TIM_OCMODE_TOGGLE) \
|| ((__VALUE__) == LL_TIM_OCMODE_FORCED_INACTIVE) \
|| ((__VALUE__) == LL_TIM_OCMODE_FORCED_ACTIVE) \
|| ((__VALUE__) == LL_TIM_OCMODE_PWM1) \
|| ((__VALUE__) == LL_TIM_OCMODE_PWM2) \
|| ((__VALUE__) == LL_TIM_OCMODE_RETRIG_OPM1) \
|| ((__VALUE__) == LL_TIM_OCMODE_RETRIG_OPM2) \
|| ((__VALUE__) == LL_TIM_OCMODE_COMBINED_PWM1) \
|| ((__VALUE__) == LL_TIM_OCMODE_COMBINED_PWM2) \
|| ((__VALUE__) == LL_TIM_OCMODE_ASSYMETRIC_PWM1) \
|| ((__VALUE__) == LL_TIM_OCMODE_ASSYMETRIC_PWM2))
#define IS_LL_TIM_OCSTATE(__VALUE__) (((__VALUE__) == LL_TIM_OCSTATE_DISABLE) \
|| ((__VALUE__) == LL_TIM_OCSTATE_ENABLE))
#define IS_LL_TIM_OCPOLARITY(__VALUE__) (((__VALUE__) == LL_TIM_OCPOLARITY_HIGH) \
|| ((__VALUE__) == LL_TIM_OCPOLARITY_LOW))
#define IS_LL_TIM_OCIDLESTATE(__VALUE__) (((__VALUE__) == LL_TIM_OCIDLESTATE_LOW) \
|| ((__VALUE__) == LL_TIM_OCIDLESTATE_HIGH))
#define IS_LL_TIM_ACTIVEINPUT(__VALUE__) (((__VALUE__) == LL_TIM_ACTIVEINPUT_DIRECTTI) \
|| ((__VALUE__) == LL_TIM_ACTIVEINPUT_INDIRECTTI) \
|| ((__VALUE__) == LL_TIM_ACTIVEINPUT_TRC))
#define IS_LL_TIM_ICPSC(__VALUE__) (((__VALUE__) == LL_TIM_ICPSC_DIV1) \
|| ((__VALUE__) == LL_TIM_ICPSC_DIV2) \
|| ((__VALUE__) == LL_TIM_ICPSC_DIV4) \
|| ((__VALUE__) == LL_TIM_ICPSC_DIV8))
#define IS_LL_TIM_IC_FILTER(__VALUE__) (((__VALUE__) == LL_TIM_IC_FILTER_FDIV1) \
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV1_N2) \
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV1_N4) \
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV1_N8) \
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV2_N6) \
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV2_N8) \
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV4_N6) \
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV4_N8) \
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV8_N6) \
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV8_N8) \
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV16_N5) \
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV16_N6) \
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV16_N8) \
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV32_N5) \
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV32_N6) \
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV32_N8))
#define IS_LL_TIM_IC_POLARITY(__VALUE__) (((__VALUE__) == LL_TIM_IC_POLARITY_RISING) \
|| ((__VALUE__) == LL_TIM_IC_POLARITY_FALLING) \
|| ((__VALUE__) == LL_TIM_IC_POLARITY_BOTHEDGE))
#define IS_LL_TIM_ENCODERMODE(__VALUE__) (((__VALUE__) == LL_TIM_ENCODERMODE_X2_TI1) \
|| ((__VALUE__) == LL_TIM_ENCODERMODE_X2_TI2) \
|| ((__VALUE__) == LL_TIM_ENCODERMODE_X4_TI12))
#define IS_LL_TIM_IC_POLARITY_ENCODER(__VALUE__) (((__VALUE__) == LL_TIM_IC_POLARITY_RISING) \
|| ((__VALUE__) == LL_TIM_IC_POLARITY_FALLING))
#define IS_LL_TIM_OSSR_STATE(__VALUE__) (((__VALUE__) == LL_TIM_OSSR_DISABLE) \
|| ((__VALUE__) == LL_TIM_OSSR_ENABLE))
#define IS_LL_TIM_OSSI_STATE(__VALUE__) (((__VALUE__) == LL_TIM_OSSI_DISABLE) \
|| ((__VALUE__) == LL_TIM_OSSI_ENABLE))
#define IS_LL_TIM_LOCK_LEVEL(__VALUE__) (((__VALUE__) == LL_TIM_LOCKLEVEL_OFF) \
|| ((__VALUE__) == LL_TIM_LOCKLEVEL_1) \
|| ((__VALUE__) == LL_TIM_LOCKLEVEL_2) \
|| ((__VALUE__) == LL_TIM_LOCKLEVEL_3))
#define IS_LL_TIM_BREAK_STATE(__VALUE__) (((__VALUE__) == LL_TIM_BREAK_DISABLE) \
|| ((__VALUE__) == LL_TIM_BREAK_ENABLE))
#define IS_LL_TIM_BREAK_POLARITY(__VALUE__) (((__VALUE__) == LL_TIM_BREAK_POLARITY_LOW) \
|| ((__VALUE__) == LL_TIM_BREAK_POLARITY_HIGH))
#define IS_LL_TIM_BREAK_FILTER(__VALUE__) (((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV1) \
|| ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV1_N2) \
|| ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV1_N4) \
|| ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV1_N8) \
|| ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV2_N6) \
|| ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV2_N8) \
|| ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV4_N6) \
|| ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV4_N8) \
|| ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV8_N6) \
|| ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV8_N8) \
|| ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV16_N5) \
|| ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV16_N6) \
|| ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV16_N8) \
|| ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV32_N5) \
|| ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV32_N6) \
|| ((__VALUE__) == LL_TIM_BREAK_FILTER_FDIV32_N8))
#define IS_LL_TIM_BREAK2_STATE(__VALUE__) (((__VALUE__) == LL_TIM_BREAK2_DISABLE) \
|| ((__VALUE__) == LL_TIM_BREAK2_ENABLE))
#define IS_LL_TIM_BREAK2_POLARITY(__VALUE__) (((__VALUE__) == LL_TIM_BREAK2_POLARITY_LOW) \
|| ((__VALUE__) == LL_TIM_BREAK2_POLARITY_HIGH))
#define IS_LL_TIM_BREAK2_FILTER(__VALUE__) (((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV1) \
|| ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV1_N2) \
|| ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV1_N4) \
|| ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV1_N8) \
|| ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV2_N6) \
|| ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV2_N8) \
|| ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV4_N6) \
|| ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV4_N8) \
|| ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV8_N6) \
|| ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV8_N8) \
|| ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV16_N5) \
|| ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV16_N6) \
|| ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV16_N8) \
|| ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV32_N5) \
|| ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV32_N6) \
|| ((__VALUE__) == LL_TIM_BREAK2_FILTER_FDIV32_N8))
#define IS_LL_TIM_AUTOMATIC_OUTPUT_STATE(__VALUE__) (((__VALUE__) == LL_TIM_AUTOMATICOUTPUT_DISABLE) \
|| ((__VALUE__) == LL_TIM_AUTOMATICOUTPUT_ENABLE))
/**
* @}
*/
/* Private function prototypes -----------------------------------------------*/
/** @defgroup TIM_LL_Private_Functions TIM Private Functions
* @{
*/
static ErrorStatus OC1Config(TIM_TypeDef *TIMx, LL_TIM_OC_InitTypeDef *TIM_OCInitStruct);
static ErrorStatus OC2Config(TIM_TypeDef *TIMx, LL_TIM_OC_InitTypeDef *TIM_OCInitStruct);
static ErrorStatus OC3Config(TIM_TypeDef *TIMx, LL_TIM_OC_InitTypeDef *TIM_OCInitStruct);
static ErrorStatus OC4Config(TIM_TypeDef *TIMx, LL_TIM_OC_InitTypeDef *TIM_OCInitStruct);
static ErrorStatus OC5Config(TIM_TypeDef *TIMx, LL_TIM_OC_InitTypeDef *TIM_OCInitStruct);
static ErrorStatus OC6Config(TIM_TypeDef *TIMx, LL_TIM_OC_InitTypeDef *TIM_OCInitStruct);
static ErrorStatus IC1Config(TIM_TypeDef *TIMx, LL_TIM_IC_InitTypeDef *TIM_ICInitStruct);
static ErrorStatus IC2Config(TIM_TypeDef *TIMx, LL_TIM_IC_InitTypeDef *TIM_ICInitStruct);
static ErrorStatus IC3Config(TIM_TypeDef *TIMx, LL_TIM_IC_InitTypeDef *TIM_ICInitStruct);
static ErrorStatus IC4Config(TIM_TypeDef *TIMx, LL_TIM_IC_InitTypeDef *TIM_ICInitStruct);
/**
* @}
*/
/* Exported functions --------------------------------------------------------*/
/** @addtogroup TIM_LL_Exported_Functions
* @{
*/
/** @addtogroup TIM_LL_EF_Init
* @{
*/
/**
* @brief Set TIMx registers to their reset values.
* @param TIMx Timer instance
* @retval An ErrorStatus enumeration value:
* - SUCCESS: TIMx registers are de-initialized
* - ERROR: invalid TIMx instance
*/
ErrorStatus LL_TIM_DeInit(TIM_TypeDef *TIMx)
{
ErrorStatus result = SUCCESS;
/* Check the parameters */
assert_param(IS_TIM_INSTANCE(TIMx));
if (TIMx == TIM1)
{
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_TIM1);
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_TIM1);
}
else if (TIMx == TIM2)
{
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM2);
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM2);
}
#if defined(TIM3)
else if (TIMx == TIM3)
{
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM3);
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM3);
}
#endif /* TIM3 */
#if defined(TIM4)
else if (TIMx == TIM4)
{
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM4);
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM4);
}
#endif /* TIM4 */
#if defined(TIM5)
else if (TIMx == TIM5)
{
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM5);
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM5);
}
#endif /* TIM5 */
else if (TIMx == TIM6)
{
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM6);
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM6);
}
#if defined (TIM7)
else if (TIMx == TIM7)
{
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM7);
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM7);
}
#endif /* TIM7 */
#if defined(TIM8)
else if (TIMx == TIM8)
{
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_TIM8);
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_TIM8);
}
#endif /* TIM8 */
else if (TIMx == TIM15)
{
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_TIM15);
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_TIM15);
}
else if (TIMx == TIM16)
{
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_TIM16);
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_TIM16);
}
#if defined(TIM17)
else if (TIMx == TIM17)
{
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_TIM17);
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_TIM17);
}
#endif /* TIM17 */
else
{
result = ERROR;
}
return result;
}
/**
* @brief Set the fields of the time base unit configuration data structure
* to their default values.
* @param TIM_InitStruct pointer to a @ref LL_TIM_InitTypeDef structure (time base unit configuration data structure)
* @retval None
*/
void LL_TIM_StructInit(LL_TIM_InitTypeDef *TIM_InitStruct)
{
/* Set the default configuration */
TIM_InitStruct->Prescaler = (uint16_t)0x0000;
TIM_InitStruct->CounterMode = LL_TIM_COUNTERMODE_UP;
TIM_InitStruct->Autoreload = 0xFFFFFFFFU;
TIM_InitStruct->ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
TIM_InitStruct->RepetitionCounter = 0x00000000U;
}
/**
* @brief Configure the TIMx time base unit.
* @param TIMx Timer Instance
* @param TIM_InitStruct pointer to a @ref LL_TIM_InitTypeDef structure
* (TIMx time base unit configuration data structure)
* @retval An ErrorStatus enumeration value:
* - SUCCESS: TIMx registers are de-initialized
* - ERROR: not applicable
*/
ErrorStatus LL_TIM_Init(TIM_TypeDef *TIMx, LL_TIM_InitTypeDef *TIM_InitStruct)
{
uint32_t tmpcr1;
/* Check the parameters */
assert_param(IS_TIM_INSTANCE(TIMx));
assert_param(IS_LL_TIM_COUNTERMODE(TIM_InitStruct->CounterMode));
assert_param(IS_LL_TIM_CLOCKDIVISION(TIM_InitStruct->ClockDivision));
tmpcr1 = LL_TIM_ReadReg(TIMx, CR1);
if (IS_TIM_COUNTER_MODE_SELECT_INSTANCE(TIMx))
{
/* Select the Counter Mode */
MODIFY_REG(tmpcr1, (TIM_CR1_DIR | TIM_CR1_CMS), TIM_InitStruct->CounterMode);
}
if (IS_TIM_CLOCK_DIVISION_INSTANCE(TIMx))
{
/* Set the clock division */
MODIFY_REG(tmpcr1, TIM_CR1_CKD, TIM_InitStruct->ClockDivision);
}
/* Write to TIMx CR1 */
LL_TIM_WriteReg(TIMx, CR1, tmpcr1);
/* Set the Autoreload value */
LL_TIM_SetAutoReload(TIMx, TIM_InitStruct->Autoreload);
/* Set the Prescaler value */
LL_TIM_SetPrescaler(TIMx, TIM_InitStruct->Prescaler);
if (IS_TIM_REPETITION_COUNTER_INSTANCE(TIMx))
{
/* Set the Repetition Counter value */
LL_TIM_SetRepetitionCounter(TIMx, TIM_InitStruct->RepetitionCounter);
}
/* Generate an update event to reload the Prescaler
and the repetition counter value (if applicable) immediately */
LL_TIM_GenerateEvent_UPDATE(TIMx);
return SUCCESS;
}
/**
* @brief Set the fields of the TIMx output channel configuration data
* structure to their default values.
* @param TIM_OC_InitStruct pointer to a @ref LL_TIM_OC_InitTypeDef structure
* (the output channel configuration data structure)
* @retval None
*/
void LL_TIM_OC_StructInit(LL_TIM_OC_InitTypeDef *TIM_OC_InitStruct)
{
/* Set the default configuration */
TIM_OC_InitStruct->OCMode = LL_TIM_OCMODE_FROZEN;
TIM_OC_InitStruct->OCState = LL_TIM_OCSTATE_DISABLE;
TIM_OC_InitStruct->OCNState = LL_TIM_OCSTATE_DISABLE;
TIM_OC_InitStruct->CompareValue = 0x00000000U;
TIM_OC_InitStruct->OCPolarity = LL_TIM_OCPOLARITY_HIGH;
TIM_OC_InitStruct->OCNPolarity = LL_TIM_OCPOLARITY_HIGH;
TIM_OC_InitStruct->OCIdleState = LL_TIM_OCIDLESTATE_LOW;
TIM_OC_InitStruct->OCNIdleState = LL_TIM_OCIDLESTATE_LOW;
}
/**
* @brief Configure the TIMx output channel.
* @param TIMx Timer Instance
* @param Channel This parameter can be one of the following values:
* @arg @ref LL_TIM_CHANNEL_CH1
* @arg @ref LL_TIM_CHANNEL_CH2
* @arg @ref LL_TIM_CHANNEL_CH3
* @arg @ref LL_TIM_CHANNEL_CH4
* @arg @ref LL_TIM_CHANNEL_CH5
* @arg @ref LL_TIM_CHANNEL_CH6
* @param TIM_OC_InitStruct pointer to a @ref LL_TIM_OC_InitTypeDef structure (TIMx output channel configuration
* data structure)
* @retval An ErrorStatus enumeration value:
* - SUCCESS: TIMx output channel is initialized
* - ERROR: TIMx output channel is not initialized
*/
ErrorStatus LL_TIM_OC_Init(TIM_TypeDef *TIMx, uint32_t Channel, LL_TIM_OC_InitTypeDef *TIM_OC_InitStruct)
{
ErrorStatus result = ERROR;
switch (Channel)
{
case LL_TIM_CHANNEL_CH1:
result = OC1Config(TIMx, TIM_OC_InitStruct);
break;
case LL_TIM_CHANNEL_CH2:
result = OC2Config(TIMx, TIM_OC_InitStruct);
break;
case LL_TIM_CHANNEL_CH3:
result = OC3Config(TIMx, TIM_OC_InitStruct);
break;
case LL_TIM_CHANNEL_CH4:
result = OC4Config(TIMx, TIM_OC_InitStruct);
break;
case LL_TIM_CHANNEL_CH5:
result = OC5Config(TIMx, TIM_OC_InitStruct);
break;
case LL_TIM_CHANNEL_CH6:
result = OC6Config(TIMx, TIM_OC_InitStruct);
break;
default:
break;
}
return result;
}
/**
* @brief Set the fields of the TIMx input channel configuration data
* structure to their default values.
* @param TIM_ICInitStruct pointer to a @ref LL_TIM_IC_InitTypeDef structure (the input channel configuration
* data structure)
* @retval None
*/
void LL_TIM_IC_StructInit(LL_TIM_IC_InitTypeDef *TIM_ICInitStruct)
{
/* Set the default configuration */
TIM_ICInitStruct->ICPolarity = LL_TIM_IC_POLARITY_RISING;
TIM_ICInitStruct->ICActiveInput = LL_TIM_ACTIVEINPUT_DIRECTTI;
TIM_ICInitStruct->ICPrescaler = LL_TIM_ICPSC_DIV1;
TIM_ICInitStruct->ICFilter = LL_TIM_IC_FILTER_FDIV1;
}
/**
* @brief Configure the TIMx input channel.
* @param TIMx Timer Instance
* @param Channel This parameter can be one of the following values:
* @arg @ref LL_TIM_CHANNEL_CH1
* @arg @ref LL_TIM_CHANNEL_CH2
* @arg @ref LL_TIM_CHANNEL_CH3
* @arg @ref LL_TIM_CHANNEL_CH4
* @param TIM_IC_InitStruct pointer to a @ref LL_TIM_IC_InitTypeDef structure (TIMx input channel configuration data
* structure)
* @retval An ErrorStatus enumeration value:
* - SUCCESS: TIMx output channel is initialized
* - ERROR: TIMx output channel is not initialized
*/
ErrorStatus LL_TIM_IC_Init(TIM_TypeDef *TIMx, uint32_t Channel, LL_TIM_IC_InitTypeDef *TIM_IC_InitStruct)
{
ErrorStatus result = ERROR;
switch (Channel)
{
case LL_TIM_CHANNEL_CH1:
result = IC1Config(TIMx, TIM_IC_InitStruct);
break;
case LL_TIM_CHANNEL_CH2:
result = IC2Config(TIMx, TIM_IC_InitStruct);
break;
case LL_TIM_CHANNEL_CH3:
result = IC3Config(TIMx, TIM_IC_InitStruct);
break;
case LL_TIM_CHANNEL_CH4:
result = IC4Config(TIMx, TIM_IC_InitStruct);
break;
default:
break;
}
return result;
}
/**
* @brief Fills each TIM_EncoderInitStruct field with its default value
* @param TIM_EncoderInitStruct pointer to a @ref LL_TIM_ENCODER_InitTypeDef structure (encoder interface
* configuration data structure)
* @retval None
*/
void LL_TIM_ENCODER_StructInit(LL_TIM_ENCODER_InitTypeDef *TIM_EncoderInitStruct)
{
/* Set the default configuration */
TIM_EncoderInitStruct->EncoderMode = LL_TIM_ENCODERMODE_X2_TI1;
TIM_EncoderInitStruct->IC1Polarity = LL_TIM_IC_POLARITY_RISING;
TIM_EncoderInitStruct->IC1ActiveInput = LL_TIM_ACTIVEINPUT_DIRECTTI;
TIM_EncoderInitStruct->IC1Prescaler = LL_TIM_ICPSC_DIV1;
TIM_EncoderInitStruct->IC1Filter = LL_TIM_IC_FILTER_FDIV1;
TIM_EncoderInitStruct->IC2Polarity = LL_TIM_IC_POLARITY_RISING;
TIM_EncoderInitStruct->IC2ActiveInput = LL_TIM_ACTIVEINPUT_DIRECTTI;
TIM_EncoderInitStruct->IC2Prescaler = LL_TIM_ICPSC_DIV1;
TIM_EncoderInitStruct->IC2Filter = LL_TIM_IC_FILTER_FDIV1;
}
/**
* @brief Configure the encoder interface of the timer instance.
* @param TIMx Timer Instance
* @param TIM_EncoderInitStruct pointer to a @ref LL_TIM_ENCODER_InitTypeDef structure (TIMx encoder interface
* configuration data structure)
* @retval An ErrorStatus enumeration value:
* - SUCCESS: TIMx registers are de-initialized
* - ERROR: not applicable
*/
ErrorStatus LL_TIM_ENCODER_Init(TIM_TypeDef *TIMx, LL_TIM_ENCODER_InitTypeDef *TIM_EncoderInitStruct)
{
uint32_t tmpccmr1;
uint32_t tmpccer;
/* Check the parameters */
assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(TIMx));
assert_param(IS_LL_TIM_ENCODERMODE(TIM_EncoderInitStruct->EncoderMode));
assert_param(IS_LL_TIM_IC_POLARITY_ENCODER(TIM_EncoderInitStruct->IC1Polarity));
assert_param(IS_LL_TIM_ACTIVEINPUT(TIM_EncoderInitStruct->IC1ActiveInput));
assert_param(IS_LL_TIM_ICPSC(TIM_EncoderInitStruct->IC1Prescaler));
assert_param(IS_LL_TIM_IC_FILTER(TIM_EncoderInitStruct->IC1Filter));
assert_param(IS_LL_TIM_IC_POLARITY_ENCODER(TIM_EncoderInitStruct->IC2Polarity));
assert_param(IS_LL_TIM_ACTIVEINPUT(TIM_EncoderInitStruct->IC2ActiveInput));
assert_param(IS_LL_TIM_ICPSC(TIM_EncoderInitStruct->IC2Prescaler));
assert_param(IS_LL_TIM_IC_FILTER(TIM_EncoderInitStruct->IC2Filter));
/* Disable the CC1 and CC2: Reset the CC1E and CC2E Bits */
TIMx->CCER &= (uint32_t)~(TIM_CCER_CC1E | TIM_CCER_CC2E);
/* Get the TIMx CCMR1 register value */
tmpccmr1 = LL_TIM_ReadReg(TIMx, CCMR1);
/* Get the TIMx CCER register value */
tmpccer = LL_TIM_ReadReg(TIMx, CCER);
/* Configure TI1 */
tmpccmr1 &= (uint32_t)~(TIM_CCMR1_CC1S | TIM_CCMR1_IC1F | TIM_CCMR1_IC1PSC);
tmpccmr1 |= (uint32_t)(TIM_EncoderInitStruct->IC1ActiveInput >> 16U);
tmpccmr1 |= (uint32_t)(TIM_EncoderInitStruct->IC1Filter >> 16U);
tmpccmr1 |= (uint32_t)(TIM_EncoderInitStruct->IC1Prescaler >> 16U);
/* Configure TI2 */
tmpccmr1 &= (uint32_t)~(TIM_CCMR1_CC2S | TIM_CCMR1_IC2F | TIM_CCMR1_IC2PSC);
tmpccmr1 |= (uint32_t)(TIM_EncoderInitStruct->IC2ActiveInput >> 8U);
tmpccmr1 |= (uint32_t)(TIM_EncoderInitStruct->IC2Filter >> 8U);
tmpccmr1 |= (uint32_t)(TIM_EncoderInitStruct->IC2Prescaler >> 8U);
/* Set TI1 and TI2 polarity and enable TI1 and TI2 */
tmpccer &= (uint32_t)~(TIM_CCER_CC1P | TIM_CCER_CC1NP | TIM_CCER_CC2P | TIM_CCER_CC2NP);
tmpccer |= (uint32_t)(TIM_EncoderInitStruct->IC1Polarity);
tmpccer |= (uint32_t)(TIM_EncoderInitStruct->IC2Polarity << 4U);
tmpccer |= (uint32_t)(TIM_CCER_CC1E | TIM_CCER_CC2E);
/* Set encoder mode */
LL_TIM_SetEncoderMode(TIMx, TIM_EncoderInitStruct->EncoderMode);
/* Write to TIMx CCMR1 */
LL_TIM_WriteReg(TIMx, CCMR1, tmpccmr1);
/* Write to TIMx CCER */
LL_TIM_WriteReg(TIMx, CCER, tmpccer);
return SUCCESS;
}
/**
* @brief Set the fields of the TIMx Hall sensor interface configuration data
* structure to their default values.
* @param TIM_HallSensorInitStruct pointer to a @ref LL_TIM_HALLSENSOR_InitTypeDef structure (HALL sensor interface
* configuration data structure)
* @retval None
*/
void LL_TIM_HALLSENSOR_StructInit(LL_TIM_HALLSENSOR_InitTypeDef *TIM_HallSensorInitStruct)
{
/* Set the default configuration */
TIM_HallSensorInitStruct->IC1Polarity = LL_TIM_IC_POLARITY_RISING;
TIM_HallSensorInitStruct->IC1Prescaler = LL_TIM_ICPSC_DIV1;
TIM_HallSensorInitStruct->IC1Filter = LL_TIM_IC_FILTER_FDIV1;
TIM_HallSensorInitStruct->CommutationDelay = 0U;
}
/**
* @brief Configure the Hall sensor interface of the timer instance.
* @note TIMx CH1, CH2 and CH3 inputs connected through a XOR
* to the TI1 input channel
* @note TIMx slave mode controller is configured in reset mode.
Selected internal trigger is TI1F_ED.
* @note Channel 1 is configured as input, IC1 is mapped on TRC.
* @note Captured value stored in TIMx_CCR1 correspond to the time elapsed
* between 2 changes on the inputs. It gives information about motor speed.
* @note Channel 2 is configured in output PWM 2 mode.
* @note Compare value stored in TIMx_CCR2 corresponds to the commutation delay.
* @note OC2REF is selected as trigger output on TRGO.
* @note LL_TIM_IC_POLARITY_BOTHEDGE must not be used for TI1 when it is used
* when TIMx operates in Hall sensor interface mode.
* @param TIMx Timer Instance
* @param TIM_HallSensorInitStruct pointer to a @ref LL_TIM_HALLSENSOR_InitTypeDef structure (TIMx HALL sensor
* interface configuration data structure)
* @retval An ErrorStatus enumeration value:
* - SUCCESS: TIMx registers are de-initialized
* - ERROR: not applicable
*/
ErrorStatus LL_TIM_HALLSENSOR_Init(TIM_TypeDef *TIMx, LL_TIM_HALLSENSOR_InitTypeDef *TIM_HallSensorInitStruct)
{
uint32_t tmpcr2;
uint32_t tmpccmr1;
uint32_t tmpccer;
uint32_t tmpsmcr;
/* Check the parameters */
assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(TIMx));
assert_param(IS_LL_TIM_IC_POLARITY_ENCODER(TIM_HallSensorInitStruct->IC1Polarity));
assert_param(IS_LL_TIM_ICPSC(TIM_HallSensorInitStruct->IC1Prescaler));
assert_param(IS_LL_TIM_IC_FILTER(TIM_HallSensorInitStruct->IC1Filter));
/* Disable the CC1 and CC2: Reset the CC1E and CC2E Bits */
TIMx->CCER &= (uint32_t)~(TIM_CCER_CC1E | TIM_CCER_CC2E);
/* Get the TIMx CR2 register value */
tmpcr2 = LL_TIM_ReadReg(TIMx, CR2);
/* Get the TIMx CCMR1 register value */
tmpccmr1 = LL_TIM_ReadReg(TIMx, CCMR1);
/* Get the TIMx CCER register value */
tmpccer = LL_TIM_ReadReg(TIMx, CCER);
/* Get the TIMx SMCR register value */
tmpsmcr = LL_TIM_ReadReg(TIMx, SMCR);
/* Connect TIMx_CH1, CH2 and CH3 pins to the TI1 input */
tmpcr2 |= TIM_CR2_TI1S;
/* OC2REF signal is used as trigger output (TRGO) */
tmpcr2 |= LL_TIM_TRGO_OC2REF;
/* Configure the slave mode controller */
tmpsmcr &= (uint32_t)~(TIM_SMCR_TS | TIM_SMCR_SMS);
tmpsmcr |= LL_TIM_TS_TI1F_ED;
tmpsmcr |= LL_TIM_SLAVEMODE_RESET;
/* Configure input channel 1 */
tmpccmr1 &= (uint32_t)~(TIM_CCMR1_CC1S | TIM_CCMR1_IC1F | TIM_CCMR1_IC1PSC);
tmpccmr1 |= (uint32_t)(LL_TIM_ACTIVEINPUT_TRC >> 16U);
tmpccmr1 |= (uint32_t)(TIM_HallSensorInitStruct->IC1Filter >> 16U);
tmpccmr1 |= (uint32_t)(TIM_HallSensorInitStruct->IC1Prescaler >> 16U);
/* Configure input channel 2 */
tmpccmr1 &= (uint32_t)~(TIM_CCMR1_OC2M | TIM_CCMR1_OC2FE | TIM_CCMR1_OC2PE | TIM_CCMR1_OC2CE);
tmpccmr1 |= (uint32_t)(LL_TIM_OCMODE_PWM2 << 8U);
/* Set Channel 1 polarity and enable Channel 1 and Channel2 */
tmpccer &= (uint32_t)~(TIM_CCER_CC1P | TIM_CCER_CC1NP | TIM_CCER_CC2P | TIM_CCER_CC2NP);
tmpccer |= (uint32_t)(TIM_HallSensorInitStruct->IC1Polarity);
tmpccer |= (uint32_t)(TIM_CCER_CC1E | TIM_CCER_CC2E);
/* Write to TIMx CR2 */
LL_TIM_WriteReg(TIMx, CR2, tmpcr2);
/* Write to TIMx SMCR */
LL_TIM_WriteReg(TIMx, SMCR, tmpsmcr);
/* Write to TIMx CCMR1 */
LL_TIM_WriteReg(TIMx, CCMR1, tmpccmr1);
/* Write to TIMx CCER */
LL_TIM_WriteReg(TIMx, CCER, tmpccer);
/* Write to TIMx CCR2 */
LL_TIM_OC_SetCompareCH2(TIMx, TIM_HallSensorInitStruct->CommutationDelay);
return SUCCESS;
}
/**
* @brief Set the fields of the Break and Dead Time configuration data structure
* to their default values.
* @param TIM_BDTRInitStruct pointer to a @ref LL_TIM_BDTR_InitTypeDef structure (Break and Dead Time configuration
* data structure)
* @retval None
*/
void LL_TIM_BDTR_StructInit(LL_TIM_BDTR_InitTypeDef *TIM_BDTRInitStruct)
{
/* Set the default configuration */
TIM_BDTRInitStruct->OSSRState = LL_TIM_OSSR_DISABLE;
TIM_BDTRInitStruct->OSSIState = LL_TIM_OSSI_DISABLE;
TIM_BDTRInitStruct->LockLevel = LL_TIM_LOCKLEVEL_OFF;
TIM_BDTRInitStruct->DeadTime = (uint8_t)0x00;
TIM_BDTRInitStruct->BreakState = LL_TIM_BREAK_DISABLE;
TIM_BDTRInitStruct->BreakPolarity = LL_TIM_BREAK_POLARITY_LOW;
TIM_BDTRInitStruct->BreakFilter = LL_TIM_BREAK_FILTER_FDIV1;
TIM_BDTRInitStruct->Break2State = LL_TIM_BREAK2_DISABLE;
TIM_BDTRInitStruct->Break2Polarity = LL_TIM_BREAK2_POLARITY_LOW;
TIM_BDTRInitStruct->Break2Filter = LL_TIM_BREAK2_FILTER_FDIV1;
TIM_BDTRInitStruct->AutomaticOutput = LL_TIM_AUTOMATICOUTPUT_DISABLE;
}
/**
* @brief Configure the Break and Dead Time feature of the timer instance.
* @note As the bits BK2P, BK2E, BK2F[3:0], BKF[3:0], AOE, BKP, BKE, OSSI, OSSR
* and DTG[7:0] can be write-locked depending on the LOCK configuration, it
* can be necessary to configure all of them during the first write access to
* the TIMx_BDTR register.
* @note Macro IS_TIM_BREAK_INSTANCE(TIMx) can be used to check whether or not
* a timer instance provides a break input.
* @note Macro IS_TIM_BKIN2_INSTANCE(TIMx) can be used to check whether or not
* a timer instance provides a second break input.
* @param TIMx Timer Instance
* @param TIM_BDTRInitStruct pointer to a @ref LL_TIM_BDTR_InitTypeDef structure (Break and Dead Time configuration
* data structure)
* @retval An ErrorStatus enumeration value:
* - SUCCESS: Break and Dead Time is initialized
* - ERROR: not applicable
*/
ErrorStatus LL_TIM_BDTR_Init(TIM_TypeDef *TIMx, LL_TIM_BDTR_InitTypeDef *TIM_BDTRInitStruct)
{
uint32_t tmpbdtr = 0;
/* Check the parameters */
assert_param(IS_TIM_BREAK_INSTANCE(TIMx));
assert_param(IS_LL_TIM_OSSR_STATE(TIM_BDTRInitStruct->OSSRState));
assert_param(IS_LL_TIM_OSSI_STATE(TIM_BDTRInitStruct->OSSIState));
assert_param(IS_LL_TIM_LOCK_LEVEL(TIM_BDTRInitStruct->LockLevel));
assert_param(IS_LL_TIM_BREAK_STATE(TIM_BDTRInitStruct->BreakState));
assert_param(IS_LL_TIM_BREAK_POLARITY(TIM_BDTRInitStruct->BreakPolarity));
assert_param(IS_LL_TIM_AUTOMATIC_OUTPUT_STATE(TIM_BDTRInitStruct->AutomaticOutput));
/* Set the Lock level, the Break enable Bit and the Polarity, the OSSR State,
the OSSI State, the dead time value and the Automatic Output Enable Bit */
/* Set the BDTR bits */
MODIFY_REG(tmpbdtr, TIM_BDTR_DTG, TIM_BDTRInitStruct->DeadTime);
MODIFY_REG(tmpbdtr, TIM_BDTR_LOCK, TIM_BDTRInitStruct->LockLevel);
MODIFY_REG(tmpbdtr, TIM_BDTR_OSSI, TIM_BDTRInitStruct->OSSIState);
MODIFY_REG(tmpbdtr, TIM_BDTR_OSSR, TIM_BDTRInitStruct->OSSRState);
MODIFY_REG(tmpbdtr, TIM_BDTR_BKE, TIM_BDTRInitStruct->BreakState);
MODIFY_REG(tmpbdtr, TIM_BDTR_BKP, TIM_BDTRInitStruct->BreakPolarity);
MODIFY_REG(tmpbdtr, TIM_BDTR_AOE, TIM_BDTRInitStruct->AutomaticOutput);
MODIFY_REG(tmpbdtr, TIM_BDTR_MOE, TIM_BDTRInitStruct->AutomaticOutput);
if (IS_TIM_ADVANCED_INSTANCE(TIMx))
{
assert_param(IS_LL_TIM_BREAK_FILTER(TIM_BDTRInitStruct->BreakFilter));
MODIFY_REG(tmpbdtr, TIM_BDTR_BKF, TIM_BDTRInitStruct->BreakFilter);
}
if (IS_TIM_BKIN2_INSTANCE(TIMx))
{
assert_param(IS_LL_TIM_BREAK2_STATE(TIM_BDTRInitStruct->Break2State));
assert_param(IS_LL_TIM_BREAK2_POLARITY(TIM_BDTRInitStruct->Break2Polarity));
assert_param(IS_LL_TIM_BREAK2_FILTER(TIM_BDTRInitStruct->Break2Filter));
/* Set the BREAK2 input related BDTR bit-fields */
MODIFY_REG(tmpbdtr, TIM_BDTR_BK2F, (TIM_BDTRInitStruct->Break2Filter));
MODIFY_REG(tmpbdtr, TIM_BDTR_BK2E, TIM_BDTRInitStruct->Break2State);
MODIFY_REG(tmpbdtr, TIM_BDTR_BK2P, TIM_BDTRInitStruct->Break2Polarity);
}
/* Set TIMx_BDTR */
LL_TIM_WriteReg(TIMx, BDTR, tmpbdtr);
return SUCCESS;
}
/**
* @}
*/
/**
* @}
*/
/** @addtogroup TIM_LL_Private_Functions TIM Private Functions
* @brief Private functions
* @{
*/
/**
* @brief Configure the TIMx output channel 1.
* @param TIMx Timer Instance
* @param TIM_OCInitStruct pointer to the the TIMx output channel 1 configuration data structure
* @retval An ErrorStatus enumeration value:
* - SUCCESS: TIMx registers are de-initialized
* - ERROR: not applicable
*/
static ErrorStatus OC1Config(TIM_TypeDef *TIMx, LL_TIM_OC_InitTypeDef *TIM_OCInitStruct)
{
uint32_t tmpccmr1;
uint32_t tmpccer;
uint32_t tmpcr2;
/* Check the parameters */
assert_param(IS_TIM_CC1_INSTANCE(TIMx));
assert_param(IS_LL_TIM_OCMODE(TIM_OCInitStruct->OCMode));
assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCState));
assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCPolarity));
assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCNState));
assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCNPolarity));
/* Disable the Channel 1: Reset the CC1E Bit */
CLEAR_BIT(TIMx->CCER, TIM_CCER_CC1E);
/* Get the TIMx CCER register value */
tmpccer = LL_TIM_ReadReg(TIMx, CCER);
/* Get the TIMx CR2 register value */
tmpcr2 = LL_TIM_ReadReg(TIMx, CR2);
/* Get the TIMx CCMR1 register value */
tmpccmr1 = LL_TIM_ReadReg(TIMx, CCMR1);
/* Reset Capture/Compare selection Bits */
CLEAR_BIT(tmpccmr1, TIM_CCMR1_CC1S);
/* Set the Output Compare Mode */
MODIFY_REG(tmpccmr1, TIM_CCMR1_OC1M, TIM_OCInitStruct->OCMode);
/* Set the Output Compare Polarity */
MODIFY_REG(tmpccer, TIM_CCER_CC1P, TIM_OCInitStruct->OCPolarity);
/* Set the Output State */
MODIFY_REG(tmpccer, TIM_CCER_CC1E, TIM_OCInitStruct->OCState);
if (IS_TIM_BREAK_INSTANCE(TIMx))
{
assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCNIdleState));
assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCIdleState));
/* Set the complementary output Polarity */
MODIFY_REG(tmpccer, TIM_CCER_CC1NP, TIM_OCInitStruct->OCNPolarity << 2U);
/* Set the complementary output State */
MODIFY_REG(tmpccer, TIM_CCER_CC1NE, TIM_OCInitStruct->OCNState << 2U);
/* Set the Output Idle state */
MODIFY_REG(tmpcr2, TIM_CR2_OIS1, TIM_OCInitStruct->OCIdleState);
/* Set the complementary output Idle state */
MODIFY_REG(tmpcr2, TIM_CR2_OIS1N, TIM_OCInitStruct->OCNIdleState << 1U);
}
/* Write to TIMx CR2 */
LL_TIM_WriteReg(TIMx, CR2, tmpcr2);
/* Write to TIMx CCMR1 */
LL_TIM_WriteReg(TIMx, CCMR1, tmpccmr1);
/* Set the Capture Compare Register value */
LL_TIM_OC_SetCompareCH1(TIMx, TIM_OCInitStruct->CompareValue);
/* Write to TIMx CCER */
LL_TIM_WriteReg(TIMx, CCER, tmpccer);
return SUCCESS;
}
/**
* @brief Configure the TIMx output channel 2.
* @param TIMx Timer Instance
* @param TIM_OCInitStruct pointer to the the TIMx output channel 2 configuration data structure
* @retval An ErrorStatus enumeration value:
* - SUCCESS: TIMx registers are de-initialized
* - ERROR: not applicable
*/
static ErrorStatus OC2Config(TIM_TypeDef *TIMx, LL_TIM_OC_InitTypeDef *TIM_OCInitStruct)
{
uint32_t tmpccmr1;
uint32_t tmpccer;
uint32_t tmpcr2;
/* Check the parameters */
assert_param(IS_TIM_CC2_INSTANCE(TIMx));
assert_param(IS_LL_TIM_OCMODE(TIM_OCInitStruct->OCMode));
assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCState));
assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCPolarity));
assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCNState));
assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCNPolarity));
/* Disable the Channel 2: Reset the CC2E Bit */
CLEAR_BIT(TIMx->CCER, TIM_CCER_CC2E);
/* Get the TIMx CCER register value */
tmpccer = LL_TIM_ReadReg(TIMx, CCER);
/* Get the TIMx CR2 register value */
tmpcr2 = LL_TIM_ReadReg(TIMx, CR2);
/* Get the TIMx CCMR1 register value */
tmpccmr1 = LL_TIM_ReadReg(TIMx, CCMR1);
/* Reset Capture/Compare selection Bits */
CLEAR_BIT(tmpccmr1, TIM_CCMR1_CC2S);
/* Select the Output Compare Mode */
MODIFY_REG(tmpccmr1, TIM_CCMR1_OC2M, TIM_OCInitStruct->OCMode << 8U);
/* Set the Output Compare Polarity */
MODIFY_REG(tmpccer, TIM_CCER_CC2P, TIM_OCInitStruct->OCPolarity << 4U);
/* Set the Output State */
MODIFY_REG(tmpccer, TIM_CCER_CC2E, TIM_OCInitStruct->OCState << 4U);
if (IS_TIM_BREAK_INSTANCE(TIMx))
{
assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCNIdleState));
assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCIdleState));
/* Set the complementary output Polarity */
MODIFY_REG(tmpccer, TIM_CCER_CC2NP, TIM_OCInitStruct->OCNPolarity << 6U);
/* Set the complementary output State */
MODIFY_REG(tmpccer, TIM_CCER_CC2NE, TIM_OCInitStruct->OCNState << 6U);
/* Set the Output Idle state */
MODIFY_REG(tmpcr2, TIM_CR2_OIS2, TIM_OCInitStruct->OCIdleState << 2U);
/* Set the complementary output Idle state */
MODIFY_REG(tmpcr2, TIM_CR2_OIS2N, TIM_OCInitStruct->OCNIdleState << 3U);
}
/* Write to TIMx CR2 */
LL_TIM_WriteReg(TIMx, CR2, tmpcr2);
/* Write to TIMx CCMR1 */
LL_TIM_WriteReg(TIMx, CCMR1, tmpccmr1);
/* Set the Capture Compare Register value */
LL_TIM_OC_SetCompareCH2(TIMx, TIM_OCInitStruct->CompareValue);
/* Write to TIMx CCER */
LL_TIM_WriteReg(TIMx, CCER, tmpccer);
return SUCCESS;
}
/**
* @brief Configure the TIMx output channel 3.
* @param TIMx Timer Instance
* @param TIM_OCInitStruct pointer to the the TIMx output channel 3 configuration data structure
* @retval An ErrorStatus enumeration value:
* - SUCCESS: TIMx registers are de-initialized
* - ERROR: not applicable
*/
static ErrorStatus OC3Config(TIM_TypeDef *TIMx, LL_TIM_OC_InitTypeDef *TIM_OCInitStruct)
{
uint32_t tmpccmr2;
uint32_t tmpccer;
uint32_t tmpcr2;
/* Check the parameters */
assert_param(IS_TIM_CC3_INSTANCE(TIMx));
assert_param(IS_LL_TIM_OCMODE(TIM_OCInitStruct->OCMode));
assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCState));
assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCPolarity));
assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCNState));
assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCNPolarity));
/* Disable the Channel 3: Reset the CC3E Bit */
CLEAR_BIT(TIMx->CCER, TIM_CCER_CC3E);
/* Get the TIMx CCER register value */
tmpccer = LL_TIM_ReadReg(TIMx, CCER);
/* Get the TIMx CR2 register value */
tmpcr2 = LL_TIM_ReadReg(TIMx, CR2);
/* Get the TIMx CCMR2 register value */
tmpccmr2 = LL_TIM_ReadReg(TIMx, CCMR2);
/* Reset Capture/Compare selection Bits */
CLEAR_BIT(tmpccmr2, TIM_CCMR2_CC3S);
/* Select the Output Compare Mode */
MODIFY_REG(tmpccmr2, TIM_CCMR2_OC3M, TIM_OCInitStruct->OCMode);
/* Set the Output Compare Polarity */
MODIFY_REG(tmpccer, TIM_CCER_CC3P, TIM_OCInitStruct->OCPolarity << 8U);
/* Set the Output State */
MODIFY_REG(tmpccer, TIM_CCER_CC3E, TIM_OCInitStruct->OCState << 8U);
if (IS_TIM_BREAK_INSTANCE(TIMx))
{
assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCNIdleState));
assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCIdleState));
/* Set the complementary output Polarity */
MODIFY_REG(tmpccer, TIM_CCER_CC3NP, TIM_OCInitStruct->OCNPolarity << 10U);
/* Set the complementary output State */
MODIFY_REG(tmpccer, TIM_CCER_CC3NE, TIM_OCInitStruct->OCNState << 10U);
/* Set the Output Idle state */
MODIFY_REG(tmpcr2, TIM_CR2_OIS3, TIM_OCInitStruct->OCIdleState << 4U);
/* Set the complementary output Idle state */
MODIFY_REG(tmpcr2, TIM_CR2_OIS3N, TIM_OCInitStruct->OCNIdleState << 5U);
}
/* Write to TIMx CR2 */
LL_TIM_WriteReg(TIMx, CR2, tmpcr2);
/* Write to TIMx CCMR2 */
LL_TIM_WriteReg(TIMx, CCMR2, tmpccmr2);
/* Set the Capture Compare Register value */
LL_TIM_OC_SetCompareCH3(TIMx, TIM_OCInitStruct->CompareValue);
/* Write to TIMx CCER */
LL_TIM_WriteReg(TIMx, CCER, tmpccer);
return SUCCESS;
}
/**
* @brief Configure the TIMx output channel 4.
* @param TIMx Timer Instance
* @param TIM_OCInitStruct pointer to the the TIMx output channel 4 configuration data structure
* @retval An ErrorStatus enumeration value:
* - SUCCESS: TIMx registers are de-initialized
* - ERROR: not applicable
*/
static ErrorStatus OC4Config(TIM_TypeDef *TIMx, LL_TIM_OC_InitTypeDef *TIM_OCInitStruct)
{
uint32_t tmpccmr2;
uint32_t tmpccer;
uint32_t tmpcr2;
/* Check the parameters */
assert_param(IS_TIM_CC4_INSTANCE(TIMx));
assert_param(IS_LL_TIM_OCMODE(TIM_OCInitStruct->OCMode));
assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCState));
assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCPolarity));
assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCNPolarity));
assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCNState));
/* Disable the Channel 4: Reset the CC4E Bit */
CLEAR_BIT(TIMx->CCER, TIM_CCER_CC4E);
/* Get the TIMx CCER register value */
tmpccer = LL_TIM_ReadReg(TIMx, CCER);
/* Get the TIMx CR2 register value */
tmpcr2 = LL_TIM_ReadReg(TIMx, CR2);
/* Get the TIMx CCMR2 register value */
tmpccmr2 = LL_TIM_ReadReg(TIMx, CCMR2);
/* Reset Capture/Compare selection Bits */
CLEAR_BIT(tmpccmr2, TIM_CCMR2_CC4S);
/* Select the Output Compare Mode */
MODIFY_REG(tmpccmr2, TIM_CCMR2_OC4M, TIM_OCInitStruct->OCMode << 8U);
/* Set the Output Compare Polarity */
MODIFY_REG(tmpccer, TIM_CCER_CC4P, TIM_OCInitStruct->OCPolarity << 12U);
/* Set the Output State */
MODIFY_REG(tmpccer, TIM_CCER_CC4E, TIM_OCInitStruct->OCState << 12U);
if (IS_TIM_BREAK_INSTANCE(TIMx))
{
assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCNIdleState));
assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCIdleState));
/* Set the Output Idle state */
MODIFY_REG(tmpcr2, TIM_CR2_OIS4, TIM_OCInitStruct->OCIdleState << 6U);
}
/* Write to TIMx CR2 */
LL_TIM_WriteReg(TIMx, CR2, tmpcr2);
/* Write to TIMx CCMR2 */
LL_TIM_WriteReg(TIMx, CCMR2, tmpccmr2);
/* Set the Capture Compare Register value */
LL_TIM_OC_SetCompareCH4(TIMx, TIM_OCInitStruct->CompareValue);
/* Write to TIMx CCER */
LL_TIM_WriteReg(TIMx, CCER, tmpccer);
return SUCCESS;
}
/**
* @brief Configure the TIMx output channel 5.
* @param TIMx Timer Instance
* @param TIM_OCInitStruct pointer to the the TIMx output channel 5 configuration data structure
* @retval An ErrorStatus enumeration value:
* - SUCCESS: TIMx registers are de-initialized
* - ERROR: not applicable
*/
static ErrorStatus OC5Config(TIM_TypeDef *TIMx, LL_TIM_OC_InitTypeDef *TIM_OCInitStruct)
{
uint32_t tmpccmr3;
uint32_t tmpccer;
/* Check the parameters */
assert_param(IS_TIM_CC5_INSTANCE(TIMx));
assert_param(IS_LL_TIM_OCMODE(TIM_OCInitStruct->OCMode));
assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCState));
assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCPolarity));
assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCNPolarity));
assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCNState));
/* Disable the Channel 5: Reset the CC5E Bit */
CLEAR_BIT(TIMx->CCER, TIM_CCER_CC5E);
/* Get the TIMx CCER register value */
tmpccer = LL_TIM_ReadReg(TIMx, CCER);
/* Get the TIMx CCMR3 register value */
tmpccmr3 = LL_TIM_ReadReg(TIMx, CCMR3);
/* Select the Output Compare Mode */
MODIFY_REG(tmpccmr3, TIM_CCMR3_OC5M, TIM_OCInitStruct->OCMode);
/* Set the Output Compare Polarity */
MODIFY_REG(tmpccer, TIM_CCER_CC5P, TIM_OCInitStruct->OCPolarity << 16U);
/* Set the Output State */
MODIFY_REG(tmpccer, TIM_CCER_CC5E, TIM_OCInitStruct->OCState << 16U);
if (IS_TIM_BREAK_INSTANCE(TIMx))
{
assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCNIdleState));
assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCIdleState));
/* Set the Output Idle state */
MODIFY_REG(TIMx->CR2, TIM_CR2_OIS5, TIM_OCInitStruct->OCIdleState << 8U);
}
/* Write to TIMx CCMR3 */
LL_TIM_WriteReg(TIMx, CCMR3, tmpccmr3);
/* Set the Capture Compare Register value */
LL_TIM_OC_SetCompareCH5(TIMx, TIM_OCInitStruct->CompareValue);
/* Write to TIMx CCER */
LL_TIM_WriteReg(TIMx, CCER, tmpccer);
return SUCCESS;
}
/**
* @brief Configure the TIMx output channel 6.
* @param TIMx Timer Instance
* @param TIM_OCInitStruct pointer to the the TIMx output channel 6 configuration data structure
* @retval An ErrorStatus enumeration value:
* - SUCCESS: TIMx registers are de-initialized
* - ERROR: not applicable
*/
static ErrorStatus OC6Config(TIM_TypeDef *TIMx, LL_TIM_OC_InitTypeDef *TIM_OCInitStruct)
{
uint32_t tmpccmr3;
uint32_t tmpccer;
/* Check the parameters */
assert_param(IS_TIM_CC6_INSTANCE(TIMx));
assert_param(IS_LL_TIM_OCMODE(TIM_OCInitStruct->OCMode));
assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCState));
assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCPolarity));
assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCNPolarity));
assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCNState));
/* Disable the Channel 5: Reset the CC6E Bit */
CLEAR_BIT(TIMx->CCER, TIM_CCER_CC6E);
/* Get the TIMx CCER register value */
tmpccer = LL_TIM_ReadReg(TIMx, CCER);
/* Get the TIMx CCMR3 register value */
tmpccmr3 = LL_TIM_ReadReg(TIMx, CCMR3);
/* Select the Output Compare Mode */
MODIFY_REG(tmpccmr3, TIM_CCMR3_OC6M, TIM_OCInitStruct->OCMode << 8U);
/* Set the Output Compare Polarity */
MODIFY_REG(tmpccer, TIM_CCER_CC6P, TIM_OCInitStruct->OCPolarity << 20U);
/* Set the Output State */
MODIFY_REG(tmpccer, TIM_CCER_CC6E, TIM_OCInitStruct->OCState << 20U);
if (IS_TIM_BREAK_INSTANCE(TIMx))
{
assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCNIdleState));
assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCIdleState));
/* Set the Output Idle state */
MODIFY_REG(TIMx->CR2, TIM_CR2_OIS6, TIM_OCInitStruct->OCIdleState << 10U);
}
/* Write to TIMx CCMR3 */
LL_TIM_WriteReg(TIMx, CCMR3, tmpccmr3);
/* Set the Capture Compare Register value */
LL_TIM_OC_SetCompareCH6(TIMx, TIM_OCInitStruct->CompareValue);
/* Write to TIMx CCER */
LL_TIM_WriteReg(TIMx, CCER, tmpccer);
return SUCCESS;
}
/**
* @brief Configure the TIMx input channel 1.
* @param TIMx Timer Instance
* @param TIM_ICInitStruct pointer to the the TIMx input channel 1 configuration data structure
* @retval An ErrorStatus enumeration value:
* - SUCCESS: TIMx registers are de-initialized
* - ERROR: not applicable
*/
static ErrorStatus IC1Config(TIM_TypeDef *TIMx, LL_TIM_IC_InitTypeDef *TIM_ICInitStruct)
{
/* Check the parameters */
assert_param(IS_TIM_CC1_INSTANCE(TIMx));
assert_param(IS_LL_TIM_IC_POLARITY(TIM_ICInitStruct->ICPolarity));
assert_param(IS_LL_TIM_ACTIVEINPUT(TIM_ICInitStruct->ICActiveInput));
assert_param(IS_LL_TIM_ICPSC(TIM_ICInitStruct->ICPrescaler));
assert_param(IS_LL_TIM_IC_FILTER(TIM_ICInitStruct->ICFilter));
/* Disable the Channel 1: Reset the CC1E Bit */
TIMx->CCER &= (uint32_t)~TIM_CCER_CC1E;
/* Select the Input and set the filter and the prescaler value */
MODIFY_REG(TIMx->CCMR1,
(TIM_CCMR1_CC1S | TIM_CCMR1_IC1F | TIM_CCMR1_IC1PSC),
(TIM_ICInitStruct->ICActiveInput | TIM_ICInitStruct->ICFilter | TIM_ICInitStruct->ICPrescaler) >> 16U);
/* Select the Polarity and set the CC1E Bit */
MODIFY_REG(TIMx->CCER,
(TIM_CCER_CC1P | TIM_CCER_CC1NP),
(TIM_ICInitStruct->ICPolarity | TIM_CCER_CC1E));
return SUCCESS;
}
/**
* @brief Configure the TIMx input channel 2.
* @param TIMx Timer Instance
* @param TIM_ICInitStruct pointer to the the TIMx input channel 2 configuration data structure
* @retval An ErrorStatus enumeration value:
* - SUCCESS: TIMx registers are de-initialized
* - ERROR: not applicable
*/
static ErrorStatus IC2Config(TIM_TypeDef *TIMx, LL_TIM_IC_InitTypeDef *TIM_ICInitStruct)
{
/* Check the parameters */
assert_param(IS_TIM_CC2_INSTANCE(TIMx));
assert_param(IS_LL_TIM_IC_POLARITY(TIM_ICInitStruct->ICPolarity));
assert_param(IS_LL_TIM_ACTIVEINPUT(TIM_ICInitStruct->ICActiveInput));
assert_param(IS_LL_TIM_ICPSC(TIM_ICInitStruct->ICPrescaler));
assert_param(IS_LL_TIM_IC_FILTER(TIM_ICInitStruct->ICFilter));
/* Disable the Channel 2: Reset the CC2E Bit */
TIMx->CCER &= (uint32_t)~TIM_CCER_CC2E;
/* Select the Input and set the filter and the prescaler value */
MODIFY_REG(TIMx->CCMR1,
(TIM_CCMR1_CC2S | TIM_CCMR1_IC2F | TIM_CCMR1_IC2PSC),
(TIM_ICInitStruct->ICActiveInput | TIM_ICInitStruct->ICFilter | TIM_ICInitStruct->ICPrescaler) >> 8U);
/* Select the Polarity and set the CC2E Bit */
MODIFY_REG(TIMx->CCER,
(TIM_CCER_CC2P | TIM_CCER_CC2NP),
((TIM_ICInitStruct->ICPolarity << 4U) | TIM_CCER_CC2E));
return SUCCESS;
}
/**
* @brief Configure the TIMx input channel 3.
* @param TIMx Timer Instance
* @param TIM_ICInitStruct pointer to the the TIMx input channel 3 configuration data structure
* @retval An ErrorStatus enumeration value:
* - SUCCESS: TIMx registers are de-initialized
* - ERROR: not applicable
*/
static ErrorStatus IC3Config(TIM_TypeDef *TIMx, LL_TIM_IC_InitTypeDef *TIM_ICInitStruct)
{
/* Check the parameters */
assert_param(IS_TIM_CC3_INSTANCE(TIMx));
assert_param(IS_LL_TIM_IC_POLARITY(TIM_ICInitStruct->ICPolarity));
assert_param(IS_LL_TIM_ACTIVEINPUT(TIM_ICInitStruct->ICActiveInput));
assert_param(IS_LL_TIM_ICPSC(TIM_ICInitStruct->ICPrescaler));
assert_param(IS_LL_TIM_IC_FILTER(TIM_ICInitStruct->ICFilter));
/* Disable the Channel 3: Reset the CC3E Bit */
TIMx->CCER &= (uint32_t)~TIM_CCER_CC3E;
/* Select the Input and set the filter and the prescaler value */
MODIFY_REG(TIMx->CCMR2,
(TIM_CCMR2_CC3S | TIM_CCMR2_IC3F | TIM_CCMR2_IC3PSC),
(TIM_ICInitStruct->ICActiveInput | TIM_ICInitStruct->ICFilter | TIM_ICInitStruct->ICPrescaler) >> 16U);
/* Select the Polarity and set the CC3E Bit */
MODIFY_REG(TIMx->CCER,
(TIM_CCER_CC3P | TIM_CCER_CC3NP),
((TIM_ICInitStruct->ICPolarity << 8U) | TIM_CCER_CC3E));
return SUCCESS;
}
/**
* @brief Configure the TIMx input channel 4.
* @param TIMx Timer Instance
* @param TIM_ICInitStruct pointer to the the TIMx input channel 4 configuration data structure
* @retval An ErrorStatus enumeration value:
* - SUCCESS: TIMx registers are de-initialized
* - ERROR: not applicable
*/
static ErrorStatus IC4Config(TIM_TypeDef *TIMx, LL_TIM_IC_InitTypeDef *TIM_ICInitStruct)
{
/* Check the parameters */
assert_param(IS_TIM_CC4_INSTANCE(TIMx));
assert_param(IS_LL_TIM_IC_POLARITY(TIM_ICInitStruct->ICPolarity));
assert_param(IS_LL_TIM_ACTIVEINPUT(TIM_ICInitStruct->ICActiveInput));
assert_param(IS_LL_TIM_ICPSC(TIM_ICInitStruct->ICPrescaler));
assert_param(IS_LL_TIM_IC_FILTER(TIM_ICInitStruct->ICFilter));
/* Disable the Channel 4: Reset the CC4E Bit */
TIMx->CCER &= (uint32_t)~TIM_CCER_CC4E;
/* Select the Input and set the filter and the prescaler value */
MODIFY_REG(TIMx->CCMR2,
(TIM_CCMR2_CC4S | TIM_CCMR2_IC4F | TIM_CCMR2_IC4PSC),
(TIM_ICInitStruct->ICActiveInput | TIM_ICInitStruct->ICFilter | TIM_ICInitStruct->ICPrescaler) >> 8U);
/* Select the Polarity and set the CC2E Bit */
MODIFY_REG(TIMx->CCER,
(TIM_CCER_CC4P | TIM_CCER_CC4NP),
((TIM_ICInitStruct->ICPolarity << 12U) | TIM_CCER_CC4E));
return SUCCESS;
}
/**
* @}
*/
/**
* @}
*/
#endif /* TIM1 || TIM8 || TIM2 || TIM3 || TIM4 || TIM5 || TIM15 || TIM16 || TIM17 || TIM6 || TIM7 */
/**
* @}
*/
#endif /* USE_FULL_LL_DRIVER */

View File

@@ -0,0 +1,476 @@
/**
******************************************************************************
* @file stm32l4xx_ll_usart.c
* @author MCD Application Team
* @brief USART 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 "stm32l4xx_ll_usart.h"
#include "stm32l4xx_ll_rcc.h"
#include "stm32l4xx_ll_bus.h"
#ifdef USE_FULL_ASSERT
#include "stm32_assert.h"
#else
#define assert_param(expr) ((void)0U)
#endif /* USE_FULL_ASSERT */
/** @addtogroup STM32L4xx_LL_Driver
* @{
*/
#if defined (USART1) || defined (USART2) || defined (USART3) || defined (UART4) || defined (UART5)
/** @addtogroup USART_LL
* @{
*/
/* Private types -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private constants ---------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/
/** @addtogroup USART_LL_Private_Macros
* @{
*/
#if defined(USART_PRESC_PRESCALER)
#define IS_LL_USART_PRESCALER(__VALUE__) (((__VALUE__) == LL_USART_PRESCALER_DIV1) \
|| ((__VALUE__) == LL_USART_PRESCALER_DIV2) \
|| ((__VALUE__) == LL_USART_PRESCALER_DIV4) \
|| ((__VALUE__) == LL_USART_PRESCALER_DIV6) \
|| ((__VALUE__) == LL_USART_PRESCALER_DIV8) \
|| ((__VALUE__) == LL_USART_PRESCALER_DIV10) \
|| ((__VALUE__) == LL_USART_PRESCALER_DIV12) \
|| ((__VALUE__) == LL_USART_PRESCALER_DIV16) \
|| ((__VALUE__) == LL_USART_PRESCALER_DIV32) \
|| ((__VALUE__) == LL_USART_PRESCALER_DIV64) \
|| ((__VALUE__) == LL_USART_PRESCALER_DIV128) \
|| ((__VALUE__) == LL_USART_PRESCALER_DIV256))
#endif /* USART_PRESC_PRESCALER */
/* __BAUDRATE__ The maximum Baud Rate is derived from the maximum clock available
* divided by the smallest oversampling used on the USART (i.e. 8) */
#if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
#define IS_LL_USART_BAUDRATE(__BAUDRATE__) ((__BAUDRATE__) <= 15000000U)
#else
#define IS_LL_USART_BAUDRATE(__BAUDRATE__) ((__BAUDRATE__) <= 10000000U)
#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */
/* __VALUE__ In case of oversampling by 16 and 8, BRR content must be greater than or equal to 16d. */
#define IS_LL_USART_BRR_MIN(__VALUE__) ((__VALUE__) >= 16U)
#define IS_LL_USART_DIRECTION(__VALUE__) (((__VALUE__) == LL_USART_DIRECTION_NONE) \
|| ((__VALUE__) == LL_USART_DIRECTION_RX) \
|| ((__VALUE__) == LL_USART_DIRECTION_TX) \
|| ((__VALUE__) == LL_USART_DIRECTION_TX_RX))
#define IS_LL_USART_PARITY(__VALUE__) (((__VALUE__) == LL_USART_PARITY_NONE) \
|| ((__VALUE__) == LL_USART_PARITY_EVEN) \
|| ((__VALUE__) == LL_USART_PARITY_ODD))
#define IS_LL_USART_DATAWIDTH(__VALUE__) (((__VALUE__) == LL_USART_DATAWIDTH_7B) \
|| ((__VALUE__) == LL_USART_DATAWIDTH_8B) \
|| ((__VALUE__) == LL_USART_DATAWIDTH_9B))
#define IS_LL_USART_OVERSAMPLING(__VALUE__) (((__VALUE__) == LL_USART_OVERSAMPLING_16) \
|| ((__VALUE__) == LL_USART_OVERSAMPLING_8))
#define IS_LL_USART_LASTBITCLKOUTPUT(__VALUE__) (((__VALUE__) == LL_USART_LASTCLKPULSE_NO_OUTPUT) \
|| ((__VALUE__) == LL_USART_LASTCLKPULSE_OUTPUT))
#define IS_LL_USART_CLOCKPHASE(__VALUE__) (((__VALUE__) == LL_USART_PHASE_1EDGE) \
|| ((__VALUE__) == LL_USART_PHASE_2EDGE))
#define IS_LL_USART_CLOCKPOLARITY(__VALUE__) (((__VALUE__) == LL_USART_POLARITY_LOW) \
|| ((__VALUE__) == LL_USART_POLARITY_HIGH))
#define IS_LL_USART_CLOCKOUTPUT(__VALUE__) (((__VALUE__) == LL_USART_CLOCK_DISABLE) \
|| ((__VALUE__) == LL_USART_CLOCK_ENABLE))
#define IS_LL_USART_STOPBITS(__VALUE__) (((__VALUE__) == LL_USART_STOPBITS_0_5) \
|| ((__VALUE__) == LL_USART_STOPBITS_1) \
|| ((__VALUE__) == LL_USART_STOPBITS_1_5) \
|| ((__VALUE__) == LL_USART_STOPBITS_2))
#define IS_LL_USART_HWCONTROL(__VALUE__) (((__VALUE__) == LL_USART_HWCONTROL_NONE) \
|| ((__VALUE__) == LL_USART_HWCONTROL_RTS) \
|| ((__VALUE__) == LL_USART_HWCONTROL_CTS) \
|| ((__VALUE__) == LL_USART_HWCONTROL_RTS_CTS))
/**
* @}
*/
/* Private function prototypes -----------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/** @addtogroup USART_LL_Exported_Functions
* @{
*/
/** @addtogroup USART_LL_EF_Init
* @{
*/
/**
* @brief De-initialize USART registers (Registers restored to their default values).
* @param USARTx USART Instance
* @retval An ErrorStatus enumeration value:
* - SUCCESS: USART registers are de-initialized
* - ERROR: USART registers are not de-initialized
*/
ErrorStatus LL_USART_DeInit(USART_TypeDef *USARTx)
{
ErrorStatus status = SUCCESS;
/* Check the parameters */
assert_param(IS_UART_INSTANCE(USARTx));
if (USARTx == USART1)
{
/* Force reset of USART clock */
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_USART1);
/* Release reset of USART clock */
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_USART1);
}
else if (USARTx == USART2)
{
/* Force reset of USART clock */
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_USART2);
/* Release reset of USART clock */
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_USART2);
}
#if defined(USART3)
else if (USARTx == USART3)
{
/* Force reset of USART clock */
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_USART3);
/* Release reset of USART clock */
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_USART3);
}
#endif /* USART3 */
#if defined(UART4)
else if (USARTx == UART4)
{
/* Force reset of UART clock */
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_UART4);
/* Release reset of UART clock */
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_UART4);
}
#endif /* UART4 */
#if defined(UART5)
else if (USARTx == UART5)
{
/* Force reset of UART clock */
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_UART5);
/* Release reset of UART clock */
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_UART5);
}
#endif /* UART5 */
else
{
status = ERROR;
}
return (status);
}
/**
* @brief Initialize USART registers according to the specified
* parameters in USART_InitStruct.
* @note As some bits in USART configuration registers can only be written when
* the USART is disabled (USART_CR1_UE bit =0), USART Peripheral should be in disabled state prior calling
* this function. Otherwise, ERROR result will be returned.
* @note Baud rate value stored in USART_InitStruct BaudRate field, should be valid (different from 0).
* @param USARTx USART Instance
* @param USART_InitStruct pointer to a LL_USART_InitTypeDef structure
* that contains the configuration information for the specified USART peripheral.
* @retval An ErrorStatus enumeration value:
* - SUCCESS: USART registers are initialized according to USART_InitStruct content
* - ERROR: Problem occurred during USART Registers initialization
*/
ErrorStatus LL_USART_Init(USART_TypeDef *USARTx, LL_USART_InitTypeDef *USART_InitStruct)
{
ErrorStatus status = ERROR;
uint32_t periphclk = LL_RCC_PERIPH_FREQUENCY_NO;
/* Check the parameters */
assert_param(IS_UART_INSTANCE(USARTx));
#if defined(USART_PRESC_PRESCALER)
assert_param(IS_LL_USART_PRESCALER(USART_InitStruct->PrescalerValue));
#endif /* USART_PRESC_PRESCALER */
assert_param(IS_LL_USART_BAUDRATE(USART_InitStruct->BaudRate));
assert_param(IS_LL_USART_DATAWIDTH(USART_InitStruct->DataWidth));
assert_param(IS_LL_USART_STOPBITS(USART_InitStruct->StopBits));
assert_param(IS_LL_USART_PARITY(USART_InitStruct->Parity));
assert_param(IS_LL_USART_DIRECTION(USART_InitStruct->TransferDirection));
assert_param(IS_LL_USART_HWCONTROL(USART_InitStruct->HardwareFlowControl));
assert_param(IS_LL_USART_OVERSAMPLING(USART_InitStruct->OverSampling));
/* USART needs to be in disabled state, in order to be able to configure some bits in
CRx registers */
if (LL_USART_IsEnabled(USARTx) == 0U)
{
/*---------------------------- USART CR1 Configuration ---------------------
* Configure USARTx CR1 (USART Word Length, Parity, Mode and Oversampling bits) with parameters:
* - DataWidth: USART_CR1_M bits according to USART_InitStruct->DataWidth value
* - Parity: USART_CR1_PCE, USART_CR1_PS bits according to USART_InitStruct->Parity value
* - TransferDirection: USART_CR1_TE, USART_CR1_RE bits according to USART_InitStruct->TransferDirection value
* - Oversampling: USART_CR1_OVER8 bit according to USART_InitStruct->OverSampling value.
*/
MODIFY_REG(USARTx->CR1,
(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS |
USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8),
(USART_InitStruct->DataWidth | USART_InitStruct->Parity |
USART_InitStruct->TransferDirection | USART_InitStruct->OverSampling));
/*---------------------------- USART CR2 Configuration ---------------------
* Configure USARTx CR2 (Stop bits) with parameters:
* - Stop Bits: USART_CR2_STOP bits according to USART_InitStruct->StopBits value.
* - CLKEN, CPOL, CPHA and LBCL bits are to be configured using LL_USART_ClockInit().
*/
LL_USART_SetStopBitsLength(USARTx, USART_InitStruct->StopBits);
/*---------------------------- USART CR3 Configuration ---------------------
* Configure USARTx CR3 (Hardware Flow Control) with parameters:
* - HardwareFlowControl: USART_CR3_RTSE, USART_CR3_CTSE bits according to
* USART_InitStruct->HardwareFlowControl value.
*/
LL_USART_SetHWFlowCtrl(USARTx, USART_InitStruct->HardwareFlowControl);
/*---------------------------- USART BRR Configuration ---------------------
* Retrieve Clock frequency used for USART Peripheral
*/
if (USARTx == USART1)
{
periphclk = LL_RCC_GetUSARTClockFreq(LL_RCC_USART1_CLKSOURCE);
}
else if (USARTx == USART2)
{
periphclk = LL_RCC_GetUSARTClockFreq(LL_RCC_USART2_CLKSOURCE);
}
#if defined(USART3)
else if (USARTx == USART3)
{
periphclk = LL_RCC_GetUSARTClockFreq(LL_RCC_USART3_CLKSOURCE);
}
#endif /* USART3 */
#if defined(UART4)
else if (USARTx == UART4)
{
periphclk = LL_RCC_GetUARTClockFreq(LL_RCC_UART4_CLKSOURCE);
}
#endif /* UART4 */
#if defined(UART5)
else if (USARTx == UART5)
{
periphclk = LL_RCC_GetUARTClockFreq(LL_RCC_UART5_CLKSOURCE);
}
#endif /* UART5 */
else
{
/* Nothing to do, as error code is already assigned to ERROR value */
}
/* Configure the USART Baud Rate :
#if defined(USART_PRESC_PRESCALER)
- prescaler value is required
#endif
- valid baud rate value (different from 0) is required
- Peripheral clock as returned by RCC service, should be valid (different from 0).
*/
if ((periphclk != LL_RCC_PERIPH_FREQUENCY_NO)
&& (USART_InitStruct->BaudRate != 0U))
{
status = SUCCESS;
LL_USART_SetBaudRate(USARTx,
periphclk,
#if defined(USART_PRESC_PRESCALER)
USART_InitStruct->PrescalerValue,
#endif /* USART_PRESC_PRESCALER */
USART_InitStruct->OverSampling,
USART_InitStruct->BaudRate);
/* Check BRR is greater than or equal to 16d */
assert_param(IS_LL_USART_BRR_MIN(USARTx->BRR));
}
#if defined(USART_PRESC_PRESCALER)
/*---------------------------- USART PRESC Configuration -----------------------
* Configure USARTx PRESC (Prescaler) with parameters:
* - PrescalerValue: USART_PRESC_PRESCALER bits according to USART_InitStruct->PrescalerValue value.
*/
LL_USART_SetPrescaler(USARTx, USART_InitStruct->PrescalerValue);
#endif /* USART_PRESC_PRESCALER */
}
/* Endif (=> USART not in Disabled state => return ERROR) */
return (status);
}
/**
* @brief Set each @ref LL_USART_InitTypeDef field to default value.
* @param USART_InitStruct pointer to a @ref LL_USART_InitTypeDef structure
* whose fields will be set to default values.
* @retval None
*/
void LL_USART_StructInit(LL_USART_InitTypeDef *USART_InitStruct)
{
/* Set USART_InitStruct fields to default values */
#if defined(USART_PRESC_PRESCALER)
USART_InitStruct->PrescalerValue = LL_USART_PRESCALER_DIV1;
#endif /* USART_PRESC_PRESCALER */
USART_InitStruct->BaudRate = 9600U;
USART_InitStruct->DataWidth = LL_USART_DATAWIDTH_8B;
USART_InitStruct->StopBits = LL_USART_STOPBITS_1;
USART_InitStruct->Parity = LL_USART_PARITY_NONE ;
USART_InitStruct->TransferDirection = LL_USART_DIRECTION_TX_RX;
USART_InitStruct->HardwareFlowControl = LL_USART_HWCONTROL_NONE;
USART_InitStruct->OverSampling = LL_USART_OVERSAMPLING_16;
}
/**
* @brief Initialize USART Clock related settings according to the
* specified parameters in the USART_ClockInitStruct.
* @note As some bits in USART configuration registers can only be written when
* the USART is disabled (USART_CR1_UE bit =0), USART Peripheral should be in disabled state prior calling
* this function. Otherwise, ERROR result will be returned.
* @param USARTx USART Instance
* @param USART_ClockInitStruct pointer to a @ref LL_USART_ClockInitTypeDef structure
* that contains the Clock configuration information for the specified USART peripheral.
* @retval An ErrorStatus enumeration value:
* - SUCCESS: USART registers related to Clock settings are initialized according
* to USART_ClockInitStruct content
* - ERROR: Problem occurred during USART Registers initialization
*/
ErrorStatus LL_USART_ClockInit(USART_TypeDef *USARTx, LL_USART_ClockInitTypeDef *USART_ClockInitStruct)
{
ErrorStatus status = SUCCESS;
/* Check USART Instance and Clock signal output parameters */
assert_param(IS_UART_INSTANCE(USARTx));
assert_param(IS_LL_USART_CLOCKOUTPUT(USART_ClockInitStruct->ClockOutput));
/* USART needs to be in disabled state, in order to be able to configure some bits in
CRx registers */
if (LL_USART_IsEnabled(USARTx) == 0U)
{
#if defined(USART_CR2_SLVEN)
/* Ensure USART instance is USART capable */
assert_param(IS_USART_INSTANCE(USARTx));
/* Check clock related parameters */
assert_param(IS_LL_USART_CLOCKPOLARITY(USART_ClockInitStruct->ClockPolarity));
assert_param(IS_LL_USART_CLOCKPHASE(USART_ClockInitStruct->ClockPhase));
assert_param(IS_LL_USART_LASTBITCLKOUTPUT(USART_ClockInitStruct->LastBitClockPulse));
/*---------------------------- USART CR2 Configuration -----------------------
* Configure USARTx CR2 (Clock signal related bits) with parameters:
* - Clock Output: USART_CR2_CLKEN bit according to USART_ClockInitStruct->ClockOutput value
* - Clock Polarity: USART_CR2_CPOL bit according to USART_ClockInitStruct->ClockPolarity value
* - Clock Phase: USART_CR2_CPHA bit according to USART_ClockInitStruct->ClockPhase value
* - Last Bit Clock Pulse Output: USART_CR2_LBCL bit according to USART_ClockInitStruct->LastBitClockPulse value.
*/
MODIFY_REG(USARTx->CR2,
USART_CR2_CLKEN | USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_LBCL,
USART_ClockInitStruct->ClockOutput | USART_ClockInitStruct->ClockPolarity |
USART_ClockInitStruct->ClockPhase | USART_ClockInitStruct->LastBitClockPulse);
#else
/* If USART Clock signal is disabled */
if (USART_ClockInitStruct->ClockOutput == LL_USART_CLOCK_DISABLE)
{
/* Deactivate Clock signal delivery :
* - Disable Clock Output: USART_CR2_CLKEN cleared
*/
LL_USART_DisableSCLKOutput(USARTx);
}
else
{
/* Ensure USART instance is USART capable */
assert_param(IS_USART_INSTANCE(USARTx));
/* Check clock related parameters */
assert_param(IS_LL_USART_CLOCKPOLARITY(USART_ClockInitStruct->ClockPolarity));
assert_param(IS_LL_USART_CLOCKPHASE(USART_ClockInitStruct->ClockPhase));
assert_param(IS_LL_USART_LASTBITCLKOUTPUT(USART_ClockInitStruct->LastBitClockPulse));
/*---------------------------- USART CR2 Configuration -----------------------
* Configure USARTx CR2 (Clock signal related bits) with parameters:
* - Enable Clock Output: USART_CR2_CLKEN set
* - Clock Polarity: USART_CR2_CPOL bit according to USART_ClockInitStruct->ClockPolarity value
* - Clock Phase: USART_CR2_CPHA bit according to USART_ClockInitStruct->ClockPhase value
* - Last Bit Clock Pulse Output: USART_CR2_LBCL bit according to USART_ClockInitStruct->LastBitClockPulse value.
*/
MODIFY_REG(USARTx->CR2,
USART_CR2_CLKEN | USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_LBCL,
USART_CR2_CLKEN | USART_ClockInitStruct->ClockPolarity |
USART_ClockInitStruct->ClockPhase | USART_ClockInitStruct->LastBitClockPulse);
}
#endif /* USART_CR2_SLVEN */
}
/* Else (USART not in Disabled state => return ERROR */
else
{
status = ERROR;
}
return (status);
}
/**
* @brief Set each field of a @ref LL_USART_ClockInitTypeDef type structure to default value.
* @param USART_ClockInitStruct pointer to a @ref LL_USART_ClockInitTypeDef structure
* whose fields will be set to default values.
* @retval None
*/
void LL_USART_ClockStructInit(LL_USART_ClockInitTypeDef *USART_ClockInitStruct)
{
/* Set LL_USART_ClockInitStruct fields with default values */
USART_ClockInitStruct->ClockOutput = LL_USART_CLOCK_DISABLE;
USART_ClockInitStruct->ClockPolarity = LL_USART_POLARITY_LOW; /* Not relevant when ClockOutput =
LL_USART_CLOCK_DISABLE */
USART_ClockInitStruct->ClockPhase = LL_USART_PHASE_1EDGE; /* Not relevant when ClockOutput =
LL_USART_CLOCK_DISABLE */
USART_ClockInitStruct->LastBitClockPulse = LL_USART_LASTCLKPULSE_NO_OUTPUT; /* Not relevant when ClockOutput =
LL_USART_CLOCK_DISABLE */
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#endif /* USART1 || USART2 || USART3 || UART4 || UART5 */
/**
* @}
*/
#endif /* USE_FULL_LL_DRIVER */

View File

@@ -0,0 +1,913 @@
/**
******************************************************************************
* @file stm32l4xx_ll_utils.c
* @author MCD Application Team
* @brief UTILS 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.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32l4xx_ll_utils.h"
#include "stm32l4xx_ll_rcc.h"
#include "stm32l4xx_ll_system.h"
#include "stm32l4xx_ll_pwr.h"
#ifdef USE_FULL_ASSERT
#include "stm32_assert.h"
#else
#define assert_param(expr) ((void)0U)
#endif /* USE_FULL_ASSERT */
/** @addtogroup STM32L4xx_LL_Driver
* @{
*/
/** @addtogroup UTILS_LL
* @{
*/
/* Private types -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private constants ---------------------------------------------------------*/
/** @addtogroup UTILS_LL_Private_Constants
* @{
*/
#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \
defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
#define UTILS_MAX_FREQUENCY_SCALE1 120000000U /*!< Maximum frequency for system clock at power scale1, in Hz */
#define UTILS_MAX_FREQUENCY_SCALE2 26000000U /*!< Maximum frequency for system clock at power scale2, in Hz */
#else
#define UTILS_MAX_FREQUENCY_SCALE1 80000000U /*!< Maximum frequency for system clock at power scale1, in Hz */
#define UTILS_MAX_FREQUENCY_SCALE2 26000000U /*!< Maximum frequency for system clock at power scale2, in Hz */
#endif
/* Defines used for PLL range */
#define UTILS_PLLVCO_INPUT_MIN 4000000U /*!< Frequency min for PLLVCO input, in Hz */
#define UTILS_PLLVCO_INPUT_MAX 16000000U /*!< Frequency max for PLLVCO input, in Hz */
#define UTILS_PLLVCO_OUTPUT_MIN 64000000U /*!< Frequency min for PLLVCO output, in Hz */
#define UTILS_PLLVCO_OUTPUT_MAX 344000000U /*!< Frequency max for PLLVCO output, in Hz */
/* Defines used for HSE range */
#define UTILS_HSE_FREQUENCY_MIN 4000000U /*!< Frequency min for HSE frequency, in Hz */
#define UTILS_HSE_FREQUENCY_MAX 48000000U /*!< Frequency max for HSE frequency, in Hz */
/* Defines used for FLASH latency according to HCLK Frequency */
#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \
defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
#define UTILS_SCALE1_LATENCY1_FREQ 20000000U /*!< HCLK frequency to set FLASH latency 1 in power scale 1 */
#define UTILS_SCALE1_LATENCY2_FREQ 40000000U /*!< HCLK frequency to set FLASH latency 2 in power scale 1 */
#define UTILS_SCALE1_LATENCY3_FREQ 60000000U /*!< HCLK frequency to set FLASH latency 3 in power scale 1 */
#define UTILS_SCALE1_LATENCY4_FREQ 80000000U /*!< HCLK frequency to set FLASH latency 4 in power scale 1 */
#define UTILS_SCALE1_LATENCY5_FREQ 100000000U /*!< HCLK frequency to set FLASH latency 4 in power scale 1 */
#define UTILS_SCALE2_LATENCY1_FREQ 8000000U /*!< HCLK frequency to set FLASH latency 1 in power scale 2 */
#define UTILS_SCALE2_LATENCY2_FREQ 16000000U /*!< HCLK frequency to set FLASH latency 2 in power scale 2 */
#else
#define UTILS_SCALE1_LATENCY1_FREQ 16000000U /*!< HCLK frequency to set FLASH latency 1 in power scale 1 */
#define UTILS_SCALE1_LATENCY2_FREQ 32000000U /*!< HCLK frequency to set FLASH latency 2 in power scale 1 */
#define UTILS_SCALE1_LATENCY3_FREQ 48000000U /*!< HCLK frequency to set FLASH latency 3 in power scale 1 */
#define UTILS_SCALE1_LATENCY4_FREQ 64000000U /*!< HCLK frequency to set FLASH latency 4 in power scale 1 */
#define UTILS_SCALE2_LATENCY1_FREQ 6000000U /*!< HCLK frequency to set FLASH latency 1 in power scale 2 */
#define UTILS_SCALE2_LATENCY2_FREQ 12000000U /*!< HCLK frequency to set FLASH latency 2 in power scale 2 */
#define UTILS_SCALE2_LATENCY3_FREQ 18000000U /*!< HCLK frequency to set FLASH latency 3 in power scale 2 */
#endif
/**
* @}
*/
/* Private macros ------------------------------------------------------------*/
/** @addtogroup UTILS_LL_Private_Macros
* @{
*/
#define IS_LL_UTILS_SYSCLK_DIV(__VALUE__) (((__VALUE__) == LL_RCC_SYSCLK_DIV_1) \
|| ((__VALUE__) == LL_RCC_SYSCLK_DIV_2) \
|| ((__VALUE__) == LL_RCC_SYSCLK_DIV_4) \
|| ((__VALUE__) == LL_RCC_SYSCLK_DIV_8) \
|| ((__VALUE__) == LL_RCC_SYSCLK_DIV_16) \
|| ((__VALUE__) == LL_RCC_SYSCLK_DIV_64) \
|| ((__VALUE__) == LL_RCC_SYSCLK_DIV_128) \
|| ((__VALUE__) == LL_RCC_SYSCLK_DIV_256) \
|| ((__VALUE__) == LL_RCC_SYSCLK_DIV_512))
#define IS_LL_UTILS_APB1_DIV(__VALUE__) (((__VALUE__) == LL_RCC_APB1_DIV_1) \
|| ((__VALUE__) == LL_RCC_APB1_DIV_2) \
|| ((__VALUE__) == LL_RCC_APB1_DIV_4) \
|| ((__VALUE__) == LL_RCC_APB1_DIV_8) \
|| ((__VALUE__) == LL_RCC_APB1_DIV_16))
#define IS_LL_UTILS_APB2_DIV(__VALUE__) (((__VALUE__) == LL_RCC_APB2_DIV_1) \
|| ((__VALUE__) == LL_RCC_APB2_DIV_2) \
|| ((__VALUE__) == LL_RCC_APB2_DIV_4) \
|| ((__VALUE__) == LL_RCC_APB2_DIV_8) \
|| ((__VALUE__) == LL_RCC_APB2_DIV_16))
#define IS_LL_UTILS_PLLM_VALUE(__VALUE__) (((__VALUE__) == LL_RCC_PLLM_DIV_1) \
|| ((__VALUE__) == LL_RCC_PLLM_DIV_2) \
|| ((__VALUE__) == LL_RCC_PLLM_DIV_3) \
|| ((__VALUE__) == LL_RCC_PLLM_DIV_4) \
|| ((__VALUE__) == LL_RCC_PLLM_DIV_5) \
|| ((__VALUE__) == LL_RCC_PLLM_DIV_6) \
|| ((__VALUE__) == LL_RCC_PLLM_DIV_7) \
|| ((__VALUE__) == LL_RCC_PLLM_DIV_8))
#define IS_LL_UTILS_PLLN_VALUE(__VALUE__) ((8U <= (__VALUE__)) && ((__VALUE__) <= 86U))
#define IS_LL_UTILS_PLLR_VALUE(__VALUE__) (((__VALUE__) == LL_RCC_PLLR_DIV_2) \
|| ((__VALUE__) == LL_RCC_PLLR_DIV_4) \
|| ((__VALUE__) == LL_RCC_PLLR_DIV_6) \
|| ((__VALUE__) == LL_RCC_PLLR_DIV_8))
#define IS_LL_UTILS_PLLVCO_INPUT(__VALUE__) ((UTILS_PLLVCO_INPUT_MIN <= (__VALUE__)) && ((__VALUE__) <= UTILS_PLLVCO_INPUT_MAX))
#define IS_LL_UTILS_PLLVCO_OUTPUT(__VALUE__) ((UTILS_PLLVCO_OUTPUT_MIN <= (__VALUE__)) && ((__VALUE__) <= UTILS_PLLVCO_OUTPUT_MAX))
#define IS_LL_UTILS_PLL_FREQUENCY(__VALUE__) ((LL_PWR_GetRegulVoltageScaling() == LL_PWR_REGU_VOLTAGE_SCALE1) ? ((__VALUE__) <= UTILS_MAX_FREQUENCY_SCALE1) : \
((__VALUE__) <= UTILS_MAX_FREQUENCY_SCALE2))
#define IS_LL_UTILS_HSE_BYPASS(__STATE__) (((__STATE__) == LL_UTILS_HSEBYPASS_ON) \
|| ((__STATE__) == LL_UTILS_HSEBYPASS_OFF))
#define IS_LL_UTILS_HSE_FREQUENCY(__FREQUENCY__) (((__FREQUENCY__) >= UTILS_HSE_FREQUENCY_MIN) && ((__FREQUENCY__) <= UTILS_HSE_FREQUENCY_MAX))
/**
* @}
*/
/* Private function prototypes -----------------------------------------------*/
/** @defgroup UTILS_LL_Private_Functions UTILS Private functions
* @{
*/
static uint32_t UTILS_GetPLLOutputFrequency(uint32_t PLL_InputFrequency,
LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct);
static ErrorStatus UTILS_EnablePLLAndSwitchSystem(uint32_t SYSCLK_Frequency, LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct);
static ErrorStatus UTILS_PLL_IsBusy(void);
/**
* @}
*/
/* Exported functions --------------------------------------------------------*/
/** @addtogroup UTILS_LL_Exported_Functions
* @{
*/
/** @addtogroup UTILS_LL_EF_DELAY
* @{
*/
/**
* @brief This function configures the Cortex-M SysTick source to have 1ms time base.
* @note When a RTOS is used, it is recommended to avoid changing the Systick
* configuration by calling this function, for a delay use rather osDelay RTOS service.
* @param HCLKFrequency HCLK frequency in Hz
* @note HCLK frequency can be calculated thanks to RCC helper macro or function @ref LL_RCC_GetSystemClocksFreq
* @retval None
*/
void LL_Init1msTick(uint32_t HCLKFrequency)
{
/* Use frequency provided in argument */
LL_InitTick(HCLKFrequency, 1000U);
}
/**
* @brief This function provides accurate delay (in milliseconds) based
* on SysTick counter flag
* @note When a RTOS is used, it is recommended to avoid using blocking delay
* and use rather osDelay service.
* @note To respect 1ms timebase, user should call @ref LL_Init1msTick function which
* will configure Systick to 1ms
* @param Delay specifies the delay time length, in milliseconds.
* @retval None
*/
void LL_mDelay(uint32_t Delay)
{
__IO uint32_t tmp = SysTick->CTRL; /* Clear the COUNTFLAG first */
uint32_t tmpDelay = Delay;
/* Add this code to indicate that local variable is not used */
((void)tmp);
/* Add a period to guaranty minimum wait */
if(tmpDelay < LL_MAX_DELAY)
{
tmpDelay++;
}
while (tmpDelay != 0U)
{
if((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) != 0U)
{
tmpDelay--;
}
}
}
/**
* @}
*/
/** @addtogroup UTILS_EF_SYSTEM
* @brief System Configuration functions
*
@verbatim
===============================================================================
##### System Configuration functions #####
===============================================================================
[..]
System, AHB and APB buses clocks configuration
(+) The maximum frequency of the SYSCLK, HCLK, PCLK1 and PCLK2 is
120000000 Hz for STM32L4Rx/STM32L4Sx devices and 80000000 Hz for others.
@endverbatim
@internal
Depending on the device voltage range, the maximum frequency should be
adapted accordingly:
(++) Table 1. HCLK clock frequency for STM32L4+ Series devices
(++) +--------------------------------------------------------+
(++) | Latency | HCLK clock frequency (MHz) |
(++) | |--------------------------------------|
(++) | | voltage range 1 | voltage range 2 |
(++) | | 1.2 V | 1.0 V |
(++) |-----------------|-------------------|------------------|
(++) |0WS(1 CPU cycles)| 0 < HCLK <= 20 | 0 < HCLK <= 8 |
(++) |-----------------|-------------------|------------------|
(++) |1WS(2 CPU cycles)| 20 < HCLK <= 40 | 8 < HCLK <= 16 |
(++) |-----------------|-------------------|------------------|
(++) |2WS(3 CPU cycles)| 40 < HCLK <= 60 | 16 < HCLK <= 26 |
(++) |-----------------|-------------------|------------------|
(++) |3WS(4 CPU cycles)| 60 < HCLK <= 80 | 16 < HCLK <= 26 |
(++) |-----------------|-------------------|------------------|
(++) |4WS(5 CPU cycles)| 80 < HCLK <= 100 | 16 < HCLK <= 26 |
(++) |-----------------|-------------------|------------------|
(++) |5WS(6 CPU cycles)| 100 < HCLK <= 120 | 16 < HCLK <= 26 |
(++) +--------------------------------------------------------+
(++) Table 2. HCLK clock frequency for STM32L4 Series devices
(++) +-------------------------------------------------------+
(++) | Latency | HCLK clock frequency (MHz) |
(++) | |-------------------------------------|
(++) | | voltage range 1 | voltage range 2 |
(++) | | 1.2 V | 1.0 V |
(++) |-----------------|------------------|------------------|
(++) |0WS(1 CPU cycles)| 0 < HCLK <= 16 | 0 < HCLK <= 6 |
(++) |-----------------|------------------|------------------|
(++) |1WS(2 CPU cycles)| 16 < HCLK <= 32 | 6 < HCLK <= 12 |
(++) |-----------------|------------------|------------------|
(++) |2WS(3 CPU cycles)| 32 < HCLK <= 48 | 12 < HCLK <= 18 |
(++) |-----------------|------------------|------------------|
(++) |3WS(4 CPU cycles)| 48 < HCLK <= 64 | 18 < HCLK <= 26 |
(++) |-----------------|------------------|------------------|
(++) |4WS(5 CPU cycles)| 64 < HCLK <= 80 | 18 < HCLK <= 26 |
(++) +-------------------------------------------------------+
@endinternal
* @{
*/
/**
* @brief This function sets directly SystemCoreClock CMSIS variable.
* @note Variable can be calculated also through SystemCoreClockUpdate function.
* @param HCLKFrequency HCLK frequency in Hz (can be calculated thanks to RCC helper macro)
* @retval None
*/
void LL_SetSystemCoreClock(uint32_t HCLKFrequency)
{
/* HCLK clock frequency */
SystemCoreClock = HCLKFrequency;
}
/**
* @brief Update number of Flash wait states in line with new frequency and current
voltage range.
* @param HCLKFrequency HCLK frequency
* @retval An ErrorStatus enumeration value:
* - SUCCESS: Latency has been modified
* - ERROR: Latency cannot be modified
*/
ErrorStatus LL_SetFlashLatency(uint32_t HCLKFrequency)
{
ErrorStatus status = SUCCESS;
uint32_t latency = LL_FLASH_LATENCY_0; /* default value 0WS */
/* Frequency cannot be equal to 0 or greater than max clock */
if ((HCLKFrequency == 0U) || (HCLKFrequency > UTILS_MAX_FREQUENCY_SCALE1))
{
status = ERROR;
}
else
{
if(LL_PWR_GetRegulVoltageScaling() == LL_PWR_REGU_VOLTAGE_SCALE1)
{
#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \
defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
if(HCLKFrequency > UTILS_SCALE1_LATENCY5_FREQ)
{
/* 100 < HCLK <= 120 => 5WS (6 CPU cycles) */
latency = LL_FLASH_LATENCY_5;
}
else if(HCLKFrequency > UTILS_SCALE1_LATENCY4_FREQ)
{
/* 80 < HCLK <= 100 => 4WS (5 CPU cycles) */
latency = LL_FLASH_LATENCY_4;
}
else if(HCLKFrequency > UTILS_SCALE1_LATENCY3_FREQ)
{
/* 60 < HCLK <= 80 => 3WS (4 CPU cycles) */
latency = LL_FLASH_LATENCY_3;
}
else if(HCLKFrequency > UTILS_SCALE1_LATENCY2_FREQ)
{
/* 40 < HCLK <= 20 => 2WS (3 CPU cycles) */
latency = LL_FLASH_LATENCY_2;
}
else
{
if(HCLKFrequency > UTILS_SCALE1_LATENCY1_FREQ)
{
/* 20 < HCLK <= 40 => 1WS (2 CPU cycles) */
latency = LL_FLASH_LATENCY_1;
}
/* else HCLKFrequency <= 10MHz default LL_FLASH_LATENCY_0 0WS */
}
#else
if(HCLKFrequency > UTILS_SCALE1_LATENCY4_FREQ)
{
/* 64 < HCLK <= 80 => 4WS (5 CPU cycles) */
latency = LL_FLASH_LATENCY_4;
}
else if(HCLKFrequency > UTILS_SCALE1_LATENCY3_FREQ)
{
/* 48 < HCLK <= 64 => 3WS (4 CPU cycles) */
latency = LL_FLASH_LATENCY_3;
}
else if(HCLKFrequency > UTILS_SCALE1_LATENCY2_FREQ)
{
/* 32 < HCLK <= 48 => 2WS (3 CPU cycles) */
latency = LL_FLASH_LATENCY_2;
}
else
{
if(HCLKFrequency > UTILS_SCALE1_LATENCY1_FREQ)
{
/* 16 < HCLK <= 32 => 1WS (2 CPU cycles) */
latency = LL_FLASH_LATENCY_1;
}
/* else HCLKFrequency <= 16MHz default LL_FLASH_LATENCY_0 0WS */
}
#endif
}
else /* SCALE2 */
{
#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \
defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
if(HCLKFrequency > UTILS_MAX_FREQUENCY_SCALE2)
{
/* Unexpected HCLK > 26 */
status = ERROR;
}
else if(HCLKFrequency > UTILS_SCALE2_LATENCY2_FREQ)
{
/* 16 < HCLK <= 26 => 2WS (3 CPU cycles) */
latency = LL_FLASH_LATENCY_2;
}
else
{
if(HCLKFrequency > UTILS_SCALE2_LATENCY1_FREQ)
{
/* 8 < HCLK <= 16 => 1WS (2 CPU cycles) */
latency = LL_FLASH_LATENCY_1;
}
/* else HCLKFrequency <= 8MHz default LL_FLASH_LATENCY_0 0WS */
}
#else
if(HCLKFrequency > UTILS_MAX_FREQUENCY_SCALE2)
{
/* Unexpected HCLK > 26 */
status = ERROR;
}
else if(HCLKFrequency > UTILS_SCALE2_LATENCY3_FREQ)
{
/* 18 < HCLK <= 26 => 3WS (4 CPU cycles) */
latency = LL_FLASH_LATENCY_3;
}
else if(HCLKFrequency > UTILS_SCALE2_LATENCY2_FREQ)
{
/* 12 < HCLK <= 18 => 2WS (3 CPU cycles) */
latency = LL_FLASH_LATENCY_2;
}
else
{
if(HCLKFrequency > UTILS_SCALE2_LATENCY1_FREQ)
{
/* 6 < HCLK <= 12 => 1WS (2 CPU cycles) */
latency = LL_FLASH_LATENCY_1;
}
/* else HCLKFrequency <= 6MHz default LL_FLASH_LATENCY_0 0WS */
}
#endif
}
LL_FLASH_SetLatency(latency);
/* Check that the new number of wait states is taken into account to access the Flash
memory by reading the FLASH_ACR register */
if(LL_FLASH_GetLatency() != latency)
{
status = ERROR;
}
}
return status;
}
/**
* @brief This function configures system clock with MSI as clock source of the PLL
* @note The application needs to ensure that PLL, PLLSAI1 and/or PLLSAI2 are disabled.
* @note Function is based on the following formula:
* - PLL output frequency = (((MSI frequency / PLLM) * PLLN) / PLLR)
* - PLLM: ensure that the VCO input frequency ranges from 4 to 16 MHz (PLLVCO_input = MSI frequency / PLLM)
* - PLLN: ensure that the VCO output frequency is between 64 and 344 MHz (PLLVCO_output = PLLVCO_input * PLLN)
* - PLLR: ensure that max frequency at 120000000 Hz is reached (PLLVCO_output / PLLR)
* @param UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains
* the configuration information for the PLL.
* @param UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains
* the configuration information for the BUS prescalers.
* @retval An ErrorStatus enumeration value:
* - SUCCESS: Max frequency configuration done
* - ERROR: Max frequency configuration not done
*/
ErrorStatus LL_PLL_ConfigSystemClock_MSI(LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct,
LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct)
{
ErrorStatus status = SUCCESS;
uint32_t pllfreq, msi_range;
#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \
defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
uint32_t hpre = 0U; /* Set default value */
#endif
/* Check if one of the PLL is enabled */
if(UTILS_PLL_IsBusy() == SUCCESS)
{
/* Get the current MSI range */
if(LL_RCC_MSI_IsEnabledRangeSelect() != 0U)
{
msi_range = LL_RCC_MSI_GetRange();
switch (msi_range)
{
case LL_RCC_MSIRANGE_0: /* MSI = 100 KHz */
case LL_RCC_MSIRANGE_1: /* MSI = 200 KHz */
case LL_RCC_MSIRANGE_2: /* MSI = 400 KHz */
case LL_RCC_MSIRANGE_3: /* MSI = 800 KHz */
case LL_RCC_MSIRANGE_4: /* MSI = 1 MHz */
case LL_RCC_MSIRANGE_5: /* MSI = 2 MHz */
/* PLLVCO input frequency is not in the range from 4 to 16 MHz*/
status = ERROR;
break;
case LL_RCC_MSIRANGE_6: /* MSI = 4 MHz */
case LL_RCC_MSIRANGE_7: /* MSI = 8 MHz */
case LL_RCC_MSIRANGE_8: /* MSI = 16 MHz */
case LL_RCC_MSIRANGE_9: /* MSI = 24 MHz */
case LL_RCC_MSIRANGE_10: /* MSI = 32 MHz */
case LL_RCC_MSIRANGE_11: /* MSI = 48 MHz */
default:
break;
}
}
else
{
msi_range = LL_RCC_MSI_GetRangeAfterStandby();
switch (msi_range)
{
case LL_RCC_MSISRANGE_4: /* MSI = 1 MHz */
case LL_RCC_MSISRANGE_5: /* MSI = 2 MHz */
/* PLLVCO input frequency is not in the range from 4 to 16 MHz*/
status = ERROR;
break;
case LL_RCC_MSISRANGE_7: /* MSI = 8 MHz */
case LL_RCC_MSISRANGE_6: /* MSI = 4 MHz */
default:
break;
}
}
/* Main PLL configuration and activation */
if(status != ERROR)
{
/* Calculate the new PLL output frequency */
pllfreq = UTILS_GetPLLOutputFrequency(__LL_RCC_CALC_MSI_FREQ(LL_RCC_MSI_IsEnabledRangeSelect(), msi_range),
UTILS_PLLInitStruct);
/* Enable MSI if not enabled */
if(LL_RCC_MSI_IsReady() != 1U)
{
LL_RCC_MSI_Enable();
while ((LL_RCC_MSI_IsReady() != 1U))
{
/* Wait for MSI ready */
}
}
/* Configure PLL */
LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_MSI, UTILS_PLLInitStruct->PLLM, UTILS_PLLInitStruct->PLLN,
UTILS_PLLInitStruct->PLLR);
#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \
defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
/* Prevent undershoot at highest frequency by applying intermediate AHB prescaler 2 */
if(pllfreq > 80000000U)
{
if(UTILS_ClkInitStruct->AHBCLKDivider == LL_RCC_SYSCLK_DIV_1)
{
UTILS_ClkInitStruct->AHBCLKDivider = LL_RCC_SYSCLK_DIV_2;
hpre = LL_RCC_SYSCLK_DIV_2;
}
}
#endif
/* Enable PLL and switch system clock to PLL */
status = UTILS_EnablePLLAndSwitchSystem(pllfreq, UTILS_ClkInitStruct);
#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \
defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
/* Apply definitive AHB prescaler value if necessary */
if((status == SUCCESS) && (hpre != LL_RCC_SYSCLK_DIV_1))
{
/* Set FLASH latency to highest latency */
status = LL_SetFlashLatency(pllfreq);
if(status == SUCCESS)
{
UTILS_ClkInitStruct->AHBCLKDivider = LL_RCC_SYSCLK_DIV_1;
LL_RCC_SetAHBPrescaler(UTILS_ClkInitStruct->AHBCLKDivider);
LL_SetSystemCoreClock(pllfreq);
}
}
#endif
}
}
else
{
/* Current PLL configuration cannot be modified */
status = ERROR;
}
return status;
}
/**
* @brief This function configures system clock at maximum frequency with HSI as clock source of the PLL
* @note The application need to ensure that PLL, PLLSAI1 and/or PLLSAI2 are disabled.
* @note Function is based on the following formula:
* - PLL output frequency = (((HSI frequency / PLLM) * PLLN) / PLLR)
* - PLLM: ensure that the VCO input frequency ranges from 4 to 16 MHz (PLLVCO_input = HSI frequency / PLLM)
* - PLLN: ensure that the VCO output frequency is between 64 and 344 MHz (PLLVCO_output = PLLVCO_input * PLLN)
* - PLLR: ensure that max frequency at 120000000 Hz is reach (PLLVCO_output / PLLR)
* @param UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains
* the configuration information for the PLL.
* @param UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains
* the configuration information for the BUS prescalers.
* @retval An ErrorStatus enumeration value:
* - SUCCESS: Max frequency configuration done
* - ERROR: Max frequency configuration not done
*/
ErrorStatus LL_PLL_ConfigSystemClock_HSI(LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct,
LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct)
{
ErrorStatus status;
uint32_t pllfreq;
#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \
defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
uint32_t hpre = LL_RCC_SYSCLK_DIV_1; /* Set default value */
#endif
/* Check if one of the PLL is enabled */
if(UTILS_PLL_IsBusy() == SUCCESS)
{
/* Calculate the new PLL output frequency */
pllfreq = UTILS_GetPLLOutputFrequency(HSI_VALUE, UTILS_PLLInitStruct);
/* Enable HSI if not enabled */
if(LL_RCC_HSI_IsReady() != 1U)
{
LL_RCC_HSI_Enable();
while (LL_RCC_HSI_IsReady() != 1U)
{
/* Wait for HSI ready */
}
}
/* Configure PLL */
LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSI, UTILS_PLLInitStruct->PLLM, UTILS_PLLInitStruct->PLLN,
UTILS_PLLInitStruct->PLLR);
#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \
defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
/* Prevent undershoot at highest frequency by applying intermediate AHB prescaler 2 */
if(pllfreq > 80000000U)
{
if(UTILS_ClkInitStruct->AHBCLKDivider == LL_RCC_SYSCLK_DIV_1)
{
UTILS_ClkInitStruct->AHBCLKDivider = LL_RCC_SYSCLK_DIV_2;
hpre = LL_RCC_SYSCLK_DIV_2;
}
}
#endif
/* Enable PLL and switch system clock to PLL */
status = UTILS_EnablePLLAndSwitchSystem(pllfreq, UTILS_ClkInitStruct);
#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \
defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
/* Apply definitive AHB prescaler value if necessary */
if((status == SUCCESS) && (hpre != LL_RCC_SYSCLK_DIV_1))
{
/* Set FLASH latency to highest latency */
status = LL_SetFlashLatency(pllfreq);
if(status == SUCCESS)
{
UTILS_ClkInitStruct->AHBCLKDivider = LL_RCC_SYSCLK_DIV_1;
LL_RCC_SetAHBPrescaler(UTILS_ClkInitStruct->AHBCLKDivider);
LL_SetSystemCoreClock(pllfreq);
}
}
#endif
}
else
{
/* Current PLL configuration cannot be modified */
status = ERROR;
}
return status;
}
/**
* @brief This function configures system clock with HSE as clock source of the PLL
* @note The application need to ensure that PLL, PLLSAI1 and/or PLLSAI2 are disabled.
* @note Function is based on the following formula:
* - PLL output frequency = (((HSE frequency / PLLM) * PLLN) / PLLR)
* - PLLM: ensure that the VCO input frequency ranges from 4 to 16 MHz (PLLVCO_input = HSE frequency / PLLM)
* - PLLN: ensure that the VCO output frequency is between 64 and 344 MHz (PLLVCO_output = PLLVCO_input * PLLN)
* - PLLR: ensure that max frequency at 120000000 Hz is reached (PLLVCO_output / PLLR)
* @param HSEFrequency Value between Min_Data = 4000000 and Max_Data = 48000000
* @param HSEBypass This parameter can be one of the following values:
* @arg @ref LL_UTILS_HSEBYPASS_ON
* @arg @ref LL_UTILS_HSEBYPASS_OFF
* @param UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains
* the configuration information for the PLL.
* @param UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains
* the configuration information for the BUS prescalers.
* @retval An ErrorStatus enumeration value:
* - SUCCESS: Max frequency configuration done
* - ERROR: Max frequency configuration not done
*/
ErrorStatus LL_PLL_ConfigSystemClock_HSE(uint32_t HSEFrequency, uint32_t HSEBypass,
LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct, LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct)
{
ErrorStatus status;
uint32_t pllfreq;
#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \
defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
uint32_t hpre = 0U; /* Set default value */
#endif
/* Check the parameters */
assert_param(IS_LL_UTILS_HSE_FREQUENCY(HSEFrequency));
assert_param(IS_LL_UTILS_HSE_BYPASS(HSEBypass));
/* Check if one of the PLL is enabled */
if(UTILS_PLL_IsBusy() == SUCCESS)
{
/* Calculate the new PLL output frequency */
pllfreq = UTILS_GetPLLOutputFrequency(HSEFrequency, UTILS_PLLInitStruct);
/* Enable HSE if not enabled */
if(LL_RCC_HSE_IsReady() != 1U)
{
/* Check if need to enable HSE bypass feature or not */
if(HSEBypass == LL_UTILS_HSEBYPASS_ON)
{
LL_RCC_HSE_EnableBypass();
}
else
{
LL_RCC_HSE_DisableBypass();
}
/* Enable HSE */
LL_RCC_HSE_Enable();
while (LL_RCC_HSE_IsReady() != 1U)
{
/* Wait for HSE ready */
}
}
/* Configure PLL */
LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, UTILS_PLLInitStruct->PLLM, UTILS_PLLInitStruct->PLLN,
UTILS_PLLInitStruct->PLLR);
#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \
defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
/* Prevent undershoot at highest frequency by applying intermediate AHB prescaler 2 */
if(pllfreq > 80000000U)
{
if(UTILS_ClkInitStruct->AHBCLKDivider == LL_RCC_SYSCLK_DIV_1)
{
UTILS_ClkInitStruct->AHBCLKDivider = LL_RCC_SYSCLK_DIV_2;
hpre = LL_RCC_SYSCLK_DIV_2;
}
}
#endif
/* Enable PLL and switch system clock to PLL */
status = UTILS_EnablePLLAndSwitchSystem(pllfreq, UTILS_ClkInitStruct);
#if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || \
defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
/* Apply definitive AHB prescaler value if necessary */
if((status == SUCCESS) && (hpre != LL_RCC_SYSCLK_DIV_1))
{
/* Set FLASH latency to highest latency */
status = LL_SetFlashLatency(pllfreq);
if(status == SUCCESS)
{
UTILS_ClkInitStruct->AHBCLKDivider = LL_RCC_SYSCLK_DIV_1;
LL_RCC_SetAHBPrescaler(UTILS_ClkInitStruct->AHBCLKDivider);
LL_SetSystemCoreClock(pllfreq);
}
}
#endif
}
else
{
/* Current PLL configuration cannot be modified */
status = ERROR;
}
return status;
}
/**
* @}
*/
/**
* @}
*/
/** @addtogroup UTILS_LL_Private_Functions
* @{
*/
/**
* @brief Function to check that PLL can be modified
* @param PLL_InputFrequency PLL input frequency (in Hz)
* @param UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains
* the configuration information for the PLL.
* @retval PLL output frequency (in Hz)
*/
static uint32_t UTILS_GetPLLOutputFrequency(uint32_t PLL_InputFrequency, LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct)
{
uint32_t pllfreq;
/* Check the parameters */
assert_param(IS_LL_UTILS_PLLM_VALUE(UTILS_PLLInitStruct->PLLM));
assert_param(IS_LL_UTILS_PLLN_VALUE(UTILS_PLLInitStruct->PLLN));
assert_param(IS_LL_UTILS_PLLR_VALUE(UTILS_PLLInitStruct->PLLR));
/* Check different PLL parameters according to RM */
/* - PLLM: ensure that the VCO input frequency ranges from 4 to 16 MHz. */
pllfreq = PLL_InputFrequency / (((UTILS_PLLInitStruct->PLLM >> RCC_PLLCFGR_PLLM_Pos) + 1U));
assert_param(IS_LL_UTILS_PLLVCO_INPUT(pllfreq));
/* - PLLN: ensure that the VCO output frequency is between 64 and 344 MHz.*/
pllfreq = pllfreq * (UTILS_PLLInitStruct->PLLN & (RCC_PLLCFGR_PLLN >> RCC_PLLCFGR_PLLN_Pos));
assert_param(IS_LL_UTILS_PLLVCO_OUTPUT(pllfreq));
/* - PLLR: ensure that max frequency at 120000000 Hz is reached */
pllfreq = pllfreq / (((UTILS_PLLInitStruct->PLLR >> RCC_PLLCFGR_PLLR_Pos) + 1U) * 2U);
assert_param(IS_LL_UTILS_PLL_FREQUENCY(pllfreq));
return pllfreq;
}
/**
* @brief Function to check that PLL can be modified
* @retval An ErrorStatus enumeration value:
* - SUCCESS: PLL modification can be done
* - ERROR: PLL is busy
*/
static ErrorStatus UTILS_PLL_IsBusy(void)
{
ErrorStatus status = SUCCESS;
/* Check if PLL is busy*/
if(LL_RCC_PLL_IsReady() != 0U)
{
/* PLL configuration cannot be modified */
status = ERROR;
}
#if defined(RCC_PLLSAI1_SUPPORT)
/* Check if PLLSAI1 is busy*/
if(LL_RCC_PLLSAI1_IsReady() != 0U)
{
/* PLLSAI1 configuration cannot be modified */
status = ERROR;
}
#endif /*RCC_PLLSAI1_SUPPORT*/
#if defined(RCC_PLLSAI2_SUPPORT)
/* Check if PLLSAI2 is busy*/
if(LL_RCC_PLLSAI2_IsReady() != 0U)
{
/* PLLSAI2 configuration cannot be modified */
status = ERROR;
}
#endif /*RCC_PLLSAI2_SUPPORT*/
return status;
}
/**
* @brief Function to enable PLL and switch system clock to PLL
* @param SYSCLK_Frequency SYSCLK frequency
* @param UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains
* the configuration information for the BUS prescalers.
* @retval An ErrorStatus enumeration value:
* - SUCCESS: No problem to switch system to PLL
* - ERROR: Problem to switch system to PLL
*/
static ErrorStatus UTILS_EnablePLLAndSwitchSystem(uint32_t SYSCLK_Frequency, LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct)
{
ErrorStatus status = SUCCESS;
uint32_t hclk_frequency;
assert_param(IS_LL_UTILS_SYSCLK_DIV(UTILS_ClkInitStruct->AHBCLKDivider));
assert_param(IS_LL_UTILS_APB1_DIV(UTILS_ClkInitStruct->APB1CLKDivider));
assert_param(IS_LL_UTILS_APB2_DIV(UTILS_ClkInitStruct->APB2CLKDivider));
/* Calculate HCLK frequency */
hclk_frequency = __LL_RCC_CALC_HCLK_FREQ(SYSCLK_Frequency, UTILS_ClkInitStruct->AHBCLKDivider);
/* Increasing the number of wait states because of higher CPU frequency */
if(SystemCoreClock < hclk_frequency)
{
/* Set FLASH latency to highest latency */
status = LL_SetFlashLatency(hclk_frequency);
}
/* Update system clock configuration */
if(status == SUCCESS)
{
/* Enable PLL */
LL_RCC_PLL_Enable();
LL_RCC_PLL_EnableDomain_SYS();
while (LL_RCC_PLL_IsReady() != 1U)
{
/* Wait for PLL ready */
}
/* Sysclk activation on the main PLL */
LL_RCC_SetAHBPrescaler(UTILS_ClkInitStruct->AHBCLKDivider);
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);
while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
{
/* Wait for system clock switch to PLL */
}
/* Set APB1 & APB2 prescaler*/
LL_RCC_SetAPB1Prescaler(UTILS_ClkInitStruct->APB1CLKDivider);
LL_RCC_SetAPB2Prescaler(UTILS_ClkInitStruct->APB2CLKDivider);
}
/* Decreasing the number of wait states because of lower CPU frequency */
if(SystemCoreClock > hclk_frequency)
{
/* Set FLASH latency to lowest latency */
status = LL_SetFlashLatency(hclk_frequency);
}
/* Update SystemCoreClock variable */
if(status == SUCCESS)
{
LL_SetSystemCoreClock(hclk_frequency);
}
return status;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/