diff options
Diffstat (limited to 'thirdparty/STM32_USB-FS-Device_Lib_V4.0.0/Libraries/STM32L1xx_StdPeriph_Driver/src')
6 files changed, 7266 insertions, 0 deletions
diff --git a/thirdparty/STM32_USB-FS-Device_Lib_V4.0.0/Libraries/STM32L1xx_StdPeriph_Driver/src/stm32l1xx_comp.c b/thirdparty/STM32_USB-FS-Device_Lib_V4.0.0/Libraries/STM32L1xx_StdPeriph_Driver/src/stm32l1xx_comp.c new file mode 100644 index 0000000..991f822 --- /dev/null +++ b/thirdparty/STM32_USB-FS-Device_Lib_V4.0.0/Libraries/STM32L1xx_StdPeriph_Driver/src/stm32l1xx_comp.c @@ -0,0 +1,378 @@ +/** + ****************************************************************************** + * @file stm32l1xx_comp.c + * @author MCD Application Team + * @version V1.1.1 + * @date 05-March-2012 + * @brief This file provides firmware functions to manage the following + * functionalities of the comparators (COMP1 and COMP2) peripheral: + * + Comparators configuration + * + Window mode control + * + Internal Reference Voltage (VREFINT) output + * + * @verbatim + =============================================================================== + ##### How to use this driver ##### + =============================================================================== + [..] The device integrates two analog comparators COMP1 and COMP2: + (+) COMP1 is a fixed threshold (VREFINT) that shares the non inverting + input with the ADC channels. + (+) COMP2 is a rail-to-rail comparator whose the inverting input can be + selected among: DAC_OUT1, DAC_OUT2, 1/4 VREFINT, 1/2 VERFINT, 3/4 + VREFINT, VREFINT, PB3 and whose the output can be redirected to + embedded timers: TIM2, TIM3, TIM4, TIM10. + + (+) The two comparators COMP1 and COMP2 can be combined in window mode. + + -@- + (#@) Comparator APB clock must be enabled to get write access + to comparator register using + RCC_APB1PeriphClockCmd(RCC_APB1Periph_COMP, ENABLE). + + (#@) COMP1 comparator and ADC can't be used at the same time since + they share the same ADC switch matrix (analog switches). + + (#@) When an I/O is used as comparator input, the corresponding GPIO + registers should be configured in analog mode. + + (#@) Comparators outputs (CMP1OUT and CMP2OUT) are not mapped on + GPIO pin. They are only internal. + To get the comparator output level, use COMP_GetOutputLevel(). + + (#@) COMP1 and COMP2 outputs are internally connected to EXTI Line 21 + and EXTI Line 22 respectively. + Interrupts can be used by configuring the EXTI Line using the + EXTI peripheral driver. + + (#@) After enabling the comparator (COMP1 or COMP2), user should wait + for start-up time (tSTART) to get right output levels. + Please refer to product datasheet for more information on tSTART. + + (#@) Comparators cannot be used to exit the device from Sleep or Stop + mode when the internal reference voltage is switched off using + the PWR_UltraLowPowerCmd() function (ULP bit in the PWR_CR register). + + @endverbatim + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2012 STMicroelectronics</center></h2> + * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l1xx_comp.h" + +/** @addtogroup STM32L1xx_StdPeriph_Driver + * @{ + */ + +/** @defgroup COMP + * @brief COMP driver modules. + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/** @defgroup COMP_Private_Functions + * @{ + */ + +/** @defgroup COMP_Group1 Initialization and Configuration functions + * @brief Initialization and Configuration functions. + * +@verbatim + =============================================================================== + ##### Initialization and Configuration functions ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Deinitializes COMP peripheral registers to their default reset values. + * @param None + * @retval None + */ +void COMP_DeInit(void) +{ + COMP->CSR = ((uint32_t)0x00000000); /*!< Set COMP->CSR to reset value */ +} + +/** + * @brief Initializes the COMP2 peripheral according to the specified parameters + * in the COMP_InitStruct. + * @note This function configures only COMP2. + * @note COMP2 comparator is enabled as soon as the INSEL[2:0] bits are + * different from "000". + * @param COMP_InitStruct: pointer to an COMP_InitTypeDef structure that contains + * the configuration information for the specified COMP peripheral. + * @retval None + */ +void COMP_Init(COMP_InitTypeDef* COMP_InitStruct) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_COMP_INVERTING_INPUT(COMP_InitStruct->COMP_InvertingInput)); + assert_param(IS_COMP_OUTPUT(COMP_InitStruct->COMP_OutputSelect)); + assert_param(IS_COMP_SPEED(COMP_InitStruct->COMP_Speed)); + + /*!< Get the COMP CSR value */ + tmpreg = COMP->CSR; + + /*!< Clear the INSEL[2:0], OUTSEL[1:0] and SPEED bits */ + tmpreg &= (uint32_t) (~(uint32_t) (COMP_CSR_OUTSEL | COMP_CSR_INSEL | COMP_CSR_SPEED)); + + /*!< Configure COMP: speed, inversion input selection and output redirection */ + /*!< Set SPEED bit according to COMP_InitStruct->COMP_Speed value */ + /*!< Set INSEL bits according to COMP_InitStruct->COMP_InvertingInput value */ + /*!< Set OUTSEL bits according to COMP_InitStruct->COMP_OutputSelect value */ + tmpreg |= (uint32_t)((COMP_InitStruct->COMP_Speed | COMP_InitStruct->COMP_InvertingInput + | COMP_InitStruct->COMP_OutputSelect)); + + /*!< The COMP2 comparator is enabled as soon as the INSEL[2:0] bits value are + different from "000" */ + /*!< Write to COMP_CSR register */ + COMP->CSR = tmpreg; +} + +/** + * @brief Enable or disable the COMP1 peripheral. + * @note After enabling COMP1, the following functions should be called to + * connect the selected GPIO input to COMP1 non inverting input: + * @note Enable switch control mode using SYSCFG_RISwitchControlModeCmd() + * @note Close VCOMP switch using SYSCFG_RIIOSwitchConfig() + * @note Close the I/O switch number n corresponding to the I/O + * using SYSCFG_RIIOSwitchConfig() + * @param NewState: new state of the COMP1 peripheral. + * This parameter can be: ENABLE or DISABLE. + * @note This function enables/disables only the COMP1. + * @retval None + */ +void COMP_Cmd(FunctionalState NewState) +{ + /* Check the parameter */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the COMP1 */ + COMP->CSR |= (uint32_t) COMP_CSR_CMP1EN; + } + else + { + /* Disable the COMP1 */ + COMP->CSR &= (uint32_t)(~COMP_CSR_CMP1EN); + } +} + +/** + * @brief Return the output level (high or low) of the selected comparator. + * @note Comparator output is low when the noninverting input is at a lower + * voltage than the inverting input. + * @note Comparator output is high when the noninverting input is at a higher + * voltage than the inverting input. + * @note Comparators outputs aren't available on GPIO (outputs levels are + * only internal). The COMP1 and COMP2 outputs are connected internally + * to the EXTI Line 21 and Line 22 respectively. + * @param COMP_Selection: the selected comparator. + * This parameter can be one of the following values: + * @arg COMP_Selection_COMP1: COMP1 selected + * @arg COMP_Selection_COMP2: COMP2 selected + * @retval Returns the selected comparator output level. + */ +uint8_t COMP_GetOutputLevel(uint32_t COMP_Selection) +{ + uint8_t compout = 0x0; + + /* Check the parameters */ + assert_param(IS_COMP_ALL_PERIPH(COMP_Selection)); + + /* Check if Comparator 1 is selected */ + if(COMP_Selection == COMP_Selection_COMP1) + { + /* Check if comparator 1 output level is high */ + if((COMP->CSR & COMP_CSR_CMP1OUT) != (uint8_t) RESET) + { + /* Get Comparator 1 output level */ + compout = (uint8_t) COMP_OutputLevel_High; + } + /* comparator 1 output level is low */ + else + { + /* Get Comparator 1 output level */ + compout = (uint8_t) COMP_OutputLevel_Low; + } + } + /* Comparator 2 is selected */ + else + { + /* Check if comparator 2 output level is high */ + if((COMP->CSR & COMP_CSR_CMP2OUT) != (uint8_t) RESET) + { + /* Get Comparator output level */ + compout = (uint8_t) COMP_OutputLevel_High; + } + /* comparator 2 output level is low */ + else + { + /* Get Comparator 2 output level */ + compout = (uint8_t) COMP_OutputLevel_Low; + } + } + /* Return the comparator output level */ + return (uint8_t)(compout); +} + +/** + * @brief Close or Open the SW1 switch. + * @param NewState: new state of the SW1 switch. + * This parameter can be: ENABLE or DISABLE. + * @note ENABLE to close the SW1 switch + * @note DISABLE to open the SW1 switch + * @retval None. + */ +void COMP_SW1SwitchConfig(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Close SW1 switch */ + COMP->CSR |= (uint32_t) COMP_CSR_SW1; + } + else + { + /* Open SW1 switch */ + COMP->CSR &= (uint32_t)(~COMP_CSR_SW1); + } +} + +/** + * @} + */ + +/** @defgroup COMP_Group2 Window mode control function + * @brief Window mode control function. + * +@verbatim + =============================================================================== + ##### Window mode control function ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Enables or disables the window mode. + * In window mode: + * @note COMP1 inverting input is fixed to VREFINT defining the first + * threshold. + * @note COMP2 inverting input is configurable (DAC_OUT1, DAC_OUT2, VREFINT + * sub-multiples, PB3) defining the second threshold. + * @note COMP1 and COMP2 non inverting inputs are connected together. + * @note In window mode, only the Group 6 (PB4 or PB5) can be used as + * noninverting inputs. + * @param NewState: new state of the window mode. + * This parameter can be ENABLE or DISABLE. + * @retval None + */ +void COMP_WindowCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the window mode */ + COMP->CSR |= (uint32_t) COMP_CSR_WNDWE; + } + else + { + /* Disable the window mode */ + COMP->CSR &= (uint32_t)(~COMP_CSR_WNDWE); + } +} + +/** + * @} + */ + +/** @defgroup COMP_Group3 Internal Reference Voltage output function + * @brief Internal Reference Voltage (VREFINT) output function. + * +@verbatim + =============================================================================== + ##### Internal Reference Voltage (VREFINT) output function ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Enables or disables the output of internal reference voltage (VREFINT). + * The VREFINT output can be routed to any I/O in group 3: CH8 (PB0) or + * CH9 (PB1). + * To correctly use this function, the SYSCFG_RIIOSwitchConfig() function + * should be called after. + * @param NewState: new state of the Vrefint output. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void COMP_VrefintOutputCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the output of internal reference voltage */ + COMP->CSR |= (uint32_t) COMP_CSR_VREFOUTEN; + } + else + { + /* Disable the output of internal reference voltage */ + COMP->CSR &= (uint32_t) (~COMP_CSR_VREFOUTEN); + } +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/thirdparty/STM32_USB-FS-Device_Lib_V4.0.0/Libraries/STM32L1xx_StdPeriph_Driver/src/stm32l1xx_dma.c b/thirdparty/STM32_USB-FS-Device_Lib_V4.0.0/Libraries/STM32L1xx_StdPeriph_Driver/src/stm32l1xx_dma.c new file mode 100644 index 0000000..b21cef1 --- /dev/null +++ b/thirdparty/STM32_USB-FS-Device_Lib_V4.0.0/Libraries/STM32L1xx_StdPeriph_Driver/src/stm32l1xx_dma.c @@ -0,0 +1,866 @@ +/** + ****************************************************************************** + * @file stm32l1xx_dma.c + * @author MCD Application Team + * @version V1.1.1 + * @date 05-March-2012 + * @brief This file provides firmware functions to manage the following + * functionalities of the Direct Memory Access controller (DMA): + * + Initialization and Configuration + * + Data Counter + * + Interrupts and flags management + * + * @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + (#) Enable The DMA controller clock using + RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE) function for DMA1 or + using RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE) function for DMA2. + (#) Enable and configure the peripheral to be connected to the DMA channel + (except for internal SRAM / FLASH memories: no initialization is + necessary). + (#) For a given Channel, program the Source and Destination addresses, + the transfer Direction, the Buffer Size, the Peripheral and Memory + Incrementation mode and Data Size, the Circular or Normal mode, + the channel transfer Priority and the Memory-to-Memory transfer + mode (if needed) using the DMA_Init() function. + (#) Enable the NVIC and the corresponding interrupt(s) using the function + DMA_ITConfig() if you need to use DMA interrupts. + (#) Enable the DMA channel using the DMA_Cmd() function. + (#) Activate the needed channel Request using PPP_DMACmd() function for + any PPP peripheral except internal SRAM and FLASH (ie. SPI, USART ...) + The function allowing this operation is provided in each PPP peripheral + driver (ie. SPI_DMACmd for SPI peripheral). + (#) Optionally, you can configure the number of data to be transferred + when the channel is disabled (ie. after each Transfer Complete event + or when a Transfer Error occurs) using the function DMA_SetCurrDataCounter(). + And you can get the number of remaining data to be transferred using + the function DMA_GetCurrDataCounter() at run time (when the DMA channel is + enabled and running). + (#) To control DMA events you can use one of the following two methods: + (##) Check on DMA channel flags using the function DMA_GetFlagStatus(). + (##) Use DMA interrupts through the function DMA_ITConfig() at initialization + phase and DMA_GetITStatus() function into interrupt routines in + communication phase. + After checking on a flag you should clear it using DMA_ClearFlag() + function. And after checking on an interrupt event you should + clear it using DMA_ClearITPendingBit() function. + @endverbatim + + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2012 STMicroelectronics</center></h2> + * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l1xx_dma.h" +#include "stm32l1xx_rcc.h" + +/** @addtogroup STM32L1xx_StdPeriph_Driver + * @{ + */ + +/** @defgroup DMA + * @brief DMA driver modules + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ + +/* DMA1 Channelx interrupt pending bit masks */ +#define DMA1_CHANNEL1_IT_MASK ((uint32_t)(DMA_ISR_GIF1 | DMA_ISR_TCIF1 | DMA_ISR_HTIF1 | DMA_ISR_TEIF1)) +#define DMA1_CHANNEL2_IT_MASK ((uint32_t)(DMA_ISR_GIF2 | DMA_ISR_TCIF2 | DMA_ISR_HTIF2 | DMA_ISR_TEIF2)) +#define DMA1_CHANNEL3_IT_MASK ((uint32_t)(DMA_ISR_GIF3 | DMA_ISR_TCIF3 | DMA_ISR_HTIF3 | DMA_ISR_TEIF3)) +#define DMA1_CHANNEL4_IT_MASK ((uint32_t)(DMA_ISR_GIF4 | DMA_ISR_TCIF4 | DMA_ISR_HTIF4 | DMA_ISR_TEIF4)) +#define DMA1_CHANNEL5_IT_MASK ((uint32_t)(DMA_ISR_GIF5 | DMA_ISR_TCIF5 | DMA_ISR_HTIF5 | DMA_ISR_TEIF5)) +#define DMA1_CHANNEL6_IT_MASK ((uint32_t)(DMA_ISR_GIF6 | DMA_ISR_TCIF6 | DMA_ISR_HTIF6 | DMA_ISR_TEIF6)) +#define DMA1_CHANNEL7_IT_MASK ((uint32_t)(DMA_ISR_GIF7 | DMA_ISR_TCIF7 | DMA_ISR_HTIF7 | DMA_ISR_TEIF7)) + +/* DMA2 Channelx interrupt pending bit masks */ +#define DMA2_CHANNEL1_IT_MASK ((uint32_t)(DMA_ISR_GIF1 | DMA_ISR_TCIF1 | DMA_ISR_HTIF1 | DMA_ISR_TEIF1)) +#define DMA2_CHANNEL2_IT_MASK ((uint32_t)(DMA_ISR_GIF2 | DMA_ISR_TCIF2 | DMA_ISR_HTIF2 | DMA_ISR_TEIF2)) +#define DMA2_CHANNEL3_IT_MASK ((uint32_t)(DMA_ISR_GIF3 | DMA_ISR_TCIF3 | DMA_ISR_HTIF3 | DMA_ISR_TEIF3)) +#define DMA2_CHANNEL4_IT_MASK ((uint32_t)(DMA_ISR_GIF4 | DMA_ISR_TCIF4 | DMA_ISR_HTIF4 | DMA_ISR_TEIF4)) +#define DMA2_CHANNEL5_IT_MASK ((uint32_t)(DMA_ISR_GIF5 | DMA_ISR_TCIF5 | DMA_ISR_HTIF5 | DMA_ISR_TEIF5)) + +/* DMA FLAG mask */ +#define FLAG_MASK ((uint32_t)0x10000000) + +/* DMA registers Masks */ +#define CCR_CLEAR_MASK ((uint32_t)0xFFFF800F) + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + + +/** @defgroup DMA_Private_Functions + * @{ + */ + +/** @defgroup DMA_Group1 Initialization and Configuration functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and Configuration functions ##### + =============================================================================== + [..] This subsection provides functions allowing to initialize the DMA channel + source and destination addresses, incrementation and data sizes, transfer + direction, buffer size, circular/normal mode selection, memory-to-memory + mode selection and channel priority value. + [..] The DMA_Init() function follows the DMA configuration procedures as described + in reference manual (RM0038). +@endverbatim + * @{ + */ + +/** + * @brief Deinitializes the DMAy Channelx registers to their default reset + * values. + * @param DMAy_Channelx: where y can be 1 or 2 to select the DMA and x can be + * 1 to 7 for DMA1 and 1 to 5 for DMA2 to select the DMA Channel. + * @retval None + */ +void DMA_DeInit(DMA_Channel_TypeDef* DMAy_Channelx) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Channelx)); + + /* Disable the selected DMAy Channelx */ + DMAy_Channelx->CCR &= (uint16_t)(~DMA_CCR1_EN); + + /* Reset DMAy Channelx control register */ + DMAy_Channelx->CCR = 0; + + /* Reset DMAy Channelx remaining bytes register */ + DMAy_Channelx->CNDTR = 0; + + /* Reset DMAy Channelx peripheral address register */ + DMAy_Channelx->CPAR = 0; + + /* Reset DMAy Channelx memory address register */ + DMAy_Channelx->CMAR = 0; + + if (DMAy_Channelx == DMA1_Channel1) + { + /* Reset interrupt pending bits for DMA1 Channel1 */ + DMA1->IFCR |= DMA1_CHANNEL1_IT_MASK; + } + else if (DMAy_Channelx == DMA1_Channel2) + { + /* Reset interrupt pending bits for DMA1 Channel2 */ + DMA1->IFCR |= DMA1_CHANNEL2_IT_MASK; + } + else if (DMAy_Channelx == DMA1_Channel3) + { + /* Reset interrupt pending bits for DMA1 Channel3 */ + DMA1->IFCR |= DMA1_CHANNEL3_IT_MASK; + } + else if (DMAy_Channelx == DMA1_Channel4) + { + /* Reset interrupt pending bits for DMA1 Channel4 */ + DMA1->IFCR |= DMA1_CHANNEL4_IT_MASK; + } + else if (DMAy_Channelx == DMA1_Channel5) + { + /* Reset interrupt pending bits for DMA1 Channel5 */ + DMA1->IFCR |= DMA1_CHANNEL5_IT_MASK; + } + else if (DMAy_Channelx == DMA1_Channel6) + { + /* Reset interrupt pending bits for DMA1 Channel6 */ + DMA1->IFCR |= DMA1_CHANNEL6_IT_MASK; + } + else if (DMAy_Channelx == DMA1_Channel7) + { + /* Reset interrupt pending bits for DMA1 Channel7 */ + DMA1->IFCR |= DMA1_CHANNEL7_IT_MASK; + } + else if (DMAy_Channelx == DMA2_Channel1) + { + /* Reset interrupt pending bits for DMA2 Channel1 */ + DMA2->IFCR |= DMA2_CHANNEL1_IT_MASK; + } + else if (DMAy_Channelx == DMA2_Channel2) + { + /* Reset interrupt pending bits for DMA2 Channel2 */ + DMA2->IFCR |= DMA2_CHANNEL2_IT_MASK; + } + else if (DMAy_Channelx == DMA2_Channel3) + { + /* Reset interrupt pending bits for DMA2 Channel3 */ + DMA2->IFCR |= DMA2_CHANNEL3_IT_MASK; + } + else if (DMAy_Channelx == DMA2_Channel4) + { + /* Reset interrupt pending bits for DMA2 Channel4 */ + DMA2->IFCR |= DMA2_CHANNEL4_IT_MASK; + } + else + { + if (DMAy_Channelx == DMA2_Channel5) + { + /* Reset interrupt pending bits for DMA2 Channel5 */ + DMA2->IFCR |= DMA2_CHANNEL5_IT_MASK; + } + } +} + +/** + * @brief Initializes the DMAy Channelx according to the specified + * parameters in the DMA_InitStruct. + * @param DMAy_Channelx: where y can be 1 or 2 to select the DMA and x can be + * 1 to 7 for DMA1 and 1 to 5 for DMA2 to select the DMA Channel. + * @param DMA_InitStruct: pointer to a DMA_InitTypeDef structure that + * contains the configuration information for the specified DMA Channel. + * @retval None + */ +void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Channelx)); + assert_param(IS_DMA_DIR(DMA_InitStruct->DMA_DIR)); + assert_param(IS_DMA_BUFFER_SIZE(DMA_InitStruct->DMA_BufferSize)); + assert_param(IS_DMA_PERIPHERAL_INC_STATE(DMA_InitStruct->DMA_PeripheralInc)); + assert_param(IS_DMA_MEMORY_INC_STATE(DMA_InitStruct->DMA_MemoryInc)); + assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(DMA_InitStruct->DMA_PeripheralDataSize)); + assert_param(IS_DMA_MEMORY_DATA_SIZE(DMA_InitStruct->DMA_MemoryDataSize)); + assert_param(IS_DMA_MODE(DMA_InitStruct->DMA_Mode)); + assert_param(IS_DMA_PRIORITY(DMA_InitStruct->DMA_Priority)); + assert_param(IS_DMA_M2M_STATE(DMA_InitStruct->DMA_M2M)); + +/*--------------------------- DMAy Channelx CCR Configuration -----------------*/ + /* Get the DMAy_Channelx CCR value */ + tmpreg = DMAy_Channelx->CCR; + /* Clear MEM2MEM, PL, MSIZE, PSIZE, MINC, PINC, CIRC and DIR bits */ + tmpreg &= CCR_CLEAR_MASK; + /* Configure DMAy Channelx: data transfer, data size, priority level and mode */ + /* Set DIR bit according to DMA_DIR value */ + /* Set CIRC bit according to DMA_Mode value */ + /* Set PINC bit according to DMA_PeripheralInc value */ + /* Set MINC bit according to DMA_MemoryInc value */ + /* Set PSIZE bits according to DMA_PeripheralDataSize value */ + /* Set MSIZE bits according to DMA_MemoryDataSize value */ + /* Set PL bits according to DMA_Priority value */ + /* Set the MEM2MEM bit according to DMA_M2M value */ + tmpreg |= DMA_InitStruct->DMA_DIR | DMA_InitStruct->DMA_Mode | + DMA_InitStruct->DMA_PeripheralInc | DMA_InitStruct->DMA_MemoryInc | + DMA_InitStruct->DMA_PeripheralDataSize | DMA_InitStruct->DMA_MemoryDataSize | + DMA_InitStruct->DMA_Priority | DMA_InitStruct->DMA_M2M; + + /* Write to DMAy Channelx CCR */ + DMAy_Channelx->CCR = tmpreg; + +/*--------------------------- DMAy Channelx CNDTR Configuration ---------------*/ + /* Write to DMAy Channelx CNDTR */ + DMAy_Channelx->CNDTR = DMA_InitStruct->DMA_BufferSize; + +/*--------------------------- DMAy Channelx CPAR Configuration ----------------*/ + /* Write to DMAy Channelx CPAR */ + DMAy_Channelx->CPAR = DMA_InitStruct->DMA_PeripheralBaseAddr; + +/*--------------------------- DMAy Channelx CMAR Configuration ----------------*/ + /* Write to DMAy Channelx CMAR */ + DMAy_Channelx->CMAR = DMA_InitStruct->DMA_MemoryBaseAddr; +} + +/** + * @brief Fills each DMA_InitStruct member with its default value. + * @param DMA_InitStruct: pointer to a DMA_InitTypeDef structure which will + * be initialized. + * @retval None + */ +void DMA_StructInit(DMA_InitTypeDef* DMA_InitStruct) +{ +/*-------------- Reset DMA init structure parameters values ------------------*/ + /* Initialize the DMA_PeripheralBaseAddr member */ + DMA_InitStruct->DMA_PeripheralBaseAddr = 0; + /* Initialize the DMA_MemoryBaseAddr member */ + DMA_InitStruct->DMA_MemoryBaseAddr = 0; + /* Initialize the DMA_DIR member */ + DMA_InitStruct->DMA_DIR = DMA_DIR_PeripheralSRC; + /* Initialize the DMA_BufferSize member */ + DMA_InitStruct->DMA_BufferSize = 0; + /* Initialize the DMA_PeripheralInc member */ + DMA_InitStruct->DMA_PeripheralInc = DMA_PeripheralInc_Disable; + /* Initialize the DMA_MemoryInc member */ + DMA_InitStruct->DMA_MemoryInc = DMA_MemoryInc_Disable; + /* Initialize the DMA_PeripheralDataSize member */ + DMA_InitStruct->DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; + /* Initialize the DMA_MemoryDataSize member */ + DMA_InitStruct->DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; + /* Initialize the DMA_Mode member */ + DMA_InitStruct->DMA_Mode = DMA_Mode_Normal; + /* Initialize the DMA_Priority member */ + DMA_InitStruct->DMA_Priority = DMA_Priority_Low; + /* Initialize the DMA_M2M member */ + DMA_InitStruct->DMA_M2M = DMA_M2M_Disable; +} + +/** + * @brief Enables or disables the specified DMAy Channelx. + * @param DMAy_Channelx: where y can be 1 or 2 to select the DMA and x can be + * 1 to 7 for DMA1 and 1 to 5 for DMA2 to select the DMA Channel. + * @param NewState: new state of the DMAy Channelx. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void DMA_Cmd(DMA_Channel_TypeDef* DMAy_Channelx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Channelx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the selected DMAy Channelx */ + DMAy_Channelx->CCR |= DMA_CCR1_EN; + } + else + { + /* Disable the selected DMAy Channelx */ + DMAy_Channelx->CCR &= (uint16_t)(~DMA_CCR1_EN); + } +} + +/** + * @} + */ + +/** @defgroup DMA_Group2 Data Counter functions + * @brief Data Counter functions + * +@verbatim + =============================================================================== + ##### Data Counter functions ##### + =============================================================================== + [..] This subsection provides function allowing to configure and read the buffer + size (number of data to be transferred).The DMA data counter can be written + only when the DMA channel is disabled (ie. after transfer complete event). + [..] The following function can be used to write the Channel data counter value: + (+) void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t + DataNumber). + -@- It is advised to use this function rather than DMA_Init() in situations + where only the Data buffer needs to be reloaded. + [..] The DMA data counter can be read to indicate the number of remaining transfers + for the relative DMA channel. This counter is decremented at the end of each + data transfer and when the transfer is complete: + (+) If Normal mode is selected: the counter is set to 0. + (+) If Circular mode is selected: the counter is reloaded with the initial + value(configured before enabling the DMA channel). + [..] The following function can be used to read the Channel data counter value: + (+) uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx). + +@endverbatim + * @{ + */ + +/** + * @brief Sets the number of data units in the current DMAy Channelx transfer. + * @param DMAy_Channelx: where y can be 1 or 2 to select the DMA and x can be + * 1 to 7 for DMA1 and 1 to 5 for DMA2 to select the DMA Channel. + * @param DataNumber: The number of data units in the current DMAy Channelx + * transfer. + * @note This function can only be used when the DMAy_Channelx is disabled. + * @retval None. + */ +void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t DataNumber) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Channelx)); + +/*--------------------------- DMAy Channelx CNDTR Configuration ---------------*/ + /* Write to DMAy Channelx CNDTR */ + DMAy_Channelx->CNDTR = DataNumber; +} + +/** + * @brief Returns the number of remaining data units in the current + * DMAy Channelx transfer. + * @param DMAy_Channelx: where y can be 1 or 2 to select the DMA and x can be + * 1 to 7 for DMA1 and 1 to 5 for DMA2 to select the DMA Channel. + * @retval The number of remaining data units in the current DMAy Channelx + * transfer. + */ +uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Channelx)); + /* Return the number of remaining data units for DMAy Channelx */ + return ((uint16_t)(DMAy_Channelx->CNDTR)); +} + +/** + * @} + */ + +/** @defgroup DMA_Group3 Interrupts and flags management functions + * @brief Interrupts and flags management functions + * +@verbatim + =============================================================================== + ##### Interrupts and flags management functions ##### + =============================================================================== + [..] This subsection provides functions allowing to configure the DMA Interrupts + sources and check or clear the flags or pending bits status. + The user should identify which mode will be used in his application to manage + the DMA controller events: Polling mode or Interrupt mode. + *** Polling Mode *** + ==================== + [..] Each DMA channel can be managed through 4 event Flags:(y : DMA Controller + number x : DMA channel number ). + (#) DMAy_FLAG_TCx : to indicate that a Transfer Complete event occurred. + (#) DMAy_FLAG_HTx : to indicate that a Half-Transfer Complete event occurred. + (#) DMAy_FLAG_TEx : to indicate that a Transfer Error occurred. + (#) DMAy_FLAG_GLx : to indicate that at least one of the events described + above occurred. + -@- Clearing DMAy_FLAG_GLx results in clearing all other pending flags of the + same channel (DMAy_FLAG_TCx, DMAy_FLAG_HTx and DMAy_FLAG_TEx). + [..]In this Mode it is advised to use the following functions: + (+) FlagStatus DMA_GetFlagStatus(uint32_t DMA_FLAG); + (+) void DMA_ClearFlag(uint32_t DMA_FLAG); + + *** Interrupt Mode *** + ====================== + [..] Each DMA channel can be managed through 4 Interrupts: + (+) Interrupt Source + (##) DMA_IT_TC: specifies the interrupt source for the Transfer Complete + event. + (##) DMA_IT_HT : specifies the interrupt source for the Half-transfer Complete + event. + (##) DMA_IT_TE : specifies the interrupt source for the transfer errors event. + (##) DMA_IT_GL : to indicate that at least one of the interrupts described + above occurred. + -@@- Clearing DMA_IT_GL interrupt results in clearing all other interrupts of + the same channel (DMA_IT_TCx, DMA_IT_HT and DMA_IT_TE). + [..]In this Mode it is advised to use the following functions: + (+) void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, uint32_t DMA_IT, + FunctionalState NewState); + (+) ITStatus DMA_GetITStatus(uint32_t DMA_IT); + (+) void DMA_ClearITPendingBit(uint32_t DMA_IT); + +@endverbatim + * @{ + */ + +/** + * @brief Enables or disables the specified DMAy Channelx interrupts. + * @param DMAy_Channelx: where y can be 1 or 2 to select the DMA and x can be + * 1 to 7 for DMA1 and 1 to 5 for DMA2 to select the DMA Channel. + * @param DMA_IT: specifies the DMA interrupts sources to be enabled + * or disabled. + * This parameter can be any combination of the following values: + * @arg DMA_IT_TC: Transfer complete interrupt mask + * @arg DMA_IT_HT: Half transfer interrupt mask + * @arg DMA_IT_TE: Transfer error interrupt mask + * @param NewState: new state of the specified DMA interrupts. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, uint32_t DMA_IT, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAy_Channelx)); + assert_param(IS_DMA_CONFIG_IT(DMA_IT)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the selected DMA interrupts */ + DMAy_Channelx->CCR |= DMA_IT; + } + else + { + /* Disable the selected DMA interrupts */ + DMAy_Channelx->CCR &= ~DMA_IT; + } +} + +/** + * @brief Checks whether the specified DMAy Channelx flag is set or not. + * @param DMAy_FLAG: specifies the flag to check. + * This parameter can be one of the following values: + * @arg DMA1_FLAG_GL1: DMA1 Channel1 global flag. + * @arg DMA1_FLAG_TC1: DMA1 Channel1 transfer complete flag. + * @arg DMA1_FLAG_HT1: DMA1 Channel1 half transfer flag. + * @arg DMA1_FLAG_TE1: DMA1 Channel1 transfer error flag. + * @arg DMA1_FLAG_GL2: DMA1 Channel2 global flag. + * @arg DMA1_FLAG_TC2: DMA1 Channel2 transfer complete flag. + * @arg DMA1_FLAG_HT2: DMA1 Channel2 half transfer flag. + * @arg DMA1_FLAG_TE2: DMA1 Channel2 transfer error flag. + * @arg DMA1_FLAG_GL3: DMA1 Channel3 global flag. + * @arg DMA1_FLAG_TC3: DMA1 Channel3 transfer complete flag. + * @arg DMA1_FLAG_HT3: DMA1 Channel3 half transfer flag. + * @arg DMA1_FLAG_TE3: DMA1 Channel3 transfer error flag. + * @arg DMA1_FLAG_GL4: DMA1 Channel4 global flag. + * @arg DMA1_FLAG_TC4: DMA1 Channel4 transfer complete flag. + * @arg DMA1_FLAG_HT4: DMA1 Channel4 half transfer flag. + * @arg DMA1_FLAG_TE4: DMA1 Channel4 transfer error flag. + * @arg DMA1_FLAG_GL5: DMA1 Channel5 global flag. + * @arg DMA1_FLAG_TC5: DMA1 Channel5 transfer complete flag. + * @arg DMA1_FLAG_HT5: DMA1 Channel5 half transfer flag. + * @arg DMA1_FLAG_TE5: DMA1 Channel5 transfer error flag. + * @arg DMA1_FLAG_GL6: DMA1 Channel6 global flag. + * @arg DMA1_FLAG_TC6: DMA1 Channel6 transfer complete flag. + * @arg DMA1_FLAG_HT6: DMA1 Channel6 half transfer flag. + * @arg DMA1_FLAG_TE6: DMA1 Channel6 transfer error flag. + * @arg DMA1_FLAG_GL7: DMA1 Channel7 global flag. + * @arg DMA1_FLAG_TC7: DMA1 Channel7 transfer complete flag. + * @arg DMA1_FLAG_HT7: DMA1 Channel7 half transfer flag. + * @arg DMA1_FLAG_TE7: DMA1 Channel7 transfer error flag. + * @arg DMA2_FLAG_GL1: DMA2 Channel1 global flag. + * @arg DMA2_FLAG_TC1: DMA2 Channel1 transfer complete flag. + * @arg DMA2_FLAG_HT1: DMA2 Channel1 half transfer flag. + * @arg DMA2_FLAG_TE1: DMA2 Channel1 transfer error flag. + * @arg DMA2_FLAG_GL2: DMA2 Channel2 global flag. + * @arg DMA2_FLAG_TC2: DMA2 Channel2 transfer complete flag. + * @arg DMA2_FLAG_HT2: DMA2 Channel2 half transfer flag. + * @arg DMA2_FLAG_TE2: DMA2 Channel2 transfer error flag. + * @arg DMA2_FLAG_GL3: DMA2 Channel3 global flag. + * @arg DMA2_FLAG_TC3: DMA2 Channel3 transfer complete flag. + * @arg DMA2_FLAG_HT3: DMA2 Channel3 half transfer flag. + * @arg DMA2_FLAG_TE3: DMA2 Channel3 transfer error flag. + * @arg DMA2_FLAG_GL4: DMA2 Channel4 global flag. + * @arg DMA2_FLAG_TC4: DMA2 Channel4 transfer complete flag. + * @arg DMA2_FLAG_HT4: DMA2 Channel4 half transfer flag. + * @arg DMA2_FLAG_TE4: DMA2 Channel4 transfer error flag. + * @arg DMA2_FLAG_GL5: DMA2 Channel5 global flag. + * @arg DMA2_FLAG_TC5: DMA2 Channel5 transfer complete flag. + * @arg DMA2_FLAG_HT5: DMA2 Channel5 half transfer flag. + * @arg DMA2_FLAG_TE5: DMA2 Channel5 transfer error flag. + * + * @note + * The Global flag (DMAy_FLAG_GLx) is set whenever any of the other flags + * relative to the same channel is set (Transfer Complete, Half-transfer + * Complete or Transfer Error flags: DMAy_FLAG_TCx, DMAy_FLAG_HTx or + * DMAy_FLAG_TEx). + * + * @retval The new state of DMAy_FLAG (SET or RESET). + */ +FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG) +{ + FlagStatus bitstatus = RESET; + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_DMA_GET_FLAG(DMAy_FLAG)); + + /* Calculate the used DMAy */ + if ((DMAy_FLAG & FLAG_MASK) == (uint32_t)RESET) + { + /* Get DMA1 ISR register value */ + tmpreg = DMA1->ISR; + } + else + { + /* Get DMA2 ISR register value */ + tmpreg = DMA2->ISR; + } + + /* Check the status of the specified DMAy flag */ + if ((tmpreg & DMAy_FLAG) != (uint32_t)RESET) + { + /* DMAy_FLAG is set */ + bitstatus = SET; + } + else + { + /* DMAy_FLAG is reset */ + bitstatus = RESET; + } + + /* Return the DMAy_FLAG status */ + return bitstatus; +} + +/** + * @brief Clears the DMAy Channelx's pending flags. + * @param DMAy_FLAG: specifies the flag to clear. + * This parameter can be any combination (for the same DMA) of the following values: + * @arg DMA1_FLAG_GL1: DMA1 Channel1 global flag. + * @arg DMA1_FLAG_TC1: DMA1 Channel1 transfer complete flag. + * @arg DMA1_FLAG_HT1: DMA1 Channel1 half transfer flag. + * @arg DMA1_FLAG_TE1: DMA1 Channel1 transfer error flag. + * @arg DMA1_FLAG_GL2: DMA1 Channel2 global flag. + * @arg DMA1_FLAG_TC2: DMA1 Channel2 transfer complete flag. + * @arg DMA1_FLAG_HT2: DMA1 Channel2 half transfer flag. + * @arg DMA1_FLAG_TE2: DMA1 Channel2 transfer error flag. + * @arg DMA1_FLAG_GL3: DMA1 Channel3 global flag. + * @arg DMA1_FLAG_TC3: DMA1 Channel3 transfer complete flag. + * @arg DMA1_FLAG_HT3: DMA1 Channel3 half transfer flag. + * @arg DMA1_FLAG_TE3: DMA1 Channel3 transfer error flag. + * @arg DMA1_FLAG_GL4: DMA1 Channel4 global flag. + * @arg DMA1_FLAG_TC4: DMA1 Channel4 transfer complete flag. + * @arg DMA1_FLAG_HT4: DMA1 Channel4 half transfer flag. + * @arg DMA1_FLAG_TE4: DMA1 Channel4 transfer error flag. + * @arg DMA1_FLAG_GL5: DMA1 Channel5 global flag. + * @arg DMA1_FLAG_TC5: DMA1 Channel5 transfer complete flag. + * @arg DMA1_FLAG_HT5: DMA1 Channel5 half transfer flag. + * @arg DMA1_FLAG_TE5: DMA1 Channel5 transfer error flag. + * @arg DMA1_FLAG_GL6: DMA1 Channel6 global flag. + * @arg DMA1_FLAG_TC6: DMA1 Channel6 transfer complete flag. + * @arg DMA1_FLAG_HT6: DMA1 Channel6 half transfer flag. + * @arg DMA1_FLAG_TE6: DMA1 Channel6 transfer error flag. + * @arg DMA1_FLAG_GL7: DMA1 Channel7 global flag. + * @arg DMA1_FLAG_TC7: DMA1 Channel7 transfer complete flag. + * @arg DMA1_FLAG_HT7: DMA1 Channel7 half transfer flag. + * @arg DMA1_FLAG_TE7: DMA1 Channel7 transfer error flag. + * @arg DMA2_FLAG_GL1: DMA2 Channel1 global flag. + * @arg DMA2_FLAG_TC1: DMA2 Channel1 transfer complete flag. + * @arg DMA2_FLAG_HT1: DMA2 Channel1 half transfer flag. + * @arg DMA2_FLAG_TE1: DMA2 Channel1 transfer error flag. + * @arg DMA2_FLAG_GL2: DMA2 Channel2 global flag. + * @arg DMA2_FLAG_TC2: DMA2 Channel2 transfer complete flag. + * @arg DMA2_FLAG_HT2: DMA2 Channel2 half transfer flag. + * @arg DMA2_FLAG_TE2: DMA2 Channel2 transfer error flag. + * @arg DMA2_FLAG_GL3: DMA2 Channel3 global flag. + * @arg DMA2_FLAG_TC3: DMA2 Channel3 transfer complete flag. + * @arg DMA2_FLAG_HT3: DMA2 Channel3 half transfer flag. + * @arg DMA2_FLAG_TE3: DMA2 Channel3 transfer error flag. + * @arg DMA2_FLAG_GL4: DMA2 Channel4 global flag. + * @arg DMA2_FLAG_TC4: DMA2 Channel4 transfer complete flag. + * @arg DMA2_FLAG_HT4: DMA2 Channel4 half transfer flag. + * @arg DMA2_FLAG_TE4: DMA2 Channel4 transfer error flag. + * @arg DMA2_FLAG_GL5: DMA2 Channel5 global flag. + * @arg DMA2_FLAG_TC5: DMA2 Channel5 transfer complete flag. + * @arg DMA2_FLAG_HT5: DMA2 Channel5 half transfer flag. + * @arg DMA2_FLAG_TE5: DMA2 Channel5 transfer error flag. + * + * @note + * Clearing the Global flag (DMAy_FLAG_GLx) results in clearing all other flags + * relative to the same channel (Transfer Complete, Half-transfer Complete and + * Transfer Error flags: DMAy_FLAG_TCx, DMAy_FLAG_HTx and DMAy_FLAG_TEx). + * + * @retval None + */ +void DMA_ClearFlag(uint32_t DMAy_FLAG) +{ + /* Check the parameters */ + assert_param(IS_DMA_CLEAR_FLAG(DMAy_FLAG)); + + if ((DMAy_FLAG & FLAG_MASK) == (uint32_t)RESET) + { + /* Clear the selected DMAy flags */ + DMA1->IFCR = DMAy_FLAG; + } + else + { + /* Clear the selected DMAy flags */ + DMA2->IFCR = DMAy_FLAG; + } +} + +/** + * @brief Checks whether the specified DMAy Channelx interrupt has occurred or not. + * @param DMAy_IT: specifies the DMAy interrupt source to check. + * This parameter can be one of the following values: + * @arg DMA1_IT_GL1: DMA1 Channel1 global interrupt. + * @arg DMA1_IT_TC1: DMA1 Channel1 transfer complete interrupt. + * @arg DMA1_IT_HT1: DMA1 Channel1 half transfer interrupt. + * @arg DMA1_IT_TE1: DMA1 Channel1 transfer error interrupt. + * @arg DMA1_IT_GL2: DMA1 Channel2 global interrupt. + * @arg DMA1_IT_TC2: DMA1 Channel2 transfer complete interrupt. + * @arg DMA1_IT_HT2: DMA1 Channel2 half transfer interrupt. + * @arg DMA1_IT_TE2: DMA1 Channel2 transfer error interrupt. + * @arg DMA1_IT_GL3: DMA1 Channel3 global interrupt. + * @arg DMA1_IT_TC3: DMA1 Channel3 transfer complete interrupt. + * @arg DMA1_IT_HT3: DMA1 Channel3 half transfer interrupt. + * @arg DMA1_IT_TE3: DMA1 Channel3 transfer error interrupt. + * @arg DMA1_IT_GL4: DMA1 Channel4 global interrupt. + * @arg DMA1_IT_TC4: DMA1 Channel4 transfer complete interrupt. + * @arg DMA1_IT_HT4: DMA1 Channel4 half transfer interrupt. + * @arg DMA1_IT_TE4: DMA1 Channel4 transfer error interrupt. + * @arg DMA1_IT_GL5: DMA1 Channel5 global interrupt. + * @arg DMA1_IT_TC5: DMA1 Channel5 transfer complete interrupt. + * @arg DMA1_IT_HT5: DMA1 Channel5 half transfer interrupt. + * @arg DMA1_IT_TE5: DMA1 Channel5 transfer error interrupt. + * @arg DMA1_IT_GL6: DMA1 Channel6 global interrupt. + * @arg DMA1_IT_TC6: DMA1 Channel6 transfer complete interrupt. + * @arg DMA1_IT_HT6: DMA1 Channel6 half transfer interrupt. + * @arg DMA1_IT_TE6: DMA1 Channel6 transfer error interrupt. + * @arg DMA1_IT_GL7: DMA1 Channel7 global interrupt. + * @arg DMA1_IT_TC7: DMA1 Channel7 transfer complete interrupt. + * @arg DMA1_IT_HT7: DMA1 Channel7 half transfer interrupt. + * @arg DMA1_IT_TE7: DMA1 Channel7 transfer error interrupt. + * @arg DMA2_IT_GL1: DMA2 Channel1 global interrupt. + * @arg DMA2_IT_TC1: DMA2 Channel1 transfer complete interrupt. + * @arg DMA2_IT_HT1: DMA2 Channel1 half transfer interrupt. + * @arg DMA2_IT_TE1: DMA2 Channel1 transfer error interrupt. + * @arg DMA2_IT_GL2: DMA2 Channel2 global interrupt. + * @arg DMA2_IT_TC2: DMA2 Channel2 transfer complete interrupt. + * @arg DMA2_IT_HT2: DMA2 Channel2 half transfer interrupt. + * @arg DMA2_IT_TE2: DMA2 Channel2 transfer error interrupt. + * @arg DMA2_IT_GL3: DMA2 Channel3 global interrupt. + * @arg DMA2_IT_TC3: DMA2 Channel3 transfer complete interrupt. + * @arg DMA2_IT_HT3: DMA2 Channel3 half transfer interrupt. + * @arg DMA2_IT_TE3: DMA2 Channel3 transfer error interrupt. + * @arg DMA2_IT_GL4: DMA2 Channel4 global interrupt. + * @arg DMA2_IT_TC4: DMA2 Channel4 transfer complete interrupt. + * @arg DMA2_IT_HT4: DMA2 Channel4 half transfer interrupt. + * @arg DMA2_IT_TE4: DMA2 Channel4 transfer error interrupt. + * @arg DMA2_IT_GL5: DMA2 Channel5 global interrupt. + * @arg DMA2_IT_TC5: DMA2 Channel5 transfer complete interrupt. + * @arg DMA2_IT_HT5: DMA2 Channel5 half transfer interrupt. + * @arg DMA2_IT_TE5: DMA2 Channel5 transfer error interrupt. + * + * @note + * The Global interrupt (DMAy_FLAG_GLx) is set whenever any of the other + * interrupts relative to the same channel is set (Transfer Complete, + * Half-transfer Complete or Transfer Error interrupts: DMAy_IT_TCx, + * DMAy_IT_HTx or DMAy_IT_TEx). + * + * @retval The new state of DMAy_IT (SET or RESET). + */ +ITStatus DMA_GetITStatus(uint32_t DMAy_IT) +{ + ITStatus bitstatus = RESET; + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_DMA_GET_IT(DMAy_IT)); + + /* Calculate the used DMAy */ + if ((DMAy_IT & FLAG_MASK) == (uint32_t)RESET) + { + /* Get DMA1 ISR register value */ + tmpreg = DMA1->ISR; + } + else + { + /* Get DMA2 ISR register value */ + tmpreg = DMA2->ISR; + } + + /* Check the status of the specified DMAy interrupt */ + if ((tmpreg & DMAy_IT) != (uint32_t)RESET) + { + /* DMAy_IT is set */ + bitstatus = SET; + } + else + { + /* DMAy_IT is reset */ + bitstatus = RESET; + } + /* Return the DMAy_IT status */ + return bitstatus; +} + +/** + * @brief Clears the DMAy Channelx's interrupt pending bits. + * @param DMAy_IT: specifies the DMAy interrupt pending bit to clear. + * This parameter can be any combination (for the same DMA) of the following values: + * @arg DMA1_IT_GL1: DMA1 Channel1 global interrupt. + * @arg DMA1_IT_TC1: DMA1 Channel1 transfer complete interrupt. + * @arg DMA1_IT_HT1: DMA1 Channel1 half transfer interrupt. + * @arg DMA1_IT_TE1: DMA1 Channel1 transfer error interrupt. + * @arg DMA1_IT_GL2: DMA1 Channel2 global interrupt. + * @arg DMA1_IT_TC2: DMA1 Channel2 transfer complete interrupt. + * @arg DMA1_IT_HT2: DMA1 Channel2 half transfer interrupt. + * @arg DMA1_IT_TE2: DMA1 Channel2 transfer error interrupt. + * @arg DMA1_IT_GL3: DMA1 Channel3 global interrupt. + * @arg DMA1_IT_TC3: DMA1 Channel3 transfer complete interrupt. + * @arg DMA1_IT_HT3: DMA1 Channel3 half transfer interrupt. + * @arg DMA1_IT_TE3: DMA1 Channel3 transfer error interrupt. + * @arg DMA1_IT_GL4: DMA1 Channel4 global interrupt. + * @arg DMA1_IT_TC4: DMA1 Channel4 transfer complete interrupt. + * @arg DMA1_IT_HT4: DMA1 Channel4 half transfer interrupt. + * @arg DMA1_IT_TE4: DMA1 Channel4 transfer error interrupt. + * @arg DMA1_IT_GL5: DMA1 Channel5 global interrupt. + * @arg DMA1_IT_TC5: DMA1 Channel5 transfer complete interrupt. + * @arg DMA1_IT_HT5: DMA1 Channel5 half transfer interrupt. + * @arg DMA1_IT_TE5: DMA1 Channel5 transfer error interrupt. + * @arg DMA1_IT_GL6: DMA1 Channel6 global interrupt. + * @arg DMA1_IT_TC6: DMA1 Channel6 transfer complete interrupt. + * @arg DMA1_IT_HT6: DMA1 Channel6 half transfer interrupt. + * @arg DMA1_IT_TE6: DMA1 Channel6 transfer error interrupt. + * @arg DMA1_IT_GL7: DMA1 Channel7 global interrupt. + * @arg DMA1_IT_TC7: DMA1 Channel7 transfer complete interrupt. + * @arg DMA1_IT_HT7: DMA1 Channel7 half transfer interrupt. + * @arg DMA1_IT_TE7: DMA1 Channel7 transfer error interrupt. + * @arg DMA2_IT_GL1: DMA2 Channel1 global interrupt. + * @arg DMA2_IT_TC1: DMA2 Channel1 transfer complete interrupt. + * @arg DMA2_IT_HT1: DMA2 Channel1 half transfer interrupt. + * @arg DMA2_IT_TE1: DMA2 Channel1 transfer error interrupt. + * @arg DMA2_IT_GL2: DMA2 Channel2 global interrupt. + * @arg DMA2_IT_TC2: DMA2 Channel2 transfer complete interrupt. + * @arg DMA2_IT_HT2: DMA2 Channel2 half transfer interrupt. + * @arg DMA2_IT_TE2: DMA2 Channel2 transfer error interrupt. + * @arg DMA2_IT_GL3: DMA2 Channel3 global interrupt. + * @arg DMA2_IT_TC3: DMA2 Channel3 transfer complete interrupt. + * @arg DMA2_IT_HT3: DMA2 Channel3 half transfer interrupt. + * @arg DMA2_IT_TE3: DMA2 Channel3 transfer error interrupt. + * @arg DMA2_IT_GL4: DMA2 Channel4 global interrupt. + * @arg DMA2_IT_TC4: DMA2 Channel4 transfer complete interrupt. + * @arg DMA2_IT_HT4: DMA2 Channel4 half transfer interrupt. + * @arg DMA2_IT_TE4: DMA2 Channel4 transfer error interrupt. + * @arg DMA2_IT_GL5: DMA2 Channel5 global interrupt. + * @arg DMA2_IT_TC5: DMA2 Channel5 transfer complete interrupt. + * @arg DMA2_IT_HT5: DMA2 Channel5 half transfer interrupt. + * @arg DMA2_IT_TE5: DMA2 Channel5 transfer error interrupt. + * + * @note + * Clearing the Global interrupt (DMAy_IT_GLx) results in clearing all other + * interrupts relative to the same channel (Transfer Complete, Half-transfer + * Complete and Transfer Error interrupts: DMAy_IT_TCx, DMAy_IT_HTx and + * DMAy_IT_TEx). + * + * @retval None + */ +void DMA_ClearITPendingBit(uint32_t DMAy_IT) +{ + /* Check the parameters */ + assert_param(IS_DMA_CLEAR_IT(DMAy_IT)); + + /* Calculate the used DMAy */ + if ((DMAy_IT & FLAG_MASK) == (uint32_t)RESET) + { + /* Clear the selected DMAy interrupt pending bits */ + DMA1->IFCR = DMAy_IT; + } + else + { + /* Clear the selected DMAy interrupt pending bits */ + DMA2->IFCR = DMAy_IT; + } +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/thirdparty/STM32_USB-FS-Device_Lib_V4.0.0/Libraries/STM32L1xx_StdPeriph_Driver/src/stm32l1xx_flash_ramfunc.c b/thirdparty/STM32_USB-FS-Device_Lib_V4.0.0/Libraries/STM32L1xx_StdPeriph_Driver/src/stm32l1xx_flash_ramfunc.c new file mode 100644 index 0000000..e535084 --- /dev/null +++ b/thirdparty/STM32_USB-FS-Device_Lib_V4.0.0/Libraries/STM32L1xx_StdPeriph_Driver/src/stm32l1xx_flash_ramfunc.c @@ -0,0 +1,553 @@ +/** + ****************************************************************************** + * @file stm32l1xx_flash_ramfunc.c + * @author MCD Application Team + * @version V1.1.1 + * @date 05-March-2012 + * @brief This file provides all the Flash firmware functions which should be + * executed from the internal SRAM. This file should be placed in + * internal SRAM. + * Other FLASH memory functions that can be used from the FLASH are + * defined in the "stm32l1xx_flash.c" file. +@verbatim + + *** ARM Compiler *** + -------------------- + [..] RAM functions are defined using the toolchain options. + Functions that are be 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(".data")))". + + *** TASKING Compiler *** + ------------------------ + [..] RAM functions are defined using a specific toolchain pragma. This + pragma is defined inside this file. + +@endverbatim + * + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2012 STMicroelectronics</center></h2> + * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l1xx_flash.h" + +/** @addtogroup STM32L1xx_StdPeriph_Driver + * @{ + */ + +/** @defgroup FLASH + * @brief FLASH driver modules + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +static __RAM_FUNC GetStatus(void); +static __RAM_FUNC WaitForLastOperation(uint32_t Timeout); + +/* Private functions ---------------------------------------------------------*/ + +/** @defgroup FLASH_Private_Functions + * @{ + */ + +/** @addtogroup FLASH_Group1 + * +@verbatim +@endverbatim + * @{ + */ +#if defined ( __TASKING__ ) +#pragma section_code_init on +#endif + +/** + * @brief Enable or disable the power down mode during RUN mode. + * @note This function can be used only when the user code is running from Internal SRAM. + * @param NewState: new state of the power down mode during RUN mode. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +__RAM_FUNC FLASH_RUNPowerDownCmd(FunctionalState NewState) +{ + FLASH_Status status = FLASH_COMPLETE; + + if (NewState != DISABLE) + { + /* Unlock the RUN_PD bit */ + FLASH->PDKEYR = FLASH_PDKEY1; + FLASH->PDKEYR = FLASH_PDKEY2; + + /* Set the RUN_PD bit in FLASH_ACR register to put Flash in power down mode */ + FLASH->ACR |= (uint32_t)FLASH_ACR_RUN_PD; + + if((FLASH->ACR & FLASH_ACR_RUN_PD) != FLASH_ACR_RUN_PD) + { + status = FLASH_ERROR_PROGRAM; + } + } + else + { + /* Clear the RUN_PD bit in FLASH_ACR register to put Flash in idle mode */ + FLASH->ACR &= (uint32_t)(~(uint32_t)FLASH_ACR_RUN_PD); + } + + /* Return the Write Status */ + return status; +} + +/** + * @} + */ + +/** @addtogroup FLASH_Group2 + * +@verbatim +@endverbatim + * @{ + */ + +/** + * @brief Erases a specified 2 page in program memory in parallel. + * @note This function can be used only for STM32L1XX_HD density devices. + * To correctly run this function, the FLASH_Unlock() function + * must be called before. + * Call the FLASH_Lock() to disable the flash memory access + * (recommended to protect the FLASH memory against possible unwanted operation). + * @param Page_Address1: The page address in program memory to be erased in + * the first Bank (BANK1). This parameter should be between 0x08000000 + * and 0x0802FF00. + * @param Page_Address2: The page address in program memory to be erased in + * the second Bank (BANK2). This parameter should be between 0x08030000 + * and 0x0805FF00. + * @note A Page is erased in the Program memory only if the address to load + * is the start address of a page (multiple of 256 bytes). + * @retval FLASH Status: The returned value can be: + * FLASH_ERROR_PROGRAM, FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. + */ +FLASH_Status FLASH_EraseParallelPage(uint32_t Page_Address1, uint32_t Page_Address2) +{ + FLASH_Status status = FLASH_COMPLETE; + + /* Wait for last operation to be completed */ + status = WaitForLastOperation(FLASH_ER_PRG_TIMEOUT); + + if(status == FLASH_COMPLETE) + { + /* If the previous operation is completed, proceed to erase the page */ + + /* Set the PARALLBANK bit */ + FLASH->PECR |= FLASH_PECR_PARALLBANK; + + /* Set the ERASE bit */ + FLASH->PECR |= FLASH_PECR_ERASE; + + /* Set PROG bit */ + FLASH->PECR |= FLASH_PECR_PROG; + + /* Write 00000000h to the first word of the first program page to erase */ + *(__IO uint32_t *)Page_Address1 = 0x00000000; + /* Write 00000000h to the first word of the second program page to erase */ + *(__IO uint32_t *)Page_Address2 = 0x00000000; + + /* Wait for last operation to be completed */ + status = WaitForLastOperation(FLASH_ER_PRG_TIMEOUT); + + /* If the erase operation is completed, disable the ERASE, PROG and PARALLBANK bits */ + FLASH->PECR &= (uint32_t)(~FLASH_PECR_PROG); + FLASH->PECR &= (uint32_t)(~FLASH_PECR_ERASE); + FLASH->PECR &= (uint32_t)(~FLASH_PECR_PARALLBANK); + } + /* Return the Erase Status */ + return status; +} + +/** + * @brief Programs a half page in program memory. + * @param Address: specifies the address to be written. + * @param pBuffer: pointer to the buffer containing the data to be written to + * the half page. + * @note To correctly run this function, the FLASH_Unlock() function + * must be called before. + * Call the FLASH_Lock() to disable the flash memory access + * (recommended to protect the FLASH memory against possible unwanted operation) + * @note Half page write is possible only from SRAM. + * @note If there are more than 32 words to write, after 32 words another + * Half Page programming operation starts and has to be finished. + * @note A half page is written to the program memory only if the first + * address to load is the start address of a half page (multiple of 128 + * bytes) and the 31 remaining words to load are in the same half page. + * @note During the Program memory half page write all read operations are + * forbidden (this includes DMA read operations and debugger read + * operations such as breakpoints, periodic updates, etc.). + * @note If a PGAERR is set during a Program memory half page write, the + * complete write operation is aborted. Software should then reset the + * FPRG and PROG/DATA bits and restart the write operation from the + * beginning. + * @retval FLASH Status: The returned value can be: + * FLASH_ERROR_PROGRAM, FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. + */ +__RAM_FUNC FLASH_ProgramHalfPage(uint32_t Address, uint32_t* pBuffer) +{ + uint32_t count = 0; + + FLASH_Status status = FLASH_COMPLETE; + + /* Set the DISMCYCINT[0] bit in the Auxillary Control Register (0xE000E008) + This bit prevents the interruption of multicycle instructions and therefore + will increase the interrupt latency. of Cortex-M3. */ + SCnSCB->ACTLR |= SCnSCB_ACTLR_DISMCYCINT_Msk; + + /* Wait for last operation to be completed */ + status = WaitForLastOperation(FLASH_ER_PRG_TIMEOUT); + + if(status == FLASH_COMPLETE) + { + /* if the previous operation is completed, proceed to program the new + half page */ + FLASH->PECR |= FLASH_PECR_FPRG; + FLASH->PECR |= FLASH_PECR_PROG; + + /* Write one half page directly with 32 different words */ + while(count < 32) + { + *(__IO uint32_t*) (Address + (4 * count)) = *(pBuffer++); + count ++; + } + /* Wait for last operation to be completed */ + status = WaitForLastOperation(FLASH_ER_PRG_TIMEOUT); + + /* if the write operation is completed, disable the PROG and FPRG bits */ + FLASH->PECR &= (uint32_t)(~FLASH_PECR_PROG); + FLASH->PECR &= (uint32_t)(~FLASH_PECR_FPRG); + } + + SCnSCB->ACTLR &= ~SCnSCB_ACTLR_DISMCYCINT_Msk; + + /* Return the Write Status */ + return status; +} + +/** + * @brief Programs 2 half page in program memory in parallel. + * @param Address1: specifies the first address to be written in the first bank + * (BANK1). This parameter should be between 0x08000000 and 0x0802FF80. + * @param pBuffer1: pointer to the buffer containing the data to be written + * to the first half page in the first bank. + * @param Address2: specifies the second address to be written in the second bank + * (BANK2). This parameter should be between 0x08030000 and 0x0805FF80. + * @param pBuffer2: pointer to the buffer containing the data to be written + * to the second half page in the second bank. + * @note This function can be used only for STM32L1XX_HD density devices. + * @note To correctly run this function, the FLASH_Unlock() function + * must be called before. + * Call the FLASH_Lock() to disable the flash memory access + * (recommended to protect the FLASH memory against possible unwanted operation). + * @note Half page write is possible only from SRAM. + * @note If there are more than 32 words to write, after 32 words another + * Half Page programming operation starts and has to be finished. + * @note A half page is written to the program memory only if the first + * address to load is the start address of a half page (multiple of 128 + * bytes) and the 31 remaining words to load are in the same half page. + * @note During the Program memory half page write all read operations are + * forbidden (this includes DMA read operations and debugger read + * operations such as breakpoints, periodic updates, etc.). + * @note If a PGAERR is set during a Program memory half page write, the + * complete write operation is aborted. Software should then reset the + * FPRG and PROG/DATA bits and restart the write operation from the + * beginning. + * @retval FLASH Status: The returned value can be: + * FLASH_ERROR_PROGRAM, FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. + */ +__RAM_FUNC FLASH_ProgramParallelHalfPage(uint32_t Address1, uint32_t* pBuffer1, uint32_t Address2, uint32_t* pBuffer2) +{ + uint32_t count = 0; + + FLASH_Status status = FLASH_COMPLETE; + + /* Set the DISMCYCINT[0] bit in the Auxillary Control Register (0xE000E008) + This bit prevents the interruption of multicycle instructions and therefore + will increase the interrupt latency. of Cortex-M3. */ + SCnSCB->ACTLR |= SCnSCB_ACTLR_DISMCYCINT_Msk; + + /* Wait for last operation to be completed */ + status = WaitForLastOperation(FLASH_ER_PRG_TIMEOUT); + + if(status == FLASH_COMPLETE) + { + /* If the previous operation is completed, proceed to program the new + half page */ + FLASH->PECR |= FLASH_PECR_PARALLBANK; + FLASH->PECR |= FLASH_PECR_FPRG; + FLASH->PECR |= FLASH_PECR_PROG; + + /* Write the first half page directly with 32 different words */ + while(count < 32) + { + *(__IO uint32_t*) (Address1 + (4 * count)) = *(pBuffer1++); + count ++; + } + count = 0; + /* Write the second half page directly with 32 different words */ + while(count < 32) + { + *(__IO uint32_t*) (Address2 + (4 * count)) = *(pBuffer2++); + count ++; + } + /* Wait for last operation to be completed */ + status = WaitForLastOperation(FLASH_ER_PRG_TIMEOUT); + + /* if the write operation is completed, disable the PROG, FPRG and PARALLBANK bits */ + FLASH->PECR &= (uint32_t)(~FLASH_PECR_PROG); + FLASH->PECR &= (uint32_t)(~FLASH_PECR_FPRG); + FLASH->PECR &= (uint32_t)(~FLASH_PECR_PARALLBANK); + } + + SCnSCB->ACTLR &= ~SCnSCB_ACTLR_DISMCYCINT_Msk; + + /* Return the Write Status */ + return status; +} + +/** + * @} + */ + +/** @addtogroup FLASH_Group3 + * +@verbatim +@endverbatim + * @{ + */ + +/** + * @brief Erase a double word in data memory. + * @param Address: specifies the address to be erased. + * @note To correctly run this function, the DATA_EEPROM_Unlock() function + * must be called before. + * Call the DATA_EEPROM_Lock() to he data EEPROM access + * and Flash program erase control register access(recommended to protect + * the DATA_EEPROM against possible unwanted operation). + * @note Data memory double word erase is possible only from SRAM. + * @note A double word is erased to the data memory only if the first address + * to load is the start address of a double word (multiple of 8 bytes). + * @note During the Data memory double word erase, all read operations are + * forbidden (this includes DMA read operations and debugger read + * operations such as breakpoints, periodic updates, etc.). + * @retval FLASH Status: The returned value can be: + * FLASH_ERROR_PROGRAM, FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. + */ + +__RAM_FUNC DATA_EEPROM_EraseDoubleWord(uint32_t Address) +{ + FLASH_Status status = FLASH_COMPLETE; + + /* Set the DISMCYCINT[0] bit in the Auxillary Control Register (0xE000E008) + This bit prevents the interruption of multicycle instructions and therefore + will increase the interrupt latency. of Cortex-M3. */ + SCnSCB->ACTLR |= SCnSCB_ACTLR_DISMCYCINT_Msk; + + /* Wait for last operation to be completed */ + status = WaitForLastOperation(FLASH_ER_PRG_TIMEOUT); + + if(status == FLASH_COMPLETE) + { + /* If the previous operation is completed, proceed to erase the next double word */ + /* Set the ERASE bit */ + FLASH->PECR |= FLASH_PECR_ERASE; + + /* Set DATA bit */ + FLASH->PECR |= FLASH_PECR_DATA; + + /* Write 00000000h to the 2 words to erase */ + *(__IO uint32_t *)Address = 0x00000000; + Address += 4; + *(__IO uint32_t *)Address = 0x00000000; + + /* Wait for last operation to be completed */ + status = WaitForLastOperation(FLASH_ER_PRG_TIMEOUT); + + /* If the erase operation is completed, disable the ERASE and DATA bits */ + FLASH->PECR &= (uint32_t)(~FLASH_PECR_ERASE); + FLASH->PECR &= (uint32_t)(~FLASH_PECR_DATA); + } + + SCnSCB->ACTLR &= ~SCnSCB_ACTLR_DISMCYCINT_Msk; + + /* Return the erase status */ + return status; +} + +/** + * @brief Write a double word in data memory without erase. + * @param Address: specifies the address to be written. + * @param Data: specifies the data to be written. + * @note To correctly run this function, the DATA_EEPROM_Unlock() function + * must be called before. + * Call the DATA_EEPROM_Lock() to he data EEPROM access + * and Flash program erase control register access(recommended to protect + * the DATA_EEPROM against possible unwanted operation). + * @note Data memory double word write is possible only from SRAM. + * @note A data memory double word is written to the data memory only if the + * first address to load is the start address of a double word (multiple + * of double word). + * @note During the Data memory double word write, all read operations are + * forbidden (this includes DMA read operations and debugger read + * operations such as breakpoints, periodic updates, etc.). + * @retval FLASH Status: The returned value can be: + * FLASH_ERROR_PROGRAM, FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. + */ +__RAM_FUNC DATA_EEPROM_ProgramDoubleWord(uint32_t Address, uint64_t Data) +{ + FLASH_Status status = FLASH_COMPLETE; + + /* Set the DISMCYCINT[0] bit in the Auxillary Control Register (0xE000E008) + This bit prevents the interruption of multicycle instructions and therefore + will increase the interrupt latency. of Cortex-M3. */ + SCnSCB->ACTLR |= SCnSCB_ACTLR_DISMCYCINT_Msk; + + /* Wait for last operation to be completed */ + status = WaitForLastOperation(FLASH_ER_PRG_TIMEOUT); + + if(status == FLASH_COMPLETE) + { + /* If the previous operation is completed, proceed to program the new data*/ + FLASH->PECR |= FLASH_PECR_FPRG; + FLASH->PECR |= FLASH_PECR_DATA; + + /* Write the 2 words */ + *(__IO uint32_t *)Address = (uint32_t) Data; + Address += 4; + *(__IO uint32_t *)Address = (uint32_t) (Data >> 32); + + /* Wait for last operation to be completed */ + status = WaitForLastOperation(FLASH_ER_PRG_TIMEOUT); + + /* If the write operation is completed, disable the FPRG and DATA bits */ + FLASH->PECR &= (uint32_t)(~FLASH_PECR_FPRG); + FLASH->PECR &= (uint32_t)(~FLASH_PECR_DATA); + } + + SCnSCB->ACTLR &= ~SCnSCB_ACTLR_DISMCYCINT_Msk; + + /* Return the Write Status */ + return status; +} + +/** + * @} + */ + +/** + * @brief Returns the FLASH Status. + * @param None + * @retval FLASH Status: The returned value can be: FLASH_BUSY, + * FLASH_ERROR_PROGRAM, FLASH_ERROR_WRP or FLASH_COMPLETE + */ +static __RAM_FUNC GetStatus(void) +{ + FLASH_Status FLASHstatus = FLASH_COMPLETE; + + if((FLASH->SR & FLASH_FLAG_BSY) == FLASH_FLAG_BSY) + { + FLASHstatus = FLASH_BUSY; + } + else + { + if((FLASH->SR & (uint32_t)FLASH_FLAG_WRPERR)!= (uint32_t)0x00) + { + FLASHstatus = FLASH_ERROR_WRP; + } + else + { + if((FLASH->SR & (uint32_t)0x1E00) != (uint32_t)0x00) + { + FLASHstatus = FLASH_ERROR_PROGRAM; + } + else + { + FLASHstatus = FLASH_COMPLETE; + } + } + } + /* Return the FLASH Status */ + return FLASHstatus; +} + +/** + * @brief Waits for a FLASH operation to complete or a TIMEOUT to occur. + * @param Timeout: FLASH programming Timeout + * @retval FLASH Status: The returned value can be: FLASH_BUSY, + * FLASH_ERROR_PROGRAM, FLASH_ERROR_WRP, FLASH_COMPLETE or + * FLASH_TIMEOUT. + */ +static __RAM_FUNC WaitForLastOperation(uint32_t Timeout) +{ + __IO FLASH_Status status = FLASH_COMPLETE; + + /* Check for the FLASH Status */ + status = GetStatus(); + + /* Wait for a FLASH operation to complete or a TIMEOUT to occur */ + while((status == FLASH_BUSY) && (Timeout != 0x00)) + { + status = GetStatus(); + Timeout--; + } + + if(Timeout == 0x00 ) + { + status = FLASH_TIMEOUT; + } + /* Return the operation status */ + return status; +} + +#if defined ( __TASKING__ ) +#pragma section_code_init restore +#endif + +/** + * @} + */ + + /** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/thirdparty/STM32_USB-FS-Device_Lib_V4.0.0/Libraries/STM32L1xx_StdPeriph_Driver/src/stm32l1xx_rcc.c b/thirdparty/STM32_USB-FS-Device_Lib_V4.0.0/Libraries/STM32L1xx_StdPeriph_Driver/src/stm32l1xx_rcc.c new file mode 100644 index 0000000..52eb808 --- /dev/null +++ b/thirdparty/STM32_USB-FS-Device_Lib_V4.0.0/Libraries/STM32L1xx_StdPeriph_Driver/src/stm32l1xx_rcc.c @@ -0,0 +1,1642 @@ +/** + ****************************************************************************** + * @file stm32l1xx_rcc.c + * @author MCD Application Team + * @version V1.1.1 + * @date 05-March-2012 + * @brief This file provides firmware functions to manage the following + * functionalities of the Reset and clock control (RCC) peripheral: + * + Internal/external clocks, PLL, CSS and MCO configuration + * + System, AHB and APB busses clocks configuration + * + Peripheral clocks configuration + * + Interrupts and flags management + * + @verbatim + + =============================================================================== + ##### RCC specific features ##### + =============================================================================== + [..] After reset the device is running from MSI (2 MHz) with Flash 0 WS, + all peripherals are off except internal SRAM, Flash and JTAG. + (#) There is no prescaler on High speed (AHB) and Low speed (APB) 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 input floating state, 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 whose clocks are not + derived from the System clock (ADC, RTC/LCD and IWDG) + + @endverbatim + + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2012 STMicroelectronics</center></h2> + * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l1xx_rcc.h" + +/** @addtogroup STM32L1xx_StdPeriph_Driver + * @{ + */ + +/** @defgroup RCC + * @brief RCC driver modules + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ + +/* ------------ RCC registers bit address in the alias region ----------- */ +#define RCC_OFFSET (RCC_BASE - PERIPH_BASE) + +/* --- CR Register ---*/ + +/* Alias word address of HSION bit */ +#define CR_OFFSET (RCC_OFFSET + 0x00) +#define HSION_BitNumber 0x00 +#define CR_HSION_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (HSION_BitNumber * 4)) + +/* Alias word address of MSION bit */ +#define MSION_BitNumber 0x08 +#define CR_MSION_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (MSION_BitNumber * 4)) + +/* Alias word address of PLLON bit */ +#define PLLON_BitNumber 0x18 +#define CR_PLLON_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (PLLON_BitNumber * 4)) + +/* Alias word address of CSSON bit */ +#define CSSON_BitNumber 0x1C +#define CR_CSSON_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (CSSON_BitNumber * 4)) + +/* --- CSR Register ---*/ + +/* Alias word address of LSION bit */ +#define CSR_OFFSET (RCC_OFFSET + 0x34) +#define LSION_BitNumber 0x00 +#define CSR_LSION_BB (PERIPH_BB_BASE + (CSR_OFFSET * 32) + (LSION_BitNumber * 4)) + +/* Alias word address of LSECSSON bit */ +#define LSECSSON_BitNumber 0x0B +#define CSR_LSECSSON_BB (PERIPH_BB_BASE + (CSR_OFFSET * 32) + (LSECSSON_BitNumber * 4)) + +/* Alias word address of RTCEN bit */ +#define RTCEN_BitNumber 0x16 +#define CSR_RTCEN_BB (PERIPH_BB_BASE + (CSR_OFFSET * 32) + (RTCEN_BitNumber * 4)) + +/* Alias word address of RTCRST bit */ +#define RTCRST_BitNumber 0x17 +#define CSR_RTCRST_BB (PERIPH_BB_BASE + (CSR_OFFSET * 32) + (RTCRST_BitNumber * 4)) + + +/* ---------------------- RCC registers mask -------------------------------- */ +/* RCC Flag Mask */ +#define FLAG_MASK ((uint8_t)0x1F) + +/* CR register byte 3 (Bits[23:16]) base address */ +#define CR_BYTE3_ADDRESS ((uint32_t)0x40023802) + +/* ICSCR register byte 4 (Bits[31:24]) base address */ +#define ICSCR_BYTE4_ADDRESS ((uint32_t)0x40023807) + +/* CFGR register byte 3 (Bits[23:16]) base address */ +#define CFGR_BYTE3_ADDRESS ((uint32_t)0x4002380A) + +/* CFGR register byte 4 (Bits[31:24]) base address */ +#define CFGR_BYTE4_ADDRESS ((uint32_t)0x4002380B) + +/* CIR register byte 2 (Bits[15:8]) base address */ +#define CIR_BYTE2_ADDRESS ((uint32_t)0x4002380D) + +/* CIR register byte 3 (Bits[23:16]) base address */ +#define CIR_BYTE3_ADDRESS ((uint32_t)0x4002380E) + +/* CSR register byte 2 (Bits[15:8]) base address */ +#define CSR_BYTE2_ADDRESS ((uint32_t)0x40023835) + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ + +static __I uint8_t PLLMulTable[9] = {3, 4, 6, 8, 12, 16, 24, 32, 48}; +static __I uint8_t APBAHBPrescTable[16] = {0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9}; + +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/** @defgroup RCC_Private_Functions + * @{ + */ + +/** @defgroup RCC_Group1 Internal and external clocks, PLL, CSS and MCO configuration functions + * @brief Internal and external clocks, PLL, CSS and MCO configuration functions + * +@verbatim + =============================================================================== + ##### Internal-external clocks, PLL, CSS and MCO configuration functions ##### + =============================================================================== + [..] This section provide functions allowing to configure the internal/external + clocks, PLL, CSS and MCO. + (#) HSI (high-speed internal), 16 MHz factory-trimmed RC used directly + or through the PLL as System clock source. + (#) MSI (multi-speed internal), multispeed low power RC + (65.536 KHz to 4.194 MHz) MHz used as System clock source. + (#) LSI (low-speed internal), 37 KHz low consumption RC used as IWDG + and/or RTC clock source. + (#) HSE (high-speed external), 1 to 24 MHz crystal oscillator used + directly or through the PLL as System clock source. Can be used + also as RTC clock source. + (#) LSE (low-speed external), 32 KHz oscillator used as RTC clock source. + (#) PLL (clocked by HSI or HSE), for System clock and USB (48 MHz). + (#) CSS (Clock security system), once enable and if a HSE clock failure + occurs (HSE used directly or through PLL as System clock source), + the System clock is automatically switched to MSI and an interrupt + is generated if enabled. + The interrupt is linked to the Cortex-M3 NMI (Non-Maskable Interrupt) + exception vector. + (#) MCO (microcontroller clock output), used to output SYSCLK, HSI, MSI, + HSE, PLL, LSI or LSE clock (through a configurable prescaler) on + PA8 pin. + +@endverbatim + * @{ + */ + +/** + * @brief Resets the RCC clock configuration to the default reset state. + * @note The default reset state of the clock configuration is given below: + * @note MSI ON and used as system clock source (MSI range is not modified + * by this function, it keep the value configured by user application) + * @note HSI, HSE and PLL OFF + * @note AHB, APB1 and APB2 prescaler set to 1. + * @note CSS and MCO OFF + * @note All interrupts disabled + * @note However, this function doesn't modify the configuration of the + * @note Peripheral clocks + * @note LSI, LSE and RTC clocks + * @param None + * @retval None + */ +void RCC_DeInit(void) +{ + + /* Set MSION bit */ + RCC->CR |= (uint32_t)0x00000100; + + /* Reset SW[1:0], HPRE[3:0], PPRE1[2:0], PPRE2[2:0], MCOSEL[2:0] and MCOPRE[2:0] bits */ + RCC->CFGR &= (uint32_t)0x88FFC00C; + + /* Reset HSION, HSEON, CSSON and PLLON bits */ + RCC->CR &= (uint32_t)0xEEFEFFFE; + + /* Reset HSEBYP bit */ + RCC->CR &= (uint32_t)0xFFFBFFFF; + + /* Reset PLLSRC, PLLMUL[3:0] and PLLDIV[1:0] bits */ + RCC->CFGR &= (uint32_t)0xFF02FFFF; + + /* Disable all interrupts */ + RCC->CIR = 0x00000000; +} + +/** + * @brief Configures the External High Speed oscillator (HSE). + * @note After enabling the HSE (RCC_HSE_ON or RCC_HSE_Bypass), the application + * software should wait on HSERDY flag to be set indicating that HSE clock + * is stable and can be used to clock the PLL and/or system clock. + * @note HSE state can not be changed if it is used directly or through the + * PLL as system clock. In this case, you have to select another source + * of the system clock then change the HSE state (ex. disable it). + * @note The HSE is stopped by hardware when entering STOP and STANDBY modes. + * @note This function reset the CSSON bit, so if the Clock security system(CSS) + * was previously enabled you have to enable it again after calling this + * function. + * @param RCC_HSE: specifies the new state of the HSE. + * This parameter can be one of the following values: + * @arg RCC_HSE_OFF: turn OFF the HSE oscillator, HSERDY flag goes low after + * 6 HSE oscillator clock cycles. + * @arg RCC_HSE_ON: turn ON the HSE oscillator + * @arg RCC_HSE_Bypass: HSE oscillator bypassed with external clock + * @retval None + */ +void RCC_HSEConfig(uint8_t RCC_HSE) +{ + /* Check the parameters */ + assert_param(IS_RCC_HSE(RCC_HSE)); + + /* Reset HSEON and HSEBYP bits before configuring the HSE ------------------*/ + *(__IO uint8_t *) CR_BYTE3_ADDRESS = RCC_HSE_OFF; + + /* Set the new HSE configuration -------------------------------------------*/ + *(__IO uint8_t *) CR_BYTE3_ADDRESS = RCC_HSE; + +} + +/** + * @brief Waits for HSE start-up. + * @note This functions waits on HSERDY flag to be set and return SUCCESS if + * this flag is set, otherwise returns ERROR if the timeout is reached + * and this flag is not set. The timeout value is defined by the constant + * HSE_STARTUP_TIMEOUT in stm32l1xx.h file. You can tailor it depending + * on the HSE crystal used in your application. + * @param None + * @retval An ErrorStatus enumeration value: + * - SUCCESS: HSE oscillator is stable and ready to use + * - ERROR: HSE oscillator not yet ready + */ +ErrorStatus RCC_WaitForHSEStartUp(void) +{ + __IO uint32_t StartUpCounter = 0; + ErrorStatus status = ERROR; + FlagStatus HSEStatus = RESET; + + /* Wait till HSE is ready and if timeout is reached exit */ + do + { + HSEStatus = RCC_GetFlagStatus(RCC_FLAG_HSERDY); + StartUpCounter++; + } while((StartUpCounter != HSE_STARTUP_TIMEOUT) && (HSEStatus == RESET)); + + if (RCC_GetFlagStatus(RCC_FLAG_HSERDY) != RESET) + { + status = SUCCESS; + } + else + { + status = ERROR; + } + return (status); +} + +/** + * @brief Adjusts the Internal Multi Speed oscillator (MSI) calibration value. + * @note The calibration is used to compensate for the variations in voltage + * and temperature that influence the frequency of the internal MSI RC. + * Refer to the Application Note AN3300 for more details on how to + * calibrate the MSI. + * @param MSICalibrationValue: specifies the MSI calibration trimming value. + * This parameter must be a number between 0 and 0xFF. + * @retval None + */ +void RCC_AdjustMSICalibrationValue(uint8_t MSICalibrationValue) +{ + + /* Check the parameters */ + assert_param(IS_RCC_MSI_CALIBRATION_VALUE(MSICalibrationValue)); + + *(__IO uint8_t *) ICSCR_BYTE4_ADDRESS = MSICalibrationValue; +} + +/** + * @brief Configures the Internal Multi Speed oscillator (MSI) clock range. + * @note After restart from Reset or wakeup from STANDBY, the MSI clock is + * around 2.097 MHz. The MSI clock does not change after wake-up from + * STOP mode. + * @note The MSI clock range can be modified on the fly. + * @param RCC_MSIRange: specifies the MSI Clock range. + * This parameter must be one of the following values: + * @arg RCC_MSIRange_0: MSI clock is around 65.536 KHz + * @arg RCC_MSIRange_1: MSI clock is around 131.072 KHz + * @arg RCC_MSIRange_2: MSI clock is around 262.144 KHz + * @arg RCC_MSIRange_3: MSI clock is around 524.288 KHz + * @arg RCC_MSIRange_4: MSI clock is around 1.048 MHz + * @arg RCC_MSIRange_5: MSI clock is around 2.097 MHz (default after Reset or wake-up from STANDBY) + * @arg RCC_MSIRange_6: MSI clock is around 4.194 MHz + * + * @retval None + */ +void RCC_MSIRangeConfig(uint32_t RCC_MSIRange) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RCC_MSI_CLOCK_RANGE(RCC_MSIRange)); + + tmpreg = RCC->ICSCR; + + /* Clear MSIRANGE[2:0] bits */ + tmpreg &= ~RCC_ICSCR_MSIRANGE; + + /* Set the MSIRANGE[2:0] bits according to RCC_MSIRange value */ + tmpreg |= (uint32_t)RCC_MSIRange; + + /* Store the new value */ + RCC->ICSCR = tmpreg; +} + +/** + * @brief Enables or disables the Internal Multi Speed oscillator (MSI). + * @note The MSI is stopped by hardware when entering STOP and STANDBY modes. + * It is used (enabled by hardware) as system clock source after + * startup from Reset, wakeup from STOP and STANDBY mode, or in case + * of failure of the HSE used directly or indirectly as system clock + * (if the Clock Security System CSS is enabled). + * @note MSI can not be stopped if it is used as system clock source. + * In this case, you have to select another source of the system + * clock then stop the MSI. + * @note After enabling the MSI, the application software should wait on + * MSIRDY flag to be set indicating that MSI clock is stable and can + * be used as system clock source. + * @param NewState: new state of the MSI. + * This parameter can be: ENABLE or DISABLE. + * @note When the MSI is stopped, MSIRDY flag goes low after 6 MSI oscillator + * clock cycles. + * @retval None + */ +void RCC_MSICmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) CR_MSION_BB = (uint32_t)NewState; +} + +/** + * @brief Adjusts the Internal High Speed oscillator (HSI) calibration value. + * @note The calibration is used to compensate for the variations in voltage + * and temperature that influence the frequency of the internal HSI RC. + * Refer to the Application Note AN3300 for more details on how to + * calibrate the HSI. + * @param HSICalibrationValue: specifies the HSI calibration trimming value. + * This parameter must be a number between 0 and 0x1F. + * @retval None + */ +void RCC_AdjustHSICalibrationValue(uint8_t HSICalibrationValue) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RCC_HSI_CALIBRATION_VALUE(HSICalibrationValue)); + + tmpreg = RCC->ICSCR; + + /* Clear HSITRIM[4:0] bits */ + tmpreg &= ~RCC_ICSCR_HSITRIM; + + /* Set the HSITRIM[4:0] bits according to HSICalibrationValue value */ + tmpreg |= (uint32_t)HSICalibrationValue << 8; + + /* Store the new value */ + RCC->ICSCR = tmpreg; +} + +/** + * @brief Enables or disables the Internal High Speed oscillator (HSI). + * @note After enabling the HSI, the application software should wait on + * HSIRDY flag to be set indicating that HSI clock is stable and can + * be used to clock the PLL and/or system clock. + * @note HSI can not be stopped if it is used directly or through the PLL + * as system clock. In this case, you have to select another source + * of the system clock then stop the HSI. + * @note The HSI is stopped by hardware when entering STOP and STANDBY modes. + * @param NewState: new state of the HSI. + * This parameter can be: ENABLE or DISABLE. + * @note When the HSI is stopped, HSIRDY flag goes low after 6 HSI oscillator + * clock cycles. + * @retval None + */ +void RCC_HSICmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) CR_HSION_BB = (uint32_t)NewState; +} + +/** + * @brief Configures the External Low Speed oscillator (LSE). + * @note As the LSE is in the RTC domain and write access is denied to this + * domain after reset, you have to enable write access using + * PWR_RTCAccessCmd(ENABLE) function before to configure the LSE + * (to be done once after reset). + * @note After enabling the LSE (RCC_LSE_ON or RCC_LSE_Bypass), the application + * software should wait on LSERDY flag to be set indicating that LSE clock + * is stable and can be used to clock the RTC. + * @param RCC_LSE: specifies the new state of the LSE. + * This parameter can be one of the following values: + * @arg RCC_LSE_OFF: turn OFF the LSE oscillator, LSERDY flag goes low after + * 6 LSE oscillator clock cycles. + * @arg RCC_LSE_ON: turn ON the LSE oscillator + * @arg RCC_LSE_Bypass: LSE oscillator bypassed with external clock + * @retval None + */ +void RCC_LSEConfig(uint8_t RCC_LSE) +{ + /* Check the parameters */ + assert_param(IS_RCC_LSE(RCC_LSE)); + + /* Reset LSEON and LSEBYP bits before configuring the LSE ------------------*/ + *(__IO uint8_t *) CSR_BYTE2_ADDRESS = RCC_LSE_OFF; + + /* Set the new LSE configuration -------------------------------------------*/ + *(__IO uint8_t *) CSR_BYTE2_ADDRESS = RCC_LSE; +} + +/** + * @brief Enables or disables the Internal Low Speed oscillator (LSI). + * @note After enabling the LSI, the application software should wait on + * LSIRDY flag to be set indicating that LSI clock is stable and can + * be used to clock the IWDG and/or the RTC. + * @note LSI can not be disabled if the IWDG is running. + * @param NewState: new state of the LSI. + * This parameter can be: ENABLE or DISABLE. + * @note When the LSI is stopped, LSIRDY flag goes low after 6 LSI oscillator + * clock cycles. + * @retval None + */ +void RCC_LSICmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) CSR_LSION_BB = (uint32_t)NewState; +} + +/** + * @brief Configures the PLL clock source and multiplication factor. + * @note This function must be used only when the PLL is disabled. + * + * @param RCC_PLLSource: specifies the PLL entry clock source. + * This parameter can be one of the following values: + * @arg RCC_PLLSource_HSI: HSI oscillator clock selected as PLL clock source + * @arg RCC_PLLSource_HSE: HSE oscillator clock selected as PLL clock source + * @note The minimum input clock frequency for PLL is 2 MHz (when using HSE as + * PLL source). + * + * @param RCC_PLLMul: specifies the PLL multiplication factor, which drive the PLLVCO clock + * This parameter can be: + * @arg RCC_PLLMul_3: PLL clock source multiplied by 3 + * @arg RCC_PLLMul_4: PLL clock source multiplied by 4 + * @arg RCC_PLLMul_6: PLL clock source multiplied by 6 + * @arg RCC_PLLMul_8: PLL clock source multiplied by 8 + * @arg RCC_PLLMul_12: PLL clock source multiplied by 12 + * @arg RCC_PLLMul_16: PLL clock source multiplied by 16 + * @arg RCC_PLLMul_24: PLL clock source multiplied by 24 + * @arg RCC_PLLMul_32: PLL clock source multiplied by 32 + * @arg RCC_PLLMul_48: PLL clock source multiplied by 48 + * @note The application software must set correctly the PLL multiplication + * factor to avoid exceeding: + * - 96 MHz as PLLVCO when the product is in range 1 + * - 48 MHz as PLLVCO when the product is in range 2 + * - 24 MHz when the product is in range 3 + * @note When using the USB the PLLVCO should be 96MHz + * + * @param RCC_PLLDiv: specifies the PLL division factor. + * This parameter can be: + * @arg RCC_PLLDiv_2: PLL Clock output divided by 2 + * @arg RCC_PLLDiv_3: PLL Clock output divided by 3 + * @arg RCC_PLLDiv_4: PLL Clock output divided by 4 + * @note The application software must set correctly the output division to avoid + * exceeding 32 MHz as SYSCLK. + * + * @retval None + */ +void RCC_PLLConfig(uint8_t RCC_PLLSource, uint8_t RCC_PLLMul, uint8_t RCC_PLLDiv) +{ + /* Check the parameters */ + assert_param(IS_RCC_PLL_SOURCE(RCC_PLLSource)); + assert_param(IS_RCC_PLL_MUL(RCC_PLLMul)); + assert_param(IS_RCC_PLL_DIV(RCC_PLLDiv)); + + *(__IO uint8_t *) CFGR_BYTE3_ADDRESS = (uint8_t)(RCC_PLLSource | ((uint8_t)(RCC_PLLMul | (uint8_t)(RCC_PLLDiv)))); +} + +/** + * @brief Enables or disables the PLL. + * @note After enabling the PLL, the application software should wait on + * PLLRDY flag to be set indicating that PLL clock is stable and can + * be used as system clock source. + * @note The PLL can not be disabled if it is used as system clock source + * @note The PLL is disabled by hardware when entering STOP and STANDBY modes. + * @param NewState: new state of the PLL. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_PLLCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) CR_PLLON_BB = (uint32_t)NewState; +} + +/** + * @brief Enables or disables 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-M3 NMI (Non-Maskable Interrupt) exception vector. + * @param NewState: new state of the Clock Security System. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_ClockSecuritySystemCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) CR_CSSON_BB = (uint32_t)NewState; +} + +/** + * @brief Enables or disables the LSE Clock Security System. + * @param NewState: new state of the Clock Security System. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_LSEClockSecuritySystemCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) CSR_LSECSSON_BB = (uint32_t)NewState; +} + +/** + * @brief Selects the clock source to output on MCO pin (PA8). + * @note PA8 should be configured in alternate function mode. + * @param RCC_MCOSource: specifies the clock source to output. + * This parameter can be one of the following values: + * @arg RCC_MCOSource_NoClock: No clock selected + * @arg RCC_MCOSource_SYSCLK: System clock selected + * @arg RCC_MCOSource_HSI: HSI oscillator clock selected + * @arg RCC_MCOSource_MSI: MSI oscillator clock selected + * @arg RCC_MCOSource_HSE: HSE oscillator clock selected + * @arg RCC_MCOSource_PLLCLK: PLL clock selected + * @arg RCC_MCOSource_LSI: LSI clock selected + * @arg RCC_MCOSource_LSE: LSE clock selected + * @param RCC_MCODiv: specifies the MCO prescaler. + * This parameter can be one of the following values: + * @arg RCC_MCODiv_1: no division applied to MCO clock + * @arg RCC_MCODiv_2: division by 2 applied to MCO clock + * @arg RCC_MCODiv_4: division by 4 applied to MCO clock + * @arg RCC_MCODiv_8: division by 8 applied to MCO clock + * @arg RCC_MCODiv_16: division by 16 applied to MCO clock + * @retval None + */ +void RCC_MCOConfig(uint8_t RCC_MCOSource, uint8_t RCC_MCODiv) +{ + /* Check the parameters */ + assert_param(IS_RCC_MCO_SOURCE(RCC_MCOSource)); + assert_param(IS_RCC_MCO_DIV(RCC_MCODiv)); + + /* Select MCO clock source and prescaler */ + *(__IO uint8_t *) CFGR_BYTE4_ADDRESS = RCC_MCOSource | RCC_MCODiv; +} + +/** + * @} + */ + +/** @defgroup RCC_Group2 System AHB and APB busses clocks configuration functions + * @brief System, AHB and APB busses clocks configuration functions + * +@verbatim + =============================================================================== + ##### System, AHB and APB busses clocks configuration functions ##### + =============================================================================== + [..] This section provide functions allowing to configure the System, AHB, + APB1 and APB2 busses clocks. + (#) Several clock sources can be used to drive the System clock (SYSCLK): + MSI, HSI, HSE and 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 and 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 + "RCC_GetClocksFreq()" function to retrieve the frequencies of these + clocks. + + -@- All the peripheral clocks are derived from the System clock (SYSCLK) + except: + (+@) The USB 48 MHz clock which is derived from the PLL VCO clock. + (+@) The ADC clock which is always the HSI clock. A divider by 1, 2 + or 4 allows to adapt the clock frequency to the device operating + conditions. + (+@) The RTC/LCD clock which is derived from the LSE, LSI or 1 MHz + HSE_RTC (HSE divided by a programmable prescaler). + The System clock (SYSCLK) frequency must be higher or equal to + the RTC/LCD clock frequency. + (+@) IWDG clock which is always the LSI clock. + + (#) The maximum frequency of the SYSCLK, HCLK, PCLK1 and PCLK2 is 32 MHz. + Depending on the device voltage range, the maximum frequency should + be adapted accordingly: + + +----------------------------------------------------------------+ + | Wait states | HCLK clock frequency (MHz) | + | |------------------------------------------------| + | (Latency) | voltage range | voltage range | + | | 1.65 V - 3.6 V | 2.0 V - 3.6 V | + | |----------------|---------------|---------------| + | | VCORE = 1.2 V | VCORE = 1.5 V | VCORE = 1.8 V | + |-------------- |----------------|---------------|---------------| + |0WS(1CPU cycle)|0 < HCLK <= 2 |0 < HCLK <= 8 |0 < HCLK <= 16 | + |---------------|----------------|---------------|---------------| + |1WS(2CPU cycle)|2 < HCLK <= 4 |8 < HCLK <= 16 |16 < HCLK <= 32| + +----------------------------------------------------------------+ + + (#) After reset, the System clock source is the MSI (2 MHz) with 0 WS, + Flash 32-bit access is enabled and prefetch is disabled. + [..] It is recommended to use the following software sequences to tune the + number of wait states needed to access the Flash memory with the CPU + frequency (HCLK). + (+) Increasing the CPU frequency (in the same voltage range) + (+) Program the Flash 64-bit access, using "FLASH_ReadAccess64Cmd(ENABLE)" + function + (+) Check that 64-bit access is taken into account by reading FLASH_ACR + (+) Program Flash WS to 1, using "FLASH_SetLatency(FLASH_Latency_1)" + function + (+) Check that the new number of WS is taken into account by reading + FLASH_ACR + (+) Modify the CPU clock source, using "RCC_SYSCLKConfig()" function + (+) If needed, modify the CPU clock prescaler by using "RCC_HCLKConfig()" + function + (+) Check that the new CPU clock source is taken into account by reading + the clock source status, using "RCC_GetSYSCLKSource()" function + (+) Decreasing the CPU frequency (in the same voltage range) + (+) Modify the CPU clock source, using "RCC_SYSCLKConfig()" function + (+) If needed, modify the CPU clock prescaler by using "RCC_HCLKConfig()" + function + (+) Check that the new CPU clock source is taken into account by reading + the clock source status, using "RCC_GetSYSCLKSource()" function + (+) Program the new number of WS, using "FLASH_SetLatency()" function + (+) Check that the new number of WS is taken into account by reading + FLASH_ACR + (+) Enable the Flash 32-bit access, using "FLASH_ReadAccess64Cmd(DISABLE)" + function + (+) Check that 32-bit access is taken into account by reading FLASH_ACR + +@endverbatim + * @{ + */ + +/** + * @brief Configures the system clock (SYSCLK). + * @note The MSI is used (enabled by hardware) as system clock source after + * startup from Reset, wake-up from STOP and STANDBY mode, 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 will be ready. + * You can use RCC_GetSYSCLKSource() function to know which clock is + * currently used as system clock source. + * @param RCC_SYSCLKSource: specifies the clock source used as system clock source + * This parameter can be one of the following values: + * @arg RCC_SYSCLKSource_MSI: MSI selected as system clock source + * @arg RCC_SYSCLKSource_HSI: HSI selected as system clock source + * @arg RCC_SYSCLKSource_HSE: HSE selected as system clock source + * @arg RCC_SYSCLKSource_PLLCLK: PLL selected as system clock source + * @retval None + */ +void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RCC_SYSCLK_SOURCE(RCC_SYSCLKSource)); + + tmpreg = RCC->CFGR; + + /* Clear SW[1:0] bits */ + tmpreg &= ~RCC_CFGR_SW; + + /* Set SW[1:0] bits according to RCC_SYSCLKSource value */ + tmpreg |= RCC_SYSCLKSource; + + /* Store the new value */ + RCC->CFGR = tmpreg; +} + +/** + * @brief Returns the clock source used as system clock. + * @param None + * @retval The clock source used as system clock. The returned value can be one + * of the following values: + * - 0x00: MSI used as system clock + * - 0x04: HSI used as system clock + * - 0x08: HSE used as system clock + * - 0x0C: PLL used as system clock + */ +uint8_t RCC_GetSYSCLKSource(void) +{ + return ((uint8_t)(RCC->CFGR & RCC_CFGR_SWS)); +} + +/** + * @brief Configures the AHB clock (HCLK). + * @note Depending on the device voltage range, the software has to set correctly + * these bits to ensure that the system frequency does not exceed the + * maximum allowed frequency (for more details refer to section above + * "CPU, AHB and APB busses clocks configuration functions") + * @param RCC_SYSCLK: defines the AHB clock divider. This clock is derived from + * the system clock (SYSCLK). + * This parameter can be one of the following values: + * @arg RCC_SYSCLK_Div1: AHB clock = SYSCLK + * @arg RCC_SYSCLK_Div2: AHB clock = SYSCLK/2 + * @arg RCC_SYSCLK_Div4: AHB clock = SYSCLK/4 + * @arg RCC_SYSCLK_Div8: AHB clock = SYSCLK/8 + * @arg RCC_SYSCLK_Div16: AHB clock = SYSCLK/16 + * @arg RCC_SYSCLK_Div64: AHB clock = SYSCLK/64 + * @arg RCC_SYSCLK_Div128: AHB clock = SYSCLK/128 + * @arg RCC_SYSCLK_Div256: AHB clock = SYSCLK/256 + * @arg RCC_SYSCLK_Div512: AHB clock = SYSCLK/512 + * @retval None + */ +void RCC_HCLKConfig(uint32_t RCC_SYSCLK) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RCC_HCLK(RCC_SYSCLK)); + + tmpreg = RCC->CFGR; + + /* Clear HPRE[3:0] bits */ + tmpreg &= ~RCC_CFGR_HPRE; + + /* Set HPRE[3:0] bits according to RCC_SYSCLK value */ + tmpreg |= RCC_SYSCLK; + + /* Store the new value */ + RCC->CFGR = tmpreg; +} + +/** + * @brief Configures the Low Speed APB clock (PCLK1). + * @param RCC_HCLK: defines the APB1 clock divider. This clock is derived from + * the AHB clock (HCLK). + * This parameter can be one of the following values: + * @arg RCC_HCLK_Div1: APB1 clock = HCLK + * @arg RCC_HCLK_Div2: APB1 clock = HCLK/2 + * @arg RCC_HCLK_Div4: APB1 clock = HCLK/4 + * @arg RCC_HCLK_Div8: APB1 clock = HCLK/8 + * @arg RCC_HCLK_Div16: APB1 clock = HCLK/16 + * @retval None + */ +void RCC_PCLK1Config(uint32_t RCC_HCLK) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RCC_PCLK(RCC_HCLK)); + + tmpreg = RCC->CFGR; + + /* Clear PPRE1[2:0] bits */ + tmpreg &= ~RCC_CFGR_PPRE1; + + /* Set PPRE1[2:0] bits according to RCC_HCLK value */ + tmpreg |= RCC_HCLK; + + /* Store the new value */ + RCC->CFGR = tmpreg; +} + +/** + * @brief Configures the High Speed APB clock (PCLK2). + * @param RCC_HCLK: defines the APB2 clock divider. This clock is derived from + * the AHB clock (HCLK). + * This parameter can be one of the following values: + * @arg RCC_HCLK_Div1: APB2 clock = HCLK + * @arg RCC_HCLK_Div2: APB2 clock = HCLK/2 + * @arg RCC_HCLK_Div4: APB2 clock = HCLK/4 + * @arg RCC_HCLK_Div8: APB2 clock = HCLK/8 + * @arg RCC_HCLK_Div16: APB2 clock = HCLK/16 + * @retval None + */ +void RCC_PCLK2Config(uint32_t RCC_HCLK) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RCC_PCLK(RCC_HCLK)); + + tmpreg = RCC->CFGR; + + /* Clear PPRE2[2:0] bits */ + tmpreg &= ~RCC_CFGR_PPRE2; + + /* Set PPRE2[2:0] bits according to RCC_HCLK value */ + tmpreg |= RCC_HCLK << 3; + + /* Store the new value */ + RCC->CFGR = tmpreg; +} + +/** + * @brief Returns the frequencies of the System, AHB and APB busses clocks. + * @note The frequency returned by this function is not the real frequency + * in the chip. It is calculated based on the predefined constant and + * the source selected by RCC_SYSCLKConfig(): + * + * @note If SYSCLK source is MSI, function returns values based on MSI + * Value as defined by the MSI range, refer to RCC_MSIRangeConfig() + * + * @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(*) multiplied/divided by the PLL factors. + * + * (*) HSI_VALUE is a constant defined in stm32l1xx.h file (default value + * 16 MHz) but the real value may vary depending on the variations + * in voltage and temperature, refer to RCC_AdjustHSICalibrationValue(). + * + * (**) HSE_VALUE is a constant defined in stm32l1xx.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 + * return wrong result. + * + * - The result of this function could be not correct when using fractional + * value for HSE crystal. + * + * @param RCC_Clocks: pointer to a RCC_ClocksTypeDef structure which will hold + * the clocks frequencies. + * + * @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, HCLK, PCLK1 and/or PCLK2 clock changes, this function + * must be called to update the structure's field. Otherwise, any + * configuration based on this function will be incorrect. + * + * @retval None + */ +void RCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks) +{ + uint32_t tmp = 0, pllmul = 0, plldiv = 0, pllsource = 0, presc = 0, msirange = 0; + + /* Get SYSCLK source -------------------------------------------------------*/ + tmp = RCC->CFGR & RCC_CFGR_SWS; + + switch (tmp) + { + case 0x00: /* MSI used as system clock */ + msirange = (RCC->ICSCR & RCC_ICSCR_MSIRANGE ) >> 13; + RCC_Clocks->SYSCLK_Frequency = (32768 * (1 << (msirange + 1))); + break; + case 0x04: /* HSI used as system clock */ + RCC_Clocks->SYSCLK_Frequency = HSI_VALUE; + break; + case 0x08: /* HSE used as system clock */ + RCC_Clocks->SYSCLK_Frequency = HSE_VALUE; + break; + case 0x0C: /* PLL used as system clock */ + /* Get PLL clock source and multiplication factor ----------------------*/ + pllmul = RCC->CFGR & RCC_CFGR_PLLMUL; + plldiv = RCC->CFGR & RCC_CFGR_PLLDIV; + pllmul = PLLMulTable[(pllmul >> 18)]; + plldiv = (plldiv >> 22) + 1; + + pllsource = RCC->CFGR & RCC_CFGR_PLLSRC; + + if (pllsource == 0x00) + { + /* HSI oscillator clock selected as PLL clock source */ + RCC_Clocks->SYSCLK_Frequency = (((HSI_VALUE) * pllmul) / plldiv); + } + else + { + /* HSE selected as PLL clock source */ + RCC_Clocks->SYSCLK_Frequency = (((HSE_VALUE) * pllmul) / plldiv); + } + break; + default: /* MSI used as system clock */ + msirange = (RCC->ICSCR & RCC_ICSCR_MSIRANGE ) >> 13; + RCC_Clocks->SYSCLK_Frequency = (32768 * (1 << (msirange + 1))); + break; + } + /* Compute HCLK, PCLK1, PCLK2 and ADCCLK clocks frequencies ----------------*/ + /* Get HCLK prescaler */ + tmp = RCC->CFGR & RCC_CFGR_HPRE; + tmp = tmp >> 4; + presc = APBAHBPrescTable[tmp]; + /* HCLK clock frequency */ + RCC_Clocks->HCLK_Frequency = RCC_Clocks->SYSCLK_Frequency >> presc; + + /* Get PCLK1 prescaler */ + tmp = RCC->CFGR & RCC_CFGR_PPRE1; + tmp = tmp >> 8; + presc = APBAHBPrescTable[tmp]; + /* PCLK1 clock frequency */ + RCC_Clocks->PCLK1_Frequency = RCC_Clocks->HCLK_Frequency >> presc; + + /* Get PCLK2 prescaler */ + tmp = RCC->CFGR & RCC_CFGR_PPRE2; + tmp = tmp >> 11; + presc = APBAHBPrescTable[tmp]; + /* PCLK2 clock frequency */ + RCC_Clocks->PCLK2_Frequency = RCC_Clocks->HCLK_Frequency >> presc; +} + +/** + * @} + */ + +/** @defgroup RCC_Group3 Peripheral clocks configuration functions + * @brief Peripheral clocks configuration functions + * +@verbatim + =============================================================================== + ##### Peripheral clocks configuration functions ##### + =============================================================================== + [..] This section provide functions allowing to configure the Peripheral clocks. + (#) The RTC/LCD clock which is derived from the LSE, LSI or 1 MHz HSE_RTC + (HSE divided by a programmable prescaler). + (#) After restart from Reset or wakeup from STANDBY, all peripherals are + off except internal SRAM, Flash and JTAG. Before to start using a + peripheral you have to enable its interface clock. You can do this + using RCC_AHBPeriphClockCmd(), RCC_APB2PeriphClockCmd() and + RCC_APB1PeriphClockCmd() functions. + + (#) To reset the peripherals configuration (to the default state after + device reset) you can use RCC_AHBPeriphResetCmd(), + RCC_APB2PeriphResetCmd() and RCC_APB1PeriphResetCmd() functions. + (#) To further reduce power consumption in SLEEP mode the peripheral + clocks can be disabled prior to executing the WFI or WFE instructions. + You can do this using RCC_AHBPeriphClockLPModeCmd(), + RCC_APB2PeriphClockLPModeCmd() and RCC_APB1PeriphClockLPModeCmd() + functions. + +@endverbatim + * @{ + */ + +/** + * @brief Configures the RTC and LCD clock (RTCCLK / LCDCLK). + * @note As the RTC clock configuration bits are in the RTC domain and write + * access is denied to this domain after reset, you have to enable write + * access using PWR_RTCAccessCmd(ENABLE) function before to configure + * the RTC clock source (to be done once after reset). + * @note Once the RTC clock is configured it can't be changed unless the RTC + * is reset using RCC_RTCResetCmd function, or by a Power On Reset (POR) + * @note The RTC clock (RTCCLK) is used also to clock the LCD (LCDCLK). + * + * @param RCC_RTCCLKSource: specifies the RTC clock source. + * This parameter can be one of the following values: + * @arg RCC_RTCCLKSource_LSE: LSE selected as RTC clock + * @arg RCC_RTCCLKSource_LSI: LSI selected as RTC clock + * @arg RCC_RTCCLKSource_HSE_Div2: HSE divided by 2 selected as RTC clock + * @arg RCC_RTCCLKSource_HSE_Div4: HSE divided by 4 selected as RTC clock + * @arg RCC_RTCCLKSource_HSE_Div8: HSE divided by 8 selected as RTC clock + * @arg RCC_RTCCLKSource_HSE_Div16: HSE divided by 16 selected as RTC clock + * + * @note If the LSE or LSI is used as RTC clock source, the RTC continues to + * work in STOP and STANDBY modes, and can be used as wakeup source. + * However, when the HSE clock is used as RTC clock source, the RTC + * cannot be used in STOP and STANDBY modes. + * + * @note The maximum input clock frequency for RTC is 1MHz (when using HSE as + * RTC clock source). + * + * @retval None + */ +void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_RCC_RTCCLK_SOURCE(RCC_RTCCLKSource)); + + if ((RCC_RTCCLKSource & RCC_CSR_RTCSEL_HSE) == RCC_CSR_RTCSEL_HSE) + { + /* If HSE is selected as RTC clock source, configure HSE division factor for RTC clock */ + tmpreg = RCC->CR; + + /* Clear RTCPRE[1:0] bits */ + tmpreg &= ~RCC_CR_RTCPRE; + + /* Configure HSE division factor for RTC clock */ + tmpreg |= (RCC_RTCCLKSource & RCC_CR_RTCPRE); + + /* Store the new value */ + RCC->CR = tmpreg; + } + + RCC->CSR &= ~RCC_CSR_RTCSEL; + + /* Select the RTC clock source */ + RCC->CSR |= (RCC_RTCCLKSource & RCC_CSR_RTCSEL); +} + +/** + * @brief Enables or disables the RTC clock. + * @note This function must be used only after the RTC clock source was selected + * using the RCC_RTCCLKConfig function. + * @param NewState: new state of the RTC clock. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_RTCCLKCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) CSR_RTCEN_BB = (uint32_t)NewState; +} + +/** + * @brief Forces or releases the RTC peripheral and associated resources reset. + * @note This function resets the RTC peripheral, RTC clock source selection + * (in RCC_CSR) and the backup registers. + * @param NewState: new state of the RTC reset. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_RTCResetCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) CSR_RTCRST_BB = (uint32_t)NewState; +} + +/** + * @brief Enables or disables the AHB peripheral clock. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + * @param RCC_AHBPeriph: specifies the AHB peripheral to gates its clock. + * This parameter can be any combination of the following values: + * @arg RCC_AHBPeriph_GPIOA: GPIOA clock + * @arg RCC_AHBPeriph_GPIOB: GPIOB clock + * @arg RCC_AHBPeriph_GPIOC: GPIOC clock + * @arg RCC_AHBPeriph_GPIOD: GPIOD clock + * @arg RCC_AHBPeriph_GPIOE: GPIOE clock + * @arg RCC_AHBPeriph_GPIOH: GPIOH clock + * @arg RCC_AHBPeriph_GPIOF: GPIOF clock + * @arg RCC_AHBPeriph_GPIOG: GPIOG clock + * @arg RCC_AHBPeriph_CRC: CRC clock + * @arg RCC_AHBPeriph_FLITF: (has effect only when the Flash memory is in power down mode) + * @arg RCC_AHBPeriph_DMA1: DMA1 clock + * @arg RCC_AHBPeriph_DMA2: DMA2 clock + * @arg RCC_AHBPeriph_AES: AES clock + * @arg RCC_AHBPeriph_FSMC: FSMC clock + * @param NewState: new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_AHB_PERIPH(RCC_AHBPeriph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + RCC->AHBENR |= RCC_AHBPeriph; + } + else + { + RCC->AHBENR &= ~RCC_AHBPeriph; + } +} + +/** + * @brief Enables or disables the High Speed APB (APB2) peripheral clock. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + * @param RCC_APB2Periph: specifies the APB2 peripheral to gates its clock. + * This parameter can be any combination of the following values: + * @arg RCC_APB2Periph_SYSCFG: SYSCFG APB2 Clock. + * @arg RCC_APB2Periph_TIM9: TIM9 APB2 Clock. + * @arg RCC_APB2Periph_TIM10: TIM10 APB2 Clock. + * @arg RCC_APB2Periph_TIM11: TIM11 APB2 Clock. + * @arg RCC_APB2Periph_ADC1: ADC1 APB2 Clock. + * @arg RCC_APB2Periph_SDIO: SDIO APB2 Clock. + * @arg RCC_APB2Periph_SPI1: SPI1 APB2 Clock. + * @arg RCC_APB2Periph_USART1: USART1 APB2 Clock. + * @param NewState: new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + RCC->APB2ENR |= RCC_APB2Periph; + } + else + { + RCC->APB2ENR &= ~RCC_APB2Periph; + } +} + +/** + * @brief Enables or disables the Low Speed APB (APB1) peripheral clock. + * @note After reset, the peripheral clock (used for registers read/write access) + * is disabled and the application software has to enable this clock before + * using it. + * @param RCC_APB1Periph: specifies the APB1 peripheral to gates its clock. + * This parameter can be any combination of the following values: + * @arg RCC_APB1Periph_TIM2: TIM2 clock + * @arg RCC_APB1Periph_TIM3: TIM3 clock + * @arg RCC_APB1Periph_TIM4: TIM4 clock + * @arg RCC_APB1Periph_TIM5: TIM5 clock + * @arg RCC_APB1Periph_TIM6: TIM6 clock + * @arg RCC_APB1Periph_TIM7: TIM7 clock + * @arg RCC_APB1Periph_LCD: LCD clock + * @arg RCC_APB1Periph_WWDG: WWDG clock + * @arg RCC_APB1Periph_SPI2: SPI2 clock + * @arg RCC_APB1Periph_SPI3: SPI3 clock + * @arg RCC_APB1Periph_USART2: USART2 clock + * @arg RCC_APB1Periph_USART3: USART3 clock + * @arg RCC_APB1Periph_UART4: UART4 clock + * @arg RCC_APB1Periph_UART5: UART5 clock + * @arg RCC_APB1Periph_I2C1: I2C1 clock + * @arg RCC_APB1Periph_I2C2: I2C2 clock + * @arg RCC_APB1Periph_USB: USB clock + * @arg RCC_APB1Periph_PWR: PWR clock + * @arg RCC_APB1Periph_DAC: DAC clock + * @arg RCC_APB1Periph_COMP COMP clock + * @param NewState: new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_APB1_PERIPH(RCC_APB1Periph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + RCC->APB1ENR |= RCC_APB1Periph; + } + else + { + RCC->APB1ENR &= ~RCC_APB1Periph; + } +} + +/** + * @brief Forces or releases AHB peripheral reset. + * @param RCC_AHBPeriph: specifies the AHB peripheral to reset. + * This parameter can be any combination of the following values: + * @arg RCC_AHBPeriph_GPIOA: GPIOA clock + * @arg RCC_AHBPeriph_GPIOB: GPIOB clock + * @arg RCC_AHBPeriph_GPIOC: GPIOC clock + * @arg RCC_AHBPeriph_GPIOD: GPIOD clock + * @arg RCC_AHBPeriph_GPIOE: GPIOE clock + * @arg RCC_AHBPeriph_GPIOH: GPIOH clock + * @arg RCC_AHBPeriph_GPIOF: GPIOF clock + * @arg RCC_AHBPeriph_GPIOG: GPIOG clock + * @arg RCC_AHBPeriph_CRC: CRC clock + * @arg RCC_AHBPeriph_FLITF: (has effect only when the Flash memory is in power down mode) + * @arg RCC_AHBPeriph_DMA1: DMA1 clock + * @arg RCC_AHBPeriph_DMA2: DMA2 clock + * @arg RCC_AHBPeriph_AES: AES clock + * @arg RCC_AHBPeriph_FSMC: FSMC clock + * @param NewState: new state of the specified peripheral reset. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_AHBPeriphResetCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_AHB_PERIPH(RCC_AHBPeriph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + RCC->AHBRSTR |= RCC_AHBPeriph; + } + else + { + RCC->AHBRSTR &= ~RCC_AHBPeriph; + } +} + +/** + * @brief Forces or releases High Speed APB (APB2) peripheral reset. + * @param RCC_APB2Periph: specifies the APB2 peripheral to reset. + * This parameter can be any combination of the following values: + * @arg RCC_APB2Periph_SYSCFG: SYSCFG clock + * @arg RCC_APB2Periph_TIM9: TIM9 clock + * @arg RCC_APB2Periph_TIM10: TIM10 clock + * @arg RCC_APB2Periph_TIM11: TIM11 clock + * @arg RCC_APB2Periph_ADC1: ADC1 clock + * @arg RCC_APB2Periph_SDIO: SDIO clock + * @arg RCC_APB2Periph_SPI1: SPI1 clock + * @arg RCC_APB2Periph_USART1: USART1 clock + * @param NewState: new state of the specified peripheral reset. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + RCC->APB2RSTR |= RCC_APB2Periph; + } + else + { + RCC->APB2RSTR &= ~RCC_APB2Periph; + } +} + +/** + * @brief Forces or releases Low Speed APB (APB1) peripheral reset. + * @param RCC_APB1Periph: specifies the APB1 peripheral to reset. + * This parameter can be any combination of the following values: + * @arg RCC_APB1Periph_TIM2: TIM2 clock + * @arg RCC_APB1Periph_TIM3: TIM3 clock + * @arg RCC_APB1Periph_TIM4: TIM4 clock + * @arg RCC_APB1Periph_TIM5: TIM5 clock + * @arg RCC_APB1Periph_TIM6: TIM6 clock + * @arg RCC_APB1Periph_TIM7: TIM7 clock + * @arg RCC_APB1Periph_LCD: LCD clock + * @arg RCC_APB1Periph_WWDG: WWDG clock + * @arg RCC_APB1Periph_SPI2: SPI2 clock + * @arg RCC_APB1Periph_SPI3: SPI3 clock + * @arg RCC_APB1Periph_USART2: USART2 clock + * @arg RCC_APB1Periph_USART3: USART3 clock + * @arg RCC_APB1Periph_UART4: UART4 clock + * @arg RCC_APB1Periph_UART5: UART5 clock + * @arg RCC_APB1Periph_I2C1: I2C1 clock + * @arg RCC_APB1Periph_I2C2: I2C2 clock + * @arg RCC_APB1Periph_USB: USB clock + * @arg RCC_APB1Periph_PWR: PWR clock + * @arg RCC_APB1Periph_DAC: DAC clock + * @arg RCC_APB1Periph_COMP + * @param NewState: new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_APB1_PERIPH(RCC_APB1Periph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + RCC->APB1RSTR |= RCC_APB1Periph; + } + else + { + RCC->APB1RSTR &= ~RCC_APB1Periph; + } +} + +/** + * @brief Enables or disables the AHB peripheral clock during SLEEP mode. + * @note Peripheral clock gating in SLEEP mode can be used to further reduce + * power consumption. + * - After wakeup from SLEEP mode, the peripheral clock is enabled again. + * - By default, all peripheral clocks are enabled during SLEEP mode. + * @param RCC_AHBPeriph: specifies the AHB peripheral to gates its clock. + * This parameter can be any combination of the following values: + * @arg RCC_AHBPeriph_GPIOA: GPIOA clock + * @arg RCC_AHBPeriph_GPIOB: GPIOB clock + * @arg RCC_AHBPeriph_GPIOC: GPIOC clock + * @arg RCC_AHBPeriph_GPIOD: GPIOD clock + * @arg RCC_AHBPeriph_GPIOE: GPIOE clock + * @arg RCC_AHBPeriph_GPIOH: GPIOH clock + * @arg RCC_AHBPeriph_GPIOF: GPIOF clock + * @arg RCC_AHBPeriph_GPIOG: GPIOG clock + * @arg RCC_AHBPeriph_CRC: CRC clock + * @arg RCC_AHBPeriph_FLITF: (has effect only when the Flash memory is in power down mode) + * @arg RCC_AHBPeriph_SRAM: SRAM clock + * @arg RCC_AHBPeriph_DMA1: DMA1 clock + * @arg RCC_AHBPeriph_DMA2: DMA2 clock + * @arg RCC_AHBPeriph_AES: AES clock + * @arg RCC_AHBPeriph_FSMC: FSMC clock + * @param NewState: new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_AHBPeriphClockLPModeCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_AHB_LPMODE_PERIPH(RCC_AHBPeriph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + RCC->AHBLPENR |= RCC_AHBPeriph; + } + else + { + RCC->AHBLPENR &= ~RCC_AHBPeriph; + } +} + +/** + * @brief Enables or disables the APB2 peripheral clock during SLEEP mode. + * @note Peripheral clock gating in SLEEP mode can be used to further reduce + * power consumption. + * @note After wakeup from SLEEP mode, the peripheral clock is enabled again. + * @note By default, all peripheral clocks are enabled during SLEEP mode. + * @param RCC_APB2Periph: specifies the APB2 peripheral to gates its clock. + * This parameter can be any combination of the following values: + * @arg RCC_APB2Periph_SYSCFG: SYSCFG clock + * @arg RCC_APB2Periph_TIM9: TIM9 clock + * @arg RCC_APB2Periph_TIM10: TIM10 clock + * @arg RCC_APB2Periph_TIM11: TIM11 clock + * @arg RCC_APB2Periph_ADC1: ADC1 clock + * @arg RCC_APB2Periph_SDIO: SDIO clock + * @arg RCC_APB2Periph_SPI1: SPI1 clock + * @arg RCC_APB2Periph_USART1: USART1 clock + * @param NewState: new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_APB2PeriphClockLPModeCmd(uint32_t RCC_APB2Periph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + RCC->APB2LPENR |= RCC_APB2Periph; + } + else + { + RCC->APB2LPENR &= ~RCC_APB2Periph; + } +} + +/** + * @brief Enables or disables the APB1 peripheral clock during SLEEP mode. + * @note Peripheral clock gating in SLEEP mode can be used to further reduce + * power consumption. + * @note After wakeup from SLEEP mode, the peripheral clock is enabled again. + * @note By default, all peripheral clocks are enabled during SLEEP mode. + * @param RCC_APB1Periph: specifies the APB1 peripheral to gates its clock. + * This parameter can be any combination of the following values: + * @arg RCC_APB1Periph_TIM2: TIM2 clock + * @arg RCC_APB1Periph_TIM3: TIM3 clock + * @arg RCC_APB1Periph_TIM4: TIM4 clock + * @arg RCC_APB1Periph_TIM5: TIM5 clock + * @arg RCC_APB1Periph_TIM6: TIM6 clock + * @arg RCC_APB1Periph_TIM7: TIM7 clock + * @arg RCC_APB1Periph_LCD: LCD clock + * @arg RCC_APB1Periph_WWDG: WWDG clock + * @arg RCC_APB1Periph_SPI2: SPI2 clock + * @arg RCC_APB1Periph_SPI3: SPI3 clock + * @arg RCC_APB1Periph_USART2: USART2 clock + * @arg RCC_APB1Periph_USART3: USART3 clock + * @arg RCC_APB1Periph_UART4: UART4 clock + * @arg RCC_APB1Periph_UART5: UART5 clock + * @arg RCC_APB1Periph_I2C1: I2C1 clock + * @arg RCC_APB1Periph_I2C2: I2C2 clock + * @arg RCC_APB1Periph_USB: USB clock + * @arg RCC_APB1Periph_PWR: PWR clock + * @arg RCC_APB1Periph_DAC: DAC clock + * @arg RCC_APB1Periph_COMP: COMP clock + * @param NewState: new state + * @param NewState: new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_APB1PeriphClockLPModeCmd(uint32_t RCC_APB1Periph, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_APB1_PERIPH(RCC_APB1Periph)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + RCC->APB1LPENR |= RCC_APB1Periph; + } + else + { + RCC->APB1LPENR &= ~RCC_APB1Periph; + } +} + +/** + * @} + */ + +/** @defgroup RCC_Group4 Interrupts and flags management functions + * @brief Interrupts and flags management functions + * +@verbatim + =============================================================================== + ##### Interrupts and flags management functions ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Enables or disables the specified RCC interrupts. + * @note The CSS interrupt doesn't have an enable bit; once the CSS is enabled + * and if the HSE clock fails, the CSS interrupt occurs and an NMI is + * automatically generated. The NMI will be executed indefinitely, and + * since NMI has higher priority than any other IRQ (and main program) + * the application will be stacked in the NMI ISR unless the CSS interrupt + * pending bit is cleared. + * @param RCC_IT: specifies the RCC interrupt sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg RCC_IT_LSIRDY: LSI ready interrupt + * @arg RCC_IT_LSERDY: LSE ready interrupt + * @arg RCC_IT_HSIRDY: HSI ready interrupt + * @arg RCC_IT_HSERDY: HSE ready interrupt + * @arg RCC_IT_PLLRDY: PLL ready interrupt + * @arg RCC_IT_MSIRDY: MSI ready interrupt + * @arg RCC_IT_LSECSS: LSE CSS interrupt + * @param NewState: new state of the specified RCC interrupts. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void RCC_ITConfig(uint8_t RCC_IT, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_RCC_IT(RCC_IT)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Perform Byte access to RCC_CIR[12:8] bits to enable the selected interrupts */ + *(__IO uint8_t *) CIR_BYTE2_ADDRESS |= RCC_IT; + } + else + { + /* Perform Byte access to RCC_CIR[12:8] bits to disable the selected interrupts */ + *(__IO uint8_t *) CIR_BYTE2_ADDRESS &= (uint8_t)~RCC_IT; + } +} + +/** + * @brief Checks whether the specified RCC flag is set or not. + * @param RCC_FLAG: specifies the flag to check. + * This parameter can be one of the following values: + * @arg RCC_FLAG_HSIRDY: HSI oscillator clock ready + * @arg RCC_FLAG_MSIRDY: MSI oscillator clock ready + * @arg RCC_FLAG_HSERDY: HSE oscillator clock ready + * @arg RCC_FLAG_PLLRDY: PLL clock ready + * @arg RCC_FLAG_LSECSS: LSE oscillator clock CSS detected + * @arg RCC_FLAG_LSERDY: LSE oscillator clock ready + * @arg RCC_FLAG_LSIRDY: LSI oscillator clock ready + * @arg RCC_FLAG_OBLRST: Option Byte Loader (OBL) reset + * @arg RCC_FLAG_PINRST: Pin reset + * @arg RCC_FLAG_PORRST: POR/PDR reset + * @arg RCC_FLAG_SFTRST: Software reset + * @arg RCC_FLAG_IWDGRST: Independent Watchdog reset + * @arg RCC_FLAG_WWDGRST: Window Watchdog reset + * @arg RCC_FLAG_LPWRRST: Low Power reset + * @retval The new state of RCC_FLAG (SET or RESET). + */ +FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG) +{ + uint32_t tmp = 0; + uint32_t statusreg = 0; + FlagStatus bitstatus = RESET; + + /* Check the parameters */ + assert_param(IS_RCC_FLAG(RCC_FLAG)); + + /* Get the RCC register index */ + tmp = RCC_FLAG >> 5; + + if (tmp == 1) /* The flag to check is in CR register */ + { + statusreg = RCC->CR; + } + else /* The flag to check is in CSR register (tmp == 2) */ + { + statusreg = RCC->CSR; + } + + /* Get the flag position */ + tmp = RCC_FLAG & FLAG_MASK; + + if ((statusreg & ((uint32_t)1 << tmp)) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + /* Return the flag status */ + return bitstatus; +} + +/** + * @brief Clears the RCC reset flags. + * The reset flags are: RCC_FLAG_OBLRST, RCC_FLAG_PINRST, RCC_FLAG_PORRST, + * RCC_FLAG_SFTRST, RCC_FLAG_IWDGRST, RCC_FLAG_WWDGRST, RCC_FLAG_LPWRRST. + * @param None + * @retval None + */ +void RCC_ClearFlag(void) +{ + /* Set RMVF bit to clear the reset flags */ + RCC->CSR |= RCC_CSR_RMVF; +} + +/** + * @brief Checks whether the specified RCC interrupt has occurred or not. + * @param RCC_IT: specifies the RCC interrupt source to check. + * This parameter can be one of the following values: + * @arg RCC_IT_LSIRDY: LSI ready interrupt + * @arg RCC_IT_LSERDY: LSE ready interrupt + * @arg RCC_IT_HSIRDY: HSI ready interrupt + * @arg RCC_IT_HSERDY: HSE ready interrupt + * @arg RCC_IT_PLLRDY: PLL ready interrupt + * @arg RCC_IT_MSIRDY: MSI ready interrupt + * @arg RCC_IT_LSECSS: LSE CSS interrupt + * @arg RCC_IT_CSS: Clock Security System interrupt + * @retval The new state of RCC_IT (SET or RESET). + */ +ITStatus RCC_GetITStatus(uint8_t RCC_IT) +{ + ITStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_RCC_GET_IT(RCC_IT)); + + /* Check the status of the specified RCC interrupt */ + if ((RCC->CIR & RCC_IT) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + /* Return the RCC_IT status */ + return bitstatus; +} + +/** + * @brief Clears the RCC's interrupt pending bits. + * @param RCC_IT: specifies the interrupt pending bit to clear. + * This parameter can be any combination of the following values: + * @arg RCC_IT_LSIRDY: LSI ready interrupt + * @arg RCC_IT_LSERDY: LSE ready interrupt + * @arg RCC_IT_HSIRDY: HSI ready interrupt + * @arg RCC_IT_HSERDY: HSE ready interrupt + * @arg RCC_IT_PLLRDY: PLL ready interrupt + * @arg RCC_IT_MSIRDY: MSI ready interrupt + * @arg RCC_IT_LSECSS: LSE CSS interrupt + * @arg RCC_IT_CSS: Clock Security System interrupt + * @retval None + */ +void RCC_ClearITPendingBit(uint8_t RCC_IT) +{ + /* Check the parameters */ + assert_param(IS_RCC_CLEAR_IT(RCC_IT)); + + /* Perform Byte access to RCC_CIR[23:16] bits to clear the selected interrupt + pending bits */ + *(__IO uint8_t *) CIR_BYTE3_ADDRESS = RCC_IT; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/thirdparty/STM32_USB-FS-Device_Lib_V4.0.0/Libraries/STM32L1xx_StdPeriph_Driver/src/stm32l1xx_sdio.c b/thirdparty/STM32_USB-FS-Device_Lib_V4.0.0/Libraries/STM32L1xx_StdPeriph_Driver/src/stm32l1xx_sdio.c new file mode 100644 index 0000000..9c63ec4 --- /dev/null +++ b/thirdparty/STM32_USB-FS-Device_Lib_V4.0.0/Libraries/STM32L1xx_StdPeriph_Driver/src/stm32l1xx_sdio.c @@ -0,0 +1,984 @@ +/** + ****************************************************************************** + * @file stm32l1xx_sdio.c + * @author MCD Application Team + * @version V1.1.1 + * @date 05-March-2012 + * @brief This file provides firmware functions to manage the following + * functionalities of the SDIO peripheral: + * + Initialization + * + Interrupts and flags management + * + * @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + (#) The SDIO clock (SDIOCLK = 48 MHz) is coming from a specific output of PLL + (PLLVCO) througth a fixed divider by 2. + Before to start working with SDIO peripheral make sure that the PLLVCO is + well configured to 96MHz. + The SDIO peripheral uses two clock signals: + (++) SDIO adapter clock (SDIOCLK = 48 MHz). + (++) APB2 bus clock (PCLK2). + PCLK2 and SDIO_CK clock frequencies must respect the following + condition: Frequenc(PCLK2) >= (3 / 8 x Frequency(SDIO_CK)). + (#) Enable peripheral clock using + RCC_APB2PeriphClockCmd(RCC_APB2Periph_SDIO, ENABLE). + (#) According to the SDIO mode, enable the GPIO clocks using + RCC_AHBPeriphClockCmd() function. + The I/O can be one of the following configurations: + (++) 1-bit data length: SDIO_CMD, SDIO_CK and D0. + (++) 4-bit data length: SDIO_CMD, SDIO_CK and D[3:0]. + (++) 8-bit data length: SDIO_CMD, SDIO_CK and D[7:0]. + + (#) Peripheral's alternate function: + (++) Connect the pin to the desired peripherals' Alternate + Function (AF) using GPIO_PinAFConfig() function. + (++) Configure the desired pin in alternate function by: + GPIO_InitStruct->GPIO_Mode = GPIO_Mode_AF. + (++) Select the type, pull-up/pull-down and output speed via + GPIO_PuPd, GPIO_OType and GPIO_Speed members. + (++) Call GPIO_Init() function. + + (#) Program the Clock Edge, Clock Bypass, Clock Power Save, Bus Wide, + hardware, flow control and the Clock Divider using the SDIO_Init() + function. + (#) Enable the Power ON State using the SDIO_SetPowerState(SDIO_PowerState_ON) + function. + (#) Enable the clock using the SDIO_ClockCmd() function. + (#) Enable the NVIC and the corresponding interrupt using the function + SDIO_ITConfig() if you need to use interrupt mode. + (#) When using the DMA mode + (++) Configure the DMA using DMA_Init() function. + (++) Active the needed channel Request using SDIO_DMACmd() function. + (#) Enable the DMA using the DMA_Cmd() function, when using DMA mode. + (#) To control the CPSM (Command Path State Machine) and send commands to the + card use the SDIO_SendCommand(), SDIO_GetCommandResponse() and + SDIO_GetResponse() functions. First, user has to fill the command + structure (pointer to SDIO_CmdInitTypeDef) according to the selected + command to be sent. The parameters that should be filled are: + (++) Command Argument. + (++) Command Index. + (++) Command Response type. + (++) Command Wait. + (++) CPSM Status (Enable or Disable). + To check if the command is well received, read the SDIO_CMDRESP register + using the SDIO_GetCommandResponse(). The SDIO responses registers + (SDIO_RESP1 to SDIO_RESP2), use the SDIO_GetResponse() function. + (#) To control the DPSM (Data Path State Machine) and send/receive + data to/from the card use the SDIO_DataConfig(), SDIO_GetDataCounter(), + SDIO_ReadData(), SDIO_WriteData() and SDIO_GetFIFOCount() functions. + + *** Read Operations *** + ----------------------- + [..] + (#) First, user has to fill the data structure (pointer to + SDIO_DataInitTypeDef) according to the selected data type to be received. + The parameters that should be filled are: + (++) Data TimeOut. + (++) Data Length. + (++) Data Block size. + (++) Data Transfer direction: should be from card (To SDIO). + (++) Data Transfer mode. + (++) DPSM Status (Enable or Disable). + (#) Configure the SDIO resources to receive the data from the card + according to selected transfer mode (Refer to Step 8, 9 and 10). + (#) Send the selected Read command (refer to step 11). + (#) Use the SDIO flags/interrupts to check the transfer status. + + *** Write Operations *** + ------------------------ + [..] + (#) First, user has to fill the data structure (pointer to + SDIO_DataInitTypeDef) according to the selected data type to be received. + The parameters that should be filled are: + (++) Data TimeOut. + (++) Data Length. + (++) Data Block size. + (++) Data Transfer direction: should be to card (To CARD). + (++) Data Transfer mode. + (++) DPSM Status (Enable or Disable). + (#) Configure the SDIO resources to send the data to the card + according to selected transfer mode (Refer to Step 8, 9 and 10). + (#) Send the selected Write command (refer to step 11). + (#) Use the SDIO flags/interrupts to check the transfer status. + + @endverbatim + * + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2012 STMicroelectronics</center></h2> + * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l1xx_sdio.h" +#include "stm32l1xx_rcc.h" + +/** @addtogroup STM32L1xx_StdPeriph_Driver + * @{ + */ + +/** @defgroup SDIO + * @brief SDIO driver modules + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ + +/* ------------ SDIO registers bit address in the alias region ----------- */ +#define SDIO_OFFSET (SDIO_BASE - PERIPH_BASE) + +/* --- CLKCR Register ---*/ + +/* Alias word address of CLKEN bit */ +#define CLKCR_OFFSET (SDIO_OFFSET + 0x04) +#define CLKEN_BitNumber 0x08 +#define CLKCR_CLKEN_BB (PERIPH_BB_BASE + (CLKCR_OFFSET * 32) + (CLKEN_BitNumber * 4)) + +/* --- CMD Register ---*/ + +/* Alias word address of SDIOSUSPEND bit */ +#define CMD_OFFSET (SDIO_OFFSET + 0x0C) +#define SDIOSUSPEND_BitNumber 0x0B +#define CMD_SDIOSUSPEND_BB (PERIPH_BB_BASE + (CMD_OFFSET * 32) + (SDIOSUSPEND_BitNumber * 4)) + +/* Alias word address of ENCMDCOMPL bit */ +#define ENCMDCOMPL_BitNumber 0x0C +#define CMD_ENCMDCOMPL_BB (PERIPH_BB_BASE + (CMD_OFFSET * 32) + (ENCMDCOMPL_BitNumber * 4)) + +/* Alias word address of NIEN bit */ +#define NIEN_BitNumber 0x0D +#define CMD_NIEN_BB (PERIPH_BB_BASE + (CMD_OFFSET * 32) + (NIEN_BitNumber * 4)) + +/* Alias word address of ATACMD bit */ +#define ATACMD_BitNumber 0x0E +#define CMD_ATACMD_BB (PERIPH_BB_BASE + (CMD_OFFSET * 32) + (ATACMD_BitNumber * 4)) + +/* --- DCTRL Register ---*/ + +/* Alias word address of DMAEN bit */ +#define DCTRL_OFFSET (SDIO_OFFSET + 0x2C) +#define DMAEN_BitNumber 0x03 +#define DCTRL_DMAEN_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (DMAEN_BitNumber * 4)) + +/* Alias word address of RWSTART bit */ +#define RWSTART_BitNumber 0x08 +#define DCTRL_RWSTART_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (RWSTART_BitNumber * 4)) + +/* Alias word address of RWSTOP bit */ +#define RWSTOP_BitNumber 0x09 +#define DCTRL_RWSTOP_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (RWSTOP_BitNumber * 4)) + +/* Alias word address of RWMOD bit */ +#define RWMOD_BitNumber 0x0A +#define DCTRL_RWMOD_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (RWMOD_BitNumber * 4)) + +/* Alias word address of SDIOEN bit */ +#define SDIOEN_BitNumber 0x0B +#define DCTRL_SDIOEN_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (SDIOEN_BitNumber * 4)) + +/* ---------------------- SDIO registers bit mask ------------------------ */ + +/* --- CLKCR Register ---*/ + +/* CLKCR register clear mask */ +#define CLKCR_CLEAR_MASK ((uint32_t)0xFFFF8100) + +/* --- PWRCTRL Register ---*/ + +/* SDIO PWRCTRL Mask */ +#define PWR_PWRCTRL_MASK ((uint32_t)0xFFFFFFFC) + +/* --- DCTRL Register ---*/ + +/* SDIO DCTRL Clear Mask */ +#define DCTRL_CLEAR_MASK ((uint32_t)0xFFFFFF08) + +/* --- CMD Register ---*/ + +/* CMD Register clear mask */ +#define CMD_CLEAR_MASK ((uint32_t)0xFFFFF800) + +/* SDIO RESP Registers Address */ +#define SDIO_RESP_ADDR ((uint32_t)(SDIO_BASE + 0x14)) + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/** @defgroup SDIO_Private_Functions + * @{ + */ + +/** @defgroup SDIO_Group1 Initialization and Configuration functions + * @brief Initialization and Configuration functions + * + @verbatim + ============================================================================== + ##### Initialization and Configuration functions ##### + ============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Deinitializes the SDIO peripheral registers to their default reset values. + * @param None + * @retval None + */ +void SDIO_DeInit(void) +{ + RCC_APB2PeriphResetCmd(RCC_APB2Periph_SDIO, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_SDIO, DISABLE); +} + +/** + * @brief Initializes the SDIO peripheral according to the specified + * parameters in the SDIO_InitStruct. + * @param SDIO_InitStruct : pointer to a SDIO_InitTypeDef structure + * that contains the configuration information for the SDIO peripheral. + * @retval None + */ +void SDIO_Init(SDIO_InitTypeDef* SDIO_InitStruct) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_SDIO_CLOCK_EDGE(SDIO_InitStruct->SDIO_ClockEdge)); + assert_param(IS_SDIO_CLOCK_BYPASS(SDIO_InitStruct->SDIO_ClockBypass)); + assert_param(IS_SDIO_CLOCK_POWER_SAVE(SDIO_InitStruct->SDIO_ClockPowerSave)); + assert_param(IS_SDIO_BUS_WIDE(SDIO_InitStruct->SDIO_BusWide)); + assert_param(IS_SDIO_HARDWARE_FLOW_CONTROL(SDIO_InitStruct->SDIO_HardwareFlowControl)); + +/*---------------------------- SDIO CLKCR Configuration ------------------------*/ + /* Get the SDIO CLKCR value */ + tmpreg = SDIO->CLKCR; + + /* Clear CLKDIV, PWRSAV, BYPASS, WIDBUS, NEGEDGE, HWFC_EN bits */ + tmpreg &= CLKCR_CLEAR_MASK; + + /* Set CLKDIV bits according to SDIO_ClockDiv value */ + /* Set PWRSAV bit according to SDIO_ClockPowerSave value */ + /* Set BYPASS bit according to SDIO_ClockBypass value */ + /* Set WIDBUS bits according to SDIO_BusWide value */ + /* Set NEGEDGE bits according to SDIO_ClockEdge value */ + /* Set HWFC_EN bits according to SDIO_HardwareFlowControl value */ + tmpreg |= (SDIO_InitStruct->SDIO_ClockDiv | SDIO_InitStruct->SDIO_ClockPowerSave | + SDIO_InitStruct->SDIO_ClockBypass | SDIO_InitStruct->SDIO_BusWide | + SDIO_InitStruct->SDIO_ClockEdge | SDIO_InitStruct->SDIO_HardwareFlowControl); + + /* Write to SDIO CLKCR */ + SDIO->CLKCR = tmpreg; +} + +/** + * @brief Fills each SDIO_InitStruct member with its default value. + * @param SDIO_InitStruct: pointer to an SDIO_InitTypeDef structure which + * will be initialized. + * @retval None + */ +void SDIO_StructInit(SDIO_InitTypeDef* SDIO_InitStruct) +{ + /* SDIO_InitStruct members default value */ + SDIO_InitStruct->SDIO_ClockDiv = 0x00; + SDIO_InitStruct->SDIO_ClockEdge = SDIO_ClockEdge_Rising; + SDIO_InitStruct->SDIO_ClockBypass = SDIO_ClockBypass_Disable; + SDIO_InitStruct->SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable; + SDIO_InitStruct->SDIO_BusWide = SDIO_BusWide_1b; + SDIO_InitStruct->SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_Disable; +} + +/** + * @brief Enables or disables the SDIO Clock. + * @param NewState: new state of the SDIO Clock. This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void SDIO_ClockCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) CLKCR_CLKEN_BB = (uint32_t)NewState; +} + +/** + * @brief Sets the power status of the controller. + * @param SDIO_PowerState: new state of the Power state. + * This parameter can be one of the following values: + * @arg SDIO_PowerState_OFF: SDIO Power OFF. + * @arg SDIO_PowerState_ON: SDIO Power ON. + * @retval None + */ +void SDIO_SetPowerState(uint32_t SDIO_PowerState) +{ + /* Check the parameters */ + assert_param(IS_SDIO_POWER_STATE(SDIO_PowerState)); + + SDIO->POWER = SDIO_PowerState; +} + +/** + * @brief Gets the power status of the controller. + * @param None + * @retval Power status of the controller. The returned value can + * be one of the following: + * - 0x00: Power OFF + * - 0x02: Power UP + * - 0x03: Power ON + */ +uint32_t SDIO_GetPowerState(void) +{ + return (SDIO->POWER & (~PWR_PWRCTRL_MASK)); +} + +/** + * @} + */ + +/** @defgroup SDIO_Group2 DMA transfers management functions + * @brief DMA transfers management functions + * + @verbatim + ============================================================================== + ##### DMA transfers management functions ##### + ============================================================================== + [..] This section provide functions allowing to program SDIO DMA transfer. + +@endverbatim + * @{ + */ + +/** + * @brief Enables or disables the SDIO DMA request. + * @param NewState: new state of the selected SDIO DMA request. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void SDIO_DMACmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) DCTRL_DMAEN_BB = (uint32_t)NewState; +} + +/** + * @} + */ + +/** @defgroup SDIO_Group3 Command path state machine (CPSM) management functions + * @brief Command path state machine (CPSM) management functions + * + @verbatim + ============================================================================== + ##### Command path state machine (CPSM) management functions ##### + ============================================================================== + [..] This section provide functions allowing to program and read the Command + path state machine (CPSM). + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the SDIO Command according to the specified + * parameters in the SDIO_CmdInitStruct and send the command. + * @param SDIO_CmdInitStruct : pointer to a SDIO_CmdInitTypeDef + * structure that contains the configuration information for the SDIO command. + * @retval None + */ +void SDIO_SendCommand(SDIO_CmdInitTypeDef *SDIO_CmdInitStruct) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_SDIO_CMD_INDEX(SDIO_CmdInitStruct->SDIO_CmdIndex)); + assert_param(IS_SDIO_RESPONSE(SDIO_CmdInitStruct->SDIO_Response)); + assert_param(IS_SDIO_WAIT(SDIO_CmdInitStruct->SDIO_Wait)); + assert_param(IS_SDIO_CPSM(SDIO_CmdInitStruct->SDIO_CPSM)); + +/*---------------------------- SDIO ARG Configuration ------------------------*/ + /* Set the SDIO Argument value */ + SDIO->ARG = SDIO_CmdInitStruct->SDIO_Argument; + +/*---------------------------- SDIO CMD Configuration ------------------------*/ + /* Get the SDIO CMD value */ + tmpreg = SDIO->CMD; + /* Clear CMDINDEX, WAITRESP, WAITINT, WAITPEND, CPSMEN bits */ + tmpreg &= CMD_CLEAR_MASK; + /* Set CMDINDEX bits according to SDIO_CmdIndex value */ + /* Set WAITRESP bits according to SDIO_Response value */ + /* Set WAITINT and WAITPEND bits according to SDIO_Wait value */ + /* Set CPSMEN bits according to SDIO_CPSM value */ + tmpreg |= (uint32_t)SDIO_CmdInitStruct->SDIO_CmdIndex | SDIO_CmdInitStruct->SDIO_Response + | SDIO_CmdInitStruct->SDIO_Wait | SDIO_CmdInitStruct->SDIO_CPSM; + + /* Write to SDIO CMD */ + SDIO->CMD = tmpreg; +} + +/** + * @brief Fills each SDIO_CmdInitStruct member with its default value. + * @param SDIO_CmdInitStruct: pointer to an SDIO_CmdInitTypeDef + * structure which will be initialized. + * @retval None + */ +void SDIO_CmdStructInit(SDIO_CmdInitTypeDef* SDIO_CmdInitStruct) +{ + /* SDIO_CmdInitStruct members default value */ + SDIO_CmdInitStruct->SDIO_Argument = 0x00; + SDIO_CmdInitStruct->SDIO_CmdIndex = 0x00; + SDIO_CmdInitStruct->SDIO_Response = SDIO_Response_No; + SDIO_CmdInitStruct->SDIO_Wait = SDIO_Wait_No; + SDIO_CmdInitStruct->SDIO_CPSM = SDIO_CPSM_Disable; +} + +/** + * @brief Returns command index of last command for which response received. + * @param None + * @retval Returns the command index of the last command response received. + */ +uint8_t SDIO_GetCommandResponse(void) +{ + return (uint8_t)(SDIO->RESPCMD); +} + +/** + * @brief Returns response received from the card for the last command. + * @param SDIO_RESP: Specifies the SDIO response register. + * This parameter can be one of the following values: + * @arg SDIO_RESP1: Response Register 1. + * @arg SDIO_RESP2: Response Register 2. + * @arg SDIO_RESP3: Response Register 3. + * @arg SDIO_RESP4: Response Register 4. + * @retval The Corresponding response register value. + */ +uint32_t SDIO_GetResponse(uint32_t SDIO_RESP) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_SDIO_RESP(SDIO_RESP)); + + tmp = SDIO_RESP_ADDR + SDIO_RESP; + + return (*(__IO uint32_t *) tmp); +} + +/** + * @} + */ + +/** @defgroup SDIO_Group4 Data path state machine (DPSM) management functions + * @brief Data path state machine (DPSM) management functions + * + @verbatim + ============================================================================== + ##### Data path state machine (DPSM) management functions ##### + ============================================================================== + [..] This section provide functions allowing to program and read the Data path + state machine (DPSM). + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the SDIO data path according to the specified + * parameters in the SDIO_DataInitStruct. + * @param SDIO_DataInitStruct : pointer to a SDIO_DataInitTypeDef structure that + * contains the configuration information for the SDIO command. + * @retval None + */ +void SDIO_DataConfig(SDIO_DataInitTypeDef* SDIO_DataInitStruct) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_SDIO_DATA_LENGTH(SDIO_DataInitStruct->SDIO_DataLength)); + assert_param(IS_SDIO_BLOCK_SIZE(SDIO_DataInitStruct->SDIO_DataBlockSize)); + assert_param(IS_SDIO_TRANSFER_DIR(SDIO_DataInitStruct->SDIO_TransferDir)); + assert_param(IS_SDIO_TRANSFER_MODE(SDIO_DataInitStruct->SDIO_TransferMode)); + assert_param(IS_SDIO_DPSM(SDIO_DataInitStruct->SDIO_DPSM)); + +/*---------------------------- SDIO DTIMER Configuration ---------------------*/ + /* Set the SDIO Data TimeOut value */ + SDIO->DTIMER = SDIO_DataInitStruct->SDIO_DataTimeOut; + +/*---------------------------- SDIO DLEN Configuration -----------------------*/ + /* Set the SDIO DataLength value */ + SDIO->DLEN = SDIO_DataInitStruct->SDIO_DataLength; + +/*---------------------------- SDIO DCTRL Configuration ----------------------*/ + /* Get the SDIO DCTRL value */ + tmpreg = SDIO->DCTRL; + /* Clear DEN, DTMODE, DTDIR and DBCKSIZE bits */ + tmpreg &= DCTRL_CLEAR_MASK; + /* Set DEN bit according to SDIO_DPSM value */ + /* Set DTMODE bit according to SDIO_TransferMode value */ + /* Set DTDIR bit according to SDIO_TransferDir value */ + /* Set DBCKSIZE bits according to SDIO_DataBlockSize value */ + tmpreg |= (uint32_t)SDIO_DataInitStruct->SDIO_DataBlockSize | SDIO_DataInitStruct->SDIO_TransferDir + | SDIO_DataInitStruct->SDIO_TransferMode | SDIO_DataInitStruct->SDIO_DPSM; + + /* Write to SDIO DCTRL */ + SDIO->DCTRL = tmpreg; +} + +/** + * @brief Fills each SDIO_DataInitStruct member with its default value. + * @param SDIO_DataInitStruct: pointer to an SDIO_DataInitTypeDef structure which + * will be initialized. + * @retval None + */ +void SDIO_DataStructInit(SDIO_DataInitTypeDef* SDIO_DataInitStruct) +{ + /* SDIO_DataInitStruct members default value */ + SDIO_DataInitStruct->SDIO_DataTimeOut = 0xFFFFFFFF; + SDIO_DataInitStruct->SDIO_DataLength = 0x00; + SDIO_DataInitStruct->SDIO_DataBlockSize = SDIO_DataBlockSize_1b; + SDIO_DataInitStruct->SDIO_TransferDir = SDIO_TransferDir_ToCard; + SDIO_DataInitStruct->SDIO_TransferMode = SDIO_TransferMode_Block; + SDIO_DataInitStruct->SDIO_DPSM = SDIO_DPSM_Disable; +} + +/** + * @brief Returns number of remaining data bytes to be transferred. + * @param None + * @retval Number of remaining data bytes to be transferred + */ +uint32_t SDIO_GetDataCounter(void) +{ + return SDIO->DCOUNT; +} + +/** + * @brief Read one data word from Rx FIFO. + * @param None + * @retval Data received + */ +uint32_t SDIO_ReadData(void) +{ + return SDIO->FIFO; +} + +/** + * @brief Write one data word to Tx FIFO. + * @param Data: 32-bit data word to write. + * @retval None + */ +void SDIO_WriteData(uint32_t Data) +{ + SDIO->FIFO = Data; +} + +/** + * @brief Returns the number of words left to be written to or read from FIFO. + * @param None + * @retval Remaining number of words. + */ +uint32_t SDIO_GetFIFOCount(void) +{ + return SDIO->FIFOCNT; +} + +/** + * @} + */ + +/** @defgroup SDIO_Group5 SDIO IO Cards mode management functions + * @brief SDIO IO Cards mode management functions + * + @verbatim + ============================================================================== + ##### SDIO IO Cards mode management functions ##### + ============================================================================== + [..] This section provide functions allowing to program and read the SDIO IO + Cards. + +@endverbatim + * @{ + */ + +/** + * @brief Starts the SD I/O Read Wait operation. + * @param NewState: new state of the Start SDIO Read Wait operation. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void SDIO_StartSDIOReadWait(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) DCTRL_RWSTART_BB = (uint32_t) NewState; +} + +/** + * @brief Stops the SD I/O Read Wait operation. + * @param NewState: new state of the Stop SDIO Read Wait operation. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void SDIO_StopSDIOReadWait(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) DCTRL_RWSTOP_BB = (uint32_t) NewState; +} + +/** + * @brief Sets one of the two options of inserting read wait interval. + * @param SDIO_ReadWaitMode: SD I/O Read Wait operation mode. + * This parametre can be: + * @arg SDIO_ReadWaitMode_CLK: Read Wait control by stopping SDIOCLK. + * @arg SDIO_ReadWaitMode_DATA2: Read Wait control using SDIO_DATA2. + * @retval None + */ +void SDIO_SetSDIOReadWaitMode(uint32_t SDIO_ReadWaitMode) +{ + /* Check the parameters */ + assert_param(IS_SDIO_READWAIT_MODE(SDIO_ReadWaitMode)); + + *(__IO uint32_t *) DCTRL_RWMOD_BB = SDIO_ReadWaitMode; +} + +/** + * @brief Enables or disables the SD I/O Mode Operation. + * @param NewState: new state of SDIO specific operation. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void SDIO_SetSDIOOperation(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) DCTRL_SDIOEN_BB = (uint32_t)NewState; +} + +/** + * @brief Enables or disables the SD I/O Mode suspend command sending. + * @param NewState: new state of the SD I/O Mode suspend command. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void SDIO_SendSDIOSuspendCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) CMD_SDIOSUSPEND_BB = (uint32_t)NewState; +} + +/** + * @} + */ + +/** @defgroup SDIO_Group6 CE-ATA mode management functions + * @brief CE-ATA mode management functions + * + @verbatim + ============================================================================== + ##### CE-ATA mode management functions ##### + ============================================================================== + [..] This section provide functions allowing to program and read the CE-ATA + card. + +@endverbatim + * @{ + */ + +/** + * @brief Enables or disables the command completion signal. + * @param NewState: new state of command completion signal. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void SDIO_CommandCompletionCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) CMD_ENCMDCOMPL_BB = (uint32_t)NewState; +} + +/** + * @brief Enables or disables the CE-ATA interrupt. + * @param NewState: new state of CE-ATA interrupt. This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void SDIO_CEATAITCmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) CMD_NIEN_BB = (uint32_t)((~((uint32_t)NewState)) & ((uint32_t)0x1)); +} + +/** + * @brief Sends CE-ATA command (CMD61). + * @param NewState: new state of CE-ATA command. This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void SDIO_SendCEATACmd(FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + *(__IO uint32_t *) CMD_ATACMD_BB = (uint32_t)NewState; +} + +/** + * @} + */ + +/** @defgroup SDIO_Group7 Interrupts and flags management functions + * @brief Interrupts and flags management functions + + + @verbatim + ============================================================================== + ##### Interrupts and flags management functions ##### + ============================================================================== + + @endverbatim + * @{ + */ + +/** + * @brief Enables or disables the SDIO interrupts. + * @param SDIO_IT: specifies the SDIO interrupt sources to be enabled or disabled. + * This parameter can be one or a combination of the following values: + * @arg SDIO_IT_CCRCFAIL: Command response received (CRC check failed) interrupt. + * @arg SDIO_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt. + * @arg SDIO_IT_CTIMEOUT: Command response timeout interrupt. + * @arg SDIO_IT_DTIMEOUT: Data timeout interrupt. + * @arg SDIO_IT_TXUNDERR: Transmit FIFO underrun error interrupt. + * @arg SDIO_IT_RXOVERR: Received FIFO overrun error interrupt. + * @arg SDIO_IT_CMDREND: Command response received (CRC check passed) interrupt. + * @arg SDIO_IT_CMDSENT: Command sent (no response required) interrupt. + * @arg SDIO_IT_DATAEND: Data end (data counter, SDIDCOUNT, is zero) interrupt. + * @arg SDIO_IT_STBITERR: Start bit not detected on all data signals in wide + * bus mode interrupt. + * @arg SDIO_IT_DBCKEND: Data block sent/received (CRC check passed) interrupt. + * @arg SDIO_IT_CMDACT: Command transfer in progress interrupt. + * @arg SDIO_IT_TXACT: Data transmit in progress interrupt. + * @arg SDIO_IT_RXACT: Data receive in progress interrupt. + * @arg SDIO_IT_TXFIFOHE: Transmit FIFO Half Empty interrupt. + * @arg SDIO_IT_RXFIFOHF: Receive FIFO Half Full interrupt. + * @arg SDIO_IT_TXFIFOF: Transmit FIFO full interrupt. + * @arg SDIO_IT_RXFIFOF: Receive FIFO full interrupt. + * @arg SDIO_IT_TXFIFOE: Transmit FIFO empty interrupt. + * @arg SDIO_IT_RXFIFOE: Receive FIFO empty interrupt. + * @arg SDIO_IT_TXDAVL: Data available in transmit FIFO interrupt. + * @arg SDIO_IT_RXDAVL: Data available in receive FIFO interrupt. + * @arg SDIO_IT_SDIOIT: SD I/O interrupt received interrupt. + * @arg SDIO_IT_CEATAEND: CE-ATA command completion signal received for CMD61 interrupt. + * @param NewState: new state of the specified SDIO interrupts. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void SDIO_ITConfig(uint32_t SDIO_IT, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_SDIO_IT(SDIO_IT)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the SDIO interrupts */ + SDIO->MASK |= SDIO_IT; + } + else + { + /* Disable the SDIO interrupts */ + SDIO->MASK &= ~SDIO_IT; + } +} + +/** + * @brief Checks whether the specified SDIO flag is set or not. + * @param SDIO_FLAG: specifies the flag to check. + * This parameter can be one of the following values: + * @arg SDIO_FLAG_CCRCFAIL: Command response received (CRC check failed). + * @arg SDIO_FLAG_DCRCFAIL: Data block sent/received (CRC check failed). + * @arg SDIO_FLAG_CTIMEOUT: Command response timeout. + * @arg SDIO_FLAG_DTIMEOUT: Data timeout. + * @arg SDIO_FLAG_TXUNDERR: Transmit FIFO underrun error. + * @arg SDIO_FLAG_RXOVERR: Received FIFO overrun error. + * @arg SDIO_FLAG_CMDREND: Command response received (CRC check passed). + * @arg SDIO_FLAG_CMDSENT: Command sent (no response required). + * @arg SDIO_FLAG_DATAEND: Data end (data counter, SDIDCOUNT, is zero). + * @arg SDIO_FLAG_STBITERR: Start bit not detected on all data signals in wide + * bus mode. + * @arg SDIO_FLAG_DBCKEND: Data block sent/received (CRC check passed). + * @arg SDIO_FLAG_CMDACT: Command transfer in progress. + * @arg SDIO_FLAG_TXACT: Data transmit in progress. + * @arg SDIO_FLAG_RXACT: Data receive in progress. + * @arg SDIO_FLAG_TXFIFOHE: Transmit FIFO Half Empty. + * @arg SDIO_FLAG_RXFIFOHF: Receive FIFO Half Full. + * @arg SDIO_FLAG_TXFIFOF: Transmit FIFO full. + * @arg SDIO_FLAG_RXFIFOF: Receive FIFO full. + * @arg SDIO_FLAG_TXFIFOE: Transmit FIFO empty. + * @arg SDIO_FLAG_RXFIFOE: Receive FIFO empty. + * @arg SDIO_FLAG_TXDAVL: Data available in transmit FIFO. + * @arg SDIO_FLAG_RXDAVL: Data available in receive FIFO. + * @arg SDIO_FLAG_SDIOIT: SD I/O interrupt received. + * @arg SDIO_FLAG_CEATAEND: CE-ATA command completion signal received for CMD61. + * @retval The new state of SDIO_FLAG (SET or RESET). + */ +FlagStatus SDIO_GetFlagStatus(uint32_t SDIO_FLAG) +{ + FlagStatus bitstatus = RESET; + + /* Check the parameters */ + assert_param(IS_SDIO_FLAG(SDIO_FLAG)); + + if ((SDIO->STA & SDIO_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the SDIO's pending flags. + * @param SDIO_FLAG: specifies the flag to clear. + * This parameter can be one or a combination of the following values: + * @arg SDIO_FLAG_CCRCFAIL: Command response received (CRC check failed). + * @arg SDIO_FLAG_DCRCFAIL: Data block sent/received (CRC check failed). + * @arg SDIO_FLAG_CTIMEOUT: Command response timeout. + * @arg SDIO_FLAG_DTIMEOUT: Data timeout. + * @arg SDIO_FLAG_TXUNDERR: Transmit FIFO underrun error. + * @arg SDIO_FLAG_RXOVERR: Received FIFO overrun error. + * @arg SDIO_FLAG_CMDREND: Command response received (CRC check passed). + * @arg SDIO_FLAG_CMDSENT: Command sent (no response required). + * @arg SDIO_FLAG_DATAEND: Data end (data counter, SDIDCOUNT, is zero). + * @arg SDIO_FLAG_STBITERR: Start bit not detected on all data signals in wide + * bus mode. + * @arg SDIO_FLAG_DBCKEND: Data block sent/received (CRC check passed). + * @arg SDIO_FLAG_SDIOIT: SD I/O interrupt received. + * @arg SDIO_FLAG_CEATAEND: CE-ATA command completion signal received for CMD61. + * @retval None + */ +void SDIO_ClearFlag(uint32_t SDIO_FLAG) +{ + /* Check the parameters */ + assert_param(IS_SDIO_CLEAR_FLAG(SDIO_FLAG)); + + SDIO->ICR = SDIO_FLAG; +} + +/** + * @brief Checks whether the specified SDIO interrupt has occurred or not. + * @param SDIO_IT: specifies the SDIO interrupt source to check. + * This parameter can be one of the following values: + * @arg SDIO_IT_CCRCFAIL: Command response received (CRC check failed) interrupt. + * @arg SDIO_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt. + * @arg SDIO_IT_CTIMEOUT: Command response timeout interrupt. + * @arg SDIO_IT_DTIMEOUT: Data timeout interrupt. + * @arg SDIO_IT_TXUNDERR: Transmit FIFO underrun error interrupt. + * @arg SDIO_IT_RXOVERR: Received FIFO overrun error interrupt. + * @arg SDIO_IT_CMDREND: Command response received (CRC check passed) interrupt. + * @arg SDIO_IT_CMDSENT: Command sent (no response required) interrupt. + * @arg SDIO_IT_DATAEND: Data end (data counter, SDIDCOUNT, is zero) interrupt. + * @arg SDIO_IT_STBITERR: Start bit not detected on all data signals in wide + * bus mode interrupt. + * @arg SDIO_IT_DBCKEND: Data block sent/received (CRC check passed) interrupt. + * @arg SDIO_IT_CMDACT: Command transfer in progress interrupt. + * @arg SDIO_IT_TXACT: Data transmit in progress interrupt. + * @arg SDIO_IT_RXACT: Data receive in progress interrupt. + * @arg SDIO_IT_TXFIFOHE: Transmit FIFO Half Empty interrupt. + * @arg SDIO_IT_RXFIFOHF: Receive FIFO Half Full interrupt. + * @arg SDIO_IT_TXFIFOF: Transmit FIFO full interrupt. + * @arg SDIO_IT_RXFIFOF: Receive FIFO full interrupt. + * @arg SDIO_IT_TXFIFOE: Transmit FIFO empty interrupt. + * @arg SDIO_IT_RXFIFOE: Receive FIFO empty interrupt. + * @arg SDIO_IT_TXDAVL: Data available in transmit FIFO interrupt. + * @arg SDIO_IT_RXDAVL: Data available in receive FIFO interrupt. + * @arg SDIO_IT_SDIOIT: SD I/O interrupt received interrupt. + * @arg SDIO_IT_CEATAEND: CE-ATA command completion signal received for CMD61 interrupt. + * @retval The new state of SDIO_IT (SET or RESET). + */ +ITStatus SDIO_GetITStatus(uint32_t SDIO_IT) +{ + ITStatus bitstatus = RESET; + + /* Check the parameters */ + assert_param(IS_SDIO_GET_IT(SDIO_IT)); + if ((SDIO->STA & SDIO_IT) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the SDIO's interrupt pending bits. + * @param SDIO_IT: specifies the interrupt pending bit to clear. + * This parameter can be one or a combination of the following values: + * @arg SDIO_IT_CCRCFAIL: Command response received (CRC check failed) interrupt. + * @arg SDIO_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt. + * @arg SDIO_IT_CTIMEOUT: Command response timeout interrupt. + * @arg SDIO_IT_DTIMEOUT: Data timeout interrupt. + * @arg SDIO_IT_TXUNDERR: Transmit FIFO underrun error interrupt. + * @arg SDIO_IT_RXOVERR: Received FIFO overrun error interrupt. + * @arg SDIO_IT_CMDREND: Command response received (CRC check passed) interrupt. + * @arg SDIO_IT_CMDSENT: Command sent (no response required) interrupt. + * @arg SDIO_IT_DATAEND: Data end (data counter, SDIDCOUNT, is zero) interrupt. + * @arg SDIO_IT_STBITERR: Start bit not detected on all data signals in wide + * bus mode interrupt. + * @arg SDIO_IT_SDIOIT: SD I/O interrupt received interrupt. + * @arg SDIO_IT_CEATAEND: CE-ATA command completion signal received for CMD61. + * @retval None + */ +void SDIO_ClearITPendingBit(uint32_t SDIO_IT) +{ + /* Check the parameters */ + assert_param(IS_SDIO_CLEAR_IT(SDIO_IT)); + + SDIO->ICR = SDIO_IT; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/thirdparty/STM32_USB-FS-Device_Lib_V4.0.0/Libraries/STM32L1xx_StdPeriph_Driver/src/stm32l1xx_tim.c b/thirdparty/STM32_USB-FS-Device_Lib_V4.0.0/Libraries/STM32L1xx_StdPeriph_Driver/src/stm32l1xx_tim.c new file mode 100644 index 0000000..334f2d8 --- /dev/null +++ b/thirdparty/STM32_USB-FS-Device_Lib_V4.0.0/Libraries/STM32L1xx_StdPeriph_Driver/src/stm32l1xx_tim.c @@ -0,0 +1,2843 @@ +/** + ****************************************************************************** + * @file stm32l1xx_tim.c + * @author MCD Application Team + * @version V1.1.1 + * @date 05-March-2012 + * @brief This file provides firmware functions to manage the following + * functionalities of the TIM peripheral: + * + TimeBase management + * + Output Compare management + * + Input Capture management + * + Interrupts, DMA and flags management + * + Clocks management + * + Synchronization management + * + Specific interface management + * + Specific remapping management + * +* @verbatim + + =============================================================================== + ##### How to use this driver ##### + =============================================================================== + [..] This driver provides functions to configure and program the TIM + of all STM32L1xx devices These functions are split in 8 groups: + (#) TIM TimeBase management: this group includes all needed functions + to configure the TM Timebase unit: + (++) Set/Get Prescaler. + (++) Set/Get Autoreload. + (++) Counter modes configuration. + (++) Set Clock division. + (++) Select the One Pulse mode. + (++) Update Request Configuration. + (++) Update Disable Configuration. + (++) Auto-Preload Configuration. + (++) Enable/Disable the counter. + + (#) TIM Output Compare management: this group includes all needed + functions to configure the Capture/Compare unit used in Output + compare mode: + (++) Configure each channel, independently, in Output Compare mode. + (++) Select the output compare modes. + (++) Select the Polarities of each channel. + (++) Set/Get the Capture/Compare register values. + (++) Select the Output Compare Fast mode. + (++) Select the Output Compare Forced mode. + (++) Output Compare-Preload Configuration. + (++) Clear Output Compare Reference. + (++) Select the OCREF Clear signal. + (++) Enable/Disable the Capture/Compare Channels. + + (#) TIM Input Capture management: this group includes all needed + functions to configure the Capture/Compare unit used in + Input Capture mode: + (++) Configure each channel in input capture mode. + (++) Configure Channel1/2 in PWM Input mode. + (++) Set the Input Capture Prescaler. + (++) Get the Capture/Compare values. + + (#) TIM interrupts, DMA and flags management. + (++) Enable/Disable interrupt sources. + (++) Get flags status. + (++) Clear flags/ Pending bits. + (++) Enable/Disable DMA requests. + (++) Configure DMA burst mode. + (++) Select CaptureCompare DMA request. + + (#) TIM clocks management: this group includes all needed functions + to configure the clock controller unit: + (++) Select internal/External clock. + (++) Select the external clock mode: ETR(Mode1/Mode2), TIx or ITRx. + + (#) TIM synchronization management: this group includes all needed. + functions to configure the Synchronization unit: + (++) Select Input Trigger. + (++) Select Output Trigger. + (++) Select Master Slave Mode. + (++) ETR Configuration when used as external trigger. + + (#) TIM specific interface management, this group includes all + needed functions to use the specific TIM interface: + (++) Encoder Interface Configuration. + (++) Select Hall Sensor. + + (#) TIM specific remapping management includes the Remapping + configuration of specific timers + +@endverbatim + + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2012 STMicroelectronics</center></h2> + * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32l1xx_tim.h" +#include "stm32l1xx_rcc.h" + +/** @addtogroup STM32L1xx_StdPeriph_Driver + * @{ + */ + +/** @defgroup TIM + * @brief TIM driver modules + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ + +/* ---------------------- TIM registers bit mask ------------------------ */ +#define SMCR_ETR_MASK ((uint16_t)0x00FF) +#define CCMR_OFFSET ((uint16_t)0x0018) +#define CCER_CCE_SET ((uint16_t)0x0001) + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ + +static void TI1_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection, + uint16_t TIM_ICFilter); +static void TI2_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection, + uint16_t TIM_ICFilter); +static void TI3_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection, + uint16_t TIM_ICFilter); +static void TI4_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection, + uint16_t TIM_ICFilter); +/* Private functions ---------------------------------------------------------*/ + +/** @defgroup TIM_Private_Functions + * @{ + */ + +/** @defgroup TIM_Group1 TimeBase management functions + * @brief TimeBase management functions + * +@verbatim + =============================================================================== + ##### TimeBase management functions ##### + =============================================================================== + + *** TIM Driver: how to use it in Timing(Time base) Mode *** + =============================================================================== + [..] To use the Timer in Timing(Time base) mode, the following steps are + mandatory: + (#) Enable TIM clock using + RCC_APBxPeriphClockCmd(RCC_APBxPeriph_TIMx, ENABLE) function. + (#) Fill the TIM_TimeBaseInitStruct with the desired parameters. + (#) Call TIM_TimeBaseInit(TIMx, &TIM_TimeBaseInitStruct) to configure + the Time Base unit with the corresponding configuration. + (#) Enable the NVIC if you need to generate the update interrupt. + (#) Enable the corresponding interrupt using the function + TIM_ITConfig(TIMx, TIM_IT_Update). + (#) Call the TIM_Cmd(ENABLE) function to enable the TIM counter. + [..] + (@) All other functions can be used seperatly to modify, if needed, + a specific feature of the Timer. + +@endverbatim + * @{ + */ + +/** + * @brief Deinitializes the TIMx peripheral registers to their default reset values. + * @param TIMx: where x can be 2 to 11 to select the TIM peripheral. + * @retval None + * + */ +void TIM_DeInit(TIM_TypeDef* TIMx) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + + if (TIMx == TIM2) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM2, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM2, DISABLE); + } + else if (TIMx == TIM3) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM3, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM3, DISABLE); + } + else if (TIMx == TIM4) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM4, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM4, DISABLE); + } + else if (TIMx == TIM5) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM5, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM5, DISABLE); + } + else if (TIMx == TIM6) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM6, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM6, DISABLE); + } + else if (TIMx == TIM7) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM7, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM7, DISABLE); + } + + else if (TIMx == TIM9) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM9, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM9, DISABLE); + } + else if (TIMx == TIM10) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM10, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM10, DISABLE); + } + else + { + if (TIMx == TIM11) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM11, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM11, DISABLE); + } + } + +} + +/** + * @brief Initializes the TIMx Time Base Unit peripheral according to + * the specified parameters in the TIM_TimeBaseInitStruct. + * @param TIMx: where x can be 2 to 11 to select the TIM peripheral. + * @param TIM_TimeBaseInitStruct: pointer to a TIM_TimeBaseInitTypeDef + * structure that contains the configuration information for + * the specified TIM peripheral. + * @retval None + */ +void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct) +{ + uint16_t tmpcr1 = 0; + + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + assert_param(IS_TIM_COUNTER_MODE(TIM_TimeBaseInitStruct->TIM_CounterMode)); + assert_param(IS_TIM_CKD_DIV(TIM_TimeBaseInitStruct->TIM_ClockDivision)); + + tmpcr1 = TIMx->CR1; + + if(((TIMx) == TIM2) || ((TIMx) == TIM3) || ((TIMx) == TIM4) || ((TIMx) == TIM5)) + { + /* Select the Counter Mode */ + tmpcr1 &= (uint16_t)(~((uint16_t)(TIM_CR1_DIR | TIM_CR1_CMS))); + tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_CounterMode; + } + + if(((TIMx) != TIM6) && ((TIMx) != TIM7)) + { + /* Set the clock division */ + tmpcr1 &= (uint16_t)(~((uint16_t)TIM_CR1_CKD)); + tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_ClockDivision; + } + + TIMx->CR1 = tmpcr1; + + /* Set the Autoreload value */ + TIMx->ARR = TIM_TimeBaseInitStruct->TIM_Period ; + + /* Set the Prescaler value */ + TIMx->PSC = TIM_TimeBaseInitStruct->TIM_Prescaler; + + /* Generate an update event to reload the Prescaler value immediatly */ + TIMx->EGR = TIM_PSCReloadMode_Immediate; +} + +/** + * @brief Fills each TIM_TimeBaseInitStruct member with its default value. + * @param TIM_TimeBaseInitStruct : pointer to a TIM_TimeBaseInitTypeDef + * structure which will be initialized. + * @retval None + */ +void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct) +{ + /* Set the default configuration */ + TIM_TimeBaseInitStruct->TIM_Period = 0xFFFFFFFF; + TIM_TimeBaseInitStruct->TIM_Prescaler = 0x0000; + TIM_TimeBaseInitStruct->TIM_ClockDivision = TIM_CKD_DIV1; + TIM_TimeBaseInitStruct->TIM_CounterMode = TIM_CounterMode_Up; +} + +/** + * @brief Configures the TIMx Prescaler. + * @param TIMx: where x can be 2 to 11 to select the TIM peripheral. + * @param Prescaler: specifies the Prescaler Register value. + * @param TIM_PSCReloadMode: specifies the TIM Prescaler Reload mode + * This parameter can be one of the following values: + * @arg TIM_PSCReloadMode_Update: The Prescaler is loaded at the update event. + * @arg TIM_PSCReloadMode_Immediate: The Prescaler is loaded immediatly. + * @retval None + */ +void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + assert_param(IS_TIM_PRESCALER_RELOAD(TIM_PSCReloadMode)); + + /* Set the Prescaler value */ + TIMx->PSC = Prescaler; + /* Set or reset the UG Bit */ + TIMx->EGR = TIM_PSCReloadMode; +} + +/** + * @brief Specifies the TIMx Counter Mode to be used. + * @param TIMx: where x can be 2, 3, 4 or 5 to select the TIM peripheral. + * @param TIM_CounterMode: specifies the Counter Mode to be used + * This parameter can be one of the following values: + * @arg TIM_CounterMode_Up: TIM Up Counting Mode. + * @arg TIM_CounterMode_Down: TIM Down Counting Mode. + * @arg TIM_CounterMode_CenterAligned1: TIM Center Aligned Mode1. + * @arg TIM_CounterMode_CenterAligned2: TIM Center Aligned Mode2. + * @arg TIM_CounterMode_CenterAligned3: TIM Center Aligned Mode3. + * @retval None + */ +void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode) +{ + uint16_t tmpcr1 = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_COUNTER_MODE(TIM_CounterMode)); + + tmpcr1 = TIMx->CR1; + /* Reset the CMS and DIR Bits */ + tmpcr1 &= (uint16_t)(~((uint16_t)(TIM_CR1_DIR | TIM_CR1_CMS))); + /* Set the Counter Mode */ + tmpcr1 |= TIM_CounterMode; + /* Write to TIMx CR1 register */ + TIMx->CR1 = tmpcr1; +} + +/** + * @brief Sets the TIMx Counter Register value + * @param TIMx: where x can be 2 to 11 to select the TIM peripheral. + * @param Counter: specifies the Counter register new value. + * @retval None + */ +void TIM_SetCounter(TIM_TypeDef* TIMx, uint32_t Counter) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + + /* Set the Counter Register value */ + TIMx->CNT = Counter; +} + +/** + * @brief Sets the TIMx Autoreload Register value + * @param TIMx: where x can be 2 to 11 to select the TIM peripheral. + * @param Autoreload: specifies the Autoreload register new value. + * @retval None + */ +void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint32_t Autoreload) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + + /* Set the Autoreload Register value */ + TIMx->ARR = Autoreload; +} + +/** + * @brief Gets the TIMx Counter value. + * @param TIMx: where x can be 2 to 11 to select the TIM peripheral. + * @retval Counter Register value. + */ +uint32_t TIM_GetCounter(TIM_TypeDef* TIMx) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + + /* Get the Counter Register value */ + return TIMx->CNT; +} + +/** + * @brief Gets the TIMx Prescaler value. + * @param TIMx: where x can be 2 to 11 to select the TIM peripheral. + * @retval Prescaler Register value. + */ +uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + + /* Get the Prescaler Register value */ + return TIMx->PSC; +} + +/** + * @brief Enables or Disables the TIMx Update event. + * @param TIMx: where x can be 2 to 11 to select the TIM peripheral. + * @param NewState: new state of the TIMx UDIS bit + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void TIM_UpdateDisableConfig(TIM_TypeDef* TIMx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Set the Update Disable Bit */ + TIMx->CR1 |= TIM_CR1_UDIS; + } + else + { + /* Reset the Update Disable Bit */ + TIMx->CR1 &= (uint16_t)~((uint16_t)TIM_CR1_UDIS); + } +} + +/** + * @brief Configures the TIMx Update Request Interrupt source. + * @param TIMx: where x can be 2 to 11 to select the TIM peripheral. + * @param TIM_UpdateSource: specifies the Update source. + * This parameter can be one of the following values: + * @arg TIM_UpdateSource_Global: Source of update is the counter overflow/underflow + or the setting of UG bit, or an update generation + through the slave mode controller. + * @arg TIM_UpdateSource_Regular: Source of update is counter overflow/underflow. + * @retval None + */ +void TIM_UpdateRequestConfig(TIM_TypeDef* TIMx, uint16_t TIM_UpdateSource) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + assert_param(IS_TIM_UPDATE_SOURCE(TIM_UpdateSource)); + + if (TIM_UpdateSource != TIM_UpdateSource_Global) + { + /* Set the URS Bit */ + TIMx->CR1 |= TIM_CR1_URS; + } + else + { + /* Reset the URS Bit */ + TIMx->CR1 &= (uint16_t)~((uint16_t)TIM_CR1_URS); + } +} + +/** + * @brief Enables or disables TIMx peripheral Preload register on ARR. + * @param TIMx: where x can be 2 to 11 to select the TIM peripheral. + * @param NewState: new state of the TIMx peripheral Preload register + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Set the ARR Preload Bit */ + TIMx->CR1 |= TIM_CR1_ARPE; + } + else + { + /* Reset the ARR Preload Bit */ + TIMx->CR1 &= (uint16_t)~((uint16_t)TIM_CR1_ARPE); + } +} + +/** + * @brief Selects the TIMx's One Pulse Mode. + * @param TIMx: where x can be 2 to 11 to select the TIM peripheral. + * @param TIM_OPMode: specifies the OPM Mode to be used. + * This parameter can be one of the following values: + * @arg TIM_OPMode_Single:: TIM One Pulse Single Mode (Counter stops counting + * at the next update event (clearing the bit CEN)). + * @arg TIM_OPMode_Repetitive: TIM One Pulse Repetitive Mode + * (Counter is not stopped at update event). + * @retval None + */ +void TIM_SelectOnePulseMode(TIM_TypeDef* TIMx, uint16_t TIM_OPMode) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + assert_param(IS_TIM_OPM_MODE(TIM_OPMode)); + + /* Reset the OPM Bit */ + TIMx->CR1 &= (uint16_t)~((uint16_t)TIM_CR1_OPM); + /* Configure the OPM Mode */ + TIMx->CR1 |= TIM_OPMode; +} + +/** + * @brief Sets the TIMx Clock Division value. + * @param TIMx: where x can be 2, 3, 4, 5, 9, 10 or 11 to select the TIM peripheral. + * @param TIM_CKD: specifies the clock division value. + * This parameter can be one of the following value: + * @arg TIM_CKD_DIV1: TDTS = Tck_tim. + * @arg TIM_CKD_DIV2: TDTS = 2*Tck_tim. + * @arg TIM_CKD_DIV4: TDTS = 4*Tck_tim. + * @retval None + */ +void TIM_SetClockDivision(TIM_TypeDef* TIMx, uint16_t TIM_CKD) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST1_PERIPH(TIMx)); + assert_param(IS_TIM_CKD_DIV(TIM_CKD)); + + /* Reset the CKD Bits */ + TIMx->CR1 &= (uint16_t)~((uint16_t)TIM_CR1_CKD); + /* Set the CKD value */ + TIMx->CR1 |= TIM_CKD; +} + +/** + * @brief Enables or disables the specified TIM peripheral. + * @param TIMx: where x can be 2 to 11 to select the TIMx peripheral. + * @param NewState: new state of the TIMx peripheral. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the TIM Counter */ + TIMx->CR1 |= TIM_CR1_CEN; + } + else + { + /* Disable the TIM Counter */ + TIMx->CR1 &= (uint16_t)(~((uint16_t)TIM_CR1_CEN)); + } +} + +/** + * @} + */ + +/** @defgroup TIM_Group2 Output Compare management functions + * @brief Output Compare management functions + * +@verbatim + =============================================================================== + ##### Output Compare management functions ##### + =============================================================================== + *** TIM Driver: how to use it in Output Compare Mode *** + =============================================================================== + [..] To use the Timer in Output Compare mode, the following steps are mandatory: + (#) Enable TIM clock using + RCC_APBxPeriphClockCmd(RCC_APBxPeriph_TIMx, ENABLE) function. + (#) Configure the TIM pins by configuring the corresponding GPIO pins + (#) Configure the Time base unit as described in the first part of this + driver, if needed, else the Timer will run with the default + configuration: + (++) Autoreload value = 0xFFFF. + (++) Prescaler value = 0x0000. + (++) Counter mode = Up counting. + (++) Clock Division = TIM_CKD_DIV1. + (#) Fill the TIM_OCInitStruct with the desired parameters including: + (++) The TIM Output Compare mode: TIM_OCMode. + (++) TIM Output State: TIM_OutputState. + (++) TIM Pulse value: TIM_Pulse. + (++) TIM Output Compare Polarity : TIM_OCPolarity. + (#) Call TIM_OCxInit(TIMx, &TIM_OCInitStruct) to configure the desired + channel with the corresponding configuration. + (#) Call the TIM_Cmd(ENABLE) function to enable the TIM counter. + [..] + (@) All other functions can be used separately to modify, if needed, + a specific feature of the Timer. + (@) In case of PWM mode, this function is mandatory: + TIM_OCxPreloadConfig(TIMx, TIM_OCPreload_ENABLE). + (@) If the corresponding interrupt or DMA request are needed, the user should: + (#@) Enable the NVIC (or the DMA) to use the TIM interrupts (or DMA requests). + (#@) Enable the corresponding interrupt (or DMA request) using the function + TIM_ITConfig(TIMx, TIM_IT_CCx) (or TIM_DMA_Cmd(TIMx, TIM_DMA_CCx)). + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the TIMx Channel1 according to the specified + * parameters in the TIM_OCInitStruct. + * @param TIMx: where x can be 2, 3, 4, 5, 9, 10 or 11 to select the TIM peripheral. + * @param TIM_OCInitStruct: pointer to a TIM_OCInitTypeDef structure + * that contains the configuration information for the specified TIM + * peripheral. + * @retval None + */ +void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct) +{ + uint16_t tmpccmrx = 0, tmpccer = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST1_PERIPH(TIMx)); + assert_param(IS_TIM_OC_MODE(TIM_OCInitStruct->TIM_OCMode)); + assert_param(IS_TIM_OUTPUT_STATE(TIM_OCInitStruct->TIM_OutputState)); + assert_param(IS_TIM_OC_POLARITY(TIM_OCInitStruct->TIM_OCPolarity)); + /* Disable the Channel 1: Reset the CC1E Bit */ + TIMx->CCER &= (uint16_t)(~(uint16_t)TIM_CCER_CC1E); + + /* Get the TIMx CCER register value */ + tmpccer = TIMx->CCER; + + /* Get the TIMx CCMR1 register value */ + tmpccmrx = TIMx->CCMR1; + + /* Reset the Output Compare Mode Bits */ + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR1_OC1M)); + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR1_CC1S)); + + /* Select the Output Compare Mode */ + tmpccmrx |= TIM_OCInitStruct->TIM_OCMode; + + /* Reset the Output Polarity level */ + tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC1P)); + /* Set the Output Compare Polarity */ + tmpccer |= TIM_OCInitStruct->TIM_OCPolarity; + + /* Set the Output State */ + tmpccer |= TIM_OCInitStruct->TIM_OutputState; + + /* Set the Capture Compare Register value */ + TIMx->CCR1 = TIM_OCInitStruct->TIM_Pulse; + + /* Write to TIMx CCMR1 */ + TIMx->CCMR1 = tmpccmrx; + + /* Write to TIMx CCER */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Initializes the TIMx Channel2 according to the specified + * parameters in the TIM_OCInitStruct. + * @param TIMx: where x can be 2, 3, 4, 5 or 9 to select the TIM peripheral. + * @param TIM_OCInitStruct: pointer to a TIM_OCInitTypeDef structure + * that contains the configuration information for the specified TIM + * peripheral. + * @retval None + */ +void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct) +{ + uint16_t tmpccmrx = 0, tmpccer = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST2_PERIPH(TIMx)); + assert_param(IS_TIM_OC_MODE(TIM_OCInitStruct->TIM_OCMode)); + assert_param(IS_TIM_OUTPUT_STATE(TIM_OCInitStruct->TIM_OutputState)); + assert_param(IS_TIM_OC_POLARITY(TIM_OCInitStruct->TIM_OCPolarity)); + /* Disable the Channel 2: Reset the CC2E Bit */ + TIMx->CCER &= (uint16_t)(~((uint16_t)TIM_CCER_CC2E)); + + /* Get the TIMx CCER register value */ + tmpccer = TIMx->CCER; + + /* Get the TIMx CCMR1 register value */ + tmpccmrx = TIMx->CCMR1; + + /* Reset the Output Compare Mode Bits */ + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR1_OC2M)); + + /* Select the Output Compare Mode */ + tmpccmrx |= (uint16_t)(TIM_OCInitStruct->TIM_OCMode << 8); + + /* Reset the Output Polarity level */ + tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC2P)); + /* Set the Output Compare Polarity */ + tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OCPolarity << 4); + + /* Set the Output State */ + tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OutputState << 4); + + /* Set the Capture Compare Register value */ + TIMx->CCR2 = TIM_OCInitStruct->TIM_Pulse; + + /* Write to TIMx CCMR1 */ + TIMx->CCMR1 = tmpccmrx; + + /* Write to TIMx CCER */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Initializes the TIMx Channel3 according to the specified + * parameters in the TIM_OCInitStruct. + * @param TIMx: where x can be 2, 3, 4 or 5 to select the TIM peripheral. + * @param TIM_OCInitStruct: pointer to a TIM_OCInitTypeDef structure + * that contains the configuration information for the specified TIM + * peripheral. + * @retval None + */ +void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct) +{ + uint16_t tmpccmrx = 0, tmpccer = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_OC_MODE(TIM_OCInitStruct->TIM_OCMode)); + assert_param(IS_TIM_OUTPUT_STATE(TIM_OCInitStruct->TIM_OutputState)); + assert_param(IS_TIM_OC_POLARITY(TIM_OCInitStruct->TIM_OCPolarity)); + + /* Disable the Channel 2: Reset the CC2E Bit */ + TIMx->CCER &= (uint16_t)(~((uint16_t)TIM_CCER_CC3E)); + + /* Get the TIMx CCER register value */ + tmpccer = TIMx->CCER; + + /* Get the TIMx CCMR2 register value */ + tmpccmrx = TIMx->CCMR2; + + /* Reset the Output Compare Mode Bits */ + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR2_OC3M)); + + /* Select the Output Compare Mode */ + tmpccmrx |= TIM_OCInitStruct->TIM_OCMode; + + /* Reset the Output Polarity level */ + tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC3P)); + /* Set the Output Compare Polarity */ + tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OCPolarity << 8); + + /* Set the Output State */ + tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OutputState << 8); + + /* Set the Capture Compare Register value */ + TIMx->CCR3 = TIM_OCInitStruct->TIM_Pulse; + + /* Write to TIMx CCMR2 */ + TIMx->CCMR2 = tmpccmrx; + + /* Write to TIMx CCER */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Initializes the TIMx Channel4 according to the specified + * parameters in the TIM_OCInitStruct. + * @param TIMx: where x can be 2, 3, 4 or 5 to select the TIM peripheral. + * @param TIM_OCInitStruct: pointer to a TIM_OCInitTypeDef structure + * that contains the configuration information for the specified TIM + * peripheral. + * @retval None + */ +void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct) +{ + uint16_t tmpccmrx = 0, tmpccer = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_OC_MODE(TIM_OCInitStruct->TIM_OCMode)); + assert_param(IS_TIM_OUTPUT_STATE(TIM_OCInitStruct->TIM_OutputState)); + assert_param(IS_TIM_OC_POLARITY(TIM_OCInitStruct->TIM_OCPolarity)); + + /* Disable the Channel 2: Reset the CC4E Bit */ + TIMx->CCER &= (uint16_t)(~((uint16_t)TIM_CCER_CC4E)); + + /* Get the TIMx CCER register value */ + tmpccer = TIMx->CCER; + + /* Get the TIMx CCMR2 register value */ + tmpccmrx = TIMx->CCMR2; + + /* Reset the Output Compare Mode Bits */ + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR2_OC4M)); + + /* Select the Output Compare Mode */ + tmpccmrx |= (uint16_t)(TIM_OCInitStruct->TIM_OCMode << 8); + + /* Reset the Output Polarity level */ + tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC4P)); + /* Set the Output Compare Polarity */ + tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OCPolarity << 12); + + /* Set the Output State */ + tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OutputState << 12); + + /* Set the Capture Compare Register value */ + TIMx->CCR4 = TIM_OCInitStruct->TIM_Pulse; + + /* Write to TIMx CCMR2 */ + TIMx->CCMR2 = tmpccmrx; + + /* Write to TIMx CCER */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Fills each TIM_OCInitStruct member with its default value. + * @param TIM_OCInitStruct : pointer to a TIM_OCInitTypeDef structure which will + * be initialized. + * @retval None + */ +void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct) +{ + /* Set the default configuration */ + TIM_OCInitStruct->TIM_OCMode = TIM_OCMode_Timing; + TIM_OCInitStruct->TIM_OutputState = TIM_OutputState_Disable; + TIM_OCInitStruct->TIM_Pulse = 0x0000; + TIM_OCInitStruct->TIM_OCPolarity = TIM_OCPolarity_High; +} + +/** + * @brief Selects the TIM Output Compare Mode. + * @note This function disables the selected channel before changing the Output + * Compare Mode. + * User has to enable this channel using TIM_CCxCmd and TIM_CCxNCmd functions. + * @param TIMx: where x can be 2, 3, 4, 5, 9, 10 or 11 to select the TIM peripheral. + * @param TIM_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. + * @arg TIM_Channel_4: TIM Channel 4. + * @param TIM_OCMode: specifies the TIM Output Compare Mode. + * This parameter can be one of the following values: + * @arg TIM_OCMode_Timing: TIM Output Compare Timing mode. + * @arg TIM_OCMode_Active: TIM Output Compare Active mode. + * @arg TIM_OCMode_Inactive: TIM Output Compare Inactive mode. + * @arg TIM_OCMode_Toggle: TIM Output Compare Toggle mode. + * @arg TIM_OCMode_PWM1: TIM Output Compare PWM1 mode. + * @arg TIM_OCMode_PWM2: TIM Output Compare PWM2 mode. + * @arg TIM_ForcedAction_Active: TIM Forced Action Active mode. + * @arg TIM_ForcedAction_InActive: TIM Forced Action Inactive mode. + * @retval None + */ +void TIM_SelectOCxM(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode) +{ + uint32_t tmp = 0; + uint16_t tmp1 = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST1_PERIPH(TIMx)); + assert_param(IS_TIM_OCM(TIM_OCMode)); + + tmp = (uint32_t) TIMx; + tmp += CCMR_OFFSET; + + tmp1 = CCER_CCE_SET << (uint16_t)TIM_Channel; + + /* Disable the Channel: Reset the CCxE Bit */ + TIMx->CCER &= (uint16_t) ~tmp1; + + if((TIM_Channel == TIM_Channel_1) ||(TIM_Channel == TIM_Channel_3)) + { + tmp += (TIM_Channel>>1); + + /* Reset the OCxM bits in the CCMRx register */ + *(__IO uint32_t *) tmp &= (uint32_t)~((uint32_t)TIM_CCMR1_OC1M); + + /* Configure the OCxM bits in the CCMRx register */ + *(__IO uint32_t *) tmp |= TIM_OCMode; + } + else + { + tmp += (uint16_t)(TIM_Channel - (uint16_t)4)>> (uint16_t)1; + + /* Reset the OCxM bits in the CCMRx register */ + *(__IO uint32_t *) tmp &= (uint32_t)~((uint32_t)TIM_CCMR1_OC2M); + + /* Configure the OCxM bits in the CCMRx register */ + *(__IO uint32_t *) tmp |= (uint16_t)(TIM_OCMode << 8); + } +} + +/** + * @brief Sets the TIMx Capture Compare1 Register value + * @param TIMx: where x can be 2, 3, 4, 5, 9, 10 or 11 to select the TIM peripheral. + * @param Compare1: specifies the Capture Compare1 register new value. + * @retval None + */ +void TIM_SetCompare1(TIM_TypeDef* TIMx, uint32_t Compare1) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST1_PERIPH(TIMx)); + + /* Set the Capture Compare1 Register value */ + TIMx->CCR1 = Compare1; +} + +/** + * @brief Sets the TIMx Capture Compare2 Register value. + * @param TIMx: where x can be 2, 3, 4, 5 or 9 to select the TIM peripheral. + * @param Compare2: specifies the Capture Compare2 register new value. + * @retval None + */ +void TIM_SetCompare2(TIM_TypeDef* TIMx, uint32_t Compare2) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST2_PERIPH(TIMx)); + + /* Set the Capture Compare2 Register value */ + TIMx->CCR2 = Compare2; +} + +/** + * @brief Sets the TIMx Capture Compare3 Register value. + * @param TIMx: where x can be 2, 3, 4 or 5 to select the TIM peripheral. + * @param Compare3: specifies the Capture Compare3 register new value. + * @retval None + */ +void TIM_SetCompare3(TIM_TypeDef* TIMx, uint32_t Compare3) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + + /* Set the Capture Compare3 Register value */ + TIMx->CCR3 = Compare3; +} + +/** + * @brief Sets the TIMx Capture Compare4 Register value. + * @param TIMx: where x can be 2, 3, 4 or 5 to select the TIM peripheral. + * @param Compare4: specifies the Capture Compare4 register new value. + * @retval None + */ +void TIM_SetCompare4(TIM_TypeDef* TIMx, uint32_t Compare4) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + + /* Set the Capture Compare4 Register value */ + TIMx->CCR4 = Compare4; +} + +/** + * @brief Forces the TIMx output 1 waveform to active or inactive level. + * @param TIMx: where x can be 2, 3, 4, 5, 9, 10 or 11 to select the TIM peripheral. + * @param TIM_ForcedAction: specifies the forced Action to be set to the output waveform. + * This parameter can be one of the following values: + * @arg TIM_ForcedAction_Active: Force active level on OC1REF. + * @arg TIM_ForcedAction_InActive: Force inactive level on OC1REF. + * @retval None + */ +void TIM_ForcedOC1Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction) +{ + uint16_t tmpccmr1 = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST1_PERIPH(TIMx)); + assert_param(IS_TIM_FORCED_ACTION(TIM_ForcedAction)); + tmpccmr1 = TIMx->CCMR1; + /* Reset the OC1M Bits */ + tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC1M); + /* Configure The Forced output Mode */ + tmpccmr1 |= TIM_ForcedAction; + /* Write to TIMx CCMR1 register */ + TIMx->CCMR1 = tmpccmr1; +} + +/** + * @brief Forces the TIMx output 2 waveform to active or inactive level. + * @param TIMx: where x can be 2, 3, 4, 5 or 9 to select the TIM + * peripheral. + * @param TIM_ForcedAction: specifies the forced Action to be set to the output waveform. + * This parameter can be one of the following values: + * @arg TIM_ForcedAction_Active: Force active level on OC2REF. + * @arg TIM_ForcedAction_InActive: Force inactive level on OC2REF. + * @retval None + */ +void TIM_ForcedOC2Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction) +{ + uint16_t tmpccmr1 = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST2_PERIPH(TIMx)); + assert_param(IS_TIM_FORCED_ACTION(TIM_ForcedAction)); + + tmpccmr1 = TIMx->CCMR1; + /* Reset the OC2M Bits */ + tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC2M); + /* Configure The Forced output Mode */ + tmpccmr1 |= (uint16_t)(TIM_ForcedAction << 8); + /* Write to TIMx CCMR1 register */ + TIMx->CCMR1 = tmpccmr1; +} + +/** + * @brief Forces the TIMx output 3 waveform to active or inactive level. + * @param TIMx: where x can be 2, 3, 4 or 5 to select the TIM peripheral. + * @param TIM_ForcedAction: specifies the forced Action to be set to the output waveform. + * This parameter can be one of the following values: + * @arg TIM_ForcedAction_Active: Force active level on OC3REF. + * @arg TIM_ForcedAction_InActive: Force inactive level on OC3REF. + * @retval None + */ +void TIM_ForcedOC3Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction) +{ + uint16_t tmpccmr2 = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_FORCED_ACTION(TIM_ForcedAction)); + + tmpccmr2 = TIMx->CCMR2; + /* Reset the OC1M Bits */ + tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC3M); + /* Configure The Forced output Mode */ + tmpccmr2 |= TIM_ForcedAction; + /* Write to TIMx CCMR2 register */ + TIMx->CCMR2 = tmpccmr2; +} + +/** + * @brief Forces the TIMx output 4 waveform to active or inactive level. + * @param TIMx: where x can be 2, 3, 4 or 5 to select the TIM peripheral. + * @param TIM_ForcedAction: specifies the forced Action to be set to the output waveform. + * This parameter can be one of the following values: + * @arg TIM_ForcedAction_Active: Force active level on OC4REF. + * @arg TIM_ForcedAction_InActive: Force inactive level on OC4REF. + * @retval None + */ +void TIM_ForcedOC4Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction) +{ + uint16_t tmpccmr2 = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_FORCED_ACTION(TIM_ForcedAction)); + + tmpccmr2 = TIMx->CCMR2; + /* Reset the OC2M Bits */ + tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC4M); + /* Configure The Forced output Mode */ + tmpccmr2 |= (uint16_t)(TIM_ForcedAction << 8); + /* Write to TIMx CCMR2 register */ + TIMx->CCMR2 = tmpccmr2; +} + +/** + * @brief Enables or disables the TIMx peripheral Preload register on CCR1. + * @param TIMx: where x can be 2, 3, 4, 5, 9, 10 or 11 to select the TIM peripheral. + * @param TIM_OCPreload: new state of the TIMx peripheral Preload register. + * This parameter can be one of the following values: + * @arg TIM_OCPreload_Enable: Enable TIM output compare Preload + * @arg TIM_OCPreload_Disable: Disable TIM output compare Preload + * @retval None + */ +void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload) +{ + uint16_t tmpccmr1 = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST1_PERIPH(TIMx)); + assert_param(IS_TIM_OCPRELOAD_STATE(TIM_OCPreload)); + + tmpccmr1 = TIMx->CCMR1; + /* Reset the OC1PE Bit */ + tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC1PE); + /* Enable or Disable the Output Compare Preload feature */ + tmpccmr1 |= TIM_OCPreload; + /* Write to TIMx CCMR1 register */ + TIMx->CCMR1 = tmpccmr1; +} + +/** + * @brief Enables or disables the TIMx peripheral Preload register on CCR2. + * @param TIMx: where x can be 2, 3, 4, 5 or 9 to select the TIM peripheral. + * @param TIM_OCPreload: new state of the TIMx peripheral Preload register. + * This parameter can be one of the following values: + * @arg TIM_OCPreload_Enable: Enable TIM output compare Preload + * @arg TIM_OCPreload_Disable: Disable TIM output compare Preload + * @retval None + */ +void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload) +{ + uint16_t tmpccmr1 = 0; + /* Check the parameters */ + assert_param(IS_TIM_LIST2_PERIPH(TIMx)); + assert_param(IS_TIM_OCPRELOAD_STATE(TIM_OCPreload)); + + tmpccmr1 = TIMx->CCMR1; + /* Reset the OC2PE Bit */ + tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC2PE); + /* Enable or Disable the Output Compare Preload feature */ + tmpccmr1 |= (uint16_t)(TIM_OCPreload << 8); + /* Write to TIMx CCMR1 register */ + TIMx->CCMR1 = tmpccmr1; +} + +/** + * @brief Enables or disables the TIMx peripheral Preload register on CCR3. + * @param TIMx: where x can be 2, 3, 4 or 5 to select the TIM peripheral. + * @param TIM_OCPreload: new state of the TIMx peripheral Preload register. + * This parameter can be one of the following values: + * @arg TIM_OCPreload_Enable: Enable TIM output compare Preload + * @arg TIM_OCPreload_Disable: Disable TIM output compare Preload + * @retval None + */ +void TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload) +{ + uint16_t tmpccmr2 = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_OCPRELOAD_STATE(TIM_OCPreload)); + + tmpccmr2 = TIMx->CCMR2; + /* Reset the OC3PE Bit */ + tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC3PE); + /* Enable or Disable the Output Compare Preload feature */ + tmpccmr2 |= TIM_OCPreload; + /* Write to TIMx CCMR2 register */ + TIMx->CCMR2 = tmpccmr2; +} + +/** + * @brief Enables or disables the TIMx peripheral Preload register on CCR4. + * @param TIMx: where x can be 2, 3, 4 or 5 to select the TIM peripheral. + * @param TIM_OCPreload: new state of the TIMx peripheral Preload register. + * This parameter can be one of the following values: + * @arg TIM_OCPreload_Enable: Enable TIM output compare Preload + * @arg TIM_OCPreload_Disable: Disable TIM output compare Preload + * @retval None + */ +void TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload) +{ + uint16_t tmpccmr2 = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_OCPRELOAD_STATE(TIM_OCPreload)); + + tmpccmr2 = TIMx->CCMR2; + /* Reset the OC4PE Bit */ + tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC4PE); + /* Enable or Disable the Output Compare Preload feature */ + tmpccmr2 |= (uint16_t)(TIM_OCPreload << 8); + /* Write to TIMx CCMR2 register */ + TIMx->CCMR2 = tmpccmr2; +} + +/** + * @brief Configures the TIMx Output Compare 1 Fast feature. + * @param TIMx: where x can be 2, 3, 4, 5, 9, 10 or 11 to select the TIM peripheral. + * @param TIM_OCFast: new state of the Output Compare Fast Enable Bit. + * This parameter can be one of the following values: + * @arg TIM_OCFast_Enable: TIM output compare fast enable. + * @arg TIM_OCFast_Disable: TIM output compare fast disable. + * @retval None + */ +void TIM_OC1FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast) +{ + uint16_t tmpccmr1 = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST1_PERIPH(TIMx)); + assert_param(IS_TIM_OCFAST_STATE(TIM_OCFast)); + + /* Get the TIMx CCMR1 register value */ + tmpccmr1 = TIMx->CCMR1; + /* Reset the OC1FE Bit */ + tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC1FE); + /* Enable or Disable the Output Compare Fast Bit */ + tmpccmr1 |= TIM_OCFast; + /* Write to TIMx CCMR1 */ + TIMx->CCMR1 = tmpccmr1; +} + +/** + * @brief Configures the TIMx Output Compare 2 Fast feature. + * @param TIMx: where x can be 2, 3, 4, 5 or 9 to select the TIM peripheral. + * @param TIM_OCFast: new state of the Output Compare Fast Enable Bit. + * This parameter can be one of the following values: + * @arg TIM_OCFast_Enable: TIM output compare fast enable. + * @arg TIM_OCFast_Disable: TIM output compare fast disable. + * @retval None + */ +void TIM_OC2FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast) +{ + uint16_t tmpccmr1 = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST2_PERIPH(TIMx)); + assert_param(IS_TIM_OCFAST_STATE(TIM_OCFast)); + + /* Get the TIMx CCMR1 register value */ + tmpccmr1 = TIMx->CCMR1; + /* Reset the OC2FE Bit */ + tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC2FE); + /* Enable or Disable the Output Compare Fast Bit */ + tmpccmr1 |= (uint16_t)(TIM_OCFast << 8); + /* Write to TIMx CCMR1 */ + TIMx->CCMR1 = tmpccmr1; +} + +/** + * @brief Configures the TIMx Output Compare 3 Fast feature. + * @param TIMx: where x can be 2, 3, 4 or 5 to select the TIM peripheral. + * @param TIM_OCFast: new state of the Output Compare Fast Enable Bit. + * This parameter can be one of the following values: + * @arg TIM_OCFast_Enable: TIM output compare fast enable. + * @arg TIM_OCFast_Disable: TIM output compare fast disable. + * @retval None + */ +void TIM_OC3FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast) +{ + uint16_t tmpccmr2 = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_OCFAST_STATE(TIM_OCFast)); + + /* Get the TIMx CCMR2 register value */ + tmpccmr2 = TIMx->CCMR2; + /* Reset the OC3FE Bit */ + tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC3FE); + /* Enable or Disable the Output Compare Fast Bit */ + tmpccmr2 |= TIM_OCFast; + /* Write to TIMx CCMR2 */ + TIMx->CCMR2 = tmpccmr2; +} + +/** + * @brief Configures the TIMx Output Compare 4 Fast feature. + * @param TIMx: where x can be 2, 3, 4 or 5 to select the TIM peripheral. + * @param TIM_OCFast: new state of the Output Compare Fast Enable Bit. + * This parameter can be one of the following values: + * @arg TIM_OCFast_Enable: TIM output compare fast enable. + * @arg TIM_OCFast_Disable: TIM output compare fast disable. + * @retval None + */ +void TIM_OC4FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast) +{ + uint16_t tmpccmr2 = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_OCFAST_STATE(TIM_OCFast)); + + /* Get the TIMx CCMR2 register value */ + tmpccmr2 = TIMx->CCMR2; + /* Reset the OC4FE Bit */ + tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC4FE); + /* Enable or Disable the Output Compare Fast Bit */ + tmpccmr2 |= (uint16_t)(TIM_OCFast << 8); + /* Write to TIMx CCMR2 */ + TIMx->CCMR2 = tmpccmr2; +} + +/** + * @brief Clears or safeguards the OCREF1 signal on an external event + * @param TIMx: where x can be 2, 3, 4, 5, 9, 10 or 11 to select the TIM peripheral. + * @param TIM_OCClear: new state of the Output Compare Clear Enable Bit. + * This parameter can be one of the following values: + * @arg TIM_OCClear_Enable: TIM Output clear enable. + * @arg TIM_OCClear_Disable: TIM Output clear disable. + * @retval None + */ +void TIM_ClearOC1Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear) +{ + uint16_t tmpccmr1 = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST1_PERIPH(TIMx)); + assert_param(IS_TIM_OCCLEAR_STATE(TIM_OCClear)); + + tmpccmr1 = TIMx->CCMR1; + /* Reset the OC1CE Bit */ + tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC1CE); + /* Enable or Disable the Output Compare Clear Bit */ + tmpccmr1 |= TIM_OCClear; + /* Write to TIMx CCMR1 register */ + TIMx->CCMR1 = tmpccmr1; +} + +/** + * @brief Clears or safeguards the OCREF2 signal on an external event + * @param TIMx: where x can be 2, 3, 4, 5 or 9 to select the TIM peripheral. + * @param TIM_OCClear: new state of the Output Compare Clear Enable Bit. + + * This parameter can be one of the following values: + * @arg TIM_OCClear_Enable: TIM Output clear enable. + * @arg TIM_OCClear_Disable: TIM Output clear disable . + * @retval None + */ +void TIM_ClearOC2Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear) +{ + uint16_t tmpccmr1 = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST2_PERIPH(TIMx)); + assert_param(IS_TIM_OCCLEAR_STATE(TIM_OCClear)); + + tmpccmr1 = TIMx->CCMR1; + /* Reset the OC2CE Bit */ + tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC2CE); + /* Enable or Disable the Output Compare Clear Bit */ + tmpccmr1 |= (uint16_t)(TIM_OCClear << 8); + /* Write to TIMx CCMR1 register */ + TIMx->CCMR1 = tmpccmr1; +} + +/** + * @brief Clears or safeguards the OCREF3 signal on an external event + * @param TIMx: where x can be 2, 3, 4 or 5 to select the TIM peripheral. + * @param TIM_OCClear: new state of the Output Compare Clear Enable Bit. + * This parameter can be one of the following values: + * @arg TIM_OCClear_Enable: TIM Output clear enable. + * @arg TIM_OCClear_Disable: TIM Output clear disable. + * @retval None + */ +void TIM_ClearOC3Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear) +{ + uint16_t tmpccmr2 = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_OCCLEAR_STATE(TIM_OCClear)); + + tmpccmr2 = TIMx->CCMR2; + /* Reset the OC3CE Bit */ + tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC3CE); + /* Enable or Disable the Output Compare Clear Bit */ + tmpccmr2 |= TIM_OCClear; + /* Write to TIMx CCMR2 register */ + TIMx->CCMR2 = tmpccmr2; +} + +/** + * @brief Clears or safeguards the OCREF4 signal on an external event + * @param TIMx: where x can be 2, 3, 4 or 5 to select the TIM peripheral. + * @param TIM_OCClear: new state of the Output Compare Clear Enable Bit. + * This parameter can be one of the following values: + * @arg TIM_OCClear_Enable: TIM Output clear enable. + * @arg TIM_OCClear_Disable: TIM Output clear disable. + * @retval None + */ +void TIM_ClearOC4Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear) +{ + uint16_t tmpccmr2 = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_OCCLEAR_STATE(TIM_OCClear)); + + tmpccmr2 = TIMx->CCMR2; + /* Reset the OC4CE Bit */ + tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC4CE); + /* Enable or Disable the Output Compare Clear Bit */ + tmpccmr2 |= (uint16_t)(TIM_OCClear << 8); + /* Write to TIMx CCMR2 register */ + TIMx->CCMR2 = tmpccmr2; +} + +/** + * @brief Configures the TIMx channel 1 polarity. + * @param TIMx: where x can be 2, 3, 4, 5, 9, 10 or 11 to select the TIM peripheral. + * @param TIM_OCPolarity: specifies the OC1 Polarity. + * This parameter can be one of the following values: + * @arg TIM_OCPolarity_High: Output Compare active high. + * @arg TIM_OCPolarity_Low: Output Compare active low. + * @retval None + */ +void TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity) +{ + uint16_t tmpccer = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST1_PERIPH(TIMx)); + assert_param(IS_TIM_OC_POLARITY(TIM_OCPolarity)); + + tmpccer = TIMx->CCER; + /* Set or Reset the CC1P Bit */ + tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC1P); + tmpccer |= TIM_OCPolarity; + /* Write to TIMx CCER register */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Configures the TIMx channel 2 polarity. + * @param TIMx: where x can be 2, 3, 4, 5 or 9 to select the TIM peripheral. + * @param TIM_OCPolarity: specifies the OC2 Polarity. + * This parameter can be one of the following values: + * @arg TIM_OCPolarity_High: Output Compare active high. + * @arg TIM_OCPolarity_Low: Output Compare active low. + * @retval None + */ +void TIM_OC2PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity) +{ + uint16_t tmpccer = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST2_PERIPH(TIMx)); + assert_param(IS_TIM_OC_POLARITY(TIM_OCPolarity)); + + tmpccer = TIMx->CCER; + /* Set or Reset the CC2P Bit */ + tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC2P); + tmpccer |= (uint16_t)(TIM_OCPolarity << 4); + /* Write to TIMx CCER register */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Configures the TIMx channel 3 polarity. + * @param TIMx: where x can be 2, 3, 4 or 5 to select the TIM peripheral. + * @param TIM_OCPolarity: specifies the OC3 Polarity. + * This parameter can be one of the following values: + * @arg TIM_OCPolarity_High: Output Compare active high. + * @arg TIM_OCPolarity_Low: Output Compare active low. + * @retval None + */ +void TIM_OC3PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity) +{ + uint16_t tmpccer = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_OC_POLARITY(TIM_OCPolarity)); + + tmpccer = TIMx->CCER; + /* Set or Reset the CC3P Bit */ + tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC3P); + tmpccer |= (uint16_t)(TIM_OCPolarity << 8); + /* Write to TIMx CCER register */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Configures the TIMx channel 4 polarity. + * @param TIMx: where x can be 2, 3, 4 or 5 to select the TIM peripheral. + * @param TIM_OCPolarity: specifies the OC4 Polarity. + * This parameter can be one of the following values: + * @arg TIM_OCPolarity_High: Output Compare active high. + * @arg TIM_OCPolarity_Low: Output Compare active low. + * @retval None + */ +void TIM_OC4PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity) +{ + uint16_t tmpccer = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_OC_POLARITY(TIM_OCPolarity)); + + tmpccer = TIMx->CCER; + /* Set or Reset the CC4P Bit */ + tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC4P); + tmpccer |= (uint16_t)(TIM_OCPolarity << 12); + /* Write to TIMx CCER register */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Selects the OCReference Clear source. + * @param TIMx: where x can be 2, 3, 4 or 5 to select the TIM peripheral. + * @param TIM_OCReferenceClear: specifies the OCReference Clear source. + * This parameter can be one of the following values: + * @arg TIM_OCReferenceClear_ETRF: The internal OCreference clear input is connected to ETRF. + * @arg TIM_OCReferenceClear_OCREFCLR: The internal OCreference clear input is connected to OCREF_CLR input. + * @retval None + */ +void TIM_SelectOCREFClear(TIM_TypeDef* TIMx, uint16_t TIM_OCReferenceClear) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(TIM_OCREFERENCECECLEAR_SOURCE(TIM_OCReferenceClear)); + + /* Set the TIM_OCReferenceClear source */ + TIMx->SMCR &= (uint16_t)~((uint16_t)TIM_SMCR_OCCS); + TIMx->SMCR |= TIM_OCReferenceClear; +} + +/** + * @brief Enables or disables the TIM Capture Compare Channel x. + * @param TIMx: where x can be 2, 3, 4, 5, 9, 10 or 11 to select the TIM peripheral. + * @param TIM_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. + * @arg TIM_Channel_4: TIM Channel 4. + * @param TIM_CCx: specifies the TIM Channel CCxE bit new state. + * This parameter can be: TIM_CCx_Enable or TIM_CCx_Disable. + * @retval None + */ +void TIM_CCxCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCx) +{ + uint16_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST1_PERIPH(TIMx)); + assert_param(IS_TIM_CCX(TIM_CCx)); + + tmp = CCER_CCE_SET << TIM_Channel; + + /* Reset the CCxE Bit */ + TIMx->CCER &= (uint16_t)~ tmp; + + /* Set or reset the CCxE Bit */ + TIMx->CCER |= (uint16_t)(TIM_CCx << TIM_Channel); +} + +/** + * @} + */ + +/** @defgroup TIM_Group3 Input Capture management functions + * @brief Input Capture management functions + * +@verbatim + =============================================================================== + ##### Input Capture management functions ##### + =============================================================================== + + *** TIM Driver: how to use it in Input Capture Mode *** + =============================================================================== + [..] To use the Timer in Input Capture mode, the following steps are mandatory: + (#) Enable TIM clock using RCC_APBxPeriphClockCmd(RCC_APBxPeriph_TIMx, ENABLE) + function. + (#) Configure the TIM pins by configuring the corresponding GPIO pins. + (#) Configure the Time base unit as described in the first part of this + driver, if needed, else the Timer will run with the default configuration: + (++) Autoreload value = 0xFFFF. + (++) Prescaler value = 0x0000. + (++) Counter mode = Up counting. + (++) Clock Division = TIM_CKD_DIV1. + (#) Fill the TIM_ICInitStruct with the desired parameters including: + (++) TIM Channel: TIM_Channel. + (++) TIM Input Capture polarity: TIM_ICPolarity. + (++) TIM Input Capture selection: TIM_ICSelection. + (++) TIM Input Capture Prescaler: TIM_ICPrescaler. + (++) TIM Input CApture filter value: TIM_ICFilter. + (#) Call TIM_ICInit(TIMx, &TIM_ICInitStruct) to configure the desired + channel with the corresponding configuration and to measure only + frequency or duty cycle of the input signal,or, Call + TIM_PWMIConfig(TIMx, &TIM_ICInitStruct) to configure the desired + channels with the corresponding configuration and to measure the + frequency and the duty cycle of the input signal. + (#) Enable the NVIC or the DMA to read the measured frequency. + (#) Enable the corresponding interrupt (or DMA request) to read + the Captured value, using the function TIM_ITConfig(TIMx, TIM_IT_CCx) + (or TIM_DMA_Cmd(TIMx, TIM_DMA_CCx)). + (#) Call the TIM_Cmd(ENABLE) function to enable the TIM counter. + (#) Use TIM_GetCapturex(TIMx); to read the captured value. + [..] + (@) All other functions can be used separately to modify, if needed, + a specific feature of the Timer. + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the TIM peripheral according to the specified + * parameters in the TIM_ICInitStruct. + * @param TIMx: where x can be 2, 3, 4, 5, 9, 10 or 11 to select the TIM peripheral. + * @param TIM_ICInitStruct: pointer to a TIM_ICInitTypeDef structure + * that contains the configuration information for the specified TIM + * peripheral. + * @retval None + */ +void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST1_PERIPH(TIMx)); + assert_param(IS_TIM_IC_POLARITY(TIM_ICInitStruct->TIM_ICPolarity)); + assert_param(IS_TIM_IC_SELECTION(TIM_ICInitStruct->TIM_ICSelection)); + assert_param(IS_TIM_IC_PRESCALER(TIM_ICInitStruct->TIM_ICPrescaler)); + assert_param(IS_TIM_IC_FILTER(TIM_ICInitStruct->TIM_ICFilter)); + + if (TIM_ICInitStruct->TIM_Channel == TIM_Channel_1) + { + /* TI1 Configuration */ + TI1_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity, + TIM_ICInitStruct->TIM_ICSelection, + TIM_ICInitStruct->TIM_ICFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetIC1Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler); + } + else if (TIM_ICInitStruct->TIM_Channel == TIM_Channel_2) + { + /* TI2 Configuration */ + assert_param(IS_TIM_LIST2_PERIPH(TIMx)); + TI2_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity, + TIM_ICInitStruct->TIM_ICSelection, + TIM_ICInitStruct->TIM_ICFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetIC2Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler); + } + else if (TIM_ICInitStruct->TIM_Channel == TIM_Channel_3) + { + /* TI3 Configuration */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + TI3_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity, + TIM_ICInitStruct->TIM_ICSelection, + TIM_ICInitStruct->TIM_ICFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetIC3Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler); + } + else + { + /* TI4 Configuration */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + TI4_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity, + TIM_ICInitStruct->TIM_ICSelection, + TIM_ICInitStruct->TIM_ICFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetIC4Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler); + } +} + +/** + * @brief Fills each TIM_ICInitStruct member with its default value. + * @param TIM_ICInitStruct : pointer to a TIM_ICInitTypeDef structure which will + * be initialized. + * @retval None + */ +void TIM_ICStructInit(TIM_ICInitTypeDef* TIM_ICInitStruct) +{ + /* Set the default configuration */ + TIM_ICInitStruct->TIM_Channel = TIM_Channel_1; + TIM_ICInitStruct->TIM_ICPolarity = TIM_ICPolarity_Rising; + TIM_ICInitStruct->TIM_ICSelection = TIM_ICSelection_DirectTI; + TIM_ICInitStruct->TIM_ICPrescaler = TIM_ICPSC_DIV1; + TIM_ICInitStruct->TIM_ICFilter = 0x00; +} + +/** + * @brief Configures the TIM peripheral according to the specified + * parameters in the TIM_ICInitStruct to measure an external PWM signal. + * @param TIMx: where x can be 2, 3, 4, 5 or 9 to select the TIM peripheral. + * @param TIM_ICInitStruct: pointer to a TIM_ICInitTypeDef structure + * that contains the configuration information for the specified TIM + * peripheral. + * @retval None + */ +void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct) +{ + uint16_t icoppositepolarity = TIM_ICPolarity_Rising; + uint16_t icoppositeselection = TIM_ICSelection_DirectTI; + /* Check the parameters */ + assert_param(IS_TIM_LIST2_PERIPH(TIMx)); + /* Select the Opposite Input Polarity */ + if (TIM_ICInitStruct->TIM_ICPolarity == TIM_ICPolarity_Rising) + { + icoppositepolarity = TIM_ICPolarity_Falling; + } + else + { + icoppositepolarity = TIM_ICPolarity_Rising; + } + /* Select the Opposite Input */ + if (TIM_ICInitStruct->TIM_ICSelection == TIM_ICSelection_DirectTI) + { + icoppositeselection = TIM_ICSelection_IndirectTI; + } + else + { + icoppositeselection = TIM_ICSelection_DirectTI; + } + if (TIM_ICInitStruct->TIM_Channel == TIM_Channel_1) + { + /* TI1 Configuration */ + TI1_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity, TIM_ICInitStruct->TIM_ICSelection, + TIM_ICInitStruct->TIM_ICFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetIC1Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler); + /* TI2 Configuration */ + TI2_Config(TIMx, icoppositepolarity, icoppositeselection, TIM_ICInitStruct->TIM_ICFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetIC2Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler); + } + else + { + /* TI2 Configuration */ + TI2_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity, TIM_ICInitStruct->TIM_ICSelection, + TIM_ICInitStruct->TIM_ICFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetIC2Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler); + /* TI1 Configuration */ + TI1_Config(TIMx, icoppositepolarity, icoppositeselection, TIM_ICInitStruct->TIM_ICFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetIC1Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler); + } +} + +/** + * @brief Gets the TIMx Input Capture 1 value. + * @param TIMx: where x can be 2, 3, 4, 5, 9, 10 or 11 to select the TIM peripheral. + * @retval Capture Compare 1 Register value. + */ +uint32_t TIM_GetCapture1(TIM_TypeDef* TIMx) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST1_PERIPH(TIMx)); + + /* Get the Capture 1 Register value */ + return TIMx->CCR1; +} + +/** + * @brief Gets the TIMx Input Capture 2 value. + * @param TIMx: where x can be 2, 3, 4, 5 or 9 to select the TIM peripheral. + * @retval Capture Compare 2 Register value. + */ +uint32_t TIM_GetCapture2(TIM_TypeDef* TIMx) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST2_PERIPH(TIMx)); + + /* Get the Capture 2 Register value */ + return TIMx->CCR2; +} + +/** + * @brief Gets the TIMx Input Capture 3 value. + * @param TIMx: where x can be 2, 3, 4 or 5 to select the TIM peripheral. + * @retval Capture Compare 3 Register value. + */ +uint32_t TIM_GetCapture3(TIM_TypeDef* TIMx) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + + /* Get the Capture 3 Register value */ + return TIMx->CCR3; +} + +/** + * @brief Gets the TIMx Input Capture 4 value. + * @param TIMx: where x can be 2, 3, 4 or 5 to select the TIM peripheral. + * @retval Capture Compare 4 Register value. + */ +uint32_t TIM_GetCapture4(TIM_TypeDef* TIMx) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + + /* Get the Capture 4 Register value */ + return TIMx->CCR4; +} + +/** + * @brief Sets the TIMx Input Capture 1 prescaler. + * @param TIMx: where x can be 2, 3, 4, 5, 9, 10 or 11 to select the TIM peripheral. + * @param TIM_ICPSC: specifies the Input Capture1 prescaler new value. + * This parameter can be one of the following values: + * @arg TIM_ICPSC_DIV1: no prescaler. + * @arg TIM_ICPSC_DIV2: capture is done once every 2 events. + * @arg TIM_ICPSC_DIV4: capture is done once every 4 events. + * @arg TIM_ICPSC_DIV8: capture is done once every 8 events. + * @retval None + */ +void TIM_SetIC1Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST1_PERIPH(TIMx)); + assert_param(IS_TIM_IC_PRESCALER(TIM_ICPSC)); + + /* Reset the IC1PSC Bits */ + TIMx->CCMR1 &= (uint16_t)~((uint16_t)TIM_CCMR1_IC1PSC); + /* Set the IC1PSC value */ + TIMx->CCMR1 |= TIM_ICPSC; +} + +/** + * @brief Sets the TIMx Input Capture 2 prescaler. + * @param TIMx: where x can be 2, 3, 4, 5 or 9 to select the TIM peripheral. + * @param TIM_ICPSC: specifies the Input Capture2 prescaler new value. + * This parameter can be one of the following values: + * @arg TIM_ICPSC_DIV1: no prescaler. + * @arg TIM_ICPSC_DIV2: capture is done once every 2 events. + * @arg TIM_ICPSC_DIV4: capture is done once every 4 events. + * @arg TIM_ICPSC_DIV8: capture is done once every 8 events. + * @retval None + */ +void TIM_SetIC2Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST2_PERIPH(TIMx)); + assert_param(IS_TIM_IC_PRESCALER(TIM_ICPSC)); + + /* Reset the IC2PSC Bits */ + TIMx->CCMR1 &= (uint16_t)~((uint16_t)TIM_CCMR1_IC2PSC); + /* Set the IC2PSC value */ + TIMx->CCMR1 |= (uint16_t)(TIM_ICPSC << 8); +} + +/** + * @brief Sets the TIMx Input Capture 3 prescaler. + * @param TIMx: where x can be 2, 3, 4 or 5 to select the TIM peripheral. + * @param TIM_ICPSC: specifies the Input Capture3 prescaler new value. + * This parameter can be one of the following values: + * @arg TIM_ICPSC_DIV1: no prescaler. + * @arg TIM_ICPSC_DIV2: capture is done once every 2 events. + * @arg TIM_ICPSC_DIV4: capture is done once every 4 events. + * @arg TIM_ICPSC_DIV8: capture is done once every 8 events. + * @retval None + */ +void TIM_SetIC3Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_IC_PRESCALER(TIM_ICPSC)); + + /* Reset the IC3PSC Bits */ + TIMx->CCMR2 &= (uint16_t)~((uint16_t)TIM_CCMR2_IC3PSC); + /* Set the IC3PSC value */ + TIMx->CCMR2 |= TIM_ICPSC; +} + +/** + * @brief Sets the TIMx Input Capture 4 prescaler. + * @param TIMx: where x can be 2, 3, 4 or 5 to select the TIM peripheral. + * @param TIM_ICPSC: specifies the Input Capture4 prescaler new value. + * This parameter can be one of the following values: + * @arg TIM_ICPSC_DIV1: no prescaler. + * @arg TIM_ICPSC_DIV2: capture is done once every 2 events. + * @arg TIM_ICPSC_DIV4: capture is done once every 4 events. + * @arg TIM_ICPSC_DIV8: capture is done once every 8 events. + * @retval None + */ +void TIM_SetIC4Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_IC_PRESCALER(TIM_ICPSC)); + + /* Reset the IC4PSC Bits */ + TIMx->CCMR2 &= (uint16_t)~((uint16_t)TIM_CCMR2_IC4PSC); + /* Set the IC4PSC value */ + TIMx->CCMR2 |= (uint16_t)(TIM_ICPSC << 8); +} + +/** + * @} + */ + +/** @defgroup TIM_Group4 Interrupts DMA and flags management functions + * @brief Interrupts, DMA and flags management functions + * +@verbatim + =============================================================================== + ##### Interrupts, DMA and flags management functions ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Enables or disables the specified TIM interrupts. + * @param TIMx: where x can be 2 to 11 to select the TIMx peripheral. + * @param TIM_IT: specifies the TIM interrupts sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg TIM_IT_Update: TIM update Interrupt source. + * @arg TIM_IT_CC1: TIM Capture Compare 1 Interrupt source. + * @arg TIM_IT_CC2: TIM Capture Compare 2 Interrupt source. + * @arg TIM_IT_CC3: TIM Capture Compare 3 Interrupt source. + * @arg TIM_IT_CC4: TIM Capture Compare 4 Interrupt source. + * @arg TIM_IT_Trigger: TIM Trigger Interrupt source. + * @note TIM6 and TIM7 can only generate an update interrupt. + * @note TIM_IT_CC2, TIM_IT_CC3, TIM_IT_CC4 and TIM_IT_Trigger can not be used with TIM10 and TIM11. + * @note TIM_IT_CC3, TIM_IT_CC4 can not be used with TIM9. + * @param NewState: new state of the TIM interrupts. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + assert_param(IS_TIM_IT(TIM_IT)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the Interrupt sources */ + TIMx->DIER |= TIM_IT; + } + else + { + /* Disable the Interrupt sources */ + TIMx->DIER &= (uint16_t)~TIM_IT; + } +} + +/** + * @brief Configures the TIMx event to be generate by software. + * @param TIMx: where x can be 2 to 11 to select the TIM peripheral. + * @param TIM_EventSource: specifies the event source. + * This parameter can be one or more of the following values: + * @arg TIM_EventSource_Update: Timer update Event source. + * @arg TIM_EventSource_CC1: Timer Capture Compare 1 Event source. + * @arg TIM_EventSource_CC2: Timer Capture Compare 2 Event source. + * @arg TIM_EventSource_CC3: Timer Capture Compare 3 Event source. + * @arg TIM_EventSource_CC4: Timer Capture Compare 4 Event source. + * @arg TIM_EventSource_Trigger: Timer Trigger Event source. + * @note TIM6 and TIM7 can only generate an update event. + * @note TIM9 can only generate an update event, Capture Compare 1 event, + * Capture Compare 2 event and TIM_EventSource_Trigger. + * @note TIM10 and TIM11 can only generate an update event and Capture Compare 1 event. + * @retval None + */ +void TIM_GenerateEvent(TIM_TypeDef* TIMx, uint16_t TIM_EventSource) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + assert_param(IS_TIM_EVENT_SOURCE(TIM_EventSource)); + /* Set the event sources */ + TIMx->EGR = TIM_EventSource; +} + +/** + * @brief Checks whether the specified TIM flag is set or not. + * @param TIMx: where x can be 2 to 11 to select the TIM peripheral. + * @param TIM_FLAG: specifies the flag to check. + * This parameter can be one of the following values: + * @arg TIM_FLAG_Update: TIM update Flag. + * @arg TIM_FLAG_CC1: TIM Capture Compare 1 Flag. + * @arg TIM_FLAG_CC2: TIM Capture Compare 2 Flag. + * @arg TIM_FLAG_CC3: TIM Capture Compare 3 Flag. + * @arg TIM_FLAG_CC4: TIM Capture Compare 4 Flag. + * @arg TIM_FLAG_Trigger: TIM Trigger Flag. + * @arg TIM_FLAG_CC1OF: TIM Capture Compare 1 overcapture Flag. + * @arg TIM_FLAG_CC2OF: TIM Capture Compare 2 overcapture Flag. + * @arg TIM_FLAG_CC3OF: TIM Capture Compare 3 overcapture Flag. + * @arg TIM_FLAG_CC4OF: TIM Capture Compare 4 overcapture Flag. + * + * @note TIM6 and TIM7 can have only one update flag. + * @note TIM9 can have only update flag, TIM_FLAG_CC1, TIM_FLAG_CC2 and TIM_FLAG_Trigger, + * TIM_FLAG_CC1OF or TIM_FLAG_CC2OF flags. + * @note TIM10 and TIM11 can have only update flag, TIM_FLAG_CC1 or TIM_FLAG_CC1OF flags + * @retval The new state of TIM_FLAG (SET or RESET). + */ +FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG) +{ + ITStatus bitstatus = RESET; + + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + assert_param(IS_TIM_GET_FLAG(TIM_FLAG)); + + if ((TIMx->SR & TIM_FLAG) != (uint16_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the TIMx's pending flags. + * @param TIMx: where x can be 2 to 11 to select the TIM peripheral. + * @param TIM_FLAG: specifies the flag bit to clear. + * This parameter can be any combination of the following values: + * @arg TIM_FLAG_Update: TIM update Flag. + * @arg TIM_FLAG_CC1: TIM Capture Compare 1 Flag. + * @arg TIM_FLAG_CC2: TIM Capture Compare 2 Flag. + * @arg TIM_FLAG_CC3: TIM Capture Compare 3 Flag. + * @arg TIM_FLAG_CC4: TIM Capture Compare 4 Flag. + * @arg TIM_FLAG_Trigger: TIM Trigger Flag. + * @arg TIM_FLAG_CC1OF: TIM Capture Compare 1 overcapture Flag. + * @arg TIM_FLAG_CC2OF: TIM Capture Compare 2 overcapture Flag. + * @arg TIM_FLAG_CC3OF: TIM Capture Compare 3 overcapture Flag. + * @arg TIM_FLAG_CC4OF: TIM Capture Compare 4 overcapture Flag. + * @note TIM6 and TIM7 can have only one update flag. + * @note TIM9 can have only update flag, TIM_FLAG_CC1, TIM_FLAG_CC2 and TIM_FLAG_Trigger flags + * TIM_FLAG_CC1OF or TIM_FLAG_CC2OF flags. + * @note TIM10 and TIM11 can have only update flag, TIM_FLAG_CC1 + * or TIM_FLAG_CC1OF flags + * @retval None + */ +void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + assert_param(IS_TIM_CLEAR_FLAG(TIM_FLAG)); + + /* Clear the flags */ + TIMx->SR = (uint16_t)~TIM_FLAG; +} + +/** + * @brief Checks whether the TIM interrupt has occurred or not. + * @param TIMx: where x can be 2 to 11 to select the TIM peripheral. + * @param TIM_IT: specifies the TIM interrupt source to check. + * This parameter can be one of the following values: + * @arg TIM_IT_Update: TIM update Interrupt source. + * @arg TIM_IT_CC1: TIM Capture Compare 1 Interrupt source. + * @arg TIM_IT_CC2: TIM Capture Compare 2 Interrupt source. + * @arg TIM_IT_CC3: TIM Capture Compare 3 Interrupt source. + * @arg TIM_IT_CC4: TIM Capture Compare 4 Interrupt source. + * @arg TIM_IT_Trigger: TIM Trigger Interrupt source. + * + * @note TIM6 and TIM7 can generate only an update interrupt. + * @note TIM9 can have only update interrupt, TIM_FLAG_CC1 or TIM_FLAG_CC2, + * interrupt and TIM_IT_Trigger interrupt. + * @note TIM10 and TIM11 can have only update interrupt or TIM_FLAG_CC1 + * interrupt + * @retval The new state of the TIM_IT(SET or RESET). + */ +ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT) +{ + ITStatus bitstatus = RESET; + uint16_t itstatus = 0x0, itenable = 0x0; + + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + assert_param(IS_TIM_GET_IT(TIM_IT)); + + itstatus = TIMx->SR & TIM_IT; + + itenable = TIMx->DIER & TIM_IT; + if ((itstatus != (uint16_t)RESET) && (itenable != (uint16_t)RESET)) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the TIMx's interrupt pending bits. + * @param TIMx: where x can be 2 to 11 to select the TIM peripheral. + * @param TIM_IT: specifies the pending bit to clear. + * This parameter can be any combination of the following values: + * @arg TIM_IT_Update: TIM update Interrupt source. + * @arg TIM_IT_CC1: TIM Capture Compare 1 Interrupt source. + * @arg TIM_IT_CC2: TIM Capture Compare 2 Interrupt source. + * @arg TIM_IT_CC3: TIM Capture Compare 3 Interrupt source. + * @arg TIM_IT_CC4: TIM Capture Compare 4 Interrupt source. + * @arg TIM_IT_Trigger: TIM Trigger Interrupt source. + * @note + * @note TIM6 and TIM7 can generate only an update interrupt. + * @note TIM9 can have only update interrupt, TIM_IT_CC1 or TIM_IT_CC2, + * and TIM_IT_Trigger interrupt. + * @note TIM10 and TIM11 can have only update interrupt or TIM_IT_CC1 + * interrupt + * @retval None + */ +void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT) +{ + /* Check the parameters */ + assert_param(IS_TIM_ALL_PERIPH(TIMx)); + assert_param(IS_TIM_IT(TIM_IT)); + + /* Clear the IT pending Bit */ + TIMx->SR = (uint16_t)~TIM_IT; +} + +/** + * @brief Configures the TIMx's DMA interface. + * @param TIMx: where x can be 2, 3, 4 or 5 to select the TIM peripheral. + * @param TIM_DMABase: DMA Base address. + * This parameter can be one of the following values: + * @arg TIM_DMABase_CR1: TIM CR1 register as TIM DMA Base. + * @arg TIM_DMABase_CR2: TIM CR2 register as TIM DMA Base. + * @arg TIM_DMABase_SMCR: TIM SMCR register as TIM DMA Base. + * @arg TIM_DMABase_DIER: TIM DIER register as TIM DMA Base. + * @arg TIM_DMABase_SR: TIM SR register as TIM DMA Base. + * @arg TIM_DMABase_EGR: TIM EGR register as TIM DMA Base. + * @arg TIM_DMABase_CCMR1: TIM CCMR1 register as TIM DMA Base. + * @arg TIM_DMABase_CCMR2: TIM CCMR2 register as TIM DMA Base. + * @arg TIM_DMABase_CCER: TIM CCER register as TIM DMA Base. + * @arg TIM_DMABase_CNT: TIM CNT register as TIM DMA Base. + * @arg TIM_DMABase_PSC: TIM PSC register as TIM DMA Base. + * @arg TIM_DMABase_ARR: TIM ARR register as TIM DMA Base. + * @arg TIM_DMABase_CCR1: TIM CCR1 register as TIM DMA Base. + * @arg TIM_DMABase_CCR2: TIM CCR2 register as TIM DMA Base. + * @arg TIM_DMABase_CCR3: TIM CCR3 register as TIM DMA Base. + * @arg TIM_DMABase_CCR4: TIM CCR4 register as TIM DMA Base. + * @arg TIM_DMABase_DCR: TIM DCR register as TIM DMA Base. + * @arg TIM_DMABase_OR: TIM OR register as TIM DMA Base. + * @param TIM_DMABurstLength: DMA Burst length. + * This parameter can be one value between: + * TIM_DMABurstLength_1Transfer and TIM_DMABurstLength_18Transfers. + * @retval None + */ +void TIM_DMAConfig(TIM_TypeDef* TIMx, uint16_t TIM_DMABase, uint16_t TIM_DMABurstLength) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_DMA_BASE(TIM_DMABase)); + assert_param(IS_TIM_DMA_LENGTH(TIM_DMABurstLength)); + /* Set the DMA Base and the DMA Burst Length */ + TIMx->DCR = TIM_DMABase | TIM_DMABurstLength; +} + +/** + * @brief Enables or disables the TIMx's DMA Requests. + * @param TIMx: where x can be 2, 3, 4, 5, 6 or 7 to select the TIM peripheral. + * @param TIM_DMASource: specifies the DMA Request sources. + * This parameter can be any combination of the following values: + * @arg TIM_DMA_Update: TIM update Interrupt source. + * @arg TIM_DMA_CC1: TIM Capture Compare 1 DMA source. + * @arg TIM_DMA_CC2: TIM Capture Compare 2 DMA source. + * @arg TIM_DMA_CC3: TIM Capture Compare 3 DMA source. + * @arg TIM_DMA_CC4: TIM Capture Compare 4 DMA source. + * @arg TIM_DMA_Trigger: TIM Trigger DMA source. + * @param NewState: new state of the DMA Request sources. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void TIM_DMACmd(TIM_TypeDef* TIMx, uint16_t TIM_DMASource, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST4_PERIPH(TIMx)); + assert_param(IS_TIM_DMA_SOURCE(TIM_DMASource)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Enable the DMA sources */ + TIMx->DIER |= TIM_DMASource; + } + else + { + /* Disable the DMA sources */ + TIMx->DIER &= (uint16_t)~TIM_DMASource; + } +} + +/** + * @brief Selects the TIMx peripheral Capture Compare DMA source. + * @param TIMx: where x can be 2, 3, 4 or 5 to select the TIM peripheral. + * @param NewState: new state of the Capture Compare DMA source + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void TIM_SelectCCDMA(TIM_TypeDef* TIMx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Set the CCDS Bit */ + TIMx->CR2 |= TIM_CR2_CCDS; + } + else + { + /* Reset the CCDS Bit */ + TIMx->CR2 &= (uint16_t)~((uint16_t)TIM_CR2_CCDS); + } +} + +/** + * @} + */ + +/** @defgroup TIM_Group5 Clocks management functions + * @brief Clocks management functions + * +@verbatim + =============================================================================== + ##### Clocks management functions ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Configures the TIMx internal Clock + * @param TIMx: where x can be 2, 3, 4, 5 or 9 to select the TIM peripheral. + * @retval None + */ +void TIM_InternalClockConfig(TIM_TypeDef* TIMx) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST2_PERIPH(TIMx)); + /* Disable slave mode to clock the prescaler directly with the internal clock */ + TIMx->SMCR &= (uint16_t)(~((uint16_t)TIM_SMCR_SMS)); +} + +/** + * @brief Configures the TIMx Internal Trigger as External Clock + * @param TIMx: where x can be 2, 3, 4, 5 or 9 to select the TIM peripheral. + * @param TIM_ITRSource: Trigger source. + * This parameter can be one of the following values: + * @param TIM_TS_ITR0: Internal Trigger 0. + * @param TIM_TS_ITR1: Internal Trigger 1. + * @param TIM_TS_ITR2: Internal Trigger 2. + * @param TIM_TS_ITR3: Internal Trigger 3. + * @retval None + */ +void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST2_PERIPH(TIMx)); + assert_param(IS_TIM_INTERNAL_TRIGGER_SELECTION(TIM_InputTriggerSource)); + /* Select the Internal Trigger */ + TIM_SelectInputTrigger(TIMx, TIM_InputTriggerSource); + /* Select the External clock mode1 */ + TIMx->SMCR |= TIM_SlaveMode_External1; +} + +/** + * @brief Configures the TIMx Trigger as External Clock + * @param TIMx: where x can be 2, 3, 4, 5 or 9 to select the TIM peripheral. + * @param TIM_TIxExternalCLKSource: Trigger source. + * This parameter can be one of the following values: + * @arg TIM_TIxExternalCLK1Source_TI1ED: TI1 Edge Detector. + * @arg TIM_TIxExternalCLK1Source_TI1: Filtered Timer Input 1. + * @arg TIM_TIxExternalCLK1Source_TI2: Filtered Timer Input 2. + * @param TIM_ICPolarity: specifies the TIx Polarity. + * This parameter can be one of the following values: + * @arg TIM_ICPolarity_Rising: + * @arg TIM_ICPolarity_Falling: + * @param ICFilter : specifies the filter value. + * This parameter must be a value between 0x0 and 0xF. + * @retval None + */ +void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource, + uint16_t TIM_ICPolarity, uint16_t ICFilter) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST2_PERIPH(TIMx)); + assert_param(IS_TIM_IC_POLARITY(TIM_ICPolarity)); + assert_param(IS_TIM_IC_FILTER(ICFilter)); + + /* Configure the Timer Input Clock Source */ + if (TIM_TIxExternalCLKSource == TIM_TIxExternalCLK1Source_TI2) + { + TI2_Config(TIMx, TIM_ICPolarity, TIM_ICSelection_DirectTI, ICFilter); + } + else + { + TI1_Config(TIMx, TIM_ICPolarity, TIM_ICSelection_DirectTI, ICFilter); + } + /* Select the Trigger source */ + TIM_SelectInputTrigger(TIMx, TIM_TIxExternalCLKSource); + /* Select the External clock mode1 */ + TIMx->SMCR |= TIM_SlaveMode_External1; +} + +/** + * @brief Configures the External clock Mode1 + * @param TIMx: where x can be 2, 3, 4, 5 or 9 to select the TIM peripheral. + * @param TIM_ExtTRGPrescaler: The external Trigger Prescaler. + * This parameter can be one of the following values: + * @arg TIM_ExtTRGPSC_OFF: ETRP Prescaler OFF. + * @arg TIM_ExtTRGPSC_DIV2: ETRP frequency divided by 2. + * @arg TIM_ExtTRGPSC_DIV4: ETRP frequency divided by 4. + * @arg TIM_ExtTRGPSC_DIV8: ETRP frequency divided by 8. + * @param TIM_ExtTRGPolarity: The external Trigger Polarity. + * This parameter can be one of the following values: + * @arg TIM_ExtTRGPolarity_Inverted: active low or falling edge active. + * @arg TIM_ExtTRGPolarity_NonInverted: active high or rising edge active. + * @param ExtTRGFilter: External Trigger Filter. + * This parameter must be a value between 0x00 and 0x0F + * @retval None + */ +void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, + uint16_t ExtTRGFilter) +{ + uint16_t tmpsmcr = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST2_PERIPH(TIMx)); + assert_param(IS_TIM_EXT_PRESCALER(TIM_ExtTRGPrescaler)); + assert_param(IS_TIM_EXT_POLARITY(TIM_ExtTRGPolarity)); + assert_param(IS_TIM_EXT_FILTER(ExtTRGFilter)); + + /* Configure the ETR Clock source */ + TIM_ETRConfig(TIMx, TIM_ExtTRGPrescaler, TIM_ExtTRGPolarity, ExtTRGFilter); + + /* Get the TIMx SMCR register value */ + tmpsmcr = TIMx->SMCR; + /* Reset the SMS Bits */ + tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCR_SMS)); + /* Select the External clock mode1 */ + tmpsmcr |= TIM_SlaveMode_External1; + /* Select the Trigger selection : ETRF */ + tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCR_TS)); + tmpsmcr |= TIM_TS_ETRF; + /* Write to TIMx SMCR */ + TIMx->SMCR = tmpsmcr; +} + +/** + * @brief Configures the External clock Mode2 + * @param TIMx: where x can be 2, 3, 4, 5, 9, 10 or 11 to select the TIM peripheral. + * @param TIM_ExtTRGPrescaler: The external Trigger Prescaler. + * This parameter can be one of the following values: + * @arg TIM_ExtTRGPSC_OFF: ETRP Prescaler OFF. + * @arg TIM_ExtTRGPSC_DIV2: ETRP frequency divided by 2. + * @arg TIM_ExtTRGPSC_DIV4: ETRP frequency divided by 4. + * @arg TIM_ExtTRGPSC_DIV8: ETRP frequency divided by 8. + * @param TIM_ExtTRGPolarity: The external Trigger Polarity. + * This parameter can be one of the following values: + * @arg TIM_ExtTRGPolarity_Inverted: active low or falling edge active. + * @arg TIM_ExtTRGPolarity_NonInverted: active high or rising edge active. + * @param ExtTRGFilter: External Trigger Filter. + * This parameter must be a value between 0x00 and 0x0F + * @retval None + */ +void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, + uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST1_PERIPH(TIMx)); + assert_param(IS_TIM_EXT_PRESCALER(TIM_ExtTRGPrescaler)); + assert_param(IS_TIM_EXT_POLARITY(TIM_ExtTRGPolarity)); + assert_param(IS_TIM_EXT_FILTER(ExtTRGFilter)); + + /* Configure the ETR Clock source */ + TIM_ETRConfig(TIMx, TIM_ExtTRGPrescaler, TIM_ExtTRGPolarity, ExtTRGFilter); + /* Enable the External clock mode2 */ + TIMx->SMCR |= TIM_SMCR_ECE; +} + +/** + * @} + */ + +/** @defgroup TIM_Group6 Synchronization management functions + * @brief Synchronization management functions + * +@verbatim + =============================================================================== + ##### Synchronization management functions ##### + =============================================================================== + *** TIM Driver: how to use it in synchronization Mode *** + =============================================================================== + [..] Case of two/several Timers + (#) Configure the Master Timers using the following functions: + (++) void TIM_SelectOutputTrigger(TIM_TypeDef* TIMx, + uint16_t TIM_TRGOSource). + (++) void TIM_SelectMasterSlaveMode(TIM_TypeDef* TIMx, + uint16_t TIM_MasterSlaveMode); + (#) Configure the Slave Timers using the following functions: + (++) void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, + uint16_t TIM_InputTriggerSource); + (++) void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode); + [..] Case of Timers and external trigger(ETR pin) + (#) Configure the Etrenal trigger using this function: + (++) void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, + uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter); + (#) Configure the Slave Timers using the following functions: + (++) void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, + uint16_t TIM_InputTriggerSource); + (++) void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode); + +@endverbatim + * @{ + */ + +/** + * @brief Selects the Input Trigger source + * @param TIMx: where x can be 2, 3, 4, 5, or 9 to select the TIM peripheral. + * @param TIM_InputTriggerSource: The Input Trigger source. + * This parameter can be one of the following values: + * @arg TIM_TS_ITR0: Internal Trigger 0. + * @arg TIM_TS_ITR1: Internal Trigger 1. + * @arg TIM_TS_ITR2: Internal Trigger 2. + * @arg TIM_TS_ITR3: Internal Trigger 3. + * @arg TIM_TS_TI1F_ED: TI1 Edge Detector. + * @arg TIM_TS_TI1FP1: Filtered Timer Input 1. + * @arg TIM_TS_TI2FP2: Filtered Timer Input 2. + * @arg TIM_TS_ETRF: External Trigger input. + * @retval None + */ +void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource) +{ + uint16_t tmpsmcr = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST1_PERIPH(TIMx)); + assert_param(IS_TIM_TRIGGER_SELECTION(TIM_InputTriggerSource)); + + /* Get the TIMx SMCR register value */ + tmpsmcr = TIMx->SMCR; + /* Reset the TS Bits */ + tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCR_TS)); + /* Set the Input Trigger source */ + tmpsmcr |= TIM_InputTriggerSource; + /* Write to TIMx SMCR */ + TIMx->SMCR = tmpsmcr; +} + +/** + * @brief Selects the TIMx Trigger Output Mode. + * @param TIMx: where x can be 2, 3, 4, 5, 6, 7 or 9 to select the TIM peripheral. + * @param TIM_TRGOSource: specifies the Trigger Output source. + * This paramter can be one of the following values: + * + * @param For all TIMx + * @arg TIM_TRGOSource_Reset: The UG bit in the TIM_EGR register is used as the trigger output (TRGO). + * @arg TIM_TRGOSource_Enable: The Counter Enable CEN is used as the trigger output (TRGO). + * @arg TIM_TRGOSource_Update: The update event is selected as the trigger output (TRGO). + * + * @param For all TIMx except TIM6 and TIM7 + * @arg TIM_TRGOSource_OC1: The trigger output sends a positive pulse when the CC1IF flag + * is to be set, as soon as a capture or compare match occurs (TRGO). + * @arg TIM_TRGOSource_OC1Ref: OC1REF signal is used as the trigger output (TRGO). + + * @param For all TIMx except TIM6, TIM7, TIM10 and TIM11 + * @arg TIM_TRGOSource_OC2Ref: OC2REF signal is used as the trigger output (TRGO). + + * @param For TIM2, TIM3 and TIM4 + * @arg TIM_TRGOSource_OC3Ref: OC3REF signal is used as the trigger output (TRGO). + * @arg TIM_TRGOSource_OC4Ref: OC4REF signal is used as the trigger output (TRGO). + * + * @retval None + */ +void TIM_SelectOutputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_TRGOSource) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST5_PERIPH(TIMx)); + assert_param(IS_TIM_TRGO_SOURCE(TIM_TRGOSource)); + + /* Reset the MMS Bits */ + TIMx->CR2 &= (uint16_t)~((uint16_t)TIM_CR2_MMS); + /* Select the TRGO source */ + TIMx->CR2 |= TIM_TRGOSource; +} + +/** + * @brief Selects the TIMx Slave Mode. + * @param TIMx: where x can be 2, 3, 4, 5 or 9 to select the TIM peripheral. + * @param TIM_SlaveMode: specifies the Timer Slave Mode. + * This paramter can be one of the following values: + * @arg TIM_SlaveMode_Reset: Rising edge of the selected trigger signal (TRGI) re-initializes + * the counter and triggers an update of the registers. + * @arg TIM_SlaveMode_Gated: The counter clock is enabled when the trigger signal (TRGI) is high. + * @arg TIM_SlaveMode_Trigger: The counter starts at a rising edge of the trigger TRGI. + * @arg TIM_SlaveMode_External1: Rising edges of the selected trigger (TRGI) clock the counter. + * @retval None + */ +void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST2_PERIPH(TIMx)); + assert_param(IS_TIM_SLAVE_MODE(TIM_SlaveMode)); + + /* Reset the SMS Bits */ + TIMx->SMCR &= (uint16_t)~((uint16_t)TIM_SMCR_SMS); + /* Select the Slave Mode */ + TIMx->SMCR |= TIM_SlaveMode; +} + +/** + * @brief Sets or Resets the TIMx Master/Slave Mode. + * @param TIMx: where x can be 2, 3, 4, 5 or 9 to select the TIM peripheral. + * @param TIM_MasterSlaveMode: specifies the Timer Master Slave Mode. + * This paramter can be one of the following values: + * @arg TIM_MasterSlaveMode_Enable: synchronization between the current timer + * and its slaves (through TRGO). + * @arg TIM_MasterSlaveMode_Disable: No action + * @retval None + */ +void TIM_SelectMasterSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_MasterSlaveMode) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST2_PERIPH(TIMx)); + assert_param(IS_TIM_MSM_STATE(TIM_MasterSlaveMode)); + + /* Reset the MSM Bit */ + TIMx->SMCR &= (uint16_t)~((uint16_t)TIM_SMCR_MSM); + + /* Set or Reset the MSM Bit */ + TIMx->SMCR |= TIM_MasterSlaveMode; +} + +/** + * @brief Configures the TIMx External Trigger (ETR). + * @param TIMx: where x can be 2, 3, 4, 5, 9, 10 or 11 to select the TIM peripheral. + * @param TIM_ExtTRGPrescaler: The external Trigger Prescaler. + * This parameter can be one of the following values: + * @arg TIM_ExtTRGPSC_OFF: ETRP Prescaler OFF. + * @arg TIM_ExtTRGPSC_DIV2: ETRP frequency divided by 2. + * @arg TIM_ExtTRGPSC_DIV4: ETRP frequency divided by 4. + * @arg TIM_ExtTRGPSC_DIV8: ETRP frequency divided by 8. + * @param TIM_ExtTRGPolarity: The external Trigger Polarity. + * This parameter can be one of the following values: + * @arg TIM_ExtTRGPolarity_Inverted: active low or falling edge active. + * @arg TIM_ExtTRGPolarity_NonInverted: active high or rising edge active. + * @param ExtTRGFilter: External Trigger Filter. + * This parameter must be a value between 0x00 and 0x0F + * @retval None + */ +void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, + uint16_t ExtTRGFilter) +{ + uint16_t tmpsmcr = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST1_PERIPH(TIMx)); + assert_param(IS_TIM_EXT_PRESCALER(TIM_ExtTRGPrescaler)); + assert_param(IS_TIM_EXT_POLARITY(TIM_ExtTRGPolarity)); + assert_param(IS_TIM_EXT_FILTER(ExtTRGFilter)); + + tmpsmcr = TIMx->SMCR; + /* Reset the ETR Bits */ + tmpsmcr &= SMCR_ETR_MASK; + /* Set the Prescaler, the Filter value and the Polarity */ + tmpsmcr |= (uint16_t)(TIM_ExtTRGPrescaler | (uint16_t)(TIM_ExtTRGPolarity | (uint16_t)(ExtTRGFilter << (uint16_t)8))); + /* Write to TIMx SMCR */ + TIMx->SMCR = tmpsmcr; +} + +/** + * @} + */ + +/** @defgroup TIM_Group7 Specific interface management functions + * @brief Specific interface management functions + * +@verbatim + =============================================================================== + ##### Specific interface management functions ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Configures the TIMx Encoder Interface. + * @param TIMx: where x can be 2, 3, 4 or 5 to select the TIM peripheral. + * @param TIM_EncoderMode: specifies the TIMx Encoder Mode. + * This parameter can be one of the following values: + * @arg TIM_EncoderMode_TI1: Counter counts on TI1FP1 edge depending on TI2FP2 level. + * @arg TIM_EncoderMode_TI2: Counter counts on TI2FP2 edge depending on TI1FP1 level. + * @arg TIM_EncoderMode_TI12: Counter counts on both TI1FP1 and TI2FP2 edges depending + * on the level of the other input. + * @param TIM_IC1Polarity: specifies the IC1 Polarity. + * This parmeter can be one of the following values: + * @arg TIM_ICPolarity_Falling: IC Falling edge. + * @arg TIM_ICPolarity_Rising: IC Rising edge. + * @param TIM_IC2Polarity: specifies the IC2 Polarity + * This parmeter can be one of the following values: + * @arg TIM_ICPolarity_Falling: IC Falling edge. + * @arg TIM_ICPolarity_Rising: IC Rising edge. + * @retval None + */ +void TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx, uint16_t TIM_EncoderMode, + uint16_t TIM_IC1Polarity, uint16_t TIM_IC2Polarity) +{ + uint16_t tmpsmcr = 0; + uint16_t tmpccmr1 = 0; + uint16_t tmpccer = 0; + + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_TIM_ENCODER_MODE(TIM_EncoderMode)); + assert_param(IS_TIM_IC_POLARITY(TIM_IC1Polarity)); + assert_param(IS_TIM_IC_POLARITY(TIM_IC2Polarity)); + + /* Get the TIMx SMCR register value */ + tmpsmcr = TIMx->SMCR; + /* Get the TIMx CCMR1 register value */ + tmpccmr1 = TIMx->CCMR1; + /* Get the TIMx CCER register value */ + tmpccer = TIMx->CCER; + /* Set the encoder Mode */ + tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCR_SMS)); + tmpsmcr |= TIM_EncoderMode; + /* Select the Capture Compare 1 and the Capture Compare 2 as input */ + tmpccmr1 &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CCMR1_CC1S)) & (uint16_t)(~((uint16_t)TIM_CCMR1_CC2S))); + tmpccmr1 |= TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0; + /* Set the TI1 and the TI2 Polarities */ + tmpccer &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CCER_CC1P)) & ((uint16_t)~((uint16_t)TIM_CCER_CC2P))); + tmpccer |= (uint16_t)(TIM_IC1Polarity | (uint16_t)(TIM_IC2Polarity << (uint16_t)4)); + /* Write to TIMx SMCR */ + TIMx->SMCR = tmpsmcr; + /* Write to TIMx CCMR1 */ + TIMx->CCMR1 = tmpccmr1; + /* Write to TIMx CCER */ + TIMx->CCER = tmpccer; +} + +/** + * @brief Enables or disables the TIMx's Hall sensor interface. + * @param TIMx: where x can be 2, 3, 4 or 5 to select the TIM peripheral. + * @param NewState: new state of the TIMx Hall sensor interface. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void TIM_SelectHallSensor(TIM_TypeDef* TIMx, FunctionalState NewState) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST3_PERIPH(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(NewState)); + + if (NewState != DISABLE) + { + /* Set the TI1S Bit */ + TIMx->CR2 |= TIM_CR2_TI1S; + } + else + { + /* Reset the TI1S Bit */ + TIMx->CR2 &= (uint16_t)~((uint16_t)TIM_CR2_TI1S); + } +} + +/** + * @} + */ + +/** @defgroup TIM_Group8 Specific remapping management function + * @brief Specific remapping management function + * +@verbatim + =============================================================================== + ##### Specific remapping management function ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Configures the TIM2, TIM3, TIM9, TIM10 and TIM11 Remapping input + * Capabilities. + * @param TIMx: where x can be 2, 3, 9, 10 or 11 to select the TIM peripheral. + * @param TIM_Remap: specifies the TIM input remapping source. + * This parameter can be one of the following values: + * @arg TIM2_TIM10_OC: TIM2 ITR1 is connected to TIM10 output compare(default). + * @arg TIM2_TIM5_TRGO: TIM2 ITR1 is connected to TIM5 Trigger output. + * @arg TIM3_TIM11_OC: TIM3 ITR2 is connected to TIM11 output compare(default). + * @arg TIM3_TIM5_TRGO: TIM3 ITR2 is connected to TIM5 Trigger output. + * @arg TIM9_GPIO: TIM9 Channel 1 is connected to dedicated Timer pin(default). + * @arg TIM9_LSE: TIM9 Channel 1 is connected to LSE clock. + * @arg TIM9_TIM3_TRGO: TIM9 ITR1 is connected to TIM3 TRGO. + * @arg TIM9_TS_IO: TIM9 ITR1 is connected to Touch Sense IO. + * @arg TIM10_GPIO: TIM10 Channel 1 is connected to dedicated Timer pin(default). + * @arg TIM10_LSI: TIM10 Channel 1 is connected to LSI clock. + * @arg TIM10_LSE: TIM10 Channel 1 is connected to LSE clock. + * @arg TIM10_RTC: TIM10 Channel 1 is connected to RTC Output event. + * @arg TIM10_RI: TIM10 Channel 1 is connected to Routing Interface (RI). + * @arg TIM10_ETR_LSE: TIM10 ETR input is connected to LSE Clock. + * @arg TIM10_ETR_TIM9_TRGO: TIM10 ETR input is connected to TIM9 Trigger Output. + * @arg TIM11_GPIO: TIM11 Channel 1 is connected to dedicated Timer pin(default). + * @arg TIM11_MSI: TIM11 Channel 1 is connected to MSI clock. + * @arg TIM11_HSE_RTC: TIM11 Channel 1 is connected to HSE_RTC clock. + * @arg TIM11_RI: TIM11 Channel 1 is connected to Routing Interface (RI). + * @arg TIM11_ETR_LSE: TIM11 ETR input is connected to LSE Clock. + * @arg TIM11_ETR_TIM9_TRGO: TIM11 ETR input is connected to TIM9 Trigger Output. + * @retval None + */ +void TIM_RemapConfig(TIM_TypeDef* TIMx, uint32_t TIM_Remap) +{ + /* Check the parameters */ + assert_param(IS_TIM_LIST6_PERIPH(TIMx)); + assert_param(IS_TIM_REMAP(TIM_Remap)); + + /* Set the Timer remapping configuration */ + TIMx->OR &= (uint16_t)(TIM_Remap >> 16); + TIMx->OR |= (uint16_t)TIM_Remap; +} + +/** + * @} + */ + +/** + * @brief Configure the TI1 as Input. + * @param TIMx: where x can be 2, 3, 4, 9, 10 or 11 to select the TIM peripheral. + * @param TIM_ICPolarity : The Input Polarity. + * This parameter can be one of the following values: + * @arg TIM_ICPolarity_Rising: IC Rising edge. + * @arg TIM_ICPolarity_Falling: IC Falling edge. + * @param TIM_ICSelection: specifies the input to be used. + * This parameter can be one of the following values: + * @arg TIM_ICSelection_DirectTI: TIM Input 1 is selected to be connected to IC1. + * @arg TIM_ICSelection_IndirectTI: TIM Input 1 is selected to be connected to IC2. + * @arg TIM_ICSelection_TRC: TIM Input 1 is selected to be connected to TRC. + * @param TIM_ICFilter: Specifies the Input Capture Filter. + * This parameter must be a value between 0x00 and 0x0F. + * @retval None + */ +static void TI1_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection, + uint16_t TIM_ICFilter) +{ + uint16_t tmpccmr1 = 0, tmpccer = 0; + + /* Disable the Channel 1: Reset the CC1E Bit */ + TIMx->CCER &= (uint16_t)~((uint16_t)TIM_CCER_CC1E); + tmpccmr1 = TIMx->CCMR1; + tmpccer = TIMx->CCER; + /* Select the Input and set the filter */ + tmpccmr1 &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CCMR1_CC1S)) & ((uint16_t)~((uint16_t)TIM_CCMR1_IC1F))); + tmpccmr1 |= (uint16_t)(TIM_ICSelection | (uint16_t)(TIM_ICFilter << (uint16_t)4)); + /* Select the Polarity and set the CC1E Bit */ + tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC1P | TIM_CCER_CC1NP)); + tmpccer |= (uint16_t)(TIM_ICPolarity | (uint16_t)TIM_CCER_CC1E); + /* Write to TIMx CCMR1 and CCER registers */ + TIMx->CCMR1 = tmpccmr1; + TIMx->CCER = tmpccer; +} + +/** + * @brief Configure the TI2 as Input. + * @param TIMx: where x can be 2, 3, 4 or 9 to select the TIM peripheral. + * @param TIM_ICPolarity : The Input Polarity. + * This parameter can be one of the following values: + * @arg TIM_ICPolarity_Rising: IC Rising edge. + * @arg TIM_ICPolarity_Falling: IC Falling edge. + * @param TIM_ICSelection: specifies the input to be used. + * This parameter can be one of the following values: + * @arg TIM_ICSelection_DirectTI: TIM Input 2 is selected to be connected to IC2. + * @arg TIM_ICSelection_IndirectTI: TIM Input 2 is selected to be connected to IC1. + * @arg TIM_ICSelection_TRC: TIM Input 2 is selected to be connected to TRC. + * @param TIM_ICFilter: Specifies the Input Capture Filter. + * This parameter must be a value between 0x00 and 0x0F. + * @retval None + */ +static void TI2_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection, + uint16_t TIM_ICFilter) +{ + uint16_t tmpccmr1 = 0, tmpccer = 0, tmp = 0; + + /* Disable the Channel 2: Reset the CC2E Bit */ + TIMx->CCER &= (uint16_t)~((uint16_t)TIM_CCER_CC2E); + tmpccmr1 = TIMx->CCMR1; + tmpccer = TIMx->CCER; + tmp = (uint16_t)(TIM_ICPolarity << 4); + /* Select the Input and set the filter */ + tmpccmr1 &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CCMR1_CC2S)) & ((uint16_t)~((uint16_t)TIM_CCMR1_IC2F))); + tmpccmr1 |= (uint16_t)(TIM_ICFilter << 12); + tmpccmr1 |= (uint16_t)(TIM_ICSelection << 8); + /* Select the Polarity and set the CC2E Bit */ + tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC2P | TIM_CCER_CC2NP)); + tmpccer |= (uint16_t)(tmp | (uint16_t)TIM_CCER_CC2E); + /* Write to TIMx CCMR1 and CCER registers */ + TIMx->CCMR1 = tmpccmr1 ; + TIMx->CCER = tmpccer; +} + +/** + * @brief Configure the TI3 as Input. + * @param TIMx: where x can be 2, 3 or 4 to select the TIM peripheral. + * @param TIM_ICPolarity : The Input Polarity. + * This parameter can be one of the following values: + * @arg TIM_ICPolarity_Rising: IC Rising edge. + * @arg TIM_ICPolarity_Falling: IC Falling edge. + * @param TIM_ICSelection: specifies the input to be used. + * This parameter can be one of the following values: + * @arg TIM_ICSelection_DirectTI: TIM Input 3 is selected to be connected to IC3. + * @arg TIM_ICSelection_IndirectTI: TIM Input 3 is selected to be connected to IC4. + * @arg TIM_ICSelection_TRC: TIM Input 3 is selected to be connected to TRC. + * @param TIM_ICFilter: Specifies the Input Capture Filter. + * This parameter must be a value between 0x00 and 0x0F. + * @retval None + */ +static void TI3_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection, + uint16_t TIM_ICFilter) +{ + uint16_t tmpccmr2 = 0, tmpccer = 0, tmp = 0; + + /* Disable the Channel 3: Reset the CC3E Bit */ + TIMx->CCER &= (uint16_t)~((uint16_t)TIM_CCER_CC3E); + tmpccmr2 = TIMx->CCMR2; + tmpccer = TIMx->CCER; + tmp = (uint16_t)(TIM_ICPolarity << 8); + /* Select the Input and set the filter */ + tmpccmr2 &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CCMR2_CC3S)) & ((uint16_t)~((uint16_t)TIM_CCMR2_IC3F))); + tmpccmr2 |= (uint16_t)(TIM_ICSelection | (uint16_t)(TIM_ICFilter << (uint16_t)4)); + /* Select the Polarity and set the CC3E Bit */ + tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC3P | TIM_CCER_CC3NP)); + tmpccer |= (uint16_t)(tmp | (uint16_t)TIM_CCER_CC3E); + /* Write to TIMx CCMR2 and CCER registers */ + TIMx->CCMR2 = tmpccmr2; + TIMx->CCER = tmpccer; +} + +/** + * @brief Configure the TI4 as Input. + * @param TIMx: where x can be 2, 3 or 4 to select the TIM peripheral. + * @param TIM_ICPolarity : The Input Polarity. + * This parameter can be one of the following values: + * @arg TIM_ICPolarity_Rising: IC Rising edge. + * @arg TIM_ICPolarity_Falling: IC Falling edge. + * @param TIM_ICSelection: specifies the input to be used. + * This parameter can be one of the following values: + * @arg TIM_ICSelection_DirectTI: TIM Input 4 is selected to be connected to IC4. + * @arg TIM_ICSelection_IndirectTI: TIM Input 4 is selected to be connected to IC3. + * @arg TIM_ICSelection_TRC: TIM Input 4 is selected to be connected to TRC. + * @param TIM_ICFilter: Specifies the Input Capture Filter. + * This parameter must be a value between 0x00 and 0x0F. + * @retval None + */ +static void TI4_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection, + uint16_t TIM_ICFilter) +{ + uint16_t tmpccmr2 = 0, tmpccer = 0, tmp = 0; + + /* Disable the Channel 4: Reset the CC4E Bit */ + TIMx->CCER &= (uint16_t)~((uint16_t)TIM_CCER_CC4E); + tmpccmr2 = TIMx->CCMR2; + tmpccer = TIMx->CCER; + tmp = (uint16_t)(TIM_ICPolarity << 12); + /* Select the Input and set the filter */ + tmpccmr2 &= (uint16_t)((uint16_t)(~(uint16_t)TIM_CCMR2_CC4S) & ((uint16_t)~((uint16_t)TIM_CCMR2_IC4F))); + tmpccmr2 |= (uint16_t)(TIM_ICSelection << 8); + tmpccmr2 |= (uint16_t)(TIM_ICFilter << 12); + + /* Select the Polarity and set the CC4E Bit */ + tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC4P | TIM_CCER_CC4NP)); + tmpccer |= (uint16_t)(tmp | (uint16_t)TIM_CCER_CC4E); + /* Write to TIMx CCMR2 and CCER registers */ + TIMx->CCMR2 = tmpccmr2; + TIMx->CCER = tmpccer ; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |