From ff860844705993c18153b586b3efde8f2b77ddad Mon Sep 17 00:00:00 2001 From: cfif Date: Wed, 4 Dec 2024 13:10:47 +0300 Subject: [PATCH] Init --- inc/misc.h | 229 +++ inc/n32g45x_adc.h | 657 ++++++++ inc/n32g45x_bkp.h | 182 ++ inc/n32g45x_can.h | 670 ++++++++ inc/n32g45x_comp.h | 385 +++++ inc/n32g45x_crc.h | 105 ++ inc/n32g45x_dac.h | 307 ++++ inc/n32g45x_dbg.h | 124 ++ inc/n32g45x_dma.h | 569 +++++++ inc/n32g45x_dvp.h | 602 +++++++ inc/n32g45x_eth.h | 1608 ++++++++++++++++++ inc/n32g45x_exti.h | 206 +++ inc/n32g45x_flash.h | 375 +++++ inc/n32g45x_gpio.h | 463 ++++++ inc/n32g45x_i2c.h | 672 ++++++++ inc/n32g45x_iwdg.h | 145 ++ inc/n32g45x_opamp.h | 213 +++ inc/n32g45x_pwr.h | 179 ++ inc/n32g45x_qspi.h | 333 ++++ inc/n32g45x_rcc.h | 708 ++++++++ inc/n32g45x_rtc.h | 662 ++++++++ inc/n32g45x_sdio.h | 494 ++++++ inc/n32g45x_spi.h | 471 ++++++ inc/n32g45x_tim.h | 1114 +++++++++++++ inc/n32g45x_tsc.h | 576 +++++++ inc/n32g45x_usart.h | 398 +++++ inc/n32g45x_wwdg.h | 122 ++ inc/n32xx_tsc_alg_api.h | 302 ++++ inc/n32xx_tsc_alg_api.lib | Bin 0 -> 3211910 bytes modular.json | 12 + src/misc.c | 229 +++ src/n32g45x_adc.c | 1468 ++++++++++++++++ src/n32g45x_bkp.c | 252 +++ src/n32g45x_can.c | 1478 +++++++++++++++++ src/n32g45x_comp.c | 297 ++++ src/n32g45x_crc.c | 228 +++ src/n32g45x_dac.c | 425 +++++ src/n32g45x_dbg.c | 263 +++ src/n32g45x_dma.c | 888 ++++++++++ src/n32g45x_dvp.c | 166 ++ src/n32g45x_eth.c | 3100 ++++++++++++++++++++++++++++++++++ src/n32g45x_exti.c | 286 ++++ src/n32g45x_flash.c | 1124 +++++++++++++ src/n32g45x_gpio.c | 870 ++++++++++ src/n32g45x_i2c.c | 1306 +++++++++++++++ src/n32g45x_iwdg.c | 193 +++ src/n32g45x_opamp.c | 201 +++ src/n32g45x_pwr.c | 399 +++++ src/n32g45x_qspi.c | 612 +++++++ src/n32g45x_rcc.c | 1364 +++++++++++++++ src/n32g45x_rtc.c | 2007 ++++++++++++++++++++++ src/n32g45x_sdio.c | 789 +++++++++ src/n32g45x_spi.c | 862 ++++++++++ src/n32g45x_tim.c | 3307 +++++++++++++++++++++++++++++++++++++ src/n32g45x_tsc.c | 500 ++++++ src/n32g45x_usart.c | 970 +++++++++++ src/n32g45x_wwdg.c | 223 +++ 57 files changed, 36690 insertions(+) create mode 100644 inc/misc.h create mode 100644 inc/n32g45x_adc.h create mode 100644 inc/n32g45x_bkp.h create mode 100644 inc/n32g45x_can.h create mode 100644 inc/n32g45x_comp.h create mode 100644 inc/n32g45x_crc.h create mode 100644 inc/n32g45x_dac.h create mode 100644 inc/n32g45x_dbg.h create mode 100644 inc/n32g45x_dma.h create mode 100644 inc/n32g45x_dvp.h create mode 100644 inc/n32g45x_eth.h create mode 100644 inc/n32g45x_exti.h create mode 100644 inc/n32g45x_flash.h create mode 100644 inc/n32g45x_gpio.h create mode 100644 inc/n32g45x_i2c.h create mode 100644 inc/n32g45x_iwdg.h create mode 100644 inc/n32g45x_opamp.h create mode 100644 inc/n32g45x_pwr.h create mode 100644 inc/n32g45x_qspi.h create mode 100644 inc/n32g45x_rcc.h create mode 100644 inc/n32g45x_rtc.h create mode 100644 inc/n32g45x_sdio.h create mode 100644 inc/n32g45x_spi.h create mode 100644 inc/n32g45x_tim.h create mode 100644 inc/n32g45x_tsc.h create mode 100644 inc/n32g45x_usart.h create mode 100644 inc/n32g45x_wwdg.h create mode 100644 inc/n32xx_tsc_alg_api.h create mode 100644 inc/n32xx_tsc_alg_api.lib create mode 100644 modular.json create mode 100644 src/misc.c create mode 100644 src/n32g45x_adc.c create mode 100644 src/n32g45x_bkp.c create mode 100644 src/n32g45x_can.c create mode 100644 src/n32g45x_comp.c create mode 100644 src/n32g45x_crc.c create mode 100644 src/n32g45x_dac.c create mode 100644 src/n32g45x_dbg.c create mode 100644 src/n32g45x_dma.c create mode 100644 src/n32g45x_dvp.c create mode 100644 src/n32g45x_eth.c create mode 100644 src/n32g45x_exti.c create mode 100644 src/n32g45x_flash.c create mode 100644 src/n32g45x_gpio.c create mode 100644 src/n32g45x_i2c.c create mode 100644 src/n32g45x_iwdg.c create mode 100644 src/n32g45x_opamp.c create mode 100644 src/n32g45x_pwr.c create mode 100644 src/n32g45x_qspi.c create mode 100644 src/n32g45x_rcc.c create mode 100644 src/n32g45x_rtc.c create mode 100644 src/n32g45x_sdio.c create mode 100644 src/n32g45x_spi.c create mode 100644 src/n32g45x_tim.c create mode 100644 src/n32g45x_tsc.c create mode 100644 src/n32g45x_usart.c create mode 100644 src/n32g45x_wwdg.c diff --git a/inc/misc.h b/inc/misc.h new file mode 100644 index 0000000..543e4d1 --- /dev/null +++ b/inc/misc.h @@ -0,0 +1,229 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file misc.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __MISC_H__ +#define __MISC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup MISC + * @{ + */ + +/** @addtogroup MISC_Exported_Types + * @{ + */ + +/** + * @brief NVIC Init Structure definition + */ + +typedef struct +{ + uint8_t NVIC_IRQChannel; /*!< Specifies the IRQ channel to be enabled or disabled. + This parameter can be a value of @ref IRQn_Type + (For the complete N32G45X Devices IRQ Channels list, please + refer to n32g45x.h file) */ + + uint8_t + NVIC_IRQChannelPreemptionPriority; /*!< Specifies the pre-emption priority for the IRQ channel + specified in NVIC_IRQChannel. This parameter can be a value + between 0 and 15 as described in the table @ref NVIC_Priority_Table */ + + uint8_t NVIC_IRQChannelSubPriority; /*!< Specifies the subpriority level for the IRQ channel specified + in NVIC_IRQChannel. This parameter can be a value + between 0 and 15 as described in the table @ref NVIC_Priority_Table */ + + FunctionalState NVIC_IRQChannelCmd; /*!< Specifies whether the IRQ channel defined in NVIC_IRQChannel + will be enabled or disabled. + This parameter can be set either to ENABLE or DISABLE */ +} NVIC_InitType; + +/** + * @} + */ + +/** @addtogroup NVIC_Priority_Table + * @{ + */ + +/** +@code + The table below gives the allowed values of the pre-emption priority and subpriority according + to the Priority Grouping configuration performed by NVIC_PriorityGroupConfig function + ============================================================================================================================ + NVIC_PriorityGroup | NVIC_IRQChannelPreemptionPriority | NVIC_IRQChannelSubPriority | Description + ============================================================================================================================ + NVIC_PriorityGroup_0 | 0 | 0-15 | 0 bits for pre-emption +priority | | | 4 bits for subpriority + ---------------------------------------------------------------------------------------------------------------------------- + NVIC_PriorityGroup_1 | 0-1 | 0-7 | 1 bits for pre-emption +priority | | | 3 bits for subpriority + ---------------------------------------------------------------------------------------------------------------------------- + NVIC_PriorityGroup_2 | 0-3 | 0-3 | 2 bits for pre-emption +priority | | | 2 bits for subpriority + ---------------------------------------------------------------------------------------------------------------------------- + NVIC_PriorityGroup_3 | 0-7 | 0-1 | 3 bits for pre-emption +priority | | | 1 bits for subpriority + ---------------------------------------------------------------------------------------------------------------------------- + NVIC_PriorityGroup_4 | 0-15 | 0 | 4 bits for pre-emption +priority | | | 0 bits for subpriority + ============================================================================================================================ +@endcode +*/ + +/** + * @} + */ + +/** @addtogroup MISC_Exported_Constants + * @{ + */ + +/** @addtogroup Vector_Table_Base + * @{ + */ + +#define NVIC_VectTab_RAM ((uint32_t)0x20000000) +#define NVIC_VectTab_FLASH ((uint32_t)0x08000000) +#define IS_NVIC_VECTTAB(VECTTAB) (((VECTTAB) == NVIC_VectTab_RAM) || ((VECTTAB) == NVIC_VectTab_FLASH)) +/** + * @} + */ + +/** @addtogroup System_Low_Power + * @{ + */ + +#define NVIC_LP_SEVONPEND ((uint8_t)0x10) +#define NVIC_LP_SLEEPDEEP ((uint8_t)0x04) +#define NVIC_LP_SLEEPONEXIT ((uint8_t)0x02) +#define IS_NVIC_LP(LP) (((LP) == NVIC_LP_SEVONPEND) || ((LP) == NVIC_LP_SLEEPDEEP) || ((LP) == NVIC_LP_SLEEPONEXIT)) +/** + * @} + */ + +/** @addtogroup Preemption_Priority_Group + * @{ + */ + +#define NVIC_PriorityGroup_0 \ + ((uint32_t)0x700) /*!< 0 bits for pre-emption priority \ + 4 bits for subpriority */ +#define NVIC_PriorityGroup_1 \ + ((uint32_t)0x600) /*!< 1 bits for pre-emption priority \ + 3 bits for subpriority */ +#define NVIC_PriorityGroup_2 \ + ((uint32_t)0x500) /*!< 2 bits for pre-emption priority \ + 2 bits for subpriority */ +#define NVIC_PriorityGroup_3 \ + ((uint32_t)0x400) /*!< 3 bits for pre-emption priority \ + 1 bits for subpriority */ +#define NVIC_PriorityGroup_4 \ + ((uint32_t)0x300) /*!< 4 bits for pre-emption priority \ + 0 bits for subpriority */ + +#define IS_NVIC_PRIORITY_GROUP(GROUP) \ + (((GROUP) == NVIC_PriorityGroup_0) || ((GROUP) == NVIC_PriorityGroup_1) || ((GROUP) == NVIC_PriorityGroup_2) \ + || ((GROUP) == NVIC_PriorityGroup_3) || ((GROUP) == NVIC_PriorityGroup_4)) + +#define IS_NVIC_PREEMPTION_PRIORITY(PRIORITY) ((PRIORITY) < 0x10) + +#define IS_NVIC_SUB_PRIORITY(PRIORITY) ((PRIORITY) < 0x10) + +#define IS_NVIC_OFFSET(OFFSET) ((OFFSET) < 0x000FFFFF) + +/** + * @} + */ + +/** @addtogroup SysTick_clock_source + * @{ + */ + +#define SysTick_CLKSource_HCLK_Div8 ((uint32_t)0xFFFFFFFB) +#define SysTick_CLKSource_HCLK ((uint32_t)0x00000004) +#define IS_SYSTICK_CLK_SOURCE(SOURCE) \ + (((SOURCE) == SysTick_CLKSource_HCLK) || ((SOURCE) == SysTick_CLKSource_HCLK_Div8)) +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup MISC_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup MISC_Exported_Functions + * @{ + */ + +void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup); +void NVIC_Init(NVIC_InitType* NVIC_InitStruct); +void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset); +void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState Cmd); +void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource); + +#ifdef __cplusplus +} +#endif + +#endif /* __MISC_H__ */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/inc/n32g45x_adc.h b/inc/n32g45x_adc.h new file mode 100644 index 0000000..37d99ca --- /dev/null +++ b/inc/n32g45x_adc.h @@ -0,0 +1,657 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_adc.h + * @author Nations + * @version v1.0.3 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_ADC_H__ +#define __N32G45X_ADC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" +#include + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ +#define VREF1P2_CTRL (*(uint32_t*)(0x40001800+0x20)) +#define _EnVref1p2() do{VREF1P2_CTRL|=(1<<10);}while(0); +#define _DisVref1p2() do{VREF1P2_CTRL&=~(1<<10);}while(0); +/** @addtogroup ADC + * @{ + */ + +/** @addtogroup ADC_Exported_Types + * @{ + */ + +/** + * @brief ADC Init structure definition + */ +typedef struct +{ + uint32_t WorkMode; /*!< Configures the ADC to operate in independent or + dual mode. + This parameter can be a value of @ref ADC_mode */ + + FunctionalState MultiChEn; /*!< Specifies whether the conversion is performed in + Scan (multichannels) or Single (one channel) mode. + This parameter can be set to ENABLE or DISABLE */ + + FunctionalState ContinueConvEn; /*!< Specifies whether the conversion is performed in + Continuous or Single mode. + This parameter can be set to ENABLE or DISABLE. */ + + uint32_t ExtTrigSelect; /*!< Defines the external trigger used to start the analog + to digital conversion of regular channels. This parameter + can be a value of @ref + ADC_external_trigger_sources_for_regular_channels_conversion */ + + uint32_t DatAlign; /*!< Specifies whether the ADC data alignment is left or right. + This parameter can be a value of @ref ADC_data_align */ + + uint8_t ChsNumber; /*!< Specifies the number of ADC channels that will be converted + using the sequencer for regular channel group. + This parameter must range from 1 to 16. */ +} ADC_InitType; +/** + * @} + */ + +/** @addtogroup ADC_Exported_Constants + * @{ + */ + +#define IsAdcModule(PERIPH) (((PERIPH) == ADC1) || ((PERIPH) == ADC2) || ((PERIPH) == ADC3) || ((PERIPH) == ADC4)) + +#define IsAdcDmaModule(PERIPH) (((PERIPH) == ADC1) || ((PERIPH) == ADC2) || ((PERIPH) == ADC3) || ((PERIPH) == ADC4)) + +/** @addtogroup ADC_mode + * @{ + */ + +#define ADC_WORKMODE_INDEPENDENT ((uint32_t)0x00000000) +#define ADC_WORKMODE_REG_INJECT_SIMULT ((uint32_t)0x00010000) +#define ADC_WORKMODE_REG_SIMULT_ALTER_TRIG ((uint32_t)0x00020000) +#define ADC_WORKMODE_INJ_SIMULT_FAST_INTERL ((uint32_t)0x00030000) +#define ADC_WORKMODE_INJ_SIMULT_SLOW_INTERL ((uint32_t)0x00040000) +#define ADC_WORKMODE_INJ_SIMULT ((uint32_t)0x00050000) +#define ADC_WORKMODE_REG_SIMULT ((uint32_t)0x00060000) +#define ADC_WORKMODE_FAST_INTERL ((uint32_t)0x00070000) +#define ADC_WORKMODE_SLOW_INTERL ((uint32_t)0x00080000) +#define ADC_WORKMODE_ALTER_TRIG ((uint32_t)0x00090000) + +#define IsAdcWorkMode(MODE) \ + (((MODE) == ADC_WORKMODE_INDEPENDENT) || ((MODE) == ADC_WORKMODE_REG_INJECT_SIMULT) \ + || ((MODE) == ADC_WORKMODE_REG_SIMULT_ALTER_TRIG) || ((MODE) == ADC_WORKMODE_INJ_SIMULT_FAST_INTERL) \ + || ((MODE) == ADC_WORKMODE_INJ_SIMULT_SLOW_INTERL) || ((MODE) == ADC_WORKMODE_INJ_SIMULT) \ + || ((MODE) == ADC_WORKMODE_REG_SIMULT) || ((MODE) == ADC_WORKMODE_FAST_INTERL) \ + || ((MODE) == ADC_WORKMODE_SLOW_INTERL) || ((MODE) == ADC_WORKMODE_ALTER_TRIG)) +/** + * @} + */ + +/** @addtogroup ADC_external_trigger_sources_for_regular_channels_conversion + * @{ + */ + +#define ADC_EXT_TRIGCONV_T1_CC1 ((uint32_t)0x00000000) /*!< For ADC1 and ADC2 */ +#define ADC_EXT_TRIGCONV_T1_CC2 ((uint32_t)0x00020000) /*!< For ADC1 and ADC2 */ +#define ADC_EXT_TRIGCONV_T2_CC2 ((uint32_t)0x00060000) /*!< For ADC1 and ADC2 */ +#define ADC_EXT_TRIGCONV_T3_TRGO ((uint32_t)0x00080000) /*!< For ADC1 and ADC2 */ +#define ADC_EXT_TRIGCONV_T4_CC4 ((uint32_t)0x000A0000) /*!< For ADC1 and ADC2 */ +#define ADC_EXT_TRIGCONV_EXT_INT11_TIM8_TRGO ((uint32_t)0x000C0000) /*!< For ADC1 and ADC2 */ + +#define ADC_EXT_TRIGCONV_T1_CC3 ((uint32_t)0x00040000) /*!< For ADC1, ADC2 , ADC3 and ADC4 */ +#define ADC_EXT_TRIGCONV_NONE ((uint32_t)0x000E0000) /*!< For ADC1, ADC2 , ADC3 and ADC4 */ + +#define ADC_EXT_TRIGCONV_T3_CC1 ((uint32_t)0x00000000) /*!< For ADC3 and ADC4 */ +#define ADC_EXT_TRIGCONV_T2_CC3 ((uint32_t)0x00020000) /*!< For ADC3 and ADC4 */ +#define ADC_EXT_TRIGCONV_T8_CC1 ((uint32_t)0x00060000) /*!< For ADC3 and ADC4 */ +#define ADC_EXT_TRIGCONV_T8_TRGO ((uint32_t)0x00080000) /*!< For ADC3 and ADC4 */ +#define ADC_EXT_TRIGCONV_T5_CC1 ((uint32_t)0x000A0000) /*!< For ADC3 and ADC4 */ +#define ADC_EXT_TRIGCONV_EXT_INT10_T5_CC3 ((uint32_t)0x000C0000) /*!< For ADC3 and ADC4 */ + +#define IsAdcExtTrig(REGTRIG) \ + (((REGTRIG) == ADC_EXT_TRIGCONV_T1_CC1) || ((REGTRIG) == ADC_EXT_TRIGCONV_T1_CC2) \ + || ((REGTRIG) == ADC_EXT_TRIGCONV_T1_CC3) || ((REGTRIG) == ADC_EXT_TRIGCONV_T2_CC2) \ + || ((REGTRIG) == ADC_EXT_TRIGCONV_T3_TRGO) || ((REGTRIG) == ADC_EXT_TRIGCONV_T4_CC4) \ + || ((REGTRIG) == ADC_EXT_TRIGCONV_EXT_INT11_TIM8_TRGO) || ((REGTRIG) == ADC_EXT_TRIGCONV_NONE) \ + || ((REGTRIG) == ADC_EXT_TRIGCONV_T3_CC1) || ((REGTRIG) == ADC_EXT_TRIGCONV_T2_CC3) \ + || ((REGTRIG) == ADC_EXT_TRIGCONV_T8_CC1) || ((REGTRIG) == ADC_EXT_TRIGCONV_T8_TRGO) \ + || ((REGTRIG) == ADC_EXT_TRIGCONV_T5_CC1) || ((REGTRIG) == ADC_EXT_TRIGCONV_EXT_INT10_T5_CC3)) +/** + * @} + */ + +/** @addtogroup ADC_data_align + * @{ + */ + +#define ADC_DAT_ALIGN_R ((uint32_t)0x00000000) +#define ADC_DAT_ALIGN_L ((uint32_t)0x00000800) +#define IsAdcDatAlign(ALIGN) (((ALIGN) == ADC_DAT_ALIGN_R) || ((ALIGN) == ADC_DAT_ALIGN_L)) +/** + * @} + */ + +/** @addtogroup ADC_channels + * @{ + */ + +#define ADC_CH_0 ((uint8_t)0x00) +#define ADC_CH_1 ((uint8_t)0x01) +#define ADC_CH_2 ((uint8_t)0x02) +#define ADC_CH_3 ((uint8_t)0x03) +#define ADC_CH_4 ((uint8_t)0x04) +#define ADC_CH_5 ((uint8_t)0x05) +#define ADC_CH_6 ((uint8_t)0x06) +#define ADC_CH_7 ((uint8_t)0x07) +#define ADC_CH_8 ((uint8_t)0x08) +#define ADC_CH_9 ((uint8_t)0x09) +#define ADC_CH_10 ((uint8_t)0x0A) +#define ADC_CH_11 ((uint8_t)0x0B) +#define ADC_CH_12 ((uint8_t)0x0C) +#define ADC_CH_13 ((uint8_t)0x0D) +#define ADC_CH_14 ((uint8_t)0x0E) +#define ADC_CH_15 ((uint8_t)0x0F) +#define ADC_CH_16 ((uint8_t)0x10) +#define ADC_CH_17 ((uint8_t)0x11) +#define ADC_CH_18 ((uint8_t)0x12) + +#define ADC_CH_TEMP_SENSOR ((uint8_t)ADC_CH_16) +#define ADC_CH_INT_VREF ((uint8_t)ADC_CH_18) + +#define IsAdcChannel(CHANNEL) \ + (((CHANNEL) == ADC_CH_0) || ((CHANNEL) == ADC_CH_1) || ((CHANNEL) == ADC_CH_2) || ((CHANNEL) == ADC_CH_3) \ + || ((CHANNEL) == ADC_CH_4) || ((CHANNEL) == ADC_CH_5) || ((CHANNEL) == ADC_CH_6) || ((CHANNEL) == ADC_CH_7) \ + || ((CHANNEL) == ADC_CH_8) || ((CHANNEL) == ADC_CH_9) || ((CHANNEL) == ADC_CH_10) || ((CHANNEL) == ADC_CH_11) \ + || ((CHANNEL) == ADC_CH_12) || ((CHANNEL) == ADC_CH_13) || ((CHANNEL) == ADC_CH_14) || ((CHANNEL) == ADC_CH_15) \ + || ((CHANNEL) == ADC_CH_16) || ((CHANNEL) == ADC_CH_17) || ((CHANNEL) == ADC_CH_18)) +/** + * @} + */ + +/** @addtogroup ADC_sampling_time + * @{ + */ + +#define ADC_SAMP_TIME_1CYCLES5 ((uint8_t)0x00) +#define ADC_SAMP_TIME_7CYCLES5 ((uint8_t)0x01) +#define ADC_SAMP_TIME_13CYCLES5 ((uint8_t)0x02) +#define ADC_SAMP_TIME_28CYCLES5 ((uint8_t)0x03) +#define ADC_SAMP_TIME_41CYCLES5 ((uint8_t)0x04) +#define ADC_SAMP_TIME_55CYCLES5 ((uint8_t)0x05) +#define ADC_SAMP_TIME_71CYCLES5 ((uint8_t)0x06) +#define ADC_SAMP_TIME_239CYCLES5 ((uint8_t)0x07) +#define IsAdcSampleTime(TIME) \ + (((TIME) == ADC_SAMP_TIME_1CYCLES5) || ((TIME) == ADC_SAMP_TIME_7CYCLES5) || ((TIME) == ADC_SAMP_TIME_13CYCLES5) \ + || ((TIME) == ADC_SAMP_TIME_28CYCLES5) || ((TIME) == ADC_SAMP_TIME_41CYCLES5) \ + || ((TIME) == ADC_SAMP_TIME_55CYCLES5) || ((TIME) == ADC_SAMP_TIME_71CYCLES5) \ + || ((TIME) == ADC_SAMP_TIME_239CYCLES5)) +/** + * @} + */ + +/** @addtogroup ADC_external_trigger_sources_for_injected_channels_conversion + * @{ + */ + +#define ADC_EXT_TRIG_INJ_CONV_T2_TRGO ((uint32_t)0x00002000) /*!< For ADC1 and ADC2 */ +#define ADC_EXT_TRIG_INJ_CONV_T2_CC1 ((uint32_t)0x00003000) /*!< For ADC1 and ADC2 */ +#define ADC_EXT_TRIG_INJ_CONV_T3_CC4 ((uint32_t)0x00004000) /*!< For ADC1 and ADC2 */ +#define ADC_EXT_TRIG_INJ_CONV_T4_TRGO ((uint32_t)0x00005000) /*!< For ADC1 and ADC2 */ +#define ADC_EXT_TRIG_INJ_CONV_EXT_INT15_TIM8_CC4 ((uint32_t)0x00006000) /*!< For ADC1 and ADC2 */ + +#define ADC_EXT_TRIG_INJ_CONV_T1_TRGO ((uint32_t)0x00000000) /*!< For ADC1, ADC2, ADC3 and ADC4 */ +#define ADC_EXT_TRIG_INJ_CONV_T1_CC4 ((uint32_t)0x00001000) /*!< For ADC1, ADC2, ADC3 and ADC4 */ +#define ADC_EXT_TRIG_INJ_CONV_NONE ((uint32_t)0x00007000) /*!< For ADC1, ADC2, ADC3 and ADC4 */ + +#define ADC_EXT_TRIG_INJ_CONV_T4_CC3 ((uint32_t)0x00002000) /*!< For ADC3 and ADC4 */ +#define ADC_EXT_TRIG_INJ_CONV_T8_CC2 ((uint32_t)0x00003000) /*!< For ADC3 and ADC4 */ +#define ADC_EXT_TRIG_INJ_CONV_T8_CC4 ((uint32_t)0x00004000) /*!< For ADC3 and ADC4 */ +#define ADC_EXT_TRIG_INJ_CONV_T5_TRGO ((uint32_t)0x00005000) /*!< For ADC3 and ADC4 */ +#define ADC_EXT_TRIG_INJ_CONV_EXT_INT14_T5_CC4 ((uint32_t)0x00006000) /*!< For ADC3 and ADC4 */ + +#define IsAdcExtInjTrig(INJTRIG) \ + (((INJTRIG) == ADC_EXT_TRIG_INJ_CONV_T1_TRGO) || ((INJTRIG) == ADC_EXT_TRIG_INJ_CONV_T1_CC4) \ + || ((INJTRIG) == ADC_EXT_TRIG_INJ_CONV_T2_TRGO) || ((INJTRIG) == ADC_EXT_TRIG_INJ_CONV_T2_CC1) \ + || ((INJTRIG) == ADC_EXT_TRIG_INJ_CONV_T3_CC4) || ((INJTRIG) == ADC_EXT_TRIG_INJ_CONV_T4_TRGO) \ + || ((INJTRIG) == ADC_EXT_TRIG_INJ_CONV_EXT_INT15_TIM8_CC4) || ((INJTRIG) == ADC_EXT_TRIG_INJ_CONV_NONE) \ + || ((INJTRIG) == ADC_EXT_TRIG_INJ_CONV_T4_CC3) || ((INJTRIG) == ADC_EXT_TRIG_INJ_CONV_T8_CC2) \ + || ((INJTRIG) == ADC_EXT_TRIG_INJ_CONV_T8_CC4) || ((INJTRIG) == ADC_EXT_TRIG_INJ_CONV_T5_TRGO) \ + || ((INJTRIG) == ADC_EXT_TRIG_INJ_CONV_EXT_INT14_T5_CC4)) +/** + * @} + */ + +/** @addtogroup ADC_injected_channel_selection + * @{ + */ + +#define ADC_INJ_CH_1 ((uint8_t)0x14) +#define ADC_INJ_CH_2 ((uint8_t)0x18) +#define ADC_INJ_CH_3 ((uint8_t)0x1C) +#define ADC_INJ_CH_4 ((uint8_t)0x20) +#define IsAdcInjCh(CHANNEL) \ + (((CHANNEL) == ADC_INJ_CH_1) || ((CHANNEL) == ADC_INJ_CH_2) || ((CHANNEL) == ADC_INJ_CH_3) \ + || ((CHANNEL) == ADC_INJ_CH_4)) +/** + * @} + */ + +/** @addtogroup ADC_analog_watchdog_selection + * @{ + */ + +#define ADC_ANALOG_WTDG_SINGLEREG_ENABLE ((uint32_t)0x00800200) +#define ADC_ANALOG_WTDG_SINGLEINJEC_ENABLE ((uint32_t)0x00400200) +#define ADC_ANALOG_WTDG_SINGLEREG_OR_INJEC_ENABLE ((uint32_t)0x00C00200) +#define ADC_ANALOG_WTDG_ALLREG_ENABLE ((uint32_t)0x00800000) +#define ADC_ANALOG_WTDG_ALLINJEC_ENABLE ((uint32_t)0x00400000) +#define ADC_ANALOG_WTDG_ALLREG_ALLINJEC_ENABLE ((uint32_t)0x00C00000) +#define ADC_ANALOG_WTDG_NONE ((uint32_t)0x00000000) + +#define IsAdcAnalogWatchdog(WATCHDOG) \ + (((WATCHDOG) == ADC_ANALOG_WTDG_SINGLEREG_ENABLE) || ((WATCHDOG) == ADC_ANALOG_WTDG_SINGLEINJEC_ENABLE) \ + || ((WATCHDOG) == ADC_ANALOG_WTDG_SINGLEREG_OR_INJEC_ENABLE) || ((WATCHDOG) == ADC_ANALOG_WTDG_ALLREG_ENABLE) \ + || ((WATCHDOG) == ADC_ANALOG_WTDG_ALLINJEC_ENABLE) || ((WATCHDOG) == ADC_ANALOG_WTDG_ALLREG_ALLINJEC_ENABLE) \ + || ((WATCHDOG) == ADC_ANALOG_WTDG_NONE)) +/** + * @} + */ + +/** @addtogroup ADC_interrupts_definition + * @{ + */ + +#define ADC_INT_ENDC ((uint16_t)0x0220) +#define ADC_INT_AWD ((uint16_t)0x0140) +#define ADC_INT_JENDC ((uint16_t)0x0480) + +#define IsAdcInt(IT) ((((IT) & (uint16_t)0xF81F) == 0x00) && ((IT) != 0x00)) + +#define IsAdcGetInt(IT) (((IT) == ADC_INT_ENDC) || ((IT) == ADC_INT_AWD) || ((IT) == ADC_INT_JENDC)) +/** + * @} + */ + +/** @addtogroup ADC_flags_definition + * @{ + */ + +#define ADC_FLAG_AWDG ((uint8_t)0x01) +#define ADC_FLAG_ENDC ((uint8_t)0x02) +#define ADC_FLAG_JENDC ((uint8_t)0x04) +#define ADC_FLAG_JSTR ((uint8_t)0x08) +#define ADC_FLAG_STR ((uint8_t)0x10) +#define ADC_FLAG_EOC_ANY ((uint8_t)0x20) +#define ADC_FLAG_JEOC_ANY ((uint8_t)0x40) +#define IsAdcClrFlag(FLAG) ((((FLAG) & (uint8_t)0x80) == 0x00) && ((FLAG) != 0x00)) +#define IsAdcGetFlag(FLAG) \ + (((FLAG) == ADC_FLAG_AWDG) || ((FLAG) == ADC_FLAG_ENDC) || ((FLAG) == ADC_FLAG_JENDC) || ((FLAG) == ADC_FLAG_JSTR) \ + || ((FLAG) == ADC_FLAG_STR) || ((FLAG) == ADC_FLAG_EOC_ANY) || ((FLAG) == ADC_FLAG_JEOC_ANY)) +/** + * @} + */ + +/** @addtogroup ADC_thresholds + * @{ + */ +#define IsAdcValid(THRESHOLD) ((THRESHOLD) <= 0xFFF) +/** + * @} + */ + +/** @addtogroup ADC_injected_offset + * @{ + */ + +#define IsAdcOffsetValid(OFFSET) ((OFFSET) <= 0xFFF) + +/** + * @} + */ + +/** @addtogroup ADC_injected_length + * @{ + */ + +#define IsAdcInjLenValid(LENGTH) (((LENGTH) >= 0x1) && ((LENGTH) <= 0x4)) + +/** + * @} + */ + +/** @addtogroup ADC_injected_rank + * @{ + */ + +#define IsAdcInjRankValid(RANK) (((RANK) >= 0x1) && ((RANK) <= 0x4)) + +/** + * @} + */ + +/** @addtogroup ADC_regular_length + * @{ + */ + +#define IsAdcSeqLenValid(LENGTH) (((LENGTH) >= 0x1) && ((LENGTH) <= 0x10)) +/** + * @} + */ + +/** @addtogroup ADC_regular_rank + * @{ + */ + +#define IsAdcReqRankValid(RANK) (((RANK) >= 0x1) && ((RANK) <= 0x10)) + +/** + * @} + */ + +/** @addtogroup ADC_regular_discontinuous_mode_number + * @{ + */ + +#define IsAdcSeqDiscNumberValid(NUMBER) (((NUMBER) >= 0x1) && ((NUMBER) <= 0x8)) + +/** + * @} + */ + +/************************** fllowing bit seg in ex register **********************/ +/**@addtogroup ADC_channels_ex_style + * @{ + */ +#define ADC1_Channel_01_PA0 ((uint8_t)0x01) +#define ADC1_Channel_02_PA1 ((uint8_t)0x02) +#define ADC1_Channel_03_PA6 ((uint8_t)0x03) +#define ADC1_Channel_04_PA3 ((uint8_t)0x04) +#define ADC1_Channel_05_PF4 ((uint8_t)0x05) +#define ADC1_Channel_06_PC0 ((uint8_t)0x06) +#define ADC1_Channel_07_PC1 ((uint8_t)0x07) +#define ADC1_Channel_08_PC2 ((uint8_t)0x08) +#define ADC1_Channel_09_PC3 ((uint8_t)0x09) +#define ADC1_Channel_10_PF2 ((uint8_t)0x0A) +#define ADC1_Channel_11_PA2 ((uint8_t)0x0B) + +#define ADC2_Channel_01_PA4 ((uint8_t)0x01) +#define ADC2_Channel_02_PA5 ((uint8_t)0x02) +#define ADC2_Channel_03_PB1 ((uint8_t)0x03) +#define ADC2_Channel_04_PA7 ((uint8_t)0x04) +#define ADC2_Channel_05_PC4 ((uint8_t)0x05) +#define ADC2_Channel_06_PC0 ((uint8_t)0x06) +#define ADC2_Channel_07_PC1 ((uint8_t)0x07) +#define ADC2_Channel_08_PC2 ((uint8_t)0x08) +#define ADC2_Channel_09_PC3 ((uint8_t)0x09) +#define ADC2_Channel_10_PF2 ((uint8_t)0x0A) +#define ADC2_Channel_11_PA2 ((uint8_t)0x0B) +#define ADC2_Channel_12_PC5 ((uint8_t)0x0C) +#define ADC2_Channel_13_PB2 ((uint8_t)0x0D) + +#define ADC3_Channel_01_PB11 ((uint8_t)0x01) +#define ADC3_Channel_02_PE9 ((uint8_t)0x02) +#define ADC3_Channel_03_PE13 ((uint8_t)0x03) +#define ADC3_Channel_04_PE12 ((uint8_t)0x04) +#define ADC3_Channel_05_PB13 ((uint8_t)0x05) +#define ADC3_Channel_06_PE8 ((uint8_t)0x06) +#define ADC3_Channel_07_PD10 ((uint8_t)0x07) +#define ADC3_Channel_08_PD11 ((uint8_t)0x08) +#define ADC3_Channel_09_PD12 ((uint8_t)0x09) +#define ADC3_Channel_10_PD13 ((uint8_t)0x0A) +#define ADC3_Channel_11_PD14 ((uint8_t)0x0B) +#define ADC3_Channel_12_PB0 ((uint8_t)0x0C) +#define ADC3_Channel_13_PE7 ((uint8_t)0x0D) +#define ADC3_Channel_14_PE10 ((uint8_t)0x0E) +#define ADC3_Channel_15_PE11 ((uint8_t)0x0F) + +#define ADC4_Channel_01_PE14 ((uint8_t)0x01) +#define ADC4_Channel_02_PE15 ((uint8_t)0x02) +#define ADC4_Channel_03_PB12 ((uint8_t)0x03) +#define ADC4_Channel_04_PB14 ((uint8_t)0x04) +#define ADC4_Channel_05_PB15 ((uint8_t)0x05) +#define ADC4_Channel_06_PE8 ((uint8_t)0x06) +#define ADC4_Channel_07_PD10 ((uint8_t)0x07) +#define ADC4_Channel_08_PD11 ((uint8_t)0x08) +#define ADC4_Channel_09_PD12 ((uint8_t)0x09) +#define ADC4_Channel_10_PD13 ((uint8_t)0x0A) +#define ADC4_Channel_11_PD14 ((uint8_t)0x0B) +#define ADC4_Channel_12_PD8 ((uint8_t)0x0C) +#define ADC4_Channel_13_PD9 ((uint8_t)0x0D) + +#define ADC_CH_0 ((uint8_t)0x00) +#define ADC_CH_1 ((uint8_t)0x01) +#define ADC_CH_2 ((uint8_t)0x02) +#define ADC_CH_3 ((uint8_t)0x03) +#define ADC_CH_4 ((uint8_t)0x04) +#define ADC_CH_5 ((uint8_t)0x05) +#define ADC_CH_6 ((uint8_t)0x06) +#define ADC_CH_7 ((uint8_t)0x07) +#define ADC_CH_8 ((uint8_t)0x08) +#define ADC_CH_9 ((uint8_t)0x09) +#define ADC_CH_10 ((uint8_t)0x0A) +#define ADC_CH_11 ((uint8_t)0x0B) +#define ADC_CH_12 ((uint8_t)0x0C) +#define ADC_CH_13 ((uint8_t)0x0D) +#define ADC_CH_14 ((uint8_t)0x0E) +#define ADC_CH_15 ((uint8_t)0x0F) +#define ADC_CH_16 ((uint8_t)0x10) +#define ADC_CH_17 ((uint8_t)0x11) +#define ADC_CH_18 ((uint8_t)0x12) +/** + * @} + */ + +/**@addtogroup ADC_dif_sel_ch_definition + * @{ + */ +#define ADC_DIFSEL_CHS_MASK ((uint32_t)0x0007FFFE) +#define ADC_DIFSEL_CHS_1 ((uint32_t)0x00000002) +#define ADC_DIFSEL_CHS_2 ((uint32_t)0x00000004) +#define ADC_DIFSEL_CHS_3 ((uint32_t)0x00000008) +#define ADC_DIFSEL_CHS_4 ((uint32_t)0x00000010) +#define ADC_DIFSEL_CHS_5 ((uint32_t)0x00000020) +#define ADC_DIFSEL_CHS_6 ((uint32_t)0x00000040) +#define ADC_DIFSEL_CHS_7 ((uint32_t)0x00000080) +#define ADC_DIFSEL_CHS_8 ((uint32_t)0x00000100) +#define ADC_DIFSEL_CHS_9 ((uint32_t)0x00000200) +#define ADC_DIFSEL_CHS_10 ((uint32_t)0x00000400) +#define ADC_DIFSEL_CHS_11 ((uint32_t)0x00000800) +#define ADC_DIFSEL_CHS_12 ((uint32_t)0x00001000) +#define ADC_DIFSEL_CHS_13 ((uint32_t)0x00002000) +#define ADC_DIFSEL_CHS_14 ((uint32_t)0x00004000) +#define ADC_DIFSEL_CHS_15 ((uint32_t)0x00008000) +#define ADC_DIFSEL_CHS_16 ((uint32_t)0x00010000) +#define ADC_DIFSEL_CHS_17 ((uint32_t)0x00020000) +#define ADC_DIFSEL_CHS_18 ((uint32_t)0x00040000) +/** + * @} + */ + +/**@addtogroup ADC_calfact_definition + * @{ + */ +#define ADC_CALFACT_CALFACTD_MSK ((uint32_t)0x3FL << 16) +#define ADC_CALFACT_CALFACTS_MSK ((uint32_t)0x3FL << 0) +/** + * @} + */ + +/**@addtogroup ADC_ctrl3_definition + * @{ + */ +#define ADC_CTRL3_VABTMEN_MSK ((uint32_t)0x01L << 11) +#define ADC_CTRL3_DPWMOD_MSK ((uint32_t)0x01L << 10) +#define ADC_CTRL3_JENDCAIEN_MSK ((uint32_t)0x01L << 9) +#define ADC_CTRL3_ENDCAIEN_MSK ((uint32_t)0x01L << 8) +#define ADC_CTRL3_BPCAL_MSK ((uint32_t)0x01L << 7) +#define ADC_CTRL3_PDRDY_MSK ((uint32_t)0x01L << 6) +#define ADC_CTRL3_RDY_MSK ((uint32_t)0x01L << 5) +#define ADC_CTRL3_CKMOD_MSK ((uint32_t)0x01L << 4) +#define ADC_CTRL3_CALALD_MSK ((uint32_t)0x01L << 3) +#define ADC_CTRL3_CALDIF_MSK ((uint32_t)0x01L << 2) +#define ADC_CTRL3_RES_MSK ((uint32_t)0x03L << 0) +/** + * @} + */ + +/**@addtogroup ADC_sampt3_definition + * @{ + */ +#define ADC_SAMPT3_SAMPSEL_MSK ((uint32_t)0x01L << 3) +/** + * @} + */ + +typedef enum +{ + ADC_CTRL3_CKMOD_AHB = 0, + ADC_CTRL3_CKMOD_PLL = 1, +} ADC_CTRL3_CKMOD; +typedef enum +{ + ADC_CTRL3_RES_12BIT = 3, + ADC_CTRL3_RES_10BIT = 2, + ADC_CTRL3_RES_8BIT = 1, + ADC_CTRL3_RES_6BIT = 0, +} ADC_CTRL3_RES; +typedef struct +{ + FunctionalState VbatMinitEn; + FunctionalState DeepPowerModEn; + FunctionalState JendcIntEn; + FunctionalState EndcIntEn; + ADC_CTRL3_CKMOD ClkMode; + FunctionalState CalAtuoLoadEn; + bool DifModCal; + ADC_CTRL3_RES ResBit; + bool SampSecondStyle; +} ADC_InitTypeEx; +/** + * @} + */ + +/*ADC_SAMPT3 only have samp time and smp18[2:0],samp18 is refint ch, change to row function*/ +/*ADC_IPTST reseverd register ,not to do it*/ + +/**@addtogroup ADC_bit_num_definition + * @{ + */ +#define ADC_RST_BIT_12 ((uint32_t)0x03) +#define ADC_RST_BIT_10 ((uint32_t)0x02) +#define ADC_RST_BIT_8 ((uint32_t)0x01) +#define ADC_RESULT_BIT_6 ((uint32_t)0x00) +/** + * @} + */ + +/** @addtogroup ADC_flags_ex_definition + * @{ + */ +#define ADC_FLAG_RDY ((uint8_t)0x20) +#define ADC_FLAG_PD_RDY ((uint8_t)0x40) +#define IS_ADC_GET_READY(FLAG) (((FLAG) == ADC_FLAG_RDY) || ((FLAG) == ADC_FLAG_PD_RDY) +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup ADC_Exported_Functions + * @{ + */ + +void ADC_DeInit(ADC_Module* ADCx); +void ADC_Init(ADC_Module* ADCx, ADC_InitType* ADC_InitStruct); +void ADC_InitStruct(ADC_InitType* ADC_InitStruct); +void ADC_Enable(ADC_Module* ADCx, FunctionalState Cmd); +void ADC_EnableDMA(ADC_Module* ADCx, FunctionalState Cmd); +void ADC_ConfigInt(ADC_Module* ADCx, uint16_t ADC_IT, FunctionalState Cmd); +void ADC_StartCalibration(ADC_Module* ADCx); +FlagStatus ADC_GetCalibrationStatus(ADC_Module* ADCx); +void ADC_EnableSoftwareStartConv(ADC_Module* ADCx, FunctionalState Cmd); +FlagStatus ADC_GetSoftwareStartConvStatus(ADC_Module* ADCx); +void ADC_ConfigDiscModeChannelCount(ADC_Module* ADCx, uint8_t Number); +void ADC_EnableDiscMode(ADC_Module* ADCx, FunctionalState Cmd); +void ADC_ConfigRegularChannel(ADC_Module* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime); +void ADC_EnableExternalTrigConv(ADC_Module* ADCx, FunctionalState Cmd); +uint16_t ADC_GetDat(ADC_Module* ADCx); +uint32_t ADC_GetDualModeConversionDat(ADC_Module* ADCx); +void ADC_EnableAutoInjectedConv(ADC_Module* ADCx, FunctionalState Cmd); +void ADC_EnableInjectedDiscMode(ADC_Module* ADCx, FunctionalState Cmd); +void ADC_ConfigExternalTrigInjectedConv(ADC_Module* ADCx, uint32_t ADC_ExternalTrigInjecConv); +void ADC_EnableExternalTrigInjectedConv(ADC_Module* ADCx, FunctionalState Cmd); +void ADC_EnableSoftwareStartInjectedConv(ADC_Module* ADCx, FunctionalState Cmd); +FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_Module* ADCx); +void ADC_ConfigInjectedChannel(ADC_Module* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime); +void ADC_ConfigInjectedSequencerLength(ADC_Module* ADCx, uint8_t Length); +void ADC_SetInjectedOffsetDat(ADC_Module* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset); +uint16_t ADC_GetInjectedConversionDat(ADC_Module* ADCx, uint8_t ADC_InjectedChannel); +void ADC_ConfigAnalogWatchdogWorkChannelType(ADC_Module* ADCx, uint32_t ADC_AnalogWatchdog); +void ADC_ConfigAnalogWatchdogThresholds(ADC_Module* ADCx, uint16_t HighThreshold, uint16_t LowThreshold); +void ADC_ConfigAnalogWatchdogSingleChannel(ADC_Module* ADCx, uint8_t ADC_Channel); +void ADC_EnableTempSensorVrefint(FunctionalState Cmd); +FlagStatus ADC_GetFlagStatus(ADC_Module* ADCx, uint8_t ADC_FLAG); +void ADC_ClearFlag(ADC_Module* ADCx, uint8_t ADC_FLAG); +INTStatus ADC_GetIntStatus(ADC_Module* ADCx, uint16_t ADC_IT); +void ADC_ClearIntPendingBit(ADC_Module* ADCx, uint16_t ADC_IT); + +void ADC_InitEx(ADC_Module* ADCx, ADC_InitTypeEx* ADC_InitStructEx); +void ADC_SetDifChs(ADC_Module* ADCx,uint32_t DifChs); +FlagStatus ADC_GetFlagStatusNew(ADC_Module* ADCx, uint8_t ADC_FLAG_NEW); +void ADC_SetBypassCalibration(ADC_Module* ADCx, FunctionalState en); +void ADC_SetConvResultBitNum(ADC_Module* ADCx, uint32_t ResultBitNum); + +void ADC_ConfigClk(ADC_CTRL3_CKMOD ADC_ClkMode, uint32_t RCC_ADCHCLKPrescaler); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /*__N32G45X_ADC_H__ */ + +/** + * @} + */ +/** + * @} + */ diff --git a/inc/n32g45x_bkp.h b/inc/n32g45x_bkp.h new file mode 100644 index 0000000..7b47b97 --- /dev/null +++ b/inc/n32g45x_bkp.h @@ -0,0 +1,182 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_bkp.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_BKP_H__ +#define __N32G45X_BKP_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup BKP + * @{ + */ + +/** @addtogroup BKP_Exported_Types + * @{ + */ + +/** + * @} + */ + +/** @addtogroup BKP_Exported_Constants + * @{ + */ + +/** @addtogroup Tamper_Pin_active_level + * @{ + */ + +#define BKP_TP_HIGH ((uint16_t)0x0000) +#define BKP_TP_LOW ((uint16_t)0x0001) +#define IS_BKP_TP_LEVEL(LEVEL) (((LEVEL) == BKP_TP_HIGH) || ((LEVEL) == BKP_TP_LOW)) +/** + * @} + */ + +/** @addtogroup Data_Backup_Register + * @{ + */ + +#define BKP_DAT1 ((uint16_t)0x0004) +#define BKP_DAT2 ((uint16_t)0x0008) +#define BKP_DAT3 ((uint16_t)0x000C) +#define BKP_DAT4 ((uint16_t)0x0010) +#define BKP_DAT5 ((uint16_t)0x0014) +#define BKP_DAT6 ((uint16_t)0x0018) +#define BKP_DAT7 ((uint16_t)0x001C) +#define BKP_DAT8 ((uint16_t)0x0020) +#define BKP_DAT9 ((uint16_t)0x0024) +#define BKP_DAT10 ((uint16_t)0x0028) +#define BKP_DAT11 ((uint16_t)0x0040) +#define BKP_DAT12 ((uint16_t)0x0044) +#define BKP_DAT13 ((uint16_t)0x0048) +#define BKP_DAT14 ((uint16_t)0x004C) +#define BKP_DAT15 ((uint16_t)0x0050) +#define BKP_DAT16 ((uint16_t)0x0054) +#define BKP_DAT17 ((uint16_t)0x0058) +#define BKP_DAT18 ((uint16_t)0x005C) +#define BKP_DAT19 ((uint16_t)0x0060) +#define BKP_DAT20 ((uint16_t)0x0064) +#define BKP_DAT21 ((uint16_t)0x0068) +#define BKP_DAT22 ((uint16_t)0x006C) +#define BKP_DAT23 ((uint16_t)0x0070) +#define BKP_DAT24 ((uint16_t)0x0074) +#define BKP_DAT25 ((uint16_t)0x0078) +#define BKP_DAT26 ((uint16_t)0x007C) +#define BKP_DAT27 ((uint16_t)0x0080) +#define BKP_DAT28 ((uint16_t)0x0084) +#define BKP_DAT29 ((uint16_t)0x0088) +#define BKP_DAT30 ((uint16_t)0x008C) +#define BKP_DAT31 ((uint16_t)0x0090) +#define BKP_DAT32 ((uint16_t)0x0094) +#define BKP_DAT33 ((uint16_t)0x0098) +#define BKP_DAT34 ((uint16_t)0x009C) +#define BKP_DAT35 ((uint16_t)0x00A0) +#define BKP_DAT36 ((uint16_t)0x00A4) +#define BKP_DAT37 ((uint16_t)0x00A8) +#define BKP_DAT38 ((uint16_t)0x00AC) +#define BKP_DAT39 ((uint16_t)0x00B0) +#define BKP_DAT40 ((uint16_t)0x00B4) +#define BKP_DAT41 ((uint16_t)0x00B8) +#define BKP_DAT42 ((uint16_t)0x00BC) + +#define IS_BKP_DAT(DAT) \ + (((DAT) == BKP_DAT1) || ((DAT) == BKP_DAT2) || ((DAT) == BKP_DAT3) || ((DAT) == BKP_DAT4) || ((DAT) == BKP_DAT5) \ + || ((DAT) == BKP_DAT6) || ((DAT) == BKP_DAT7) || ((DAT) == BKP_DAT8) || ((DAT) == BKP_DAT9) \ + || ((DAT) == BKP_DAT10) || ((DAT) == BKP_DAT11) || ((DAT) == BKP_DAT12) || ((DAT) == BKP_DAT13) \ + || ((DAT) == BKP_DAT14) || ((DAT) == BKP_DAT15) || ((DAT) == BKP_DAT16) || ((DAT) == BKP_DAT17) \ + || ((DAT) == BKP_DAT18) || ((DAT) == BKP_DAT19) || ((DAT) == BKP_DAT20) || ((DAT) == BKP_DAT21) \ + || ((DAT) == BKP_DAT22) || ((DAT) == BKP_DAT23) || ((DAT) == BKP_DAT24) || ((DAT) == BKP_DAT25) \ + || ((DAT) == BKP_DAT26) || ((DAT) == BKP_DAT27) || ((DAT) == BKP_DAT28) || ((DAT) == BKP_DAT29) \ + || ((DAT) == BKP_DAT30) || ((DAT) == BKP_DAT31) || ((DAT) == BKP_DAT32) || ((DAT) == BKP_DAT33) \ + || ((DAT) == BKP_DAT34) || ((DAT) == BKP_DAT35) || ((DAT) == BKP_DAT36) || ((DAT) == BKP_DAT37) \ + || ((DAT) == BKP_DAT38) || ((DAT) == BKP_DAT39) || ((DAT) == BKP_DAT40) || ((DAT) == BKP_DAT41) \ + || ((DAT) == BKP_DAT42)) + + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup BKP_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup BKP_Exported_Functions + * @{ + */ + +void BKP_DeInit(void); +void BKP_ConfigTPLevel(uint16_t BKP_TamperPinLevel); +void BKP_TPEnable(FunctionalState Cmd); +void BKP_TPIntEnable(FunctionalState Cmd); +void BKP_WriteBkpData(uint16_t BKP_DAT, uint16_t Data); +uint16_t BKP_ReadBkpData(uint16_t BKP_DAT); +FlagStatus BKP_GetTEFlag(void); +void BKP_ClrTEFlag(void); +INTStatus BKP_GetTINTFlag(void); +void BKP_ClrTINTFlag(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __N32G45X_BKP_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/inc/n32g45x_can.h b/inc/n32g45x_can.h new file mode 100644 index 0000000..a8c2cdd --- /dev/null +++ b/inc/n32g45x_can.h @@ -0,0 +1,670 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_can.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_CAN_H__ +#define __N32G45X_CAN_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup CAN + * @{ + */ + +/** @addtogroup CAN_Exported_Types + * @{ + */ + +#define IS_CAN_ALL_PERIPH(PERIPH) (((PERIPH) == CAN1) || ((PERIPH) == CAN2)) + +/** + * @brief CAN init structure definition + */ + +typedef struct +{ + uint16_t BaudRatePrescaler; /*!< Specifies the length of a time quantum. + It ranges from 1 to 1024. */ + + uint8_t OperatingMode; /*!< Specifies the CAN operating mode. + This parameter can be a value of + @ref CAN_operating_mode */ + + uint8_t RSJW; /*!< Specifies the maximum number of time quanta + the CAN hardware is allowed to lengthen or + shorten a bit to perform resynchronization. + This parameter can be a value of + @ref CAN_synchronisation_jump_width */ + + uint8_t TBS1; /*!< Specifies the number of time quanta in Bit + Segment 1. This parameter can be a value of + @ref CAN_time_quantum_in_bit_segment_1 */ + + uint8_t TBS2; /*!< Specifies the number of time quanta in Bit + Segment 2. + This parameter can be a value of + @ref CAN_time_quantum_in_bit_segment_2 */ + + FunctionalState TTCM; /*!< Enable or disable the time triggered + communication mode. This parameter can be set + either to ENABLE or DISABLE. */ + + FunctionalState ABOM; /*!< Enable or disable the automatic bus-off + management. This parameter can be set either + to ENABLE or DISABLE. */ + + FunctionalState AWKUM; /*!< Enable or disable the automatic wake-up mode. + This parameter can be set either to ENABLE or + DISABLE. */ + + FunctionalState NART; /*!< Enable or disable the no-automatic + retransmission mode. This parameter can be + set either to ENABLE or DISABLE. */ + + FunctionalState RFLM; /*!< Enable or disable the Receive DATFIFO Locked mode. + This parameter can be set either to ENABLE + or DISABLE. */ + + FunctionalState TXFP; /*!< Enable or disable the transmit DATFIFO priority. + This parameter can be set either to ENABLE + or DISABLE. */ +} CAN_InitType; + +/** + * @brief CAN filter init structure definition + */ + +typedef struct +{ + uint16_t Filter_HighId; /*!< Specifies the filter identification number (MSBs for a 32-bit + configuration, first one for a 16-bit configuration). + This parameter can be a value between 0x0000 and 0xFFFF */ + + uint16_t Filter_LowId; /*!< Specifies the filter identification number (LSBs for a 32-bit + configuration, second one for a 16-bit configuration). + This parameter can be a value between 0x0000 and 0xFFFF */ + + uint16_t FilterMask_HighId; /*!< Specifies the filter mask number or identification number, + according to the mode (MSBs for a 32-bit configuration, + first one for a 16-bit configuration). + This parameter can be a value between 0x0000 and 0xFFFF */ + + uint16_t FilterMask_LowId; /*!< Specifies the filter mask number or identification number, + according to the mode (LSBs for a 32-bit configuration, + second one for a 16-bit configuration). + This parameter can be a value between 0x0000 and 0xFFFF */ + + uint16_t Filter_FIFOAssignment; /*!< Specifies the DATFIFO (0 or 1) which will be assigned to the filter. + This parameter can be a value of @ref CAN_filter_FIFO */ + + uint8_t Filter_Num; /*!< Specifies the filter which will be initialized. It ranges from 0 to 13. */ + + uint8_t Filter_Mode; /*!< Specifies the filter mode to be initialized. + This parameter can be a value of @ref CAN_filter_mode */ + + uint8_t Filter_Scale; /*!< Specifies the filter scale. + This parameter can be a value of @ref CAN_filter_scale */ + + FunctionalState Filter_Act; /*!< Enable or disable the filter. + This parameter can be set either to ENABLE or DISABLE. */ +} CAN_FilterInitType; + +/** + * @brief CAN Tx message structure definition + */ + +typedef struct +{ + uint32_t StdId; /*!< Specifies the standard identifier. + This parameter can be a value between 0 to 0x7FF. */ + + uint32_t ExtId; /*!< Specifies the extended identifier. + This parameter can be a value between 0 to 0x1FFFFFFF. */ + + uint8_t IDE; /*!< Specifies the type of identifier for the message that + will be transmitted. This parameter can be a value + of @ref CAN_identifier_type */ + + uint8_t RTR; /*!< Specifies the type of frame for the message that will + be transmitted. This parameter can be a value of + @ref CAN_remote_transmission_request */ + + uint8_t DLC; /*!< Specifies the length of the frame that will be + transmitted. This parameter can be a value between + 0 to 8 */ + + uint8_t Data[8]; /*!< Contains the data to be transmitted. It ranges from 0 + to 0xFF. */ +} CanTxMessage; + +/** + * @brief CAN Rx message structure definition + */ + +typedef struct +{ + uint32_t StdId; /*!< Specifies the standard identifier. + This parameter can be a value between 0 to 0x7FF. */ + + uint32_t ExtId; /*!< Specifies the extended identifier. + This parameter can be a value between 0 to 0x1FFFFFFF. */ + + uint8_t IDE; /*!< Specifies the type of identifier for the message that + will be received. This parameter can be a value of + @ref CAN_identifier_type */ + + uint8_t RTR; /*!< Specifies the type of frame for the received message. + This parameter can be a value of + @ref CAN_remote_transmission_request */ + + uint8_t DLC; /*!< Specifies the length of the frame that will be received. + This parameter can be a value between 0 to 8 */ + + uint8_t Data[8]; /*!< Contains the data to be received. It ranges from 0 to + 0xFF. */ + + uint8_t FMI; /*!< Specifies the index of the filter the message stored in + the mailbox passes through. This parameter can be a + value between 0 to 0xFF */ +} CanRxMessage; + +/** + * @} + */ + +/** @addtogroup CAN_Exported_Constants + * @{ + */ + +/** @addtogroup CAN_sleep_constants + * @{ + */ + +#define CAN_InitSTS_Failed ((uint8_t)0x00) /*!< CAN initialization failed */ +#define CAN_InitSTS_Success ((uint8_t)0x01) /*!< CAN initialization OK */ + +/** + * @} + */ + +/** @addtogroup OperatingMode + * @{ + */ + +#define CAN_Normal_Mode ((uint8_t)0x00) /*!< normal mode */ +#define CAN_LoopBack_Mode ((uint8_t)0x01) /*!< loopback mode */ +#define CAN_Silent_Mode ((uint8_t)0x02) /*!< silent mode */ +#define CAN_Silent_LoopBack_Mode ((uint8_t)0x03) /*!< loopback combined with silent mode */ + +#define IS_CAN_MODE(MODE) \ + (((MODE) == CAN_Normal_Mode) || ((MODE) == CAN_LoopBack_Mode) || ((MODE) == CAN_Silent_Mode) \ + || ((MODE) == CAN_Silent_LoopBack_Mode)) +/** + * @} + */ + +/** + * @addtogroup CAN_operating_mode + * @{ + */ +#define CAN_Operating_InitMode ((uint8_t)0x00) /*!< Initialization mode */ +#define CAN_Operating_NormalMode ((uint8_t)0x01) /*!< Normal mode */ +#define CAN_Operating_SleepMode ((uint8_t)0x02) /*!< sleep mode */ + +#define IS_CAN_OPERATING_MODE(MODE) \ + (((MODE) == CAN_Operating_InitMode) || ((MODE) == CAN_Operating_NormalMode) || ((MODE) == CAN_Operating_SleepMode)) +/** + * @} + */ + +/** + * @addtogroup CAN_Mode_Status + * @{ + */ + +#define CAN_ModeSTS_Failed ((uint8_t)0x00) /*!< CAN entering the specific mode failed */ +#define CAN_ModeSTS_Success ((uint8_t)!CAN_ModeSTS_Failed) /*!< CAN entering the specific mode Succeed */ + +/** + * @} + */ + +/** @addtogroup CAN_synchronisation_jump_width + * @{ + */ + +#define CAN_RSJW_1tq ((uint8_t)0x00) /*!< 1 time quantum */ +#define CAN_RSJW_2tq ((uint8_t)0x01) /*!< 2 time quantum */ +#define CAN_RSJW_3tq ((uint8_t)0x02) /*!< 3 time quantum */ +#define CAN_RSJW_4tq ((uint8_t)0x03) /*!< 4 time quantum */ + +#define IS_CAN_RSJW(SJW) \ + (((SJW) == CAN_RSJW_1tq) || ((SJW) == CAN_RSJW_2tq) || ((SJW) == CAN_RSJW_3tq) || ((SJW) == CAN_RSJW_4tq)) +/** + * @} + */ + +/** @addtogroup CAN_time_quantum_in_bit_segment_1 + * @{ + */ + +#define CAN_TBS1_1tq ((uint8_t)0x00) /*!< 1 time quantum */ +#define CAN_TBS1_2tq ((uint8_t)0x01) /*!< 2 time quantum */ +#define CAN_TBS1_3tq ((uint8_t)0x02) /*!< 3 time quantum */ +#define CAN_TBS1_4tq ((uint8_t)0x03) /*!< 4 time quantum */ +#define CAN_TBS1_5tq ((uint8_t)0x04) /*!< 5 time quantum */ +#define CAN_TBS1_6tq ((uint8_t)0x05) /*!< 6 time quantum */ +#define CAN_TBS1_7tq ((uint8_t)0x06) /*!< 7 time quantum */ +#define CAN_TBS1_8tq ((uint8_t)0x07) /*!< 8 time quantum */ +#define CAN_TBS1_9tq ((uint8_t)0x08) /*!< 9 time quantum */ +#define CAN_TBS1_10tq ((uint8_t)0x09) /*!< 10 time quantum */ +#define CAN_TBS1_11tq ((uint8_t)0x0A) /*!< 11 time quantum */ +#define CAN_TBS1_12tq ((uint8_t)0x0B) /*!< 12 time quantum */ +#define CAN_TBS1_13tq ((uint8_t)0x0C) /*!< 13 time quantum */ +#define CAN_TBS1_14tq ((uint8_t)0x0D) /*!< 14 time quantum */ +#define CAN_TBS1_15tq ((uint8_t)0x0E) /*!< 15 time quantum */ +#define CAN_TBS1_16tq ((uint8_t)0x0F) /*!< 16 time quantum */ + +#define IS_CAN_TBS1(BS1) ((BS1) <= CAN_TBS1_16tq) +/** + * @} + */ + +/** @addtogroup CAN_time_quantum_in_bit_segment_2 + * @{ + */ + +#define CAN_TBS2_1tq ((uint8_t)0x00) /*!< 1 time quantum */ +#define CAN_TBS2_2tq ((uint8_t)0x01) /*!< 2 time quantum */ +#define CAN_TBS2_3tq ((uint8_t)0x02) /*!< 3 time quantum */ +#define CAN_TBS2_4tq ((uint8_t)0x03) /*!< 4 time quantum */ +#define CAN_TBS2_5tq ((uint8_t)0x04) /*!< 5 time quantum */ +#define CAN_TBS2_6tq ((uint8_t)0x05) /*!< 6 time quantum */ +#define CAN_TBS2_7tq ((uint8_t)0x06) /*!< 7 time quantum */ +#define CAN_TBS2_8tq ((uint8_t)0x07) /*!< 8 time quantum */ + +#define IS_CAN_TBS2(BS2) ((BS2) <= CAN_TBS2_8tq) + +/** + * @} + */ + +/** @addtogroup CAN_clock_prescaler + * @{ + */ + +#define IS_CAN_BAUDRATEPRESCALER(PRESCALER) (((PRESCALER) >= 1) && ((PRESCALER) <= 1024)) + +/** + * @} + */ + +/** @addtogroup CAN_filter_number + * @{ + */ +#define IS_CAN_FILTER_NUM(NUMBER) ((NUMBER) <= 13) +/** + * @} + */ + +/** @addtogroup CAN_filter_mode + * @{ + */ + +#define CAN_Filter_IdMaskMode ((uint8_t)0x00) /*!< identifier/mask mode */ +#define CAN_Filter_IdListMode ((uint8_t)0x01) /*!< identifier list mode */ + +#define IS_CAN_FILTER_MODE(MODE) (((MODE) == CAN_Filter_IdMaskMode) || ((MODE) == CAN_Filter_IdListMode)) +/** + * @} + */ + +/** @addtogroup CAN_filter_scale + * @{ + */ + +#define CAN_Filter_16bitScale ((uint8_t)0x00) /*!< Two 16-bit filters */ +#define CAN_Filter_32bitScale ((uint8_t)0x01) /*!< One 32-bit filter */ + +#define IS_CAN_FILTER_SCALE(SCALE) (((SCALE) == CAN_Filter_16bitScale) || ((SCALE) == CAN_Filter_32bitScale)) + +/** + * @} + */ + +/** @addtogroup CAN_filter_FIFO + * @{ + */ + +#define CAN_Filter_FIFO0 ((uint8_t)0x00) /*!< Filter DATFIFO 0 assignment for filter x */ +#define CAN_Filter_FIFO1 ((uint8_t)0x01) /*!< Filter DATFIFO 1 assignment for filter x */ +#define IS_CAN_FILTER_FIFO(DATFIFO) (((DATFIFO) == CAN_FilterFIFO0) || ((DATFIFO) == CAN_FilterFIFO1)) +/** + * @} + */ + +/** @addtogroup CAN_Tx + * @{ + */ + +#define IS_CAN_TRANSMITMAILBOX(TRANSMITMAILBOX) ((TRANSMITMAILBOX) <= ((uint8_t)0x02)) +#define IS_CAN_STDID(STDID) ((STDID) <= ((uint32_t)0x7FF)) +#define IS_CAN_EXTID(EXTID) ((EXTID) <= ((uint32_t)0x1FFFFFFF)) +#define IS_CAN_DLC(DLC) ((DLC) <= ((uint8_t)0x08)) + +/** + * @} + */ + +/** @addtogroup CAN_identifier_type + * @{ + */ + +#define CAN_Standard_Id ((uint32_t)0x00000000) /*!< Standard Id */ +#define CAN_Extended_Id ((uint32_t)0x00000004) /*!< Extended Id */ +#define IS_CAN_ID(IDTYPE) (((IDTYPE) == CAN_Standard_Id) || ((IDTYPE) == CAN_Extended_Id)) +/** + * @} + */ + +/** @addtogroup CAN_remote_transmission_request + * @{ + */ + +#define CAN_RTRQ_Data ((uint32_t)0x00000000) /*!< Data frame */ +#define CAN_RTRQ_Remote ((uint32_t)0x00000002) /*!< Remote frame */ +#define IS_CAN_RTRQ(RTR) (((RTR) == CAN_RTRQ_Data) || ((RTR) == CAN_RTRQ_Remote)) + +/** + * @} + */ + +/** @addtogroup CAN_transmit_constants + * @{ + */ + +#define CAN_TxSTS_Failed ((uint8_t)0x00) /*!< CAN transmission failed */ +#define CAN_TxSTS_Ok ((uint8_t)0x01) /*!< CAN transmission succeeded */ +#define CAN_TxSTS_Pending ((uint8_t)0x02) /*!< CAN transmission pending */ +#define CAN_TxSTS_NoMailBox ((uint8_t)0x04) /*!< CAN cell did not provide an empty mailbox */ + +/** + * @} + */ + +/** @addtogroup CAN_receive_FIFO_number_constants + * @{ + */ + +#define CAN_FIFO0 ((uint8_t)0x00) /*!< CAN DATFIFO 0 used to receive */ +#define CAN_FIFO1 ((uint8_t)0x01) /*!< CAN DATFIFO 1 used to receive */ +#define IS_CAN_FIFO(DATFIFO) (((DATFIFO) == CAN_FIFO0) || ((DATFIFO) == CAN_FIFO1)) + +/** + * @} + */ + +/** @addtogroup CAN_sleep_constants + * @{ + */ + +#define CAN_SLEEP_Failed ((uint8_t)0x00) /*!< CAN did not enter the sleep mode */ +#define CAN_SLEEP_Ok ((uint8_t)0x01) /*!< CAN entered the sleep mode */ + +/** + * @} + */ + +/** @addtogroup CAN_wake_up_constants + * @{ + */ + +#define CAN_WKU_Failed ((uint8_t)0x00) /*!< CAN did not leave the sleep mode */ +#define CAN_WKU_Ok ((uint8_t)0x01) /*!< CAN leaved the sleep mode */ + +/** + * @} + */ + +/** + * @addtogroup CAN_Error_Code_constants + * @{ + */ + +#define CAN_ERRCode_NoErr ((uint8_t)0x00) /*!< No Error */ +#define CAN_ERRCode_StuffErr ((uint8_t)0x10) /*!< Stuff Error */ +#define CAN_ERRCode_FormErr ((uint8_t)0x20) /*!< Form Error */ +#define CAN_ERRCode_ACKErr ((uint8_t)0x30) /*!< Acknowledgment Error */ +#define CAN_ERRCode_BitRecessiveErr ((uint8_t)0x40) /*!< Bit Recessive Error */ +#define CAN_ERRCode_BitDominantErr ((uint8_t)0x50) /*!< Bit Dominant Error */ +#define CAN_ERRCode_CRCErr ((uint8_t)0x60) /*!< CRC Error */ +#define CAN_ERRCode_SWSetErr ((uint8_t)0x70) /*!< Software Set Error */ + +/** + * @} + */ + +/** @addtogroup CAN_flags + * @{ + */ +/* If the flag is 0x3XXXXXXX, it means that it can be used with CAN_GetFlagSTS() + and CAN_ClearFlag() functions. */ +/* If the flag is 0x1XXXXXXX, it means that it can only be used with CAN_GetFlagSTS() function. */ + +/* Transmit Flags */ +#define CAN_FLAG_RQCPM0 ((uint32_t)0x38000001) /*!< Request MailBox0 Flag */ +#define CAN_FLAG_RQCPM1 ((uint32_t)0x38000100) /*!< Request MailBox1 Flag */ +#define CAN_FLAG_RQCPM2 ((uint32_t)0x38010000) /*!< Request MailBox2 Flag */ + +/* Receive Flags */ +#define CAN_FLAG_FFMP0 ((uint32_t)0x12000003) /*!< DATFIFO 0 Message Pending Flag */ +#define CAN_FLAG_FFULL0 ((uint32_t)0x32000008) /*!< DATFIFO 0 Full Flag */ +#define CAN_FLAG_FFOVR0 ((uint32_t)0x32000010) /*!< DATFIFO 0 Overrun Flag */ +#define CAN_FLAG_FFMP1 ((uint32_t)0x14000003) /*!< DATFIFO 1 Message Pending Flag */ +#define CAN_FLAG_FFULL1 ((uint32_t)0x34000008) /*!< DATFIFO 1 Full Flag */ +#define CAN_FLAG_FFOVR1 ((uint32_t)0x34000010) /*!< DATFIFO 1 Overrun Flag */ + +/* Operating Mode Flags */ +#define CAN_FLAG_WKU ((uint32_t)0x31000008) /*!< Wake up Flag */ +#define CAN_FLAG_SLAK ((uint32_t)0x31000012) /*!< Sleep acknowledge Flag */ +/* Note: When SLAK intterupt is disabled (SLKIE=0), no polling on SLAKI is possible. + In this case the SLAK bit can be polled.*/ + +/* Error Flags */ +#define CAN_FLAG_EWGFL ((uint32_t)0x10F00001) /*!< Error Warning Flag */ +#define CAN_FLAG_EPVFL ((uint32_t)0x10F00002) /*!< Error Passive Flag */ +#define CAN_FLAG_BOFFL ((uint32_t)0x10F00004) /*!< Bus-Off Flag */ +#define CAN_FLAG_LEC ((uint32_t)0x30F00070) /*!< Last error code Flag */ + +#define IS_CAN_GET_FLAG(FLAG) \ + (((FLAG) == CAN_FLAG_LEC) || ((FLAG) == CAN_FLAG_BOFFL) || ((FLAG) == CAN_FLAG_EPVFL) \ + || ((FLAG) == CAN_FLAG_EWGFL) || ((FLAG) == CAN_FLAG_WKU) || ((FLAG) == CAN_FLAG_FFOVR0) \ + || ((FLAG) == CAN_FLAG_FFULL0) || ((FLAG) == CAN_FLAG_FFMP0) || ((FLAG) == CAN_FLAG_FFOVR1) \ + || ((FLAG) == CAN_FLAG_FFULL1) || ((FLAG) == CAN_FLAG_FFMP1) || ((FLAG) == CAN_FLAG_RQCPM2) \ + || ((FLAG) == CAN_FLAG_RQCPM1) || ((FLAG) == CAN_FLAG_RQCPM0) || ((FLAG) == CAN_FLAG_SLAK)) + +#define IS_CAN_CLEAR_FLAG(FLAG) \ + (((FLAG) == CAN_FLAG_LEC) || ((FLAG) == CAN_FLAG_RQCPM2) || ((FLAG) == CAN_FLAG_RQCPM1) \ + || ((FLAG) == CAN_FLAG_RQCPM0) || ((FLAG) == CAN_FLAG_FFULL0) || ((FLAG) == CAN_FLAG_FFOVR0) \ + || ((FLAG) == CAN_FLAG_FFULL1) || ((FLAG) == CAN_FLAG_FFOVR1) || ((FLAG) == CAN_FLAG_WKU) \ + || ((FLAG) == CAN_FLAG_SLAK)) +/** + * @} + */ + +/** @addtogroup CAN_interrupts + * @{ + */ + +#define CAN_INT_TME ((uint32_t)0x00000001) /*!< Transmit mailbox empty Interrupt*/ + +/* Receive Interrupts */ +#define CAN_INT_FMP0 ((uint32_t)0x00000002) /*!< DATFIFO 0 message pending Interrupt*/ +#define CAN_INT_FF0 ((uint32_t)0x00000004) /*!< DATFIFO 0 full Interrupt*/ +#define CAN_INT_FOV0 ((uint32_t)0x00000008) /*!< DATFIFO 0 overrun Interrupt*/ +#define CAN_INT_FMP1 ((uint32_t)0x00000010) /*!< DATFIFO 1 message pending Interrupt*/ +#define CAN_INT_FF1 ((uint32_t)0x00000020) /*!< DATFIFO 1 full Interrupt*/ +#define CAN_INT_FOV1 ((uint32_t)0x00000040) /*!< DATFIFO 1 overrun Interrupt*/ + +/* Operating Mode Interrupts */ +#define CAN_INT_WKU ((uint32_t)0x00010000) /*!< Wake-up Interrupt*/ +#define CAN_INT_SLK ((uint32_t)0x00020000) /*!< Sleep acknowledge Interrupt*/ + +/* Error Interrupts */ +#define CAN_INT_EWG ((uint32_t)0x00000100) /*!< Error warning Interrupt*/ +#define CAN_INT_EPV ((uint32_t)0x00000200) /*!< Error passive Interrupt*/ +#define CAN_INT_BOF ((uint32_t)0x00000400) /*!< Bus-off Interrupt*/ +#define CAN_INT_LEC ((uint32_t)0x00000800) /*!< Last error code Interrupt*/ +#define CAN_INT_ERR ((uint32_t)0x00008000) /*!< Error Interrupt*/ + +/* Flags named as Interrupts : kept only for FW compatibility */ +#define CAN_INT_RQCPM0 CAN_INT_TME +#define CAN_INT_RQCPM1 CAN_INT_TME +#define CAN_INT_RQCPM2 CAN_INT_TME + +#define IS_CAN_INT(IT) \ + (((IT) == CAN_INT_TME) || ((IT) == CAN_INT_FMP0) || ((IT) == CAN_INT_FF0) || ((IT) == CAN_INT_FOV0) \ + || ((IT) == CAN_INT_FMP1) || ((IT) == CAN_INT_FF1) || ((IT) == CAN_INT_FOV1) || ((IT) == CAN_INT_EWG) \ + || ((IT) == CAN_INT_EPV) || ((IT) == CAN_INT_BOF) || ((IT) == CAN_INT_LEC) || ((IT) == CAN_INT_ERR) \ + || ((IT) == CAN_INT_WKU) || ((IT) == CAN_INT_SLK)) + +#define IS_CAN_CLEAR_INT(IT) \ + (((IT) == CAN_INT_TME) || ((IT) == CAN_INT_FF0) || ((IT) == CAN_INT_FOV0) || ((IT) == CAN_INT_FF1) \ + || ((IT) == CAN_INT_FOV1) || ((IT) == CAN_INT_EWG) || ((IT) == CAN_INT_EPV) || ((IT) == CAN_INT_BOF) \ + || ((IT) == CAN_INT_LEC) || ((IT) == CAN_INT_ERR) || ((IT) == CAN_INT_WKU) || ((IT) == CAN_INT_SLK)) + +/** + * @} + */ + +/** @addtogroup CAN_Legacy + * @{ + */ +#define CANINITSTSFAILED CAN_InitSTS_Failed +#define CANINITSTSOK CAN_InitSTS_Success +#define CAN_FilterFIFO0 CAN_Filter_FIFO0 +#define CAN_FilterFIFO1 CAN_Filter_FIFO1 +#define CAN_ID_STD CAN_Standard_Id +#define CAN_ID_EXT CAN_Extended_Id +#define CAN_RTRQ_DATA CAN_RTRQ_Data +#define CAN_RTRQ_REMOTE CAN_RTRQ_Remote +#define CANTXSTSFAILE CAN_TxSTS_Failed +#define CANTXSTSOK CAN_TxSTS_Ok +#define CANTXSTSPENDING CAN_TxSTS_Pending +#define CAN_STS_NO_MB CAN_TxSTS_NoMailBox +#define CANSLEEPFAILED CAN_SLEEP_Failed +#define CANSLEEPOK CAN_SLEEP_Ok +#define CANWKUFAILED CAN_WKU_Failed +#define CANWKUOK CAN_WKU_Ok + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup CAN_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup CAN_Exported_Functions + * @{ + */ +/* Function used to set the CAN configuration to the default reset state *****/ +void CAN_DeInit(CAN_Module* CANx); + +/* Initialization and Configuration functions *********************************/ +uint8_t CAN_Init(CAN_Module* CANx, CAN_InitType* CAN_InitParam); +void CAN1_InitFilter(CAN_FilterInitType* CAN_InitFilterStruct); +void CAN2_InitFilter(CAN_FilterInitType* CAN_InitFilterStruct); +void CAN_InitStruct(CAN_InitType* CAN_InitParam); +void CAN_DebugFreeze(CAN_Module* CANx, FunctionalState Cmd); +void CAN_EnTTComMode(CAN_Module* CANx, FunctionalState Cmd); + +/* Transmit functions *********************************************************/ +uint8_t CAN_TransmitMessage(CAN_Module* CANx, CanTxMessage* TxMessage); +uint8_t CAN_TransmitSTS(CAN_Module* CANx, uint8_t TransmitMailbox); +void CAN_CancelTransmitMessage(CAN_Module* CANx, uint8_t Mailbox); + +/* Receive functions **********************************************************/ +void CAN_ReceiveMessage(CAN_Module* CANx, uint8_t FIFONum, CanRxMessage* RxMessage); +void CAN_ReleaseFIFO(CAN_Module* CANx, uint8_t FIFONum); +uint8_t CAN_PendingMessage(CAN_Module* CANx, uint8_t FIFONum); + +/* Operation modes functions **************************************************/ +uint8_t CAN_OperatingModeReq(CAN_Module* CANx, uint8_t CAN_OperatingMode); +uint8_t CAN_EnterSleep(CAN_Module* CANx); +uint8_t CAN_WakeUp(CAN_Module* CANx); + +/* Error management functions *************************************************/ +uint8_t CAN_GetLastErrCode(CAN_Module* CANx); +uint8_t CAN_GetReceiveErrCounter(CAN_Module* CANx); +uint8_t CAN_GetLSBTransmitErrCounter(CAN_Module* CANx); + +/* Interrupts and flags management functions **********************************/ +void CAN_INTConfig(CAN_Module* CANx, uint32_t CAN_INT, FunctionalState Cmd); +FlagStatus CAN_GetFlagSTS(CAN_Module* CANx, uint32_t CAN_FLAG); +void CAN_ClearFlag(CAN_Module* CANx, uint32_t CAN_FLAG); +INTStatus CAN_GetIntStatus(CAN_Module* CANx, uint32_t CAN_INT); +void CAN_ClearINTPendingBit(CAN_Module* CANx, uint32_t CAN_INT); + +#ifdef __cplusplus +} +#endif + +#endif /* __N32G45X_CAN_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/inc/n32g45x_comp.h b/inc/n32g45x_comp.h new file mode 100644 index 0000000..ae6079a --- /dev/null +++ b/inc/n32g45x_comp.h @@ -0,0 +1,385 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_comp.h + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_COMP_H__ +#define __N32G45X_COMP_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" +#include + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup COMP + * @{ + */ + +/** @addtogroup COMP_Exported_Constants + * @{ + */ +typedef enum +{ + COMP1 = 0, + COMP2 = 1, + COMP3 = 2, + COMP4 = 3, + COMP5 = 4, + COMP6 = 5, + COMP7 = 6 +} COMPX; + +// COMPx_CTRL +#define COMP1_CTRL_INPDAC_MASK (0x01L << 18) +#define COMP_CTRL_OUT_MASK (0x01L << 17) +#define COMP_CTRL_BLKING_MASK (0x07L << 14) +typedef enum +{ + COMP_CTRL_BLKING_NO = (0x0L << 14), + COMP_CTRL_BLKING_TIM1_OC5 = (0x1L << 14), + COMP_CTRL_BLKING_TIM8_OC5 = (0x2L << 14), +} COMP_CTRL_BLKING; +#define COMPx_CTRL_HYST_MASK (0x03L << 12) +typedef enum +{ + COMP_CTRL_HYST_NO = (0x0L << 12), + COMP_CTRL_HYST_LOW = (0x1L << 12), + COMP_CTRL_HYST_MID = (0x2L << 12), + COMP_CTRL_HYST_HIGH = (0x3L << 12), +} COMP_CTRL_HYST; + +#define COMP_POL_MASK (0x01L << 11) +#define COMP_CTRL_OUTSEL_MASK (0x0FL << 7) +typedef enum +{ + COMPX_CTRL_OUTSEL_NC = (0x0L << 7), + // comp1 out trig + COMP1_CTRL_OUTSEL_NC = (0x0L << 7), + COMP1_CTRL_OUTSEL_TIM1_BKIN = (0x1L << 7), + COMP1_CTRL_OUTSEL_TIM1_IC1 = (0x2L << 7), + COMP1_CTRL_OUTSEL_TIM1_OCrefclear = (0x3L << 7), + COMP1_CTRL_OUTSEL_TIM2_IC1 = (0x4L << 7), + COMP1_CTRL_OUTSEL_TIM2_OCrefclear = (0x5L << 7), + COMP1_CTRL_OUTSEL_TIM3_IC1 = (0x6L << 7), + COMP1_CTRL_OUTSEL_TIM3_OCrefclear = (0x7L << 7), + COMP1_CTRL_OUTSEL_TIM4_IC1 = (0x8L << 7), + COMP1_CTRL_OUTSEL_TIM4_OCrefclear = (0x9L << 7), + COMP1_CTRL_OUTSEL_TIM8_BKIN = (0xAL << 7), + COMP1_CTRL_OUTSEL_TIM1_BKIN_TIM8_BKIN = (0xBL << 7), + // comp2 out trig + COMP2_CTRL_OUTSEL_NC = (0x0L << 7), + COMP2_CTRL_OUTSEL_TIM1_BKIN = (0x1L << 7), + COMP2_CTRL_OUTSEL_TIM1_IC1 = (0x2L << 7), + COMP2_CTRL_OUTSEL_TIM1_OCrefclear = (0x3L << 7), + COMP2_CTRL_OUTSEL_TIM2_IC2 = (0x4L << 7), + COMP2_CTRL_OUTSEL_TIM2_OCrefclear = (0x5L << 7), + COMP2_CTRL_OUTSEL_TIM3_IC2 = (0x6L << 7), + COMP2_CTRL_OUTSEL_TIM3_OCrefclear = (0x7L << 7), + COMP2_CTRL_OUTSEL_TIM5_IC1 = (0x8L << 7), ////(0x9L << 7) + COMP2_CTRL_OUTSEL_TIM8_BKIN = (0xAL << 7), + COMP2_CTRL_OUTSEL_TIM1_BKIN_TIM8_BKIN = (0xBL << 7), + // comp3 out trig + COMP3_CTRL_OUTSEL_NC = (0x0L << 7), + COMP3_CTRL_OUTSEL_TIM1_BKIN = (0x1L << 7), + COMP3_CTRL_OUTSEL_TIM1_IC1 = (0x2L << 7), + COMP3_CTRL_OUTSEL_TIM1_OCrefclear = (0x3L << 7), + COMP3_CTRL_OUTSEL_TIM2_IC3 = (0x4L << 7), + COMP3_CTRL_OUTSEL_TIM2_OCrefclear = (0x5L << 7), + COMP3_CTRL_OUTSEL_TIM4_IC2 = (0x6L << 7), + COMP3_CTRL_OUTSEL_TIM4_OCrefclear = (0x7L << 7), + COMP3_CTRL_OUTSEL_TIM5_IC2 = (0x8L << 7), //(0x9L << 7) + COMP3_CTRL_OUTSEL_TIM8_BKIN = (0xAL << 7), + COMP3_CTRL_OUTSEL_TIM1_BKIN_TIM8_BKIN = (0xBL << 7), + // comp4 out trig + COMP4_CTRL_OUTSEL_NC = (0x0L << 7), + COMP4_CTRL_OUTSEL_TIM1_BKIN = (0x1L << 7), + COMP4_CTRL_OUTSEL_TIM3_IC3 = (0x2L << 7), + COMP4_CTRL_OUTSEL_TIM3_OCrefclear = (0x3L << 7), + COMP4_CTRL_OUTSEL_TIM4_IC3 = (0x4L << 7), + COMP4_CTRL_OUTSEL_TIM4_OCrefclear = (0x5L << 7), + COMP4_CTRL_OUTSEL_TIM5_IC3 = (0x6L << 7), //(0x7L << 7) + COMP4_CTRL_OUTSEL_TIM8_IC1 = (0x8L << 7), + COMP4_CTRL_OUTSEL_TIM8_OCrefclear = (0x9L << 7), + COMP4_CTRL_OUTSEL_TIM8_BKIN = (0xAL << 7), + COMP4_CTRL_OUTSEL_TIM1_BKIN_TIM8_BKIN = (0xBL << 7), + // comp5 out trig + COMP5_CTRL_OUTSEL_NC = (0x0L << 7), + COMP5_CTRL_OUTSEL_TIM1_BKIN = (0x1L << 7), + COMP5_CTRL_OUTSEL_TIM2_IC4 = (0x2L << 7), + COMP5_CTRL_OUTSEL_TIM2_OCrefclear = (0x3L << 7), + COMP5_CTRL_OUTSEL_TIM3_IC4 = (0x4L << 7), + COMP5_CTRL_OUTSEL_TIM3_OCrefclear = (0x5L << 7), + COMP5_CTRL_OUTSEL_TIM4_IC4 = (0x6L << 7), + COMP5_CTRL_OUTSEL_TIM4_OCrefclear = (0x7L << 7), + COMP5_CTRL_OUTSEL_TIM8_IC1 = (0x8L << 7), + COMP5_CTRL_OUTSEL_TIM8_OCrefclear = (0x9L << 7), + COMP5_CTRL_OUTSEL_TIM8_BKIN = (0xAL << 7), + COMP5_CTRL_OUTSEL_TIM1_BKIN_TIM8_BKIN = (0xBL << 7), + // comp6 out trig + COMP6_CTRL_OUTSEL_NC = (0x0L << 7), + COMP6_CTRL_OUTSEL_TIM1_BKIN = (0x1L << 7), + COMP6_CTRL_OUTSEL_TIM2_IC1 = (0x2L << 7), + COMP6_CTRL_OUTSEL_TIM2_OCrefclear = (0x3L << 7), + COMP6_CTRL_OUTSEL_TIM3_IC1 = (0x4L << 7), + COMP6_CTRL_OUTSEL_TIM3_OCrefclear = (0x5L << 7), + COMP6_CTRL_OUTSEL_TIM5_IC1 = (0x6L << 7), //(0x7L << 7) + COMP6_CTRL_OUTSEL_TIM8_IC1 = (0x8L << 7), + COMP6_CTRL_OUTSEL_TIM8_OCrefclear = (0x9L << 7), + COMP6_CTRL_OUTSEL_TIM8_BKIN = (0xAL << 7), + COMP6_CTRL_OUTSEL_TIM1_BKIN_TIM8_BKIN = (0xBL << 7), + // comp7 out trig + COMP7_CTRL_OUTSEL_NC = (0x0L << 7), + COMP7_CTRL_OUTSEL_TIM1_BKIN = (0x1L << 7), + COMP7_CTRL_OUTSEL_TIM2_IC1 = (0x2L << 7), + COMP7_CTRL_OUTSEL_TIM2_OCrefclear = (0x3L << 7), + COMP7_CTRL_OUTSEL_TIM3_IC1 = (0x4L << 7), + COMP7_CTRL_OUTSEL_TIM3_OCrefclear = (0x5L << 7), + COMP7_CTRL_OUTSEL_TIM5_IC1 = (0x6L << 7), //(0x7L << 7) + COMP7_CTRL_OUTSEL_TIM8_IC1 = (0x8L << 7), + COMP7_CTRL_OUTSEL_TIM8_OCrefclear = (0x9L << 7), + COMP7_CTRL_OUTSEL_TIM8_BKIN = (0xAL << 7), + COMP7_CTRL_OUTSEL_TIM1_BKIN_TIM8_BKIN = (0xBL << 7), +} COMP_CTRL_OUTTRIG; + +#define COMP_CTRL_INPSEL_MASK (0x07L<<4) +typedef enum { + COMPX_CTRL_INPSEL_RES = (0x7L << 4), + //comp1 inp sel + COMP1_CTRL_INPSEL_PA1 = (0x0L << 4), + COMP1_CTRL_INPSEL_PB10 = (0x1L << 4), + //comp2 inp sel, need recheck maybe wrong + COMP2_CTRL_INPSEL_PA1 = (0x0L << 4), + COMP2_CTRL_INPSEL_PB11 = (0x1L << 4), + COMP2_CTRL_INPSEL_PA7 = (0x2L << 4), + //comp3 inp sel + COMP3_CTRL_INPSEL_PB14 = (0x0L << 4), + COMP3_CTRL_INPSEL_PB0 = (0x1L << 4), + //comp4 inp sel, need recheck maybe wrong + COMP4_CTRL_INPSEL_PB14 = (0x0L << 4), + COMP4_CTRL_INPSEL_PB0 = (0x1L << 4), + COMP4_CTRL_INPSEL_PC9 = (0x2L << 4), + COMP4_CTRL_INPSEL_PB15 = (0x3L << 4), + //comp5 inp sel + COMP5_CTRL_INPSEL_PC4 = (0x0L << 4), + COMP5_CTRL_INPSEL_PC3 = (0x1L << 4), + COMP5_CTRL_INPSEL_PA3 = (0x2L << 4), + //comp6 inp sel, need recheck maybe wrong + COMP6_CTRL_INPSEL_PC4 = (0x0L << 4), + COMP6_CTRL_INPSEL_PC3 = (0x1L << 4), + COMP6_CTRL_INPSEL_PC5 = (0x2L << 4), + COMP6_CTRL_INPSEL_PD9 = (0x3L << 4), + //comp7 inp sel + COMP7_CTRL_INPSEL_PC1 = (0x0L << 4), +}COMP_CTRL_INPSEL; + +#define COMP_CTRL_INMSEL_MASK (0x07L<<1) +typedef enum { + COMPX_CTRL_INMSEL_RES = (0x7L << 1), + //comp1 inm sel + COMP1_CTRL_INMSEL_PA0 = (0x0L << 1), + COMP1_CTRL_INMSEL_DAC1_PA4 = (0x1L << 1), + COMP1_CTRL_INMSEL_DAC2_PA5 = (0x2L << 1), + COMP1_CTRL_INMSEL_VERF1 = (0x3L << 1), + COMP1_CTRL_INMSEL_VERF2 = (0x4L << 1), + //comp2 inm sel + COMP2_CTRL_INMSEL_PB1 = (0x0L << 1), + COMP2_CTRL_INMSEL_PE8 = (0x1L << 1), + COMP2_CTRL_INMSEL_DAC1_PA4 = (0x2L << 1), + COMP2_CTRL_INMSEL_DAC2_PA5 = (0x3L << 1), + COMP2_CTRL_INMSEL_VERF1 = (0x4L << 1), + COMP2_CTRL_INMSEL_VERF2 = (0x5L << 1), + //comp3 inm sel + COMP3_CTRL_INMSEL_PB12 = (0x0L << 1), + COMP3_CTRL_INMSEL_PE7 = (0x1L << 1), + COMP3_CTRL_INMSEL_DAC1_PA4 = (0x2L << 1), + COMP3_CTRL_INMSEL_DAC2_PA5 = (0x3L << 1), + COMP3_CTRL_INMSEL_VERF1 = (0x4L << 1), + COMP3_CTRL_INMSEL_VERF2 = (0x5L << 1), + //comp4 inm sel + COMP4_CTRL_INMSEL_PC4 = (0x0L << 1), + COMP4_CTRL_INMSEL_PB13 = (0x1L << 1), + COMP4_CTRL_INMSEL_DAC1_PA4 = (0x2L << 1), + COMP4_CTRL_INMSEL_DAC2_PA5 = (0x3L << 1), + COMP4_CTRL_INMSEL_VERF1 = (0x4L << 1), + COMP4_CTRL_INMSEL_VERF2 = (0x5L << 1), + //comp5 inm sel + COMP5_CTRL_INMSEL_PB10 = (0x0L << 1), + COMP5_CTRL_INMSEL_PD10 = (0x1L << 1), + COMP5_CTRL_INMSEL_DAC1_PA4 = (0x2L << 1), + COMP5_CTRL_INMSEL_DAC2_PA5 = (0x3L << 1), + COMP5_CTRL_INMSEL_VERF1 = (0x4L << 1), + COMP5_CTRL_INMSEL_VERF2 = (0x5L << 1), + //comp6 inm sel + COMP6_CTRL_INMSEL_PA7 = (0x0L << 1), + COMP6_CTRL_INMSEL_PD8 = (0x1L << 1), + COMP6_CTRL_INMSEL_DAC1_PA4 = (0x2L << 1), + COMP6_CTRL_INMSEL_DAC2_PA5 = (0x3L << 1), + COMP6_CTRL_INMSEL_VERF1 = (0x4L << 1), + COMP6_CTRL_INMSEL_VERF2 = (0x5L << 1), + //comp7 inm sel + COMP7_CTRL_INMSEL_PC0 = (0x0L << 1), + COMP7_CTRL_INMSEL_DAC1_PA4 = (0x1L << 1), + COMP7_CTRL_INMSEL_DAC2_PA5 = (0x2L << 1), + COMP7_CTRL_INMSEL_VERF1 = (0x3L << 1), + COMP7_CTRL_INMSEL_VERF2 = (0x4L << 1), +}COMP_CTRL_INMSEL; + +#define COMP_CTRL_EN_MASK (0x01L << 0) + +//COMPx_FILC +#define COMP_FILC_SAMPW_MASK (0x1FL<<6)//Low filter sample window size. Number of samples to monitor is SAMPWIN+1. +#define COMP_FILC_THRESH_MASK (0x1FL<<1)//For proper operation, the value of THRESH must be greater than SAMPWIN / 2. +#define COMP_FILC_FILEN_MASK (0x01L<<0)//Filter enable. + +//COMPx_FILCLKCR +#define COMP_FILCLKCR_CLKPSC_MASK (0xFFFFL<<0)//Low filter sample clock prescale. Number of system clocks between samples = CLK_PRE_CYCLE + 1, e.g. + +//COMP_WINMODE @addtogroup COMP_WINMODE_CMPMD +#define COMP_WINMODE_CMPMD_MSK (0x07L <<0) +#define COMP_WINMODE_CMP56MD (0x01L <<2)//1: Comparators 5 and 6 can be used in window mode. +#define COMP_WINMODE_CMP34MD (0x01L <<1)//1: Comparators 3 and 4 can be used in window mode. +#define COMP_WINMODE_CMP12MD (0x01L <<0)//1: Comparators 1 and 2 can be used in window mode. + +//COMPx_LOCK +#define COMP_LOCK_CMPLK_MSK (0x7FL <<0) +#define COMP_LOCK_CMP1LK_MSK (0x01L <<0)//1: COMx Lock bit +#define COMP_LOCK_CMP2LK_MSK (0x01L <<1)//1: COMx Lock bit +#define COMP_LOCK_CMP3LK_MSK (0x01L <<2)//1: COMx Lock bit +#define COMP_LOCK_CMP4LK_MSK (0x01L <<3)//1: COMx Lock bit +#define COMP_LOCK_CMP5LK_MSK (0x01L <<4)//1: COMx Lock bit +#define COMP_LOCK_CMP6LK_MSK (0x01L <<5)//1: COMx Lock bit +#define COMP_LOCK_CMP7LK_MSK (0x01L <<6)//1: COMx Lock bit + +// COMP_INTEN @addtogroup COMP_INTEN_CMPIEN +#define COMP_INTEN_CMPIEN_MSK (0x7FL << 0) +#define COMP_INTEN_CMP7IEN (0x01L << 6) // This bit control Interrput enable of COMP. +#define COMP_INTEN_CMP6IEN (0x01L << 5) +#define COMP_INTEN_CMP5IEN (0x01L << 4) +#define COMP_INTEN_CMP4IEN (0x01L << 3) +#define COMP_INTEN_CMP3IEN (0x01L << 2) +#define COMP_INTEN_CMP2IEN (0x01L << 1) +#define COMP_INTEN_CMP1IEN (0x01L << 0) + +// COMP_INTSTS @addtogroup COMP_INTSTS_CMPIS +#define COMP_INTSTS_INTSTS_MSK (0x7FL << 0) +#define COMP_INTSTS_CMP7IS (0x01L << 6) // This bit control Interrput enable of COMP. +#define COMP_INTSTS_CMP6IS (0x01L << 5) +#define COMP_INTSTS_CMP5IS (0x01L << 4) +#define COMP_INTSTS_CMP4IS (0x01L << 3) +#define COMP_INTSTS_CMP3IS (0x01L << 2) +#define COMP_INTSTS_CMP2IS (0x01L << 1) +#define COMP_INTSTS_CMP1IS (0x01L << 0) + +// COMP_VREFSCL @addtogroup COMP_VREFSCL +#define COMP_VREFSCL_VV2TRM_MSK (0x3FL << 8) // Vref2 Voltage scaler triming value. +#define COMP_VREFSCL_VV2EN_MSK (0x01L << 7) +#define COMP_VREFSCL_VV1TRM_MSK (0x3FL << 1) // Vref1 Voltage scaler triming value. +#define COMP_VREFSCL_VV1EN_MSK (0x01L << 0) +/** + * @} + */ + +/** + * @brief COMP Init structure definition + */ + +typedef struct +{ + // ctrl + bool InpDacConnect; // only COMP1 have this bit + + COMP_CTRL_BLKING Blking; /*see @ref COMP_CTRL_BLKING */ + + COMP_CTRL_HYST Hyst; + + bool PolRev; // out polarity reverse + + COMP_CTRL_OUTTRIG OutSel; + COMP_CTRL_INPSEL InpSel; + COMP_CTRL_INMSEL InmSel; + + bool En; + + // filter + uint8_t SampWindow; // 5bit + uint8_t Thresh; // 5bit ,need > SampWindow/2 + bool FilterEn; + + // filter psc + uint16_t ClkPsc; +} COMP_InitType; + +/** @addtogroup COMP_Exported_Functions + * @{ + */ + +void COMP_DeInit(void); +void COMP_StructInit(COMP_InitType* COMP_InitStruct); +void COMP_Init(COMPX COMPx, COMP_InitType* COMP_InitStruct); +void COMP_Enable(COMPX COMPx, FunctionalState en); +void COMP_SetInpSel(COMPX COMPx, COMP_CTRL_INPSEL VpSel); +void COMP_SetInmSel(COMPX COMPx, COMP_CTRL_INMSEL VmSel); +void COMP_SetOutTrig(COMPX COMPx, COMP_CTRL_OUTTRIG OutTrig); +void COMP_SetLock(uint32_t Lock); // see @COMP_LOCK_CMPLK +void COMP_SetIntEn(uint32_t IntEn); // see @COMP_INTEN_CMPIEN +uint32_t COMP_GetIntSts(void); // return see @COMP_INTSTS_CMPIS +void COMP_SetRefScl(uint8_t Vv2Trim, bool Vv2En, uint8_t Vv1Trim, bool Vv1En); // parma range see @COMP_VREFSCL +FlagStatus COMP_GetOutStatus(COMPX COMPx); +FlagStatus COMP_GetIntStsOneComp(COMPX COMPx); +void COMP_SetFilterPrescaler(COMPX COMPx , uint16_t FilPreVal); +void COMP_SetFilterControl(COMPX COMPx , uint8_t FilEn, uint8_t TheresNum , uint8_t SampPW); +void COMP_SetHyst(COMPX COMPx , COMP_CTRL_HYST HYST); +void COMP_SetBlanking(COMPX COMPx , COMP_CTRL_BLKING BLK); + + + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /*__N32G45X_ADC_H */ +/** + * @} + */ +/** + * @} + */ diff --git a/inc/n32g45x_crc.h b/inc/n32g45x_crc.h new file mode 100644 index 0000000..0721f38 --- /dev/null +++ b/inc/n32g45x_crc.h @@ -0,0 +1,105 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_crc.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_CRC_H__ +#define __N32G45X_CRC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup CRC + * @{ + */ + +/** @addtogroup CRC_Exported_Types + * @{ + */ + +/** + * @} + */ + +/** @addtogroup CRC_Exported_Constants + * @{ + */ + +/** + * @} + */ + +/** @addtogroup CRC_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup CRC_Exported_Functions + * @{ + */ + +void CRC32_ResetCrc(void); +uint32_t CRC32_CalcCrc(uint32_t Data); +uint32_t CRC32_CalcBufCrc(uint32_t pBuffer[], uint32_t BufferLength); +uint32_t CRC32_GetCrc(void); +void CRC32_SetIDat(uint8_t IDValue); +uint8_t CRC32_GetIDat(void); + +uint16_t CRC16_CalcBufCrc(uint8_t pBuffer[], uint32_t BufferLength); +uint16_t CRC16_CalcCRC(uint8_t Data); + +#ifdef __cplusplus +} +#endif + +#endif /* __N32G45X_CRC_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/inc/n32g45x_dac.h b/inc/n32g45x_dac.h new file mode 100644 index 0000000..6542d30 --- /dev/null +++ b/inc/n32g45x_dac.h @@ -0,0 +1,307 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_dac.h + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_DAC_H__ +#define __N32G45X_DAC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup DAC + * @{ + */ + +/** @addtogroup DAC_Exported_Types + * @{ + */ + +/** + * @brief DAC Init structure definition + */ + +typedef struct +{ + uint32_t Trigger; /*!< Specifies the external trigger for the selected DAC channel. + This parameter can be a value of @ref DAC_trigger_selection */ + + uint32_t WaveGen; /*!< Specifies whether DAC channel noise waves or triangle waves + are generated, or whether no wave is generated. + This parameter can be a value of @ref DAC_wave_generation */ + + uint32_t + LfsrUnMaskTriAmp; /*!< Specifies the LFSR mask for noise wave generation or + the maximum amplitude triangle generation for the DAC channel. + This parameter can be a value of @ref DAC_lfsrunmask_triangleamplitude */ + + uint32_t BufferOutput; /*!< Specifies whether the DAC channel output buffer is enabled or disabled. + This parameter can be a value of @ref DAC_output_buffer */ +} DAC_InitType; + +/** + * @} + */ + +/** @addtogroup DAC_Exported_Constants + * @{ + */ + +/** @addtogroup DAC_trigger_selection + * @{ + */ + +#define DAC_TRG_NONE \ + ((uint32_t)0x00000000) /*!< Conversion is automatic once the DAC1_DHRxxxx register \ + has been loaded, and not by external trigger */ +#define DAC_TRG_T6_TRGO \ + ((uint32_t)0x00000004) /*!< TIM6 TRGO selected as external conversion trigger for DAC channel \ + */ +#define DAC_TRG_T8_TRGO \ + ((uint32_t)0x0000000C) /*!< TIM8 TRGO selected as external conversion trigger for DAC channel \ + only in High-density devices*/ +#define DAC_TRG_T3_TRGO \ + ((uint32_t)0x0000000C) /*!< TIM8 TRGO selected as external conversion trigger for DAC channel \ + only in Connectivity line, Medium-density and Low-density Value Line devices */ +#define DAC_TRG_T7_TRGO \ + ((uint32_t)0x00000014) /*!< TIM7 TRGO selected as external conversion trigger for DAC channel \ + */ +#define DAC_TRG_T5_TRGO \ + ((uint32_t)0x0000001C) /*!< TIM5 TRGO selected as external conversion trigger for DAC channel \ + */ +#define DAC_TRG_T15_TRGO \ + ((uint32_t)0x0000001C) /*!< TIM15 TRGO selected as external conversion trigger for DAC channel \ + only in Medium-density and Low-density Value Line devices*/ +#define DAC_TRG_T2_TRGO \ + ((uint32_t)0x00000024) /*!< TIM2 TRGO selected as external conversion trigger for DAC channel \ + */ +#define DAC_TRG_T4_TRGO \ + ((uint32_t)0x0000002C) /*!< TIM4 TRGO selected as external conversion trigger for DAC channel \ + */ +#define DAC_TRG_EXT_IT9 \ + ((uint32_t)0x00000034) /*!< EXTI Line9 event selected as external conversion trigger for DAC channel */ +#define DAC_TRG_SOFTWARE ((uint32_t)0x0000003C) /*!< Conversion started by software trigger for DAC channel */ + +#define IS_DAC_TRIGGER(TRIGGER) \ + (((TRIGGER) == DAC_TRG_NONE) || ((TRIGGER) == DAC_TRG_T6_TRGO) || ((TRIGGER) == DAC_TRG_T8_TRGO) \ + || ((TRIGGER) == DAC_TRG_T7_TRGO) || ((TRIGGER) == DAC_TRG_T5_TRGO) || ((TRIGGER) == DAC_TRG_T2_TRGO) \ + || ((TRIGGER) == DAC_TRG_T4_TRGO) || ((TRIGGER) == DAC_TRG_EXT_IT9) || ((TRIGGER) == DAC_TRG_SOFTWARE)) + +/** + * @} + */ + +/** @addtogroup DAC_wave_generation + * @{ + */ + +#define DAC_WAVEGEN_NONE ((uint32_t)0x00000000) +#define DAC_WAVEGEN_NOISE ((uint32_t)0x00000040) +#define DAC_WAVEGEN_TRIANGLE ((uint32_t)0x00000080) +#define IS_DAC_GENERATE_WAVE(WAVE) \ + (((WAVE) == DAC_WAVEGEN_NONE) || ((WAVE) == DAC_WAVEGEN_NOISE) || ((WAVE) == DAC_WAVEGEN_TRIANGLE)) +/** + * @} + */ + +/** @addtogroup DAC_lfsrunmask_triangleamplitude + * @{ + */ + +#define DAC_UNMASK_LFSRBIT0 ((uint32_t)0x00000000) /*!< Unmask DAC channel LFSR bit0 for noise wave generation */ +#define DAC_UNMASK_LFSRBITS1_0 \ + ((uint32_t)0x00000100) /*!< Unmask DAC channel LFSR bit[1:0] for noise wave generation \ + */ +#define DAC_UNMASK_LFSRBITS2_0 \ + ((uint32_t)0x00000200) /*!< Unmask DAC channel LFSR bit[2:0] for noise wave generation \ + */ +#define DAC_UNMASK_LFSRBITS3_0 \ + ((uint32_t)0x00000300) /*!< Unmask DAC channel LFSR bit[3:0] for noise wave generation \ + */ +#define DAC_UNMASK_LFSRBITS4_0 \ + ((uint32_t)0x00000400) /*!< Unmask DAC channel LFSR bit[4:0] for noise wave generation \ + */ +#define DAC_UNMASK_LFSRBITS5_0 \ + ((uint32_t)0x00000500) /*!< Unmask DAC channel LFSR bit[5:0] for noise wave generation \ + */ +#define DAC_UNMASK_LFSRBITS6_0 \ + ((uint32_t)0x00000600) /*!< Unmask DAC channel LFSR bit[6:0] for noise wave generation \ + */ +#define DAC_UNMASK_LFSRBITS7_0 \ + ((uint32_t)0x00000700) /*!< Unmask DAC channel LFSR bit[7:0] for noise wave generation \ + */ +#define DAC_UNMASK_LFSRBITS8_0 \ + ((uint32_t)0x00000800) /*!< Unmask DAC channel LFSR bit[8:0] for noise wave generation \ + */ +#define DAC_UNMASK_LFSRBITS9_0 \ + ((uint32_t)0x00000900) /*!< Unmask DAC channel LFSR bit[9:0] for noise wave generation \ + */ +#define DAC_UNMASK_LFSRBITS10_0 \ + ((uint32_t)0x00000A00) /*!< Unmask DAC channel LFSR bit[10:0] for noise wave generation */ +#define DAC_UNMASK_LFSRBITS11_0 \ + ((uint32_t)0x00000B00) /*!< Unmask DAC channel LFSR bit[11:0] for noise wave generation */ +#define DAC_TRIAMP_1 ((uint32_t)0x00000000) /*!< Select max triangle amplitude of 1 */ +#define DAC_TRIAMP_3 ((uint32_t)0x00000100) /*!< Select max triangle amplitude of 3 */ +#define DAC_TRIAMP_7 ((uint32_t)0x00000200) /*!< Select max triangle amplitude of 7 */ +#define DAC_TRIAMP_15 ((uint32_t)0x00000300) /*!< Select max triangle amplitude of 15 */ +#define DAC_TRIAMP_31 ((uint32_t)0x00000400) /*!< Select max triangle amplitude of 31 */ +#define DAC_TRIAMP_63 ((uint32_t)0x00000500) /*!< Select max triangle amplitude of 63 */ +#define DAC_TRIAMP_127 ((uint32_t)0x00000600) /*!< Select max triangle amplitude of 127 */ +#define DAC_TRIAMP_255 ((uint32_t)0x00000700) /*!< Select max triangle amplitude of 255 */ +#define DAC_TRIAMP_511 ((uint32_t)0x00000800) /*!< Select max triangle amplitude of 511 */ +#define DAC_TRIAMP_1023 ((uint32_t)0x00000900) /*!< Select max triangle amplitude of 1023 */ +#define DAC_TRIAMP_2047 ((uint32_t)0x00000A00) /*!< Select max triangle amplitude of 2047 */ +#define DAC_TRIAMP_4095 ((uint32_t)0x00000B00) /*!< Select max triangle amplitude of 4095 */ + +#define IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(VALUE) \ + (((VALUE) == DAC_UNMASK_LFSRBIT0) || ((VALUE) == DAC_UNMASK_LFSRBITS1_0) || ((VALUE) == DAC_UNMASK_LFSRBITS2_0) \ + || ((VALUE) == DAC_UNMASK_LFSRBITS3_0) || ((VALUE) == DAC_UNMASK_LFSRBITS4_0) \ + || ((VALUE) == DAC_UNMASK_LFSRBITS5_0) || ((VALUE) == DAC_UNMASK_LFSRBITS6_0) \ + || ((VALUE) == DAC_UNMASK_LFSRBITS7_0) || ((VALUE) == DAC_UNMASK_LFSRBITS8_0) \ + || ((VALUE) == DAC_UNMASK_LFSRBITS9_0) || ((VALUE) == DAC_UNMASK_LFSRBITS10_0) \ + || ((VALUE) == DAC_UNMASK_LFSRBITS11_0) || ((VALUE) == DAC_TRIAMP_1) || ((VALUE) == DAC_TRIAMP_3) \ + || ((VALUE) == DAC_TRIAMP_7) || ((VALUE) == DAC_TRIAMP_15) || ((VALUE) == DAC_TRIAMP_31) \ + || ((VALUE) == DAC_TRIAMP_63) || ((VALUE) == DAC_TRIAMP_127) || ((VALUE) == DAC_TRIAMP_255) \ + || ((VALUE) == DAC_TRIAMP_511) || ((VALUE) == DAC_TRIAMP_1023) || ((VALUE) == DAC_TRIAMP_2047) \ + || ((VALUE) == DAC_TRIAMP_4095)) +/** + * @} + */ + +/** @addtogroup DAC_output_buffer + * @{ + */ + +#define DAC_BUFFOUTPUT_ENABLE ((uint32_t)0x00000002) +#define DAC_BUFFOUTPUT_DISABLE ((uint32_t)0x00000000) +#define IS_DAC_OUTPUT_BUFFER_STATE(STATE) (((STATE) == DAC_BUFFOUTPUT_ENABLE) || ((STATE) == DAC_BUFFOUTPUT_DISABLE)) +/** + * @} + */ + +/** @addtogroup DAC_Channel_selection + * @{ + */ + +#define DAC_CHANNEL_1 ((uint32_t)0x00000000) +#define DAC_CHANNEL_2 ((uint32_t)0x00000010) +#define IS_DAC_CHANNEL(CHANNEL) (((CHANNEL) == DAC_CHANNEL_1) || ((CHANNEL) == DAC_CHANNEL_2)) +/** + * @} + */ + +/** @addtogroup DAC_data_alignment + * @{ + */ + +#define DAC_ALIGN_R_12BIT ((uint32_t)0x00000000) +#define DAC_ALIGN_L_12BIT ((uint32_t)0x00000004) +#define DAC_ALIGN_R_8BIT ((uint32_t)0x00000008) +#define IS_DAC_ALIGN(ALIGN) \ + (((ALIGN) == DAC_ALIGN_R_12BIT) || ((ALIGN) == DAC_ALIGN_L_12BIT) || ((ALIGN) == DAC_ALIGN_R_8BIT)) +/** + * @} + */ + +/** @addtogroup DAC_wave_generation + * @{ + */ + +#define DAC_WAVE_NOISE ((uint32_t)0x00000040) +#define DAC_WAVE_TRIANGLE ((uint32_t)0x00000080) +#define IS_DAC_WAVE(WAVE) (((WAVE) == DAC_WAVE_NOISE) || ((WAVE) == DAC_WAVE_TRIANGLE)) +/** + * @} + */ + +/** @addtogroup DAC_data + * @{ + */ + +#define IS_DAC_DATA(DATA) ((DATA) <= 0xFFF0) +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup DAC_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DAC_Exported_Functions + * @{ + */ + +void DAC_DeInit(void); +void DAC_Init(uint32_t DAC_Channel, DAC_InitType* DAC_InitStruct); +void DAC_ClearStruct(DAC_InitType* DAC_InitStruct); +void DAC_Enable(uint32_t DAC_Channel, FunctionalState Cmd); + +void DAC_DmaEnable(uint32_t DAC_Channel, FunctionalState Cmd); +void DAC_SoftTrgEnable(uint32_t DAC_Channel, FunctionalState Cmd); +void DAC_DualSoftwareTrgEnable(FunctionalState Cmd); +void DAC_WaveGenerationEnable(uint32_t DAC_Channel, uint32_t DAC_Wave, FunctionalState Cmd); +void DAC_SetCh1Data(uint32_t DAC_Align, uint16_t Data); +void DAC_SetCh2Data(uint32_t DAC_Align, uint16_t Data); +void DAC_SetDualChData(uint32_t DAC_Align, uint16_t Data2, uint16_t Data1); +uint16_t DAC_GetOutputDataVal(uint32_t DAC_Channel); + +#ifdef __cplusplus +} +#endif + +#endif /*__N32G45X_DAC_H__ */ + /** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/inc/n32g45x_dbg.h b/inc/n32g45x_dbg.h new file mode 100644 index 0000000..ca94b4a --- /dev/null +++ b/inc/n32g45x_dbg.h @@ -0,0 +1,124 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_dbg.h + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_DBG_H__ +#define __N32G45X_DBG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup DBG + * @{ + */ + +/** @addtogroup DBGMCU_Exported_Types + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DBGMCU_Exported_Constants + * @{ + */ + +#define DBG_SLEEP ((uint32_t)0x00000001) +#define DBG_STOP ((uint32_t)0x00000002) +#define DBG_STDBY ((uint32_t)0x00000004) +#define DBG_IWDG_STOP ((uint32_t)0x00000100) +#define DBG_WWDG_STOP ((uint32_t)0x00000200) +#define DBG_TIM1_STOP ((uint32_t)0x00000400) +#define DBG_TIM2_STOP ((uint32_t)0x00000800) +#define DBG_TIM3_STOP ((uint32_t)0x00001000) +#define DBG_TIM4_STOP ((uint32_t)0x00002000) +#define DBG_CAN1_STOP ((uint32_t)0x00004000) +#define DBG_I2C1SMBUS_TIMEOUT ((uint32_t)0x00008000) +#define DBG_I2C2SMBUS_TIMEOUT ((uint32_t)0x00010000) +#define DBG_TIM8_STOP ((uint32_t)0x00020000) +#define DBG_TIM5_STOP ((uint32_t)0x00040000) +#define DBG_TIM6_STOP ((uint32_t)0x00080000) +#define DBG_TIM7_STOP ((uint32_t)0x00100000) +#define DBG_CAN2_STOP ((uint32_t)0x00200000) + +#define IS_DBGMCU_PERIPH(PERIPH) ((((PERIPH)&0xFFC000F8) == 0x00) && ((PERIPH) != 0x00)) +/** + * @} + */ + +/** @addtogroup DBGMCU_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DBGMCU_Exported_Functions + * @{ + */ + +void GetUCID(uint8_t *UCIDbuf); +void GetUID(uint8_t *UIDbuf); +void GetDBGMCU_ID(uint8_t *DBGMCU_IDbuf); +uint32_t DBG_GetRevNum(void); +uint32_t DBG_GetDevNum(void); +void DBG_ConfigPeriph(uint32_t DBG_Periph, FunctionalState Cmd); + +uint32_t DBG_GetFlashSize(void); +uint32_t DBG_GetSramSize(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __N32G45X_DBG_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/inc/n32g45x_dma.h b/inc/n32g45x_dma.h new file mode 100644 index 0000000..39679d8 --- /dev/null +++ b/inc/n32g45x_dma.h @@ -0,0 +1,569 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_dma.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_DMA_H__ +#define __N32G45X_DMA_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup DMA + * @{ + */ + +/** @addtogroup DMA_Exported_Types + * @{ + */ + +/** + * @brief DMA Init structure definition + */ + +typedef struct +{ + uint32_t PeriphAddr; /*!< Specifies the peripheral base address for DMAy Channelx. */ + + uint32_t MemAddr; /*!< Specifies the memory base address for DMAy Channelx. */ + + uint32_t Direction; /*!< Specifies if the peripheral is the source or destination. + This parameter can be a value of @ref DMA_data_transfer_direction */ + + uint32_t BufSize; /*!< Specifies the buffer size, in data unit, of the specified Channel. + The data unit is equal to the configuration set in PeriphDataSize + or MemDataSize members depending in the transfer direction. */ + + uint32_t PeriphInc; /*!< Specifies whether the Peripheral address register is incremented or not. + This parameter can be a value of @ref DMA_peripheral_incremented_mode */ + + uint32_t DMA_MemoryInc; /*!< Specifies whether the memory address register is incremented or not. + This parameter can be a value of @ref DMA_memory_incremented_mode */ + + uint32_t PeriphDataSize; /*!< Specifies the Peripheral data width. + This parameter can be a value of @ref DMA_peripheral_data_size */ + + uint32_t MemDataSize; /*!< Specifies the Memory data width. + This parameter can be a value of @ref DMA_memory_data_size */ + + uint32_t CircularMode; /*!< Specifies the operation mode of the DMAy Channelx. + This parameter can be a value of @ref DMA_circular_normal_mode. + @note: The circular buffer mode cannot be used if the memory-to-memory + data transfer is configured on the selected Channel */ + + uint32_t Priority; /*!< Specifies the software priority for the DMAy Channelx. + This parameter can be a value of @ref DMA_priority_level */ + + uint32_t Mem2Mem; /*!< Specifies if the DMAy Channelx will be used in memory-to-memory transfer. + This parameter can be a value of @ref DMA_memory_to_memory */ +} DMA_InitType; + +/** + * @} + */ + +/** @addtogroup DMA_Exported_Constants + * @{ + */ + +#define IS_DMA_ALL_PERIPH(PERIPH) \ + (((PERIPH) == DMA1_CH1) || ((PERIPH) == DMA1_CH2) || ((PERIPH) == DMA1_CH3) || ((PERIPH) == DMA1_CH4) \ + || ((PERIPH) == DMA1_CH5) || ((PERIPH) == DMA1_CH6) || ((PERIPH) == DMA1_CH7) || ((PERIPH) == DMA1_CH8) \ + || ((PERIPH) == DMA2_CH1) || ((PERIPH) == DMA2_CH2) || ((PERIPH) == DMA2_CH3) || ((PERIPH) == DMA2_CH4) \ + || ((PERIPH) == DMA2_CH5) || ((PERIPH) == DMA2_CH6) || ((PERIPH) == DMA2_CH7) || ((PERIPH) == DMA2_CH8)) + +/** @addtogroup DMA_data_transfer_direction + * @{ + */ + +#define DMA_DIR_PERIPH_DST ((uint32_t)0x00000010) +#define DMA_DIR_PERIPH_SRC ((uint32_t)0x00000000) +#define IS_DMA_DIR(DIR) (((DIR) == DMA_DIR_PERIPH_DST) || ((DIR) == DMA_DIR_PERIPH_SRC)) +/** + * @} + */ + +/** @addtogroup DMA_peripheral_incremented_mode + * @{ + */ + +#define DMA_PERIPH_INC_ENABLE ((uint32_t)0x00000040) +#define DMA_PERIPH_INC_DISABLE ((uint32_t)0x00000000) +#define IS_DMA_PERIPH_INC_STATE(STATE) (((STATE) == DMA_PERIPH_INC_ENABLE) || ((STATE) == DMA_PERIPH_INC_DISABLE)) +/** + * @} + */ + +/** @addtogroup DMA_memory_incremented_mode + * @{ + */ + +#define DMA_MEM_INC_ENABLE ((uint32_t)0x00000080) +#define DMA_MEM_INC_DISABLE ((uint32_t)0x00000000) +#define IS_DMA_MEM_INC_STATE(STATE) (((STATE) == DMA_MEM_INC_ENABLE) || ((STATE) == DMA_MEM_INC_DISABLE)) +/** + * @} + */ + +/** @addtogroup DMA_peripheral_data_size + * @{ + */ + +#define DMA_PERIPH_DATA_SIZE_BYTE ((uint32_t)0x00000000) +#define DMA_PERIPH_DATA_SIZE_HALFWORD ((uint32_t)0x00000100) +#define DMA_PERIPH_DATA_SIZE_WORD ((uint32_t)0x00000200) +#define IS_DMA_PERIPH_DATA_SIZE(SIZE) \ + (((SIZE) == DMA_PERIPH_DATA_SIZE_BYTE) || ((SIZE) == DMA_PERIPH_DATA_SIZE_HALFWORD) \ + || ((SIZE) == DMA_PERIPH_DATA_SIZE_WORD)) +/** + * @} + */ + +/** @addtogroup DMA_memory_data_size + * @{ + */ + +#define DMA_MemoryDataSize_Byte ((uint32_t)0x00000000) +#define DMA_MemoryDataSize_HalfWord ((uint32_t)0x00000400) +#define DMA_MemoryDataSize_Word ((uint32_t)0x00000800) +#define IS_DMA_MEMORY_DATA_SIZE(SIZE) \ + (((SIZE) == DMA_MemoryDataSize_Byte) || ((SIZE) == DMA_MemoryDataSize_HalfWord) \ + || ((SIZE) == DMA_MemoryDataSize_Word)) +/** + * @} + */ + +/** @addtogroup DMA_circular_normal_mode + * @{ + */ + +#define DMA_MODE_CIRCULAR ((uint32_t)0x00000020) +#define DMA_MODE_NORMAL ((uint32_t)0x00000000) +#define IS_DMA_MODE(MODE) (((MODE) == DMA_MODE_CIRCULAR) || ((MODE) == DMA_MODE_NORMAL)) +/** + * @} + */ + +/** @addtogroup DMA_priority_level + * @{ + */ + +#define DMA_PRIORITY_VERY_HIGH ((uint32_t)0x00003000) +#define DMA_PRIORITY_HIGH ((uint32_t)0x00002000) +#define DMA_PRIORITY_MEDIUM ((uint32_t)0x00001000) +#define DMA_PRIORITY_LOW ((uint32_t)0x00000000) +#define IS_DMA_PRIORITY(PRIORITY) \ + (((PRIORITY) == DMA_PRIORITY_VERY_HIGH) || ((PRIORITY) == DMA_PRIORITY_HIGH) \ + || ((PRIORITY) == DMA_PRIORITY_MEDIUM) || ((PRIORITY) == DMA_PRIORITY_LOW)) +/** + * @} + */ + +/** @addtogroup DMA_memory_to_memory + * @{ + */ + +#define DMA_M2M_ENABLE ((uint32_t)0x00004000) +#define DMA_M2M_DISABLE ((uint32_t)0x00000000) +#define IS_DMA_M2M_STATE(STATE) (((STATE) == DMA_M2M_ENABLE) || ((STATE) == DMA_M2M_DISABLE)) + +/** + * @} + */ + +/** @addtogroup DMA_interrupts_definition + * @{ + */ + +#define DMA_INT_TXC ((uint32_t)0x00000002) +#define DMA_INT_HTX ((uint32_t)0x00000004) +#define DMA_INT_ERR ((uint32_t)0x00000008) +#define IS_DMA_CONFIG_INT(IT) ((((IT)&0xFFFFFFF1) == 0x00) && ((IT) != 0x00)) + +#define DMA1_INT_GLB1 ((uint32_t)0x00000001) +#define DMA1_INT_TXC1 ((uint32_t)0x00000002) +#define DMA1_INT_HTX1 ((uint32_t)0x00000004) +#define DMA1_INT_ERR1 ((uint32_t)0x00000008) +#define DMA1_INT_GLB2 ((uint32_t)0x00000010) +#define DMA1_INT_TXC2 ((uint32_t)0x00000020) +#define DMA1_INT_HTX2 ((uint32_t)0x00000040) +#define DMA1_INT_ERR2 ((uint32_t)0x00000080) +#define DMA1_INT_GLB3 ((uint32_t)0x00000100) +#define DMA1_INT_TXC3 ((uint32_t)0x00000200) +#define DMA1_INT_HTX3 ((uint32_t)0x00000400) +#define DMA1_INT_ERR3 ((uint32_t)0x00000800) +#define DMA1_INT_GLB4 ((uint32_t)0x00001000) +#define DMA1_INT_TXC4 ((uint32_t)0x00002000) +#define DMA1_INT_HTX4 ((uint32_t)0x00004000) +#define DMA1_INT_ERR4 ((uint32_t)0x00008000) +#define DMA1_INT_GLB5 ((uint32_t)0x00010000) +#define DMA1_INT_TXC5 ((uint32_t)0x00020000) +#define DMA1_INT_HTX5 ((uint32_t)0x00040000) +#define DMA1_INT_ERR5 ((uint32_t)0x00080000) +#define DMA1_INT_GLB6 ((uint32_t)0x00100000) +#define DMA1_INT_TXC6 ((uint32_t)0x00200000) +#define DMA1_INT_HTX6 ((uint32_t)0x00400000) +#define DMA1_INT_ERR6 ((uint32_t)0x00800000) +#define DMA1_INT_GLB7 ((uint32_t)0x01000000) +#define DMA1_INT_TXC7 ((uint32_t)0x02000000) +#define DMA1_INT_HTX7 ((uint32_t)0x04000000) +#define DMA1_INT_ERR7 ((uint32_t)0x08000000) +#define DMA1_INT_GLB8 ((uint32_t)0x10000000) +#define DMA1_INT_TXC8 ((uint32_t)0x20000000) +#define DMA1_INT_HTX8 ((uint32_t)0x40000000) +#define DMA1_INT_ERR8 ((uint32_t)0x80000000) + +#define DMA2_INT_GLB1 ((uint32_t)0x00000001) +#define DMA2_INT_TXC1 ((uint32_t)0x00000002) +#define DMA2_INT_HTX1 ((uint32_t)0x00000004) +#define DMA2_INT_ERR1 ((uint32_t)0x00000008) +#define DMA2_INT_GLB2 ((uint32_t)0x00000010) +#define DMA2_INT_TXC2 ((uint32_t)0x00000020) +#define DMA2_INT_HTX2 ((uint32_t)0x00000040) +#define DMA2_INT_ERR2 ((uint32_t)0x00000080) +#define DMA2_INT_GLB3 ((uint32_t)0x00000100) +#define DMA2_INT_TXC3 ((uint32_t)0x00000200) +#define DMA2_INT_HTX3 ((uint32_t)0x00000400) +#define DMA2_INT_ERR3 ((uint32_t)0x00000800) +#define DMA2_INT_GLB4 ((uint32_t)0x00001000) +#define DMA2_INT_TXC4 ((uint32_t)0x00002000) +#define DMA2_INT_HTX4 ((uint32_t)0x00004000) +#define DMA2_INT_ERR4 ((uint32_t)0x00008000) +#define DMA2_INT_GLB5 ((uint32_t)0x00010000) +#define DMA2_INT_TXC5 ((uint32_t)0x00020000) +#define DMA2_INT_HTX5 ((uint32_t)0x00040000) +#define DMA2_INT_ERR5 ((uint32_t)0x00080000) +#define DMA2_INT_GLB6 ((uint32_t)0x00100000) +#define DMA2_INT_TXC6 ((uint32_t)0x00200000) +#define DMA2_INT_HTX6 ((uint32_t)0x00400000) +#define DMA2_INT_ERR6 ((uint32_t)0x00800000) +#define DMA2_INT_GLB7 ((uint32_t)0x01000000) +#define DMA2_INT_TXC7 ((uint32_t)0x02000000) +#define DMA2_INT_HTX7 ((uint32_t)0x04000000) +#define DMA2_INT_ERR7 ((uint32_t)0x08000000) +#define DMA2_INT_GLB8 ((uint32_t)0x10000000) +#define DMA2_INT_TXC8 ((uint32_t)0x20000000) +#define DMA2_INT_HTX8 ((uint32_t)0x40000000) +#define DMA2_INT_ERR8 ((uint32_t)0x80000000) + +#define IS_DMA_CLR_INT(IT) ((IT) != 0x00) + +#define IS_DMA_GET_IT(IT) \ + (((IT) == DMA1_INT_GLB1) || ((IT) == DMA1_INT_TXC1) || ((IT) == DMA1_INT_HTX1) || ((IT) == DMA1_INT_ERR1) \ + || ((IT) == DMA1_INT_GLB2) || ((IT) == DMA1_INT_TXC2) || ((IT) == DMA1_INT_HTX2) || ((IT) == DMA1_INT_ERR2) \ + || ((IT) == DMA1_INT_GLB3) || ((IT) == DMA1_INT_TXC3) || ((IT) == DMA1_INT_HTX3) || ((IT) == DMA1_INT_ERR3) \ + || ((IT) == DMA1_INT_GLB4) || ((IT) == DMA1_INT_TXC4) || ((IT) == DMA1_INT_HTX4) || ((IT) == DMA1_INT_ERR4) \ + || ((IT) == DMA1_INT_GLB5) || ((IT) == DMA1_INT_TXC5) || ((IT) == DMA1_INT_HTX5) || ((IT) == DMA1_INT_ERR5) \ + || ((IT) == DMA1_INT_GLB6) || ((IT) == DMA1_INT_TXC6) || ((IT) == DMA1_INT_HTX6) || ((IT) == DMA1_INT_ERR6) \ + || ((IT) == DMA1_INT_GLB7) || ((IT) == DMA1_INT_TXC7) || ((IT) == DMA1_INT_HTX7) || ((IT) == DMA1_INT_ERR7) \ + || ((IT) == DMA1_INT_GLB8) || ((IT) == DMA1_INT_TXC8) || ((IT) == DMA1_INT_HTX8) || ((IT) == DMA1_INT_ERR8) \ + || ((IT) == DMA2_INT_GLB1) || ((IT) == DMA2_INT_TXC1) || ((IT) == DMA2_INT_HTX1) || ((IT) == DMA2_INT_ERR1) \ + || ((IT) == DMA2_INT_GLB2) || ((IT) == DMA2_INT_TXC2) || ((IT) == DMA2_INT_HTX2) || ((IT) == DMA2_INT_ERR2) \ + || ((IT) == DMA2_INT_GLB3) || ((IT) == DMA2_INT_TXC3) || ((IT) == DMA2_INT_HTX3) || ((IT) == DMA2_INT_ERR3) \ + || ((IT) == DMA2_INT_GLB4) || ((IT) == DMA2_INT_TXC4) || ((IT) == DMA2_INT_HTX4) || ((IT) == DMA2_INT_ERR4) \ + || ((IT) == DMA2_INT_GLB5) || ((IT) == DMA2_INT_TXC5) || ((IT) == DMA2_INT_HTX5) || ((IT) == DMA2_INT_ERR5) \ + || ((IT) == DMA2_INT_GLB6) || ((IT) == DMA2_INT_TXC6) || ((IT) == DMA2_INT_HTX6) || ((IT) == DMA2_INT_ERR6) \ + || ((IT) == DMA2_INT_GLB7) || ((IT) == DMA2_INT_TXC7) || ((IT) == DMA2_INT_HTX7) || ((IT) == DMA2_INT_ERR7) \ + || ((IT) == DMA2_INT_GLB8) || ((IT) == DMA2_INT_TXC8) || ((IT) == DMA2_INT_HTX8) || ((IT) == DMA2_INT_ERR8)) + +/** + * @} + */ + +/** @addtogroup DMA_flags_definition + * @{ + */ +#define DMA1_FLAG_GL1 ((uint32_t)0x00000001) +#define DMA1_FLAG_TC1 ((uint32_t)0x00000002) +#define DMA1_FLAG_HT1 ((uint32_t)0x00000004) +#define DMA1_FLAG_TE1 ((uint32_t)0x00000008) +#define DMA1_FLAG_GL2 ((uint32_t)0x00000010) +#define DMA1_FLAG_TC2 ((uint32_t)0x00000020) +#define DMA1_FLAG_HT2 ((uint32_t)0x00000040) +#define DMA1_FLAG_TE2 ((uint32_t)0x00000080) +#define DMA1_FLAG_GL3 ((uint32_t)0x00000100) +#define DMA1_FLAG_TC3 ((uint32_t)0x00000200) +#define DMA1_FLAG_HT3 ((uint32_t)0x00000400) +#define DMA1_FLAG_TE3 ((uint32_t)0x00000800) +#define DMA1_FLAG_GL4 ((uint32_t)0x00001000) +#define DMA1_FLAG_TC4 ((uint32_t)0x00002000) +#define DMA1_FLAG_HT4 ((uint32_t)0x00004000) +#define DMA1_FLAG_TE4 ((uint32_t)0x00008000) +#define DMA1_FLAG_GL5 ((uint32_t)0x00010000) +#define DMA1_FLAG_TC5 ((uint32_t)0x00020000) +#define DMA1_FLAG_HT5 ((uint32_t)0x00040000) +#define DMA1_FLAG_TE5 ((uint32_t)0x00080000) +#define DMA1_FLAG_GL6 ((uint32_t)0x00100000) +#define DMA1_FLAG_TC6 ((uint32_t)0x00200000) +#define DMA1_FLAG_HT6 ((uint32_t)0x00400000) +#define DMA1_FLAG_TE6 ((uint32_t)0x00800000) +#define DMA1_FLAG_GL7 ((uint32_t)0x01000000) +#define DMA1_FLAG_TC7 ((uint32_t)0x02000000) +#define DMA1_FLAG_HT7 ((uint32_t)0x04000000) +#define DMA1_FLAG_TE7 ((uint32_t)0x08000000) +#define DMA1_FLAG_GL8 ((uint32_t)0x10000000) +#define DMA1_FLAG_TC8 ((uint32_t)0x20000000) +#define DMA1_FLAG_HT8 ((uint32_t)0x40000000) +#define DMA1_FLAG_TE8 ((uint32_t)0x80000000) + +#define DMA2_FLAG_GL1 ((uint32_t)0x00000001) +#define DMA2_FLAG_TC1 ((uint32_t)0x00000002) +#define DMA2_FLAG_HT1 ((uint32_t)0x00000004) +#define DMA2_FLAG_TE1 ((uint32_t)0x00000008) +#define DMA2_FLAG_GL2 ((uint32_t)0x00000010) +#define DMA2_FLAG_TC2 ((uint32_t)0x00000020) +#define DMA2_FLAG_HT2 ((uint32_t)0x00000040) +#define DMA2_FLAG_TE2 ((uint32_t)0x00000080) +#define DMA2_FLAG_GL3 ((uint32_t)0x00000100) +#define DMA2_FLAG_TC3 ((uint32_t)0x00000200) +#define DMA2_FLAG_HT3 ((uint32_t)0x00000400) +#define DMA2_FLAG_TE3 ((uint32_t)0x00000800) +#define DMA2_FLAG_GL4 ((uint32_t)0x00001000) +#define DMA2_FLAG_TC4 ((uint32_t)0x00002000) +#define DMA2_FLAG_HT4 ((uint32_t)0x00004000) +#define DMA2_FLAG_TE4 ((uint32_t)0x00008000) +#define DMA2_FLAG_GL5 ((uint32_t)0x00010000) +#define DMA2_FLAG_TC5 ((uint32_t)0x00020000) +#define DMA2_FLAG_HT5 ((uint32_t)0x00040000) +#define DMA2_FLAG_TE5 ((uint32_t)0x00080000) +#define DMA2_FLAG_GL6 ((uint32_t)0x00100000) +#define DMA2_FLAG_TC6 ((uint32_t)0x00200000) +#define DMA2_FLAG_HT6 ((uint32_t)0x00400000) +#define DMA2_FLAG_TE6 ((uint32_t)0x00800000) +#define DMA2_FLAG_GL7 ((uint32_t)0x01000000) +#define DMA2_FLAG_TC7 ((uint32_t)0x02000000) +#define DMA2_FLAG_HT7 ((uint32_t)0x04000000) +#define DMA2_FLAG_TE7 ((uint32_t)0x08000000) +#define DMA2_FLAG_GL8 ((uint32_t)0x10000000) +#define DMA2_FLAG_TC8 ((uint32_t)0x20000000) +#define DMA2_FLAG_HT8 ((uint32_t)0x40000000) +#define DMA2_FLAG_TE8 ((uint32_t)0x80000000) + +#define IS_DMA_CLEAR_FLAG(FLAG) ((FLAG) != 0x00) + +#define IS_DMA_GET_FLAG(FLAG) \ + (((FLAG) == DMA1_FLAG_GL1) || ((FLAG) == DMA1_FLAG_TC1) || ((FLAG) == DMA1_FLAG_HT1) || ((FLAG) == DMA1_FLAG_TE1) \ + || ((FLAG) == DMA1_FLAG_GL2) || ((FLAG) == DMA1_FLAG_TC2) || ((FLAG) == DMA1_FLAG_HT2) \ + || ((FLAG) == DMA1_FLAG_TE2) || ((FLAG) == DMA1_FLAG_GL3) || ((FLAG) == DMA1_FLAG_TC3) \ + || ((FLAG) == DMA1_FLAG_HT3) || ((FLAG) == DMA1_FLAG_TE3) || ((FLAG) == DMA1_FLAG_GL4) \ + || ((FLAG) == DMA1_FLAG_TC4) || ((FLAG) == DMA1_FLAG_HT4) || ((FLAG) == DMA1_FLAG_TE4) \ + || ((FLAG) == DMA1_FLAG_GL5) || ((FLAG) == DMA1_FLAG_TC5) || ((FLAG) == DMA1_FLAG_HT5) \ + || ((FLAG) == DMA1_FLAG_TE5) || ((FLAG) == DMA1_FLAG_GL6) || ((FLAG) == DMA1_FLAG_TC6) \ + || ((FLAG) == DMA1_FLAG_HT6) || ((FLAG) == DMA1_FLAG_TE6) || ((FLAG) == DMA1_FLAG_GL7) \ + || ((FLAG) == DMA1_FLAG_TC7) || ((FLAG) == DMA1_FLAG_HT7) || ((FLAG) == DMA1_FLAG_TE7) \ + || ((FLAG) == DMA1_FLAG_GL8) || ((FLAG) == DMA1_FLAG_TC8) || ((FLAG) == DMA1_FLAG_HT8) \ + || ((FLAG) == DMA1_FLAG_TE8) || ((FLAG) == DMA2_FLAG_GL1) || ((FLAG) == DMA2_FLAG_TC1) \ + || ((FLAG) == DMA2_FLAG_HT1) || ((FLAG) == DMA2_FLAG_TE1) || ((FLAG) == DMA2_FLAG_GL2) \ + || ((FLAG) == DMA2_FLAG_TC2) || ((FLAG) == DMA2_FLAG_HT2) || ((FLAG) == DMA2_FLAG_TE2) \ + || ((FLAG) == DMA2_FLAG_GL3) || ((FLAG) == DMA2_FLAG_TC3) || ((FLAG) == DMA2_FLAG_HT3) \ + || ((FLAG) == DMA2_FLAG_TE3) || ((FLAG) == DMA2_FLAG_GL4) || ((FLAG) == DMA2_FLAG_TC4) \ + || ((FLAG) == DMA2_FLAG_HT4) || ((FLAG) == DMA2_FLAG_TE4) || ((FLAG) == DMA2_FLAG_GL5) \ + || ((FLAG) == DMA2_FLAG_TC5) || ((FLAG) == DMA2_FLAG_HT5) || ((FLAG) == DMA2_FLAG_TE5) \ + || ((FLAG) == DMA2_FLAG_GL6) || ((FLAG) == DMA2_FLAG_TC6) || ((FLAG) == DMA2_FLAG_HT6) \ + || ((FLAG) == DMA2_FLAG_TE6) || ((FLAG) == DMA2_FLAG_GL7) || ((FLAG) == DMA2_FLAG_TC7) \ + || ((FLAG) == DMA2_FLAG_HT7) || ((FLAG) == DMA2_FLAG_TE7) || ((FLAG) == DMA2_FLAG_GL8) \ + || ((FLAG) == DMA2_FLAG_TC8) || ((FLAG) == DMA2_FLAG_HT8) || ((FLAG) == DMA2_FLAG_TE8)) +/** + * @} + */ + +/** @addtogroup DMA_Buffer_Size + * @{ + */ + +#define IS_DMA_BUF_SIZE(SIZE) (((SIZE) >= 0x1) && ((SIZE) < 0x10000)) + +/** + * @} + */ + +/** @addtogroup DMA_remap_request_definition + * @{ + */ +#define DMA1_REMAP_ADC1 ((uint32_t)0x00000000) +#define DMA1_REMAP_UART5_TX ((uint32_t)0x00000001) +#define DMA1_REMAP_I2C3_TX ((uint32_t)0x00000002) +#define DMA1_REMAP_TIM2_CH3 ((uint32_t)0x00000003) +#define DMA1_REMAP_TIM4_CH1 ((uint32_t)0x00000004) +#define DMA1_REMAP_USART3_TX ((uint32_t)0x00000005) +#define DMA1_REMAP_I2C3_RX ((uint32_t)0x00000006) +#define DMA1_REMAP_TIM1_CH1 ((uint32_t)0x00000007) +#define DMA1_REMAP_TIM2_UP ((uint32_t)0x00000008) +#define DMA1_REMAP_TIM3_CH3 ((uint32_t)0x00000009) +#define DMA1_REMAP_SPI1_RX ((uint32_t)0x0000000A) +#define DMA1_REMAP_USART3_RX ((uint32_t)0x0000000B) +#define DMA1_REMAP_TIM1_CH2 ((uint32_t)0x0000000C) +#define DMA1_REMAP_TIM3_CH4 ((uint32_t)0x0000000D) +#define DMA1_REMAP_TIM3_UP ((uint32_t)0x0000000E) +#define DMA1_REMAP_SPI1_TX ((uint32_t)0x0000000F) +#define DMA1_REMAP_USART1_TX ((uint32_t)0x00000010) +#define DMA1_REMAP_TIM1_CH4 ((uint32_t)0x00000011) +#define DMA1_REMAP_TIM1_TRIG ((uint32_t)0x00000012) +#define DMA1_REMAP_TIM1_COM ((uint32_t)0x00000013) +#define DMA1_REMAP_TIM4_CH2 ((uint32_t)0x00000014) +#define DMA1_REMAP_SPI_I2S2_RX ((uint32_t)0x00000015) +#define DMA1_REMAP_I2C2_TX ((uint32_t)0x00000016) +#define DMA1_REMAP_USART1_RX ((uint32_t)0x00000017) +#define DMA1_REMAP_TIM1_UP ((uint32_t)0x00000018) +#define DMA1_REMAP_SPI_I2S2_TX ((uint32_t)0x00000019) +#define DMA1_REMAP_TIM4_CH3 ((uint32_t)0x0000001B) +#define DMA1_REMAP_I2C2_RX ((uint32_t)0x0000001C) +#define DMA1_REMAP_TIM2_CH1 ((uint32_t)0x0000001A) +#define DMA1_REMAP_USART2_RX ((uint32_t)0x0000001D) +#define DMA1_REMAP_TIM1_CH3 ((uint32_t)0x0000001E) +#define DMA1_REMAP_TIM3_CH1 ((uint32_t)0x0000001F) +#define DMA1_REMAP_TIM3_TRIG ((uint32_t)0x00000020) +#define DMA1_REMAP_I2C1_TX ((uint32_t)0x00000021) +#define DMA1_REMAP_USART2_TX ((uint32_t)0x00000022) +#define DMA1_REMAP_TIM2_CH2 ((uint32_t)0x00000023) +#define DMA1_REMAP_TIM2_CH4 ((uint32_t)0x00000024) +#define DMA1_REMAP_TIM4_UP ((uint32_t)0x00000025) +#define DMA1_REMAP_I2C1_RX ((uint32_t)0x00000026) +#define DMA1_REMAP_ADC2 ((uint32_t)0x00000027) +#define DMA1_REMAP_UART5_RX ((uint32_t)0x00000028) +#define DMA2_REMAP_TIM5_CH4 ((uint32_t)0x00000000) +#define DMA2_REMAP_TIM5_TRIG ((uint32_t)0x00000001) +#define DMA2_REMAP_TIM8_CH3 ((uint32_t)0x00000002) +#define DMA2_REMAP_TIM8_UP ((uint32_t)0x00000003) +#define DMA2_REMAP_SPI_I2S3_RX ((uint32_t)0x00000004) +#define DMA2_REMAP_UART6_RX ((uint32_t)0x00000005) +#define DMA2_REMAP_TIM8_CH4 ((uint32_t)0x00000006) +#define DMA2_REMAP_TIM8_TRIG ((uint32_t)0x00000007) +#define DMA2_REMAP_TIM8_COM ((uint32_t)0x00000008) +#define DMA2_REMAP_TIM5_CH3 ((uint32_t)0x00000009) +#define DMA2_REMAP_TIM5_UP ((uint32_t)0x0000000A) +#define DMA2_REMAP_SPI_I2S3_TX ((uint32_t)0x0000000B) +#define DMA2_REMAP_UART6_TX ((uint32_t)0x0000000C) +#define DMA2_REMAP_TIM8_CH1 ((uint32_t)0x0000000D) +#define DMA2_REMAP_UART4_RX ((uint32_t)0x0000000E) +#define DMA2_REMAP_TIM6_UP ((uint32_t)0x0000000F) +#define DMA2_REMAP_DAC1 ((uint32_t)0x00000010) +#define DMA2_REMAP_TIM5_CH2 ((uint32_t)0x00000011) +#define DMA2_REMAP_SDIO ((uint32_t)0x00000012) +#define DMA2_REMAP_TIM7_UP ((uint32_t)0x00000013) +#define DMA2_REMAP_DAC2 ((uint32_t)0x00000014) +#define DMA2_REMAP_ADC3 ((uint32_t)0x00000015) +#define DMA2_REMAP_TIM8_CH2 ((uint32_t)0x00000016) +#define DMA2_REMAP_TIM5_CH1 ((uint32_t)0x00000017) +#define DMA2_REMAP_UART4_TX ((uint32_t)0x00000018) +#define DMA2_REMAP_QSPI_RX ((uint32_t)0x00000019) +#define DMA2_REMAP_I2C4_TX ((uint32_t)0x0000001A) +#define DMA2_REMAP_UART7_RX ((uint32_t)0x0000001B) +#define DMA2_REMAP_QSPI_TX ((uint32_t)0x0000001C) +#define DMA2_REMAP_I2C4_RX ((uint32_t)0x0000001D) +#define DMA2_REMAP_UART7_TX ((uint32_t)0x0000001E) +#define DMA2_REMAP_ADC4 ((uint32_t)0x0000001F) +#define DMA2_REMAP_DVP ((uint32_t)0x00000020) + +#define IS_DMA_REMAP(FLAG) \ + (((FLAG) == DMA1_REMAP_ADC1) || ((FLAG) == DMA1_REMAP_UART5_TX) || ((FLAG) == DMA1_REMAP_I2C3_TX) \ + || ((FLAG) == DMA1_REMAP_TIM2_CH3) || ((FLAG) == DMA1_REMAP_TIM4_CH1) || ((FLAG) == DMA1_REMAP_USART3_TX) \ + || ((FLAG) == DMA1_REMAP_I2C3_RX) || ((FLAG) == DMA1_REMAP_TIM1_CH1) || ((FLAG) == DMA1_REMAP_TIM2_UP) \ + || ((FLAG) == DMA1_REMAP_TIM3_CH3) || ((FLAG) == DMA1_REMAP_SPI1_RX) || ((FLAG) == DMA1_REMAP_USART3_RX) \ + || ((FLAG) == DMA1_REMAP_TIM1_CH2) || ((FLAG) == DMA1_REMAP_TIM3_CH4) || ((FLAG) == DMA1_REMAP_TIM3_UP) \ + || ((FLAG) == DMA1_REMAP_SPI1_TX) || ((FLAG) == DMA1_REMAP_USART1_TX) || ((FLAG) == DMA1_REMAP_TIM1_CH4) \ + || ((FLAG) == DMA1_REMAP_TIM1_TRIG) || ((FLAG) == DMA1_REMAP_TIM1_COM) || ((FLAG) == DMA1_REMAP_TIM4_CH2) \ + || ((FLAG) == DMA1_REMAP_SPI_I2S2_RX) || ((FLAG) == DMA1_REMAP_I2C2_TX) || ((FLAG) == DMA1_REMAP_USART1_RX) \ + || ((FLAG) == DMA1_REMAP_TIM1_UP) || ((FLAG) == DMA1_REMAP_SPI_I2S2_TX) || ((FLAG) == DMA1_REMAP_TIM4_CH3) \ + || ((FLAG) == DMA1_REMAP_I2C2_RX) || ((FLAG) == DMA1_REMAP_TIM2_CH1) || ((FLAG) == DMA1_REMAP_USART2_RX) \ + || ((FLAG) == DMA1_REMAP_TIM1_CH3) || ((FLAG) == DMA1_REMAP_TIM3_CH1) || ((FLAG) == DMA1_REMAP_TIM3_TRIG) \ + || ((FLAG) == DMA1_REMAP_I2C1_TX) || ((FLAG) == DMA1_REMAP_USART2_TX) || ((FLAG) == DMA1_REMAP_TIM2_CH2) \ + || ((FLAG) == DMA1_REMAP_TIM2_CH4) || ((FLAG) == DMA1_REMAP_TIM4_UP) || ((FLAG) == DMA1_REMAP_I2C1_RX) \ + || ((FLAG) == DMA1_REMAP_ADC2) || ((FLAG) == DMA1_REMAP_UART5_RX) || ((FLAG) == DMA2_REMAP_TIM5_CH4) \ + || ((FLAG) == DMA2_REMAP_TIM5_TRIG) || ((FLAG) == DMA2_REMAP_TIM8_CH3) || ((FLAG) == DMA2_REMAP_TIM8_UP) \ + || ((FLAG) == DMA2_REMAP_SPI_I2S3_RX) || ((FLAG) == DMA2_REMAP_UART6_RX) || ((FLAG) == DMA2_REMAP_TIM8_CH4) \ + || ((FLAG) == DMA2_REMAP_TIM8_TRIG) || ((FLAG) == DMA2_REMAP_TIM8_COM) || ((FLAG) == DMA2_REMAP_TIM5_CH3) \ + || ((FLAG) == DMA2_REMAP_TIM5_UP) || ((FLAG) == DMA2_REMAP_SPI_I2S3_TX) || ((FLAG) == DMA2_REMAP_UART6_TX) \ + || ((FLAG) == DMA2_REMAP_TIM8_CH1) || ((FLAG) == DMA2_REMAP_UART4_RX) || ((FLAG) == DMA2_REMAP_TIM6_UP) \ + || ((FLAG) == DMA2_REMAP_DAC1) || ((FLAG) == DMA2_REMAP_TIM5_CH2) || ((FLAG) == DMA2_REMAP_SDIO) \ + || ((FLAG) == DMA2_REMAP_TIM7_UP) || ((FLAG) == DMA2_REMAP_DAC2) || ((FLAG) == DMA2_REMAP_ADC3) \ + || ((FLAG) == DMA2_REMAP_TIM8_CH2) || ((FLAG) == DMA2_REMAP_TIM5_CH1) || ((FLAG) == DMA2_REMAP_UART4_TX) \ + || ((FLAG) == DMA2_REMAP_QSPI_RX) || ((FLAG) == DMA2_REMAP_I2C4_TX) || ((FLAG) == DMA2_REMAP_UART7_RX) \ + || ((FLAG) == DMA2_REMAP_QSPI_TX) || ((FLAG) == DMA2_REMAP_I2C4_RX) || ((FLAG) == DMA2_REMAP_UART7_TX) \ + || ((FLAG) == DMA2_REMAP_ADC4) || ((FLAG) == DMA2_REMAP_DVP)) + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup DMA_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DMA_Exported_Functions + * @{ + */ + +void DMA_DeInit(DMA_ChannelType* DMAyChx); +void DMA_Init(DMA_ChannelType* DMAyChx, DMA_InitType* DMA_InitParam); +void DMA_StructInit(DMA_InitType* DMA_InitParam); +void DMA_EnableChannel(DMA_ChannelType* DMAyChx, FunctionalState Cmd); +void DMA_ConfigInt(DMA_ChannelType* DMAyChx, uint32_t DMAInt, FunctionalState Cmd); +void DMA_SetCurrDataCounter(DMA_ChannelType* DMAyChx, uint16_t DataNumber); +uint16_t DMA_GetCurrDataCounter(DMA_ChannelType* DMAyChx); +FlagStatus DMA_GetFlagStatus(uint32_t DMAyFlag, DMA_Module* DMAy); +void DMA_ClearFlag(uint32_t DMAyFlag, DMA_Module* DMAy); +INTStatus DMA_GetIntStatus(uint32_t DMAy_IT, DMA_Module* DMAy); +void DMA_ClrIntPendingBit(uint32_t DMAy_IT, DMA_Module* DMAy); +void DMA_RequestRemap(uint32_t DMAy_REMAP, DMA_Module* DMAy, DMA_ChannelType* DMAyChx, FunctionalState Cmd); + +#ifdef __cplusplus +} +#endif + +#endif /*__N32G45X_DMA_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/inc/n32g45x_dvp.h b/inc/n32g45x_dvp.h new file mode 100644 index 0000000..5f22c28 --- /dev/null +++ b/inc/n32g45x_dvp.h @@ -0,0 +1,602 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_dvp.h + * @author Nations + * @version v1.0.3 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ + +#ifndef __N32G45X_DVP_H__ +#define __N32G45X_DVP_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup DVP + * @brief DVP driver modules + * @{ + */ + +/** @addtogroup DVP_Exported_Types + * @{ + */ +/** + * @brief DVP Init Structure definition + */ +typedef struct +{ + uint32_t FifoWatermark; /*!< Specifies the max number of fifo data which will request INT or DMA + This parameter can be a value of @ref DVP_FifoWatermark */ + + uint16_t LineCapture; /*!< Specifies the number of data line captuered in x lines. + This parameter can be a value of @ref DVP_LineSelect_Mode */ + + uint16_t ByteCapture; /*!< Specifies the number of stop byte captuered in x bytes. + This parameter can be a value of @ref DVP_ByteSelect_Mode */ + + uint16_t DataInvert; /*!< Specifies the data invert. + This parameter can be a value of @ref DVP_DATA_INVERT */ + + uint16_t PixelClkPolarity; /*!< Specifies the pixel clock polarity + This parameter can be a value of @ref DVP_Pixel_Polarity */ + + uint16_t VsyncPolarity; /*!< Specifies the vertical synchronization polarity + This parameter can be a value of @ref DVP_Vsync_Polarity */ + + uint16_t HsyncPolarity; /*!< Specifies the Horizontal synchronization polarity + This parameter can be a value of @ref DVP_Hsync_Polarity */ + + uint16_t CaptureMode; /*!< Specifies the capture mode. + This parameter can be a value of @ref DVP_Capture_Mode */ + + uint16_t RowStart; /*!< Specifies the startint row of the pixel array in a frame */ + + uint16_t ColumnStart; /*!< Specifies the starting column of the pixel array row in a frame */ + + uint16_t ImageHeight; /*!< Specifies the image's height in a frame */ + + uint16_t ImageWidth; /*!< Specifies the image's width in a frame */ + +} DVP_InitType; +/** + * @} + */ + +/** @addtogroup DVP_Exported_Constants + * @{ + */ + +/** @addtogroup DVP_FIFO_SOFT_RESET + * @{ + */ +#define DVP_FIFO_SOFT_RESET (DVP_CTRL_FFSWRST) +/** + * @} + */ + +/** @addtogroup DVP_LineSelect_Mode + * @{ + */ +#define DVP_LINE_CAPTURE_ALL (0x00000000) +#define DVP_LINE_CAPTURE_1_2 (0x1UL << DVP_CTRL_LSM_SHIFT) +#define DVP_LINE_CAPTURE_1_3 (0x2UL << DVP_CTRL_LSM_SHIFT) +#define DVP_LINE_CAPTURE_1_4 (0x3UL << DVP_CTRL_LSM_SHIFT) +#define DVP_LINE_CAPTURE_1_5 (0x4UL << DVP_CTRL_LSM_SHIFT) +#define DVP_LINE_CAPTURE_1_6 (0x5UL << DVP_CTRL_LSM_SHIFT) +#define DVP_LINE_CAPTURE_1_7 (0x6UL << DVP_CTRL_LSM_SHIFT) +#define DVP_LINE_CAPTURE_1_8 (0x7UL << DVP_CTRL_LSM_SHIFT) +#define IS_DVP_LINE_CAPTURE(_LSM_) (((_LSM_) & (~DVP_CTRL_LSM_MASK) )==0) +/** + * @} + */ + +/** @addtogroup DVP_ByteSelect_Mode + * @{ + */ +#define DVP_BYTE_CAPTURE_ALL (0x00000000) +#define DVP_BYTE_CAPTURE_1_2 (0x1UL << DVP_CTRL_BSM_SHIFT) +#define DVP_BYTE_CAPTURE_1_3 (0x2UL << DVP_CTRL_BSM_SHIFT) +#define DVP_BYTE_CAPTURE_1_4 (0x3UL << DVP_CTRL_BSM_SHIFT) +#define DVP_BYTE_CAPTURE_1_5 (0x4UL << DVP_CTRL_BSM_SHIFT) +#define DVP_BYTE_CAPTURE_1_6 (0x5UL << DVP_CTRL_BSM_SHIFT) +#define DVP_BYTE_CAPTURE_1_7 (0x6UL << DVP_CTRL_BSM_SHIFT) +#define DVP_BYTE_CAPTURE_1_8 (0x7UL << DVP_CTRL_BSM_SHIFT) +#define IS_DVP_BYTE_CAPTURE(_BSM_) (((_BSM_) & (~DVP_CTRL_BSM_MASK) )==0) + +/** + * @} + */ + +/** @addtogroup DVP_DATA_INVERT + * @{ + */ +#define DVP_DATA_INVERT (DVP_CTRL_DATINV) +#define DVP_DATA_NOTINVERT (0x00000000) +#define IS_DVP_DATA_INVERT(_INV_) (((_INV_) & (~DVP_CTRL_DATINV_MASK) )==0) +/** + * @} + */ + +/** @addtogroup DVP_Pixel_Polarity + * @{ + */ +#define DVP_PIXEL_POLARITY_FALLING (0x00000000) +#define DVP_PIXEL_POLARITY_RISING (DVP_CTRL_PCKPOL) +#define IS_DVP_PIXEL_POLARITY(_POL_) (((_POL_) & (~DVP_CTRL_PCKPOL_MASK) )==0) +/** + * @} + */ + +/** @addtogroup DVP_FifoWatermark + * @{ + */ +#define DVP_WATER_MARK_0 (0x00000000) +#define DVP_WATER_MARK_1 (0x1UL << DVP_CTRL_FWM_SHIFT) +#define DVP_WATER_MARK_2 (0x2UL << DVP_CTRL_FWM_SHIFT) +#define DVP_WATER_MARK_3 (0x3UL << DVP_CTRL_FWM_SHIFT) +#define DVP_WATER_MARK_4 (0x4UL << DVP_CTRL_FWM_SHIFT) +#define DVP_WATER_MARK_5 (0x5UL << DVP_CTRL_FWM_SHIFT) +#define DVP_WATER_MARK_6 (0x6UL << DVP_CTRL_FWM_SHIFT) +#define DVP_WATER_MARK_7 (0x7UL << DVP_CTRL_FWM_SHIFT) + +#define IS_DVP_FIFOWATERMARK(_WATER_) (((_WATER_) >= DVP_WATER_MARK_1) && ((_WATER_) <= DVP_WATER_MARK_7)) + +/** @addtogroup DVP_Vsync_Polarity + * @{ + */ +#define DVP_VSYNC_POLARITY_HIGH (DVP_CTRL_VSPOL) +#define DVP_VSYNC_POLARITY_LOW (0x00000000) +#define IS_DVP_VSYNC_POLARITY(_POL_) (((_POL_) == DVP_VSYNC_POLARITY_HIGH) || ((_POL_) == DVP_VSYNC_POLARITY_LOW)) +/** + * @} + */ + +/** @addtogroup DVP_Hsync_Polarity + * @{ + */ +#define DVP_HSYNC_POLARITY_HIGH (DVP_CTRL_HSPOL) +#define DVP_HSYNC_POLARITY_LOW (0x00000000) +#define IS_DVP_HSYNC_POLARITY(_POL_) (((_POL_) == DVP_HSYNC_POLARITY_HIGH) || ((_POL_) == DVP_HSYNC_POLARITY_LOW)) +/** + * @} + */ + +/** @addtogroup DVP_Capture_Mode + * @{ + */ +#define DVP_CAPTURE_MODE_SINGLE (0x00000000) +#define DVP_CAPTURE_MODE_CONTINUE (DVP_CTRL_CM) +#define IS_DVP_CAPTURE_MODE(_MODE_) (((_MODE_) == DVP_CAPTURE_MODE_SINGLE) || ((_MODE_) == DVP_CAPTURE_MODE_CONTINUE)) +/** + * @} + */ + +/** @addtogroup DVP_CAPTURE_ENABLE + * @{ + */ +#define DVP_CAPTURE_DISABLE (0x00000000) +#define DVP_CAPTURE_ENABLE (DVP_CTRL_CAPTURE) +#define IS_DVP_CAPTURE(_CAPTURE_) (((_CAPTURE_) == DVP_CAPTURE_DISABLE) || ((_CAPTURE_) == DVP_CAPTURE_ENABLE)) +/** + * @} + */ + +/** @addtogroup DVP_DMA + * @{ + */ +#define DVP_DMA_DISABLE (0x00000000) +#define DVP_DMA_ENABLE (DVP_INTEN_DMAEN) +/** + * @} + */ + +/** @addtogroup DVP_StatusFlag + * @{ + */ +#define DVP_FLAG_HERR (DVP_INTSTS_HERRIS) +#define DVP_FLAG_VERR (DVP_INTSTS_VERRIS) +#define DVP_FLAG_FO (DVP_INTSTS_FOIS) +#define DVP_FLAG_FW (DVP_INTSTS_FWIS) +#define DVP_FLAG_FF (DVP_INTSTS_FFIS) +#define DVP_FLAG_FE (DVP_INTSTS_FEIS) +#define DVP_FLAG_LE (DVP_INTSTS_LEIS) +#define DVP_FLAG_LS (DVP_INTSTS_LSIS) +#define DVP_FLAG_FME (DVP_INTSTS_FMEIS) +#define DVP_FLAG_FMS (DVP_INTSTS_FMSIS) +#define DVP_FLAG_MASK (DVP_FLAG_HERR |DVP_FLAG_VERR |DVP_FLAG_FO \ + |DVP_FLAG_FW |DVP_FLAG_FF |DVP_FLAG_FE \ + |DVP_FLAG_LE |DVP_FLAG_LS |DVP_FLAG_FME \ + |DVP_FLAG_FMS) +#define IS_DVP_FLAG(_FLAG_) (((_FLAG_) & (~DVP_FLAG_MASK))==0) + +/** @addtogroup DVP_ClearFlag + * @{ + */ +#define DVP_CLEAR_FLAG_HERR (DVP_INTSTS_HERRIS) +#define DVP_CLEAR_FLAG_VERR (DVP_INTSTS_VERRIS) +#define DVP_CLEAR_FLAG_FO (DVP_INTSTS_FOIS) +#define DVP_CLEAR_FLAG_FE (DVP_INTSTS_FEIS) +#define DVP_CLEAR_FLAG_LE (DVP_INTSTS_LEIS) +#define DVP_CLEAR_FLAG_LS (DVP_INTSTS_LSIS) +#define DVP_CLEAR_FLAG_FME (DVP_INTSTS_FMEIS) +#define DVP_CLEAR_FLAG_FMS (DVP_INTSTS_FMSIS) +#define DVP_CLEAR_FLAG_MASK (DVP_CLEAR_FLAG_HERR |DVP_CLEAR_FLAG_VERR \ + |DVP_CLEAR_FLAG_FO |DVP_CLEAR_FLAG_FE \ + |DVP_CLEAR_FLAG_LE |DVP_CLEAR_FLAG_LS \ + |DVP_CLEAR_FLAG_FME |DVP_CLEAR_FLAG_FMS) +#define IS_DVP_CLEAR_FLAG(_FLAG_) (((_FLAG_) & (~DVP_CLEAR_FLAG_MASK))==0) + + +/** + * @} + */ + +/** @addtogroup DVP_IntEnable + * @{ + */ +#define DVP_INTEN_HERR (DVP_INTEN_HERRIE) +#define DVP_INTEN_VERR (DVP_INTEN_VERRIE) +#define DVP_INTEN_FO (DVP_INTEN_FOIE) +#define DVP_INTEN_FW (DVP_INTEN_FWIE) +#define DVP_INTEN_FF (DVP_INTEN_FFIE) +#define DVP_INTEN_FE (DVP_INTEN_FEIE) +#define DVP_INTEN_LE (DVP_INTEN_LEIE) +#define DVP_INTEN_LS (DVP_INTEN_LSIE) +#define DVP_INTEN_FME (DVP_INTEN_FMEIE) +#define DVP_INTEN_FMS (DVP_INTEN_FMSIE) +#define DVP_INTEN_MASK (DVP_INTEN_HERR |DVP_INTEN_VERR |DVP_INTEN_FO |DVP_INTEN_FW \ + |DVP_INTEN_FF |DVP_INTEN_FE |DVP_INTEN_LE |DVP_INTEN_LS \ + |DVP_INTEN_FME |DVP_INTEN_FMS) +#define IS_DVP_INTEN(_INT_) (((_INT_) & (~DVP_INTEN_MASK))==0) +/** + * @} + */ + +/** @addtogroup DVP_IntMark + * @{ + */ +#define DVP_MINT_HERR (DVP_MINTSTS_HERRMIS) +#define DVP_MINT_VERR (DVP_MINTSTS_VERRMIS) +#define DVP_MINT_FO (DVP_MINTSTS_FOMIS) +#define DVP_MINT_FW (DVP_MINTSTS_FWMIS) +#define DVP_MINT_FF (DVP_MINTSTS_FFMIS) +#define DVP_MINT_FE (DVP_MINTSTS_FEMIS) +#define DVP_MINT_LE (DVP_MINTSTS_LEMIS) +#define DVP_MINT_LS (DVP_MINTSTS_LSMIS) +#define DVP_MINT_FME (DVP_MINTSTS_FMEMIS) +#define DVP_MINT_FMS (DVP_MINTSTS_FMSMIS) +#define DVP_MINT_MASK (DVP_MINT_HERR |DVP_MINT_VERR |DVP_MINT_FO |DVP_MINT_FW \ + |DVP_MINT_FF |DVP_MINT_FE |DVP_MINT_LE |DVP_MINT_LS \ + |DVP_MINT_FME |DVP_MINT_FMS) +#define IS_DVP_MINT(_MINT_) (((_MINT_) & (~DVP_MINT_MASK))==0) +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @addtogroup DVP_Exported_Macros + * @{ + */ + +/** + * @brief Config the water mark of FIFO. + * @param _Watermark_ Select the new water mark of FIFO. + * This parameter can be one of the following values: + * @arg DVP_WATER_MARK_1 + * @arg DVP_WATER_MARK_2 + * @arg DVP_WATER_MARK_3 + * @arg DVP_WATER_MARK_4 + * @retval None + */ +#define __DVP_SetFifoWatermark(_Watermark_) (MODIFY_REG(DVP->CTRL, DVP_CTRL_FWM_MASK, _Watermark_)) + +/** + * @brief Config the line capture mode. + * @param _LSM_ Specifies the new mode of line capture. + * This parameter can be one of the following values: + * @arg DVP_LINE_CAPTURE_ALL Capture all lines + * @arg DVP_LINE_CAPTURE_1_2 Capture 1 line of each 2 lines + * @arg DVP_LINE_CAPTURE_1_3 Capture 1 line of each 3 lines + * @arg DVP_LINE_CAPTURE_1_4 Capture 1 line of each 4 lines + * @arg DVP_LINE_CAPTURE_1_5 Capture 1 line of each 5 lines + * @arg DVP_LINE_CAPTURE_1_6 Capture 1 line of each 6 lines + * @arg DVP_LINE_CAPTURE_1_7 Capture 1 line of each 7 lines + * @arg DVP_LINE_CAPTURE_1_8 Capture 1 line of each 8 lines + * @retval None + */ +#define __DVP_SetLineCaptureMode(_LSM_) (MODIFY_REG(DVP->CTRL, DVP_CTRL_LSM_MASK, _LSM_)) + +/** + * @brief Config the byte capture mode. + * @param _BSM_ Specifies the new mode of byte capture. + * This parameter can be one of the following values: + * @arg DVP_BYTE_CAPTURE_ALL Capture all pixels + * @arg DVP_BYTE_CAPTURE_1_2 Capture 1 pixel of each 2 pixels + * @arg DVP_BYTE_CAPTURE_1_3 Capture 1 pixel of each 3 pixels + * @arg DVP_BYTE_CAPTURE_1_4 Capture 1 pixel of each 4 pixels + * @arg DVP_BYTE_CAPTURE_1_5 Capture 1 pixel of each 5 pixels + * @arg DVP_BYTE_CAPTURE_1_6 Capture 1 pixel of each 6 pixels + * @arg DVP_BYTE_CAPTURE_1_7 Capture 1 pixel of each 7 pixels + * @arg DVP_BYTE_CAPTURE_1_8 Capture 1 pixel of each 8 pixels + * @retval None + */ +#define __DVP_SetByteCaptureMode(_BSM_) (MODIFY_REG(DVP->CTRL, DVP_CTRL_BSM_MASK, _BSM_)) + +/** + * @brief Config the data invert function. + * @param _INV_ Specifies the data invert or not. + * This parameter can be one of the following values: + * @arg DVP_DATA_INVERT Invert capture data + * @arg DVP_DATA_NOTINVERT Capture data not invert + * @retval None + */ +#define __DVP_SetDataInvert(_INV_) (MODIFY_REG(DVP->CTRL, DVP_CTRL_DATINV_MASK, _INV_)) + +/** + * @brief Config the pixel clock polarity. + * @param _POL_ Specifies the clock edge of pixel clock. + * This parameter can be one of the following values: + * @arg DVP_PIXEL_POLARITY_FALLING Get data at falling edge + * @arg DVP_PIXEL_POLARITY_RISING Get data at rising edge + * @retval None + */ +#define __DVP_SetPclkPol(_POL_) (MODIFY_REG(DVP->CTRL, DVP_CTRL_PCKPOL_MASK, _POL_)) + +/** + * @brief Config the VSYNC polarity. + * @param _POL_ Specifies the active polarity of VSYNC pin. + * This parameter can be one of the following values: + * @arg DVP_VSYNC_POLARITY_HIGH VSYNC active high + * @arg DVP_VSYNC_POLARITY_LOW VSYNC active low + * @retval None + */ +#define __DVP_SetVsyncPol(_POL_) (MODIFY_REG(DVP->CTRL, DVP_CTRL_VSPOL_MASK, _POL_)) + +/** + * @brief Config the HSYNC polarity. + * @param _POL_ Specifies the active polarity of HSYNC pin. + * This parameter can be one of the following values: + * @arg DVP_HSYNC_POLARITY_HIGH VSYNC active high + * @arg DVP_HSYNC_POLARITY_LOW VSYNC active low + * @retval None + */ +#define __DVP_SetHsyncPol(_POL_) (MODIFY_REG(DVP->CTRL, DVP_CTRL_HSPOL_MASK, _POL_)) + +/** + * @brief Config the capture mode. + * @param _POL_ Specifies the new capture mode. + * This parameter can be one of the following values: + * @arg DVP_CAPTURE_MODE_SINGLE Capture one frame + * @arg DVP_CAPTURE_MODE_CONTINUE Capture many frames + * @retval None + */ +#define __DVP_SetCaptureMode(_MODE_) (MODIFY_REG(DVP->CTRL, DVP_CTRL_CM_MASK, _MODE_)) + +/** + * @brief Enable DVP interface. + * @param None + * @retval None + */ +#define __DVP_StartCapture() (SET_BIT(DVP->CTRL, DVP_CAPTURE_ENABLE)) + +/** + * @brief Disable DVP interface. + * @param None + * @retval None + */ +#define __DVP_StopCapture() (CLEAR_BIT(DVP->CTRL, DVP_CAPTURE_ENABLE)) + +/** + * @brief Disable DVP interface. + * @param None + * @retval None + */ +#define __FIFOIsNotEmpty() (READ_BIT(DVP->STS, DVP_STS_FNE)) + +/** + * @brief Checks whether the specified DVP flag is set. + * @param _FLAG_ specifies the flag to check. + * This parameter can be any combination of the following values: + * @arg DVP_FLAG_HERR Hsync error interrupt flag + * @arg DVP_FLAG_VERR Vsync error interrupt flag + * @arg DVP_FLAG_FO FIFO overflow intterrupt flag + * @arg DVP_FLAG_FW FIFO watermark interrupt flag + * @arg DVP_FLAG_FF FIFO full interrupt flag + * @arg DVP_FLAG_FE FIFO empty interrupt flag + * @arg DVP_FLAG_LE Line end interrupt flag + * @arg DVP_FLAG_LS Line start interrupt flag + * @arg DVP_FLAG_FME Frame end interrupt flag + * @arg DVP_FLAG_FMS Frame start interrupt flag + * @retval true or false. + */ +#define __DVP_FlagIsSet(_FLAG_) (((DVP->INTSTS) & (_FLAG_))==(_FLAG_)) + +/** + * @brief Checks whether the specified DVP flag is not set. + * @param _FLAG_ specifies the flag to check. + * This parameter can be any combination of the following values: + * @arg DVP_FLAG_HERR Hsync error interrupt flag + * @arg DVP_FLAG_VERR Vsync error interrupt flag + * @arg DVP_FLAG_FO FIFO overflow intterrupt flag + * @arg DVP_FLAG_FW FIFO watermark interrupt flag + * @arg DVP_FLAG_FF FIFO full interrupt flag + * @arg DVP_FLAG_FE FIFO empty interrupt flag + * @arg DVP_FLAG_LE Line end interrupt flag + * @arg DVP_FLAG_LS Line start interrupt flag + * @arg DVP_FLAG_FME Frame end interrupt flag + * @arg DVP_FLAG_FMS Frame start interrupt flag + * @retval true or false. + */ +#define __DVP_FlagIsNotSet(_FLAG_) (((DVP->INTSTS) & (_FLAG_))!=(_FLAG_)) + +/** + * @brief Clears the DVP flags. + * @param _FLAG_ specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg DVP_CLEAR_FLAG_HERR Hsync error interrupt flag clear + * @arg DVP_CLEAR_FLAG_VERR Vsync error interrupt flag clear + * @arg DVP_CLEAR_FLAG_FO FIFO overflow intterrupt flag clear + * @arg DVP_CLEAR_FLAG_FE FIFO empty interrupt flag clear + * @arg DVP_CLEAR_FLAG_LE Line end interrupt flag clear + * @arg DVP_CLEAR_FLAG_LS Line start interrupt flag clear + * @arg DVP_CLEAR_FLAG_FME Frame end interrupt flag clear + * @arg DVP_CLEAR_FLAG_FMS Frame start interrupt flag clear + * @retval None. + */ +#define __DVP_ClrFlag(_FLAG_) (CLEAR_BIT(DVP->INTSTS, _FLAG_)) + +/** + * @brief Enable DVP interrupts. + * @param _INT_ specifies the interrupt to be enable. + * This parameter can be any combination of the following values: + * @arg DVP_INTEN_HERR Hsync error interrupt enable + * @arg DVP_INTEN_VERR Vsync error interrupt enable + * @arg DVP_INTEN_FO FIFO overflow intterrupt enable + * @arg DVP_INTEN_FE FIFO empty interrupt enable + * @arg DVP_INTEN_LE Line end interrupt enable + * @arg DVP_INTEN_LS Line start interrupt enable + * @arg DVP_INTEN_FME Frame end interrupt enable + * @arg DVP_INTEN_FMS Frame start interrupt enable + * @retval None. + */ +#define __DVP_EnableInt(_INT_) (SET_BIT(DVP->INTEN, _INT_)) + +/** + * @brief Disable DVP interrupts. + * @param _INT_ specifies the interrupt to be disable. + * This parameter can be any combination of the following values: + * @arg DVP_INTEN_HERR Hsync error interrupt disable + * @arg DVP_INTEN_VERR Vsync error interrupt disable + * @arg DVP_INTEN_FO FIFO overflow intterrupt disable + * @arg DVP_INTEN_FE FIFO empty interrupt disable + * @arg DVP_INTEN_LE Line end interrupt disable + * @arg DVP_INTEN_LS Line start interrupt disable + * @arg DVP_INTEN_FME Frame end interrupt disable + * @arg DVP_INTEN_FMS Frame start interrupt disable + * @retval None. + */ +#define __DVP_DisableInt(_INT_) (CLEAR_BIT(DVP->INTEN, _INT_)) + +/** + * @brief Enable DVP DMA. + * @param None. + * @retval None. + */ +#define __DVP_EnableDMA() (SET_BIT(DVP->INTEN, DVP_INTEN_DMAEN)) + +/** + * @brief Enable DVP DMA. + * @param None. + * @retval None. + */ +#define __DVP_DisableDMA() (CLEAR_BIT(DVP->INTEN, DVP_INTEN_DMAEN)) + +/** + * @brief Checks whether the specified DVP interrupt has occurred or not. + * @param _INT_ specifies the DVP interrupt source to check. + * This parameter can be one of the following values: + * @arg DVP_MINT_HERR Hsync error interrupt + * @arg DVP_MINT_VERR Vsync error interrupt + * @arg DVP_MINT_FO FIFO overflow intterrupt + * @arg DVP_MINT_FW FIFO watermark interrupt + * @arg DVP_MINT_FF FIFO full interrupt + * @arg DVP_MINT_FE FIFO empty interrupt + * @arg DVP_MINT_LE Line end interrupt + * @arg DVP_MINT_LS Line start interrupt + * @arg DVP_MINT_FME Frame end interrupt + * @arg DVP_MINT_FMS Frame start interrupt + * @retval The state of _INT_ (SET or RESET). + */ +#define __DVP_GetIntMark(_INT_) (((DVP->MINTSTS) & (_INT_))==(_INT_)) + +/** + * @brief Config the positon of first capture pixel . + * @param _VST_ specifies the line positon. + * This parameter must be less than 2048. + * @param _HST_ specifies the pixel positon. + * This parameter must be less than 2048. + * @retval None. + */ +#define __DVP_SetStartSHIFT(_VST_,_HST_) (DVP->WST=((_VST_)<WSIZE=((_VLINE_)<FIFO)) + + +/** + * @} + */ + +/** @addtogroup DVP_Exported_Functions + * @{ + */ +void DVP_ResetReg(void); +void DVP_Init(DVP_InitType* DVP_InitStruct); +void DVP_DafaultInitParam(DVP_InitType* DVP_InitStruct); +uint32_t DVP_GetFifoCount(void); +void DVP_ResetFifo(void); +void DVP_ConfigDma( FunctionalState Cmd); + +/** + * @} + */ +/** + * @} + */ +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/inc/n32g45x_eth.h b/inc/n32g45x_eth.h new file mode 100644 index 0000000..4ff243d --- /dev/null +++ b/inc/n32g45x_eth.h @@ -0,0 +1,1608 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @brief Ethernet functions. + * @file n32g45x_eth.h + * @author Nations + * @version v1.0.0 + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __N32G45X_ETH_H__ +#define __N32G45X_ETH_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup ETH + * @{ + */ + +/** @addtogroup ETH_Exported_Types + * @{ + */ + +/** + * @brief ETH MAC Init structure definition + * @note The user should not configure all the ETH_InitType structure's fields. + * By calling the ETH_InitStruct function the structures fields are set to their default values. + * Only the parameters that will be set to a non-default value should be configured. + */ +typedef struct +{ + uint32_t AutoNegotiation; /*!< Selects or not the AutoNegotiation mode for the external PHY + The AutoNegotiation allows an automatic setting of the Speed (10/100Mbps) + and the mode (half/full-duplex). + This parameter can be a value of @ref AutoNegotiation */ + + uint32_t Watchdog; /*!< Selects or not the Watchdog timer + When enabled, the MAC allows no more then 2048 bytes to be received. + When disabled, the MAC can receive up to 16384 bytes. + This parameter can be a value of @ref ETH_watchdog */ + + uint32_t Jabber; /*!< Selects or not Jabber timer + When enabled, the MAC allows no more then 2048 bytes to be sent. + When disabled, the MAC can send up to 16384 bytes. + This parameter can be a value of @ref Jabber */ + + uint32_t InterFrameGap; /*!< Selects the minimum IFG between frames during transmission + This parameter can be a value of @ref ETH_Inter_Frame_Gap */ + + uint32_t CarrierSense; /*!< Selects or not the Carrier Sense + This parameter can be a value of @ref ETH_Carrier_Sense */ + + uint32_t SpeedMode; /*!< Sets the Ethernet speed: 10/100 Mbps + This parameter can be a value of @ref SpeedMode */ + + uint32_t RxOwn; /*!< Selects or not the ReceiveOwn + ReceiveOwn allows the reception of frames when the TX_EN signal is asserted + in Half-Duplex mode + This parameter can be a value of @ref ETH_Receive_Own */ + + uint32_t LoopbackMode; /*!< Selects or not the internal MAC MII Loopback mode + This parameter can be a value of @ref ETH_Loop_Back_Mode */ + + uint32_t DuplexMode; /*!< Selects the MAC duplex mode: Half-Duplex or Full-Duplex mode + This parameter can be a value of @ref ETH_Duplex_Mode */ + + uint32_t ChecksumOffload; /*!< Selects or not the IPv4 checksum checking for received frame payloads' TCP/UDP/ICMP + headers. This parameter can be a value of @ref ETH_Checksum_Offload */ + + uint32_t RetryTransmission; /*!< Selects or not the MAC attempt retries transmission, based on the settings of BL, + when a colision occurs (Half-Duplex mode) + This parameter can be a value of @ref ETH_Retry_Transmission */ + + uint32_t AutomaticPadCRCStrip; /*!< Selects or not the Automatic MAC Pad/CRC Stripping + This parameter can be a value of @ref ETH_Automatic_Pad_CRC_Strip */ + + uint32_t BackoffLimit; /*!< Selects the BackOff limit value + This parameter can be a value of @ref ETH_Back_Off_Limit + This parameer only valid in ETH_DUPLEX_MODE_HALF mode*/ + + uint32_t DeferralCheck; /*!< Selects or not the deferral check function (Half-Duplex mode) + This parameter can be a value of @ref ETH_Deferral_Check */ + + uint32_t RxAll; /*!< Selects or not all frames reception by the MAC (No fitering) + This parameter can be a value of @ref ETH_Receive_All */ + + uint32_t SrcAddrFilter; /*!< Selects the Source Address Filter mode + This parameter can be a value of @ref ETH_Source_Addr_Filter */ + + uint32_t PassCtrlFrames; /*!< Sets the forwarding mode of the control frames (including unicast and multicast Pause + frames) This parameter can be a value of @ref ETH_Pass_Control_Frames */ + + uint32_t BroadcastFramesReception; /*!< Selects or not the reception of Broadcast Frames + This parameter can be a value of @ref ETH_Broadcast_Frames_Reception */ + + uint32_t DestAddrFilter; /*!< Sets the destination filter mode for both unicast and multicast frames + This parameter can be a value of @ref ETH_Destination_Addr_Filter */ + + uint32_t PromiscuousMode; /*!< Selects or not the Promiscuous Mode + This parameter can be a value of @ref ETH_Promiscuous_Mode */ + + uint32_t MulticastFramesFilter; /*!< Selects the Multicast Frames filter mode: + None/HashTableFilter/PerfectFilter/PerfectHashTableFilter + This parameter can be a value of @ref ETH_Multicast_Frames_Filter */ + + uint32_t UnicastFramesFilter; /*!< Selects the Unicast Frames filter mode: + HashTableFilter/PerfectFilter/PerfectHashTableFilter + This parameter can be a value of @ref ETH_Unicast_Frames_Filter */ + + uint32_t HashTableHigh; /*!< This field holds the higher 32 bits of Hash table. */ + + uint32_t HashTableLow; /*!< This field holds the lower 32 bits of Hash table. */ + + uint32_t PauseTime; /*!< This field holds the value to be used in the Pause Time field in the + transmit control frame */ + + uint32_t ZeroQuantaPause; /*!< Selects or not the automatic generation of Zero-Quanta Pause Control frames + This parameter can be a value of @ref ETH_Zero_Quanta_Pause */ + + uint32_t PauseLowThreshold; /*!< This field configures the threshold of the Pause to be checked for + automatic retransmission of Pause Frame + This parameter can be a value of @ref ETH_Pause_Low_Threshold */ + + uint32_t UnicastPauseFrameDetect; /*!< Selects or not the MAC detection of the Pause frames (with MAC Address0 + unicast address and unique multicast address) + This parameter can be a value of @ref ETH_Unicast_Pause_Frame_Detect */ + + uint32_t RxFlowCtrl; /*!< Enables or disables the MAC to decode the received Pause frame and + disable its transmitter for a specified time (Pause Time) + This parameter can be a value of @ref ETH_Receive_Flow_Control */ + + uint32_t TxFlowCtrl; /*!< Enables or disables the MAC to transmit Pause frames (Full-Duplex mode) + or the MAC back-pressure operation (Half-Duplex mode) + This parameter can be a value of @ref ETH_Transmit_Flow_Control */ + + uint32_t VLANTagComparison; /*!< Selects the 12-bit VLAN identifier or the complete 16-bit VLAN tag for + comparison and filtering + This parameter can be a value of @ref ETH_VLAN_Tag_Comparison */ + + uint32_t VLANTagIdentifier; /*!< Holds the VLAN tag identifier for receive frames */ + + uint32_t DropTCPIPChecksumErrorFrame; /*!< Selects or not the Dropping of TCP/IP Checksum Error Frames + This parameter can be a value of @ref + ETH_Drop_TCP_IP_Checksum_Error_Frame */ + + uint32_t RxStoreForward; /*!< Enables or disables the Receive store and forward mode + This parameter can be a value of @ref ETH_Receive_Store_Forward */ + + uint32_t FlushRxFrame; /*!< Enables or disables the flushing of received frames + This parameter can be a value of @ref ETH_Flush_Received_Frame */ + + uint32_t TxStoreForward; /*!< Enables or disables Transmit store and forward mode + This parameter can be a value of @ref ETH_Transmit_Store_Forward */ + + uint32_t TxThresholdCtrl; /*!< Selects or not the Transmit Threshold Control + This parameter can be a value of @ref ETH_Transmit_Threshold_Control */ + + uint32_t ForwardErrorFrames; /*!< Selects or not the forward to the DMA of erroneous frames + This parameter can be a value of @ref ETH_Forward_Error_Frames */ + + uint32_t ForwardUndersizedGoodFrames; /*!< Enables or disables the Rx DATFIFO to forward Undersized frames (frames + with no Error and length less than 64 bytes) including pad-bytes and CRC) + This parameter can be a value of @ref + ETH_Forward_Undersized_Good_Frames */ + + uint32_t RxThresholdCtrl; /*!< Selects the threshold level of the Receive DATFIFO + This parameter can be a value of @ref ETH_Receive_Threshold_Control */ + + uint32_t SecondFrameOperate; /*!< Selects or not the Operate on second frame mode, which allows the DMA to process a + second frame of Transmit data even before obtaining the status for the first frame. + This parameter can be a value of @ref ETH_Second_Frame_Operate */ + + uint32_t AddrAlignedBeats; /*!< Enables or disables the Address Aligned Beats + This parameter can be a value of @ref ETH_Address_Aligned_Beats */ + + uint32_t FixedBurst; /*!< Enables or disables the AHB Master interface fixed burst transfers + This parameter can be a value of @ref ETH_Fixed_Burst */ + + uint32_t RxDMABurstLen; /*!< Indicates the maximum number of beats to be transferred in one Rx DMA transaction + This parameter can be a value of @ref ETH_Rx_DMA_Burst_Length */ + + uint32_t TxDMABurstLen; /*!< Indicates sthe maximum number of beats to be transferred in one Tx DMA transaction + This parameter can be a value of @ref ETH_Tx_DMA_Burst_Length */ + + uint32_t DescSkipLen; /*!< Specifies the number of word to skip between two unchained descriptors (Ring mode) */ + + uint32_t DMAArbitration; /*!< Selects the DMA Tx/Rx arbitration + This parameter can be a value of @ref ETH_DMA_Arbitration */ +} ETH_InitType; + +/** + * @brief ETH DMA Desciptors data structure definition + */ +typedef struct +{ + uint32_t Status; /*!< Status */ + uint32_t CtrlOrBufSize; /*!< Control and Buffer1, Buffer2 lengths */ + uint32_t Buf1Addr; /*!< Buffer1 address pointer */ + uint32_t Buf2OrNextDescAddr; /*!< Buffer2 or next descriptor address pointer */ +} ETH_DMADescType; + +/** + * @} + */ + +/** @addtogroup ETH_Exported_Constants + * @{ + */ + +/** + * @addtogroup ETH_PHY_Registers + * @{ + */ +#define PHY_BCR 0 /*!< Tranceiver Basic Control Register */ +#define PHY_BSR 1 /*!< Tranceiver Basic Status Register */ + +#define PHY_RESET ((u16)0x8000) /*!< PHY Reset */ +#define PHY_LOOPBACK ((u16)0x4000) /*!< Select loop-back mode */ +#define PHY_FULLDUPLEX_100M ((u16)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ +#define PHY_HALFDUPLEX_100M ((u16)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ +#define PHY_FULLDUPLEX_10M ((u16)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ +#define PHY_HALFDUPLEX_10M ((u16)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ +#define PHY_AUTONEGO ((u16)0x1000) /*!< Enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGO ((u16)0x0200) /*!< Restart auto-negotiation function */ +#define PHY_POWERDOWN ((u16)0x0800) /*!< Select the power down mode */ +#define PHY_ISOLATE ((u16)0x0400) /*!< Isolate PHY from MII */ + +#define PHY_AUTONEGO_COMPLETE ((u16)0x0020) /*!< Auto-Negotioation process completed */ +#define PHY_LINKED_STATUS ((u16)0x0004) /*!< Valid link established */ +#define PHY_JABBER_DETECTION ((u16)0x0002) /*!< Jabber condition detected */ + +#define PHY_READ_TO ((uint32_t)0x0004FFFF) +#define PHY_WRITE_TO ((uint32_t)0x0004FFFF) + +#define IS_ETH_PHY_ADDRESS(ADDRESS) ((ADDRESS) < 0x20) +#define IS_ETH_PHY_REG(REG) ((REG) < 0x20) +/** + * @} + */ + +/** @addtogroup ENET_Buffers_setting + * @{ + */ +#define ETH_MAX_PACKET_SIZE 1520 /*!< ETH_HEADER + ETH_EXTRA + ETH_MAX_PAYLOAD + ETH_CRC */ +#define ETH_HEADER 14 /*!< 6 byte Dest addr, 6 byte Src addr, 2 byte length/type */ +#define ETH_CRC 4 /*!< Ethernet CRC */ +#define ETH_EXTRA 2 /*!< Extra bytes in some cases */ +#define ETH_VLAN_TAG 4 /*!< optional 802.1q VLAN Tag */ +#define ETH_MIN_PAYLOAD 46 /*!< Minimum Ethernet payload size */ +#define ETH_MAX_PAYLOAD 1500 /*!< Maximum Ethernet payload size */ +#define ETH_JUMBO_FRAME_PAYLOAD 9000 /*!< Jumbo frame payload size */ + +/* + DMA Tx Desciptor + ----------------------------------------------------------------------------------------------- + TDES0 | OWN(31) | Reserved[30:18] | Status[17:0] | + ----------------------------------------------------------------------------------------------- + TDES1 | Ctrl[31:22] | Buffer2 ByteCount[21:11] | Buffer1 ByteCount[10:0] | + ----------------------------------------------------------------------------------------------- + TDES2 | Buffer1 Address [31:0] | + ----------------------------------------------------------------------------------------------- + TDES3 | Buffer2 Address [31:0] / Next Desciptor Address [31:0] | + ----------------------------------------------------------------------------------------------- +*/ + +/* + * Bit definition of TDES0 register: DMA Tx descriptor status register + */ +#define ETH_DMA_TX_DESC_OWN ((uint32_t)0x80000000) /*!< OWN bit: descriptor is owned by DMA engine */ +#define ETH_DMA_TX_DESC_TTSS ((uint32_t)0x00020000) /*!< Tx Time Stamp Status */ +#define ETH_DMA_TX_DESC_IHE ((uint32_t)0x00010000) /*!< IP Header Error */ +#define ETH_DMA_TX_DESC_ES \ + ((uint32_t)0x00008000) /*!< Error summary: OR of the following bits: UE || ED || EC || LCO || NC || LCA || FF || \ + JT */ +#define ETH_DMA_TX_DESC_JT ((uint32_t)0x00004000) /*!< Jabber Timeout */ +#define ETH_DMA_TX_DESC_FF ((uint32_t)0x00002000) /*!< Frame Flushed: DMA/MTL flushed the frame due to SW flush */ +#define ETH_DMA_TX_DESC_PCE ((uint32_t)0x00001000) /*!< Payload Checksum Error */ +#define ETH_DMA_TX_DESC_LOC ((uint32_t)0x00000800) /*!< Loss of Carrier: carrier lost during tramsmission */ +#define ETH_DMA_TX_DESC_NC ((uint32_t)0x00000400) /*!< No Carrier: no carrier signal from the tranceiver */ +#define ETH_DMA_TX_DESC_LC ((uint32_t)0x00000200) /*!< Late Collision: transmission aborted due to collision */ +#define ETH_DMA_TX_DESC_EC ((uint32_t)0x00000100) /*!< Excessive Collision: transmission aborted after 16 collisions \ + */ +#define ETH_DMA_TX_DESC_VF ((uint32_t)0x00000080) /*!< VLAN Frame */ +#define ETH_DMA_TX_DESC_CC ((uint32_t)0x00000078) /*!< Collision Count */ +#define ETH_DMA_TX_DESC_ED ((uint32_t)0x00000004) /*!< Excessive Deferral */ +#define ETH_DMA_TX_DESC_UF ((uint32_t)0x00000002) /*!< Underflow Error: late data arrival from the memory */ +#define ETH_DMA_TX_DESC_DB ((uint32_t)0x00000001) /*!< Deferred Bit */ + +/* + * Bit definition of TDES1 register + */ +#define ETH_DMA_TX_DESC_IC ((uint32_t)0x80000000) /*!< Interrupt on Completion */ +#define ETH_DMA_TX_DESC_LS ((uint32_t)0x40000000) /*!< Last Segment */ +#define ETH_DMA_TX_DESC_FS ((uint32_t)0x20000000) /*!< First Segment */ + +#define ETH_DMA_TX_DESC_CIC ((uint32_t)0x18000000) /*!< Checksum Insertion Control: 4 cases */ +#define ETH_DMA_TX_DESC_CIC_BYPASS ((uint32_t)0x00000000) /*!< Do Nothing: Checksum Engine is bypassed */ +#define ETH_DMA_TX_DESC_CIC_IPV4_HEADER ((uint32_t)0x08000000) /*!< IPV4 header Checksum Insertion */ +#define ETH_DMA_TX_DESC_CIC_TCPUDPICMP_SEGMENT \ + ((uint32_t)0x10000000) /*!< TCP/UDP/ICMP Checksum Insertion calculated over segment only */ +#define ETH_DMA_TX_DESC_CIC_TCPUDPICMP_FULL \ + ((uint32_t)0x18000000) /*!< TCP/UDP/ICMP Checksum Insertion fully calculated */ + +#define ETH_DMA_TX_DESC_DC ((uint32_t)0x04000000) /*!< Disable CRC */ +#define ETH_DMA_TX_DESC_TER ((uint32_t)0x02000000) /*!< Transmit End of Ring */ +#define ETH_DMA_TX_DESC_TCH ((uint32_t)0x01000000) /*!< Second Address Chained */ +#define ETH_DMA_TX_DESC_DP ((uint32_t)0x00800000) /*!< Disable Padding */ +#define ETH_DMA_TX_DESC_TTSE ((uint32_t)0x00400000) /*!< Transmit Time Stamp Enable */ +#define ETH_DMA_TX_DESC_TBS2 ((uint32_t)0x003FF800) /*!< Transmit Buffer2 Size */ +#define ETH_DMA_TX_DESC_TBS1 ((uint32_t)0x000007FF) /*!< Transmit Buffer1 Size */ + +/* + * Bit definition of TDES2 register + */ +#define ETH_DMA_TX_DESC_B1ADDR ((uint32_t)0xFFFFFFFF) /*!< Buffer1 Address Pointer */ + +/* + * Bit definition of TDES3 register + */ +#define ETH_DMA_TX_DESC_B2ADDR ((uint32_t)0xFFFFFFFF) /*!< Buffer2 Address Pointer */ + +/** + * @} + */ + +/** @addtogroup DMA_Rx_descriptor + * @{ + */ + +/* + DMA Rx Desciptor + -------------------------------------------------------------------------------------------------------------------- + RDES0 | OWN(31) | Status [30:0] | + --------------------------------------------------------------------------------------------------------------------- + RDES1 | CTRL(31) | Reserved[30:26] | CTRL[25:24] | Reserved[23:22] | Buffer2 ByteCnt[21:11] | Buffer1 ByteCnt[10:0] | + --------------------------------------------------------------------------------------------------------------------- + RDES2 | Buffer1 Address [31:0] | + --------------------------------------------------------------------------------------------------------------------- + RDES3 | Buffer2 Address [31:0] / Next Desciptor Address [31:0] | + --------------------------------------------------------------------------------------------------------------------- +*/ + +/* + * Bit definition of RDES0 register: DMA Rx descriptor status register + */ +#define ETH_DMA_RX_DESC_OWN ((uint32_t)0x80000000) /*!< OWN bit: descriptor is owned by DMA engine */ +#define ETH_DMA_RX_DESC_AFM ((uint32_t)0x40000000) /*!< DA Filter Fail for the rx frame */ +#define ETH_DMA_RX_DESC_FL ((uint32_t)0x3FFF0000) /*!< Receive descriptor frame length */ +#define ETH_DMA_RX_DESC_ES \ + ((uint32_t)0x00008000) /*!< Error summary: OR of the following bits: DE || OE || IPC || LC || RWT || RE || CE */ +#define ETH_DMA_RX_DESC_DE ((uint32_t)0x00004000) /*!< Desciptor error: no more descriptors for receive frame */ +#define ETH_DMA_RX_DESC_SAF ((uint32_t)0x00002000) /*!< SA Filter Fail for the received frame */ +#define ETH_DMA_RX_DESC_LE ((uint32_t)0x00001000) /*!< Frame size not matching with length field */ +#define ETH_DMA_RX_DESC_OE ((uint32_t)0x00000800) /*!< Overflow Error: Frame was damaged due to buffer overflow */ +#define ETH_DMA_RX_DESC_VLAN ((uint32_t)0x00000400) /*!< VLAN Tag: received frame is a VLAN frame */ +#define ETH_DMA_RX_DESC_FS ((uint32_t)0x00000200) /*!< First descriptor of the frame */ +#define ETH_DMA_RX_DESC_LS ((uint32_t)0x00000100) /*!< Last descriptor of the frame */ +#define ETH_DMA_RX_DESC_IPV4HCE ((uint32_t)0x00000080) /*!< IPC Checksum Error: Rx Ipv4 header checksum error */ +#define ETH_DMA_RX_DESC_LC ((uint32_t)0x00000040) /*!< Late collision occurred during reception */ +#define ETH_DMA_RX_DESC_FT ((uint32_t)0x00000020) /*!< Frame type - Ethernet, otherwise 802.3 */ +#define ETH_DMA_RX_DESC_RWT \ + ((uint32_t)0x00000010) /*!< Receive Watchdog Timeout: watchdog timer expired during reception */ +#define ETH_DMA_RX_DESC_RE ((uint32_t)0x00000008) /*!< Receive error: error reported by MII interface */ +#define ETH_DMA_RX_DESC_DBE ((uint32_t)0x00000004) /*!< Dribble bit error: frame contains non int multiple of 8 bits \ + */ +#define ETH_DMA_RX_DESC_CE ((uint32_t)0x00000002) /*!< CRC error */ +#define ETH_DMA_RX_DESC_RMAPCE \ + ((uint32_t)0x00000001) /*!< Rx MAC Address/Payload Checksum Error: Rx MAC address matched/ Rx Payload Checksum \ + Error */ + +/* + * Bit definition of RDES1 register + */ +#define ETH_DMA_RX_DESC_DIC ((uint32_t)0x80000000) /*!< Disable Interrupt on Completion */ +#define ETH_DMA_RX_DESC_RBS2 ((uint32_t)0x003FF800) /*!< Receive Buffer2 Size */ +#define ETH_DMA_RX_DESC_RER ((uint32_t)0x02000000) /*!< Receive End of Ring */ +#define ETH_DMA_RX_DESC_RCH ((uint32_t)0x01000000) /*!< Second Address Chained */ +#define ETH_DMA_RX_DESC_RBS1 ((uint32_t)0x000007FF) /*!< Receive Buffer1 Size */ + +/* + * Bit definition of RDES2 register + */ +#define ETH_DMA_RX_DESC_B1ADDR ((uint32_t)0xFFFFFFFF) /*!< Buffer1 Address Pointer */ + +/* + * Bit definition of RDES3 register + */ +#define ETH_DMA_RX_DESC_B2ADDR ((uint32_t)0xFFFFFFFF) /*!< Buffer2 Address Pointer */ + +/** + * @} + */ + +/** @addtogroup AutoNegotiation + * @{ + */ +#define ETH_AUTONEG_ENABLE ((uint32_t)0x00000001) +#define ETH_AUTONEG_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_AUTONEG(CMDCTRL) (((CMDCTRL) == ETH_AUTONEG_ENABLE) || ((CMDCTRL) == ETH_AUTONEG_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_watchdog + * @{ + */ +#define ETH_WATCHDOG_ENABLE ((uint32_t)0x00000000) +#define ETH_WATCHDOG_DISABLE ((uint32_t)0x00800000) +#define IS_ETH_WATCHDOG(CMDCTRL) (((CMDCTRL) == ETH_WATCHDOG_ENABLE) || ((CMDCTRL) == ETH_WATCHDOG_DISABLE)) + +/** + * @} + */ + +/** @addtogroup Jabber + * @{ + */ +#define ETH_JABBER_ENABLE ((uint32_t)0x00000000) +#define ETH_JABBER_DISABLE ((uint32_t)0x00400000) +#define IS_ETH_JABBER(CMDCTRL) (((CMDCTRL) == ETH_JABBER_ENABLE) || ((CMDCTRL) == ETH_JABBER_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Inter_Frame_Gap + * @{ + */ +#define ETH_INTER_FRAME_GAP_96BIT ((uint32_t)0x00000000) /*!< minimum IFG between frames during transmission is 96Bit \ + */ +#define ETH_INTER_FRAME_GAP_88BIT ((uint32_t)0x00020000) /*!< minimum IFG between frames during transmission is 88Bit \ + */ +#define ETH_INTER_FRAME_GAP_80BIT ((uint32_t)0x00040000) /*!< minimum IFG between frames during transmission is 80Bit \ + */ +#define ETH_INTER_FRAME_GAP_72BIT ((uint32_t)0x00060000) /*!< minimum IFG between frames during transmission is 72Bit \ + */ +#define ETH_INTER_FRAME_GAP_64BIT ((uint32_t)0x00080000) /*!< minimum IFG between frames during transmission is 64Bit \ + */ +#define ETH_INTER_FRAME_GAP_56BIT ((uint32_t)0x000A0000) /*!< minimum IFG between frames during transmission is 56Bit \ + */ +#define ETH_INTER_FRAME_GAP_48BIT ((uint32_t)0x000C0000) /*!< minimum IFG between frames during transmission is 48Bit \ + */ +#define ETH_INTER_FRAME_GAP_40BIT ((uint32_t)0x000E0000) /*!< minimum IFG between frames during transmission is 40Bit \ + */ +#define IS_ETH_INTER_FRAME_GAP(GAP) \ + (((GAP) == ETH_INTER_FRAME_GAP_96BIT) || ((GAP) == ETH_INTER_FRAME_GAP_88BIT) \ + || ((GAP) == ETH_INTER_FRAME_GAP_80BIT) || ((GAP) == ETH_INTER_FRAME_GAP_72BIT) \ + || ((GAP) == ETH_INTER_FRAME_GAP_64BIT) || ((GAP) == ETH_INTER_FRAME_GAP_56BIT) \ + || ((GAP) == ETH_INTER_FRAME_GAP_48BIT) || ((GAP) == ETH_INTER_FRAME_GAP_40BIT)) + +/** + * @} + */ + +/** @addtogroup ETH_Carrier_Sense + * @{ + */ +#define ETH_CARRIER_SENSE_ENABLE ((uint32_t)0x00000000) +#define ETH_CARRIER_SENSE_DISABLE ((uint32_t)0x00010000) +#define IS_ETH_CARRIER_SENSE(CMDCTRL) \ + (((CMDCTRL) == ETH_CARRIER_SENSE_ENABLE) || ((CMDCTRL) == ETH_CARRIER_SENSE_DISABLE)) + +/** + * @} + */ + +/** @addtogroup SpeedMode + * @{ + */ +#define ETH_SPEED_MODE_10M ((uint32_t)0x00000000) +#define ETH_SPEED_MODE_100M ((uint32_t)0x00004000) +#define IS_ETH_SPEED_MODE(SPEED) (((SPEED) == ETH_SPEED_MODE_10M) || ((SPEED) == ETH_SPEED_MODE_100M)) + +/** + * @} + */ + +/** @addtogroup ETH_Receive_Own + * @{ + */ +#define ETH_RX_OWN_ENABLE ((uint32_t)0x00000000) +#define ETH_RX_OWN_DISABLE ((uint32_t)0x00002000) +#define IS_ETH_RX_OWN(CMDCTRL) (((CMDCTRL) == ETH_RX_OWN_ENABLE) || ((CMDCTRL) == ETH_RX_OWN_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Loop_Back_Mode + * @{ + */ +#define ETH_LOOPBACK_MODE_ENABLE ((uint32_t)0x00001000) +#define ETH_LOOPBACK_MODE_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_LOOPBACK_MODE(CMDCTRL) \ + (((CMDCTRL) == ETH_LOOPBACK_MODE_ENABLE) || ((CMDCTRL) == ETH_LOOPBACK_MODE_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Duplex_Mode + * @{ + */ +#define ETH_DUPLEX_MODE_FULL ((uint32_t)0x00000800) +#define ETH_DUPLEX_MODE_HALF ((uint32_t)0x00000000) +#define IS_ETH_DUPLEX_MODE(MODE) (((MODE) == ETH_DUPLEX_MODE_FULL) || ((MODE) == ETH_DUPLEX_MODE_HALF)) + +/** + * @} + */ + +/** @addtogroup ETH_Checksum_Offload + * @{ + */ +#define ETH_CHECKSUM_OFFLOAD_ENABLE ((uint32_t)0x00000400) +#define ETH_CHECKSUM_OFFLOAD_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_CHECKSUM_OFFLOAD(CMDCTRL) \ + (((CMDCTRL) == ETH_CHECKSUM_OFFLOAD_ENABLE) || ((CMDCTRL) == ETH_CHECKSUM_OFFLOAD_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Retry_Transmission + * @{ + */ +#define ETH_RETRY_TRANSMISSION_ENABLE ((uint32_t)0x00000000) +#define ETH_RETRY_TRANSMISSION_DISABLE ((uint32_t)0x00000200) +#define IS_ETH_RETRY_TRANSMISSION(CMDCTRL) \ + (((CMDCTRL) == ETH_RETRY_TRANSMISSION_ENABLE) || ((CMDCTRL) == ETH_RETRY_TRANSMISSION_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Automatic_Pad_CRC_Strip + * @{ + */ +#define ETH_AUTO_PAD_CRC_STRIP_ENABLE ((uint32_t)0x00000080) +#define ETH_AUTO_PAD_CRC_STRIP_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_AUTO_PAD_CRC_STRIP(CMDCTRL) \ + (((CMDCTRL) == ETH_AUTO_PAD_CRC_STRIP_ENABLE) || ((CMDCTRL) == ETH_AUTO_PAD_CRC_STRIP_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Back_Off_Limit + * @{ + */ +#define ETH_BACKOFF_LIMIT_10 ((uint32_t)0x00000000) +#define ETH_BACKOFF_LIMIT_8 ((uint32_t)0x00000020) +#define ETH_BACKOFF_LIMIT_4 ((uint32_t)0x00000040) +#define ETH_BACKOFF_LIMIT_1 ((uint32_t)0x00000060) +#define IS_ETH_BACKOFF_LIMIT(LIMIT) \ + (((LIMIT) == ETH_BACKOFF_LIMIT_10) || ((LIMIT) == ETH_BACKOFF_LIMIT_8) || ((LIMIT) == ETH_BACKOFF_LIMIT_4) \ + || ((LIMIT) == ETH_BACKOFF_LIMIT_1)) + +/** + * @} + */ + +/** @addtogroup ETH_Deferral_Check + * @{ + */ +#define ETH_DEFERRAL_CHECK_ENABLE ((uint32_t)0x00000010) +#define ETH_DEFERRAL_CHECK_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_DEFERRAL_CHECK(CMDCTRL) \ + (((CMDCTRL) == ETH_DEFERRAL_CHECK_ENABLE) || ((CMDCTRL) == ETH_DEFERRAL_CHECK_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Receive_All + * @{ + */ +#define ETH_RX_ALL_ENABLE ((uint32_t)0x80000000) +#define ETH_RX_ALL_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_RX_ALL(CMDCTRL) (((CMDCTRL) == ETH_RX_ALL_ENABLE) || ((CMDCTRL) == ETH_RX_ALL_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Source_Addr_Filter + * @{ + */ +#define ETH_SRC_ADDR_FILTER_NORMAL_ENABLE ((uint32_t)0x00000200) +#define ETH_SRC_ADDR_FILTER_INVERSE_ENABLE ((uint32_t)0x00000300) +#define ETH_SRC_ADDR_FILTER_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_SRC_ADDR_FILTER(CMDCTRL) \ + (((CMDCTRL) == ETH_SRC_ADDR_FILTER_NORMAL_ENABLE) || ((CMDCTRL) == ETH_SRC_ADDR_FILTER_INVERSE_ENABLE) \ + || ((CMDCTRL) == ETH_SRC_ADDR_FILTER_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Pass_Control_Frames + * @{ + */ +#define ETH_PASS_CTRL_FRAMES_BLOCK_ALL \ + ((uint32_t)0x00000040) /*!< MAC filters all control frames from reaching the application */ +#define ETH_PASS_CTRL_FRAMES_FORWARD_ALL \ + ((uint32_t)0x00000080) /*!< MAC forwards all control frames to application even if they fail the Address Filter */ +#define ETH_PASS_CTRL_FRAMES_FORWARD_PASSED_ADDR_FILTER \ + ((uint32_t)0x000000C0) /*!< MAC forwards control frames that pass the Address Filter. */ +#define IS_ETH_PASS_CTRL_FRAMES(PASS) \ + (((PASS) == ETH_PASS_CTRL_FRAMES_BLOCK_ALL) || ((PASS) == ETH_PASS_CTRL_FRAMES_FORWARD_ALL) \ + || ((PASS) == ETH_PASS_CTRL_FRAMES_FORWARD_PASSED_ADDR_FILTER)) + +/** + * @} + */ + +/** @addtogroup ETH_Broadcast_Frames_Reception + * @{ + */ +#define ETH_BROADCAST_FRAMES_RECEPTION_ENABLE ((uint32_t)0x00000000) +#define ETH_BROADCAST_FRAMES_RECEPTION_DISABLE ((uint32_t)0x00000020) +#define IS_ETH_BROADCAST_FRAMES_RECEPTION(CMDCTRL) \ + (((CMDCTRL) == ETH_BROADCAST_FRAMES_RECEPTION_ENABLE) || ((CMDCTRL) == ETH_BROADCAST_FRAMES_RECEPTION_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Destination_Addr_Filter + * @{ + */ +#define ETH_DEST_ADDR_FILTER_NORMAL ((uint32_t)0x00000000) +#define ETH_DEST_ADDR_FILTER_INVERSE ((uint32_t)0x00000008) +#define IS_ETH_DEST_ADDR_FILTER(FILTER) \ + (((FILTER) == ETH_DEST_ADDR_FILTER_NORMAL) || ((FILTER) == ETH_DEST_ADDR_FILTER_INVERSE)) + +/** + * @} + */ + +/** @addtogroup ETH_Promiscuous_Mode + * @{ + */ +#define ETH_PROMISCUOUS_MODE_ENABLE ((uint32_t)0x00000001) +#define ETH_PROMISCUOUS_MODE_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_PROMISCUOUS_MODE(CMDCTRL) \ + (((CMDCTRL) == ETH_PROMISCUOUS_MODE_ENABLE) || ((CMDCTRL) == ETH_PROMISCUOUS_MODE_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Multicast_Frames_Filter + * @{ + */ +#define ETH_MULTICAST_FRAMES_FILTER_PERFECT_HASH_TABLE ((uint32_t)0x00000404) +#define ETH_MULTICAST_FRAMES_FILTER_HASH_TABLE ((uint32_t)0x00000004) +#define ETH_MULTICAST_FRAMES_FILTER_PERFECT ((uint32_t)0x00000000) +#define ETH_MULTICAST_FRAMES_FILTER_NONE ((uint32_t)0x00000010) +#define IS_ETH_MULTICAST_FRAMES_FILTER(FILTER) \ + (((FILTER) == ETH_MULTICAST_FRAMES_FILTER_PERFECT_HASH_TABLE) \ + || ((FILTER) == ETH_MULTICAST_FRAMES_FILTER_HASH_TABLE) || ((FILTER) == ETH_MULTICAST_FRAMES_FILTER_PERFECT) \ + || ((FILTER) == ETH_MULTICAST_FRAMES_FILTER_NONE)) + +/** + * @} + */ + +/** @addtogroup ETH_Unicast_Frames_Filter + * @{ + */ +#define ETH_UNICAST_FRAMES_FILTER_PERFECTHASHTABLE ((uint32_t)0x00000402) +#define ETH_UNICAST_FRAMES_FILTER_HASHTABLE ((uint32_t)0x00000002) +#define ETH_UNICAST_FRAMES_FILTER_PERFECT ((uint32_t)0x00000000) +#define IS_ETH_UNICAST_FRAMES_FILTER(FILTER) \ + (((FILTER) == ETH_UNICAST_FRAMES_FILTER_PERFECTHASHTABLE) || ((FILTER) == ETH_UNICAST_FRAMES_FILTER_HASHTABLE) \ + || ((FILTER) == ETH_UNICAST_FRAMES_FILTER_PERFECT)) + +/** + * @} + */ + +/** @addtogroup ETH_Pause_Time + * @{ + */ +#define IS_ETH_PAUSE_TIME(TIME) ((TIME) <= 0xFFFF) + +/** + * @} + */ + +/** @addtogroup ETH_Zero_Quanta_Pause + * @{ + */ +#define ETH_ZERO_QUANTA_PAUSE_ENABLE ((uint32_t)0x00000000) +#define ETH_ZERO_QUANTA_PAUSE_DISABLE ((uint32_t)0x00000080) +#define IS_ETH_ZERO_QUANTA_PAUSE(CMDCTRL) \ + (((CMDCTRL) == ETH_ZERO_QUANTA_PAUSE_ENABLE) || ((CMDCTRL) == ETH_ZERO_QUANTA_PAUSE_DISABLE)) +/** + * @} + */ + +/** @addtogroup ETH_Pause_Low_Threshold + * @{ + */ +#define ETH_PAUSE_LOW_THRESHOLD_MINUS4 ((uint32_t)0x00000000) /*!< Pause time minus 4 slot times */ +#define ETH_PAUSE_LOW_THRESHOLD_MINUS28 ((uint32_t)0x00000010) /*!< Pause time minus 28 slot times */ +#define ETH_PAUSE_LOW_THRESHOLD_MINUS144 ((uint32_t)0x00000020) /*!< Pause time minus 144 slot times */ +#define ETH_PAUSE_LOW_THRESHOLD_MINUS256 ((uint32_t)0x00000030) /*!< Pause time minus 256 slot times */ +#define IS_ETH_PAUSE_LOW_THRESHOLD(THRESHOLD) \ + (((THRESHOLD) == ETH_PAUSE_LOW_THRESHOLD_MINUS4) || ((THRESHOLD) == ETH_PAUSE_LOW_THRESHOLD_MINUS28) \ + || ((THRESHOLD) == ETH_PAUSE_LOW_THRESHOLD_MINUS144) || ((THRESHOLD) == ETH_PAUSE_LOW_THRESHOLD_MINUS256)) + +/** + * @} + */ + +/** @addtogroup ETH_Unicast_Pause_Frame_Detect + * @{ + */ +#define ETH_UNICAST_PAUSE_FRAME_DETECT_ENABLE ((uint32_t)0x00000008) +#define ETH_UNICAST_PAUSE_FRAME_DETECT_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_UNICAST_PAUSE_FRAME_DETECT(CMDCTRL) \ + (((CMDCTRL) == ETH_UNICAST_PAUSE_FRAME_DETECT_ENABLE) || ((CMDCTRL) == ETH_UNICAST_PAUSE_FRAME_DETECT_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Receive_Flow_Control + * @{ + */ +#define ETH_RX_FLOW_CTRL_ENABLE ((uint32_t)0x00000004) +#define ETH_RX_FLOW_CTRL_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_RX_FLOW_CTRL(CMDCTRL) (((CMDCTRL) == ETH_RX_FLOW_CTRL_ENABLE) || ((CMDCTRL) == ETH_RX_FLOW_CTRL_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Transmit_Flow_Control + * @{ + */ +#define ETH_TX_FLOW_CTRL_ENABLE ((uint32_t)0x00000002) +#define ETH_TX_FLOW_CTRL_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_TX_FLOW_CTRL(CMDCTRL) (((CMDCTRL) == ETH_TX_FLOW_CTRL_ENABLE) || ((CMDCTRL) == ETH_TX_FLOW_CTRL_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_VLAN_Tag_Comparison + * @{ + */ +#define ETH_VLAN_TAG_COMPARISON_12BIT ((uint32_t)0x00010000) +#define ETH_VLAN_TAG_COMPARISON_16BIT ((uint32_t)0x00000000) +#define IS_ETH_VLAN_TAG_COMPARISON(COMPARISON) \ + (((COMPARISON) == ETH_VLAN_TAG_COMPARISON_12BIT) || ((COMPARISON) == ETH_VLAN_TAG_COMPARISON_16BIT)) +#define IS_ETH_VLAN_TAG_IDENTIFIER(IDENTIFIER) ((IDENTIFIER) <= 0xFFFF) + +/** + * @} + */ + +/** @addtogroup ETH_MAC_Flags + * @{ + */ +#define ETH_MAC_FLAG_TST ((uint32_t)0x00000200) /*!< Time stamp trigger flag (on MAC) */ +#define ETH_MAC_FLAG_MMCTX ((uint32_t)0x00000040) /*!< MMC transmit flag */ +#define ETH_MAC_FLAG_MMCRX ((uint32_t)0x00000020) /*!< MMC receive flag */ +#define ETH_MAC_FLAG_MMC ((uint32_t)0x00000010) /*!< MMC flag (on MAC) */ +#define ETH_MAC_FLAG_PMT ((uint32_t)0x00000008) /*!< PMT flag (on MAC) */ +#define IS_ETH_MAC_GET_FLAG(FLAG) \ + (((FLAG) == ETH_MAC_FLAG_TST) || ((FLAG) == ETH_MAC_FLAG_MMCTX) || ((FLAG) == ETH_MAC_FLAG_MMCRX) \ + || ((FLAG) == ETH_MAC_FLAG_MMC) || ((FLAG) == ETH_MAC_FLAG_PMT)) +/** + * @} + */ + +/** @addtogroup ETH_MAC_Interrupts + * @{ + */ +#define ETH_MAC_INT_TST ((uint32_t)0x00000200) /*!< Time stamp trigger interrupt (on MAC) */ +#define ETH_MAC_INT_MMCTX ((uint32_t)0x00000040) /*!< MMC transmit interrupt */ +#define ETH_MAC_INT_MMCRX ((uint32_t)0x00000020) /*!< MMC receive interrupt */ +#define ETH_MAC_INT_MMC ((uint32_t)0x00000010) /*!< MMC interrupt (on MAC) */ +#define ETH_MAC_INT_PMT ((uint32_t)0x00000008) /*!< PMT interrupt (on MAC) */ +#define IS_ETH_MAC_INT(IT) ((((IT) & (uint32_t)0xFFFFFDF7) == 0x00) && ((IT) != 0x00)) +#define IS_ETH_MAC_GET_INT(IT) \ + (((IT) == ETH_MAC_INT_TST) || ((IT) == ETH_MAC_INT_MMCTX) || ((IT) == ETH_MAC_INT_MMCRX) \ + || ((IT) == ETH_MAC_INT_MMC) || ((IT) == ETH_MAC_INT_PMT)) +/** + * @} + */ + +/** @addtogroup ETH_MAC_addresses + * @{ + */ +#define ETH_MAC_ADDR0 ((uint32_t)0x00000000) +#define ETH_MAC_ADDR1 ((uint32_t)0x00000008) +#define ETH_MAC_ADDR2 ((uint32_t)0x00000010) +#define ETH_MAC_ADDR3 ((uint32_t)0x00000018) +#define IS_ETH_MAC_ADDR0123(ADDRESS) \ + (((ADDRESS) == ETH_MAC_ADDR0) || ((ADDRESS) == ETH_MAC_ADDR1) || ((ADDRESS) == ETH_MAC_ADDR2) \ + || ((ADDRESS) == ETH_MAC_ADDR3)) +#define IS_ETH_MAC_ADDR123(ADDRESS) \ + (((ADDRESS) == ETH_MAC_ADDR1) || ((ADDRESS) == ETH_MAC_ADDR2) || ((ADDRESS) == ETH_MAC_ADDR3)) +/** + * @} + */ + +/** @addtogroup ETH_MAC_addresses_filter_SA_DA_filed_of_received_frames + * @{ + */ +#define ETH_MAC_ADDR_FILTER_SA ((uint32_t)0x00000000) +#define ETH_MAC_ADDR_FILTER_DA ((uint32_t)0x00000008) +#define IS_ETH_MAC_ADDR_FILTER(FILTER) (((FILTER) == ETH_MAC_ADDR_FILTER_SA) || ((FILTER) == ETH_MAC_ADDR_FILTER_DA)) +/** + * @} + */ + +/** @addtogroup ETH_MAC_addresses_filter_Mask_bytes + * @{ + */ +#define ETH_MAC_ADDR_MASK_BYTE6 ((uint32_t)0x20000000) /*!< Mask MAC Address high reg bits [15:8] */ +#define ETH_MAC_ADDR_MASK_BYTE5 ((uint32_t)0x10000000) /*!< Mask MAC Address high reg bits [7:0] */ +#define ETH_MAC_ADDR_MASK_BYTE4 ((uint32_t)0x08000000) /*!< Mask MAC Address low reg bits [31:24] */ +#define ETH_MAC_ADDR_MASK_BYTE3 ((uint32_t)0x04000000) /*!< Mask MAC Address low reg bits [23:16] */ +#define ETH_MAC_ADDR_MASK_BYTE2 ((uint32_t)0x02000000) /*!< Mask MAC Address low reg bits [15:8] */ +#define ETH_MAC_ADDR_MASK_BYTE1 ((uint32_t)0x01000000) /*!< Mask MAC Address low reg bits [70] */ +#define IS_ETH_MAC_ADDR_MASK(INTEN) \ + (((INTEN) == ETH_MAC_ADDR_MASK_BYTE6) || ((INTEN) == ETH_MAC_ADDR_MASK_BYTE5) \ + || ((INTEN) == ETH_MAC_ADDR_MASK_BYTE4) || ((INTEN) == ETH_MAC_ADDR_MASK_BYTE3) \ + || ((INTEN) == ETH_MAC_ADDR_MASK_BYTE2) || ((INTEN) == ETH_MAC_ADDR_MASK_BYTE1)) + +/** + * @} + */ + +/** @addtogroup ETH_DMA_Tx_descriptor_flags + * @{ + */ +#define IS_ETH_DMATXDESC_GET_FLAG(FLAG) \ + (((FLAG) == ETH_DMA_TX_DESC_OWN) || ((FLAG) == ETH_DMA_TX_DESC_IC) || ((FLAG) == ETH_DMA_TX_DESC_LS) \ + || ((FLAG) == ETH_DMA_TX_DESC_FS) || ((FLAG) == ETH_DMA_TX_DESC_DC) || ((FLAG) == ETH_DMA_TX_DESC_DP) \ + || ((FLAG) == ETH_DMA_TX_DESC_TTSE) || ((FLAG) == ETH_DMA_TX_DESC_TER) || ((FLAG) == ETH_DMA_TX_DESC_TCH) \ + || ((FLAG) == ETH_DMA_TX_DESC_TTSS) || ((FLAG) == ETH_DMA_TX_DESC_IHE) || ((FLAG) == ETH_DMA_TX_DESC_ES) \ + || ((FLAG) == ETH_DMA_TX_DESC_JT) || ((FLAG) == ETH_DMA_TX_DESC_FF) || ((FLAG) == ETH_DMA_TX_DESC_PCE) \ + || ((FLAG) == ETH_DMA_TX_DESC_LOC) || ((FLAG) == ETH_DMA_TX_DESC_NC) || ((FLAG) == ETH_DMA_TX_DESC_LC) \ + || ((FLAG) == ETH_DMA_TX_DESC_EC) || ((FLAG) == ETH_DMA_TX_DESC_VF) || ((FLAG) == ETH_DMA_TX_DESC_CC) \ + || ((FLAG) == ETH_DMA_TX_DESC_ED) || ((FLAG) == ETH_DMA_TX_DESC_UF) || ((FLAG) == ETH_DMA_TX_DESC_DB)) + +/** + * @} + */ + +/** @addtogroup ETH_DMA_Tx_descriptor_segment + * @{ + */ +#define ETH_DMA_TX_DESC_LAST_SEGMENT ((uint32_t)0x40000000) /*!< Last Segment */ +#define ETH_DMA_TX_DESC_FIRST_SEGMENT ((uint32_t)0x20000000) /*!< First Segment */ +#define IS_ETH_DMA_TX_DESC_SEGMENT(SEGMENT) \ + (((SEGMENT) == ETH_DMA_TX_DESC_LAST_SEGMENT) || ((SEGMENT) == ETH_DMA_TX_DESC_FIRST_SEGMENT)) + +/** + * @} + */ + +/** @addtogroup ETH_DMA_Tx_descriptor_Checksum_Insertion_Control + * @{ + */ +#define ETH_DMA_TX_DESC_CHECKSUM_BYPASS ((uint32_t)0x00000000) /*!< Checksum engine bypass */ +#define ETH_DMA_TX_DESC_CHECKSUM_IPV4_HEADER ((uint32_t)0x08000000) /*!< IPv4 header checksum insertion */ +#define ETH_DMA_TX_DESC_CHECKSUM_TCPUDPICMP_SEGMENT \ + ((uint32_t)0x10000000) /*!< TCP/UDP/ICMP checksum insertion. Pseudo header checksum is assumed to be present */ +#define ETH_DMA_TX_DESC_CHECKSUM_TCPUDPICMP_FULL \ + ((uint32_t)0x18000000) /*!< TCP/UDP/ICMP checksum fully in hardware including pseudo header */ +#define IS_ETH_DMA_TX_DESC_CHECKSUM(CHECKSUM) \ + (((CHECKSUM) == ETH_DMA_TX_DESC_CHECKSUM_BYPASS) || ((CHECKSUM) == ETH_DMA_TX_DESC_CHECKSUM_IPV4_HEADER) \ + || ((CHECKSUM) == ETH_DMA_TX_DESC_CHECKSUM_TCPUDPICMP_SEGMENT) \ + || ((CHECKSUM) == ETH_DMA_TX_DESC_CHECKSUM_TCPUDPICMP_FULL)) + +#define IS_ETH_DMA_TX_DESC_BUFFER_SIZE(SIZE) ((SIZE) <= 0x1FFF) + +/** + * @} + */ + +/** @addtogroup ETH_DMA_Rx_descriptor_flags + * @{ + */ +#define IS_ETH_DMA_RX_DESC_GET_FLAG(FLAG) \ + (((FLAG) == ETH_DMA_RX_DESC_OWN) || ((FLAG) == ETH_DMA_RX_DESC_AFM) || ((FLAG) == ETH_DMA_RX_DESC_ES) \ + || ((FLAG) == ETH_DMA_RX_DESC_DE) || ((FLAG) == ETH_DMA_RX_DESC_SAF) || ((FLAG) == ETH_DMA_RX_DESC_LE) \ + || ((FLAG) == ETH_DMA_RX_DESC_OE) || ((FLAG) == ETH_DMA_RX_DESC_VLAN) || ((FLAG) == ETH_DMA_RX_DESC_FS) \ + || ((FLAG) == ETH_DMA_RX_DESC_LS) || ((FLAG) == ETH_DMA_RX_DESC_IPV4HCE) || ((FLAG) == ETH_DMA_RX_DESC_LC) \ + || ((FLAG) == ETH_DMA_RX_DESC_FT) || ((FLAG) == ETH_DMA_RX_DESC_RWT) || ((FLAG) == ETH_DMA_RX_DESC_RE) \ + || ((FLAG) == ETH_DMA_RX_DESC_DBE) || ((FLAG) == ETH_DMA_RX_DESC_CE) || ((FLAG) == ETH_DMA_RX_DESC_RMAPCE)) + +/** + * @} + */ + +/** @addtogroup ETH_DMA_Rx_descriptor_buffers_ + * @{ + */ +#define ETH_DMA_RX_DESC_BUFFER1 ((uint32_t)0x00000000) /*!< DMA Rx Desc Buffer1 */ +#define ETH_DMA_RX_DESC_BUFFER2 ((uint32_t)0x00000001) /*!< DMA Rx Desc Buffer2 */ +#define IS_ETH_DMA_RXDESC_BUFFER(BUFFER) \ + (((BUFFER) == ETH_DMA_RX_DESC_BUFFER1) || ((BUFFER) == ETH_DMA_RX_DESC_BUFFER2)) + +/** + * @} + */ + +/** @addtogroup ETH_Drop_TCP_IP_Checksum_Error_Frame + * @{ + */ +#define ETH_DROP_TCPIP_CHECKSUM_ERROR_FRAME_ENABLE ((uint32_t)0x00000000) +#define ETH_DROP_TCPIP_CHECKSUM_ERROR_FRAME_DISABLE ((uint32_t)0x04000000) +#define IS_ETH_DROP_TCPIP_CHECKSUM_FRAME(CMDCTRL) \ + (((CMDCTRL) == ETH_DROP_TCPIP_CHECKSUM_ERROR_FRAME_ENABLE) \ + || ((CMDCTRL) == ETH_DROP_TCPIP_CHECKSUM_ERROR_FRAME_DISABLE)) +/** + * @} + */ + +/** @addtogroup ETH_Receive_Store_Forward + * @{ + */ +#define ETH_RX_STORE_FORWARD_ENABLE ((uint32_t)0x02000000) +#define ETH_RX_STORE_FORWARD_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_RX_STORE_FORWARD(CMDCTRL) \ + (((CMDCTRL) == ETH_RX_STORE_FORWARD_ENABLE) || ((CMDCTRL) == ETH_RX_STORE_FORWARD_DISABLE)) +/** + * @} + */ + +/** @addtogroup ETH_Flush_Received_Frame + * @{ + */ +#define ETH_FLUSH_RX_FRAME_ENABLE ((uint32_t)0x00000000) +#define ETH_FLUSH_RX_FRAME_DISABLE ((uint32_t)0x01000000) +#define IS_ETH_FLUSH_RX_FRAME(CMDCTRL) \ + (((CMDCTRL) == ETH_FLUSH_RX_FRAME_ENABLE) || ((CMDCTRL) == ETH_FLUSH_RX_FRAME_DISABLE)) +/** + * @} + */ + +/** @addtogroup ETH_Transmit_Store_Forward + * @{ + */ +#define ETH_TX_STORE_FORWARD_ENABLE ((uint32_t)0x00200000) +#define ETH_TX_STORE_FORWARD_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_TX_STORE_FORWARD(CMDCTRL) \ + (((CMDCTRL) == ETH_TX_STORE_FORWARD_ENABLE) || ((CMDCTRL) == ETH_TX_STORE_FORWARD_DISABLE)) +/** + * @} + */ + +/** @addtogroup ETH_Transmit_Threshold_Control + * @{ + */ +#define ETH_TX_THRESHOLD_CTRL_64BYTES \ + ((uint32_t)0x00000000) /*!< threshold level of the MTL Transmit DATFIFO is 64 Bytes */ +#define ETH_TX_THRESHOLD_CTRL_128BYTES \ + ((uint32_t)0x00004000) /*!< threshold level of the MTL Transmit DATFIFO is 128 Bytes */ +#define ETH_TX_THRESHOLD_CTRL_192BYTES \ + ((uint32_t)0x00008000) /*!< threshold level of the MTL Transmit DATFIFO is 192 Bytes */ +#define ETH_TX_THRESHOLD_CTRL_256BYTES \ + ((uint32_t)0x0000C000) /*!< threshold level of the MTL Transmit DATFIFO is 256 Bytes */ +#define ETH_TX_THRESHOLD_CTRL_40BYTES \ + ((uint32_t)0x00010000) /*!< threshold level of the MTL Transmit DATFIFO is 40 Bytes */ +#define ETH_TX_THRESHOLD_CTRL_32BYTES \ + ((uint32_t)0x00014000) /*!< threshold level of the MTL Transmit DATFIFO is 32 Bytes */ +#define ETH_TX_THRESHOLD_CTRL_24BYTES \ + ((uint32_t)0x00018000) /*!< threshold level of the MTL Transmit DATFIFO is 24 Bytes */ +#define ETH_TX_THRESHOLD_CTRL_16BYTES \ + ((uint32_t)0x0001C000) /*!< threshold level of the MTL Transmit DATFIFO is 16 Bytes */ +#define IS_ETH_TX_THRESHOLD_CTRL(THRESHOLD) \ + (((THRESHOLD) == ETH_TX_THRESHOLD_CTRL_64BYTES) || ((THRESHOLD) == ETH_TX_THRESHOLD_CTRL_128BYTES) \ + || ((THRESHOLD) == ETH_TX_THRESHOLD_CTRL_192BYTES) || ((THRESHOLD) == ETH_TX_THRESHOLD_CTRL_256BYTES) \ + || ((THRESHOLD) == ETH_TX_THRESHOLD_CTRL_40BYTES) || ((THRESHOLD) == ETH_TX_THRESHOLD_CTRL_32BYTES) \ + || ((THRESHOLD) == ETH_TX_THRESHOLD_CTRL_24BYTES) || ((THRESHOLD) == ETH_TX_THRESHOLD_CTRL_16BYTES)) +/** + * @} + */ + +/** @addtogroup ETH_Forward_Error_Frames + * @{ + */ +#define ETH_FORWARD_ERROR_FRAMES_ENABLE ((uint32_t)0x00000080) +#define ETH_FORWARD_ERROR_FRAMES_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_FORWARD_ERROR_FRAMES(CMDCTRL) \ + (((CMDCTRL) == ETH_FORWARD_ERROR_FRAMES_ENABLE) || ((CMDCTRL) == ETH_FORWARD_ERROR_FRAMES_DISABLE)) +/** + * @} + */ + +/** @addtogroup ETH_Forward_Undersized_Good_Frames + * @{ + */ +#define ETH_FORWARD_UNDERSIZED_GOOD_FRAMES_ENABLE ((uint32_t)0x00000040) +#define ETH_FORWARD_UNDERSIZED_GOOD_FRAMES_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_FORWARD_UNDERSIZED_GOOD_FRAMES(CMDCTRL) \ + (((CMDCTRL) == ETH_FORWARD_UNDERSIZED_GOOD_FRAMES_ENABLE) \ + || ((CMDCTRL) == ETH_FORWARD_UNDERSIZED_GOOD_FRAMES_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Receive_Threshold_Control + * @{ + */ +#define ETH_RX_THRESHOLD_CTRL_64BYTES \ + ((uint32_t)0x00000000) /*!< threshold level of the MTL Receive DATFIFO is 64 Bytes */ +#define ETH_RX_THRESHOLD_CTRL_32BYTES \ + ((uint32_t)0x00000008) /*!< threshold level of the MTL Receive DATFIFO is 32 Bytes */ +#define ETH_RX_THRESHOLD_CTRL_96BYTES \ + ((uint32_t)0x00000010) /*!< threshold level of the MTL Receive DATFIFO is 96 Bytes */ +#define ETH_RX_THRESHOLD_CTRL_128BYTES \ + ((uint32_t)0x00000018) /*!< threshold level of the MTL Receive DATFIFO is 128 Bytes */ +#define IS_ETH_RX_THRESHOLD_CTRL(THRESHOLD) \ + (((THRESHOLD) == ETH_RX_THRESHOLD_CTRL_64BYTES) || ((THRESHOLD) == ETH_RX_THRESHOLD_CTRL_32BYTES) \ + || ((THRESHOLD) == ETH_RX_THRESHOLD_CTRL_96BYTES) || ((THRESHOLD) == ETH_RX_THRESHOLD_CTRL_128BYTES)) +/** + * @} + */ + +/** @addtogroup ETH_Second_Frame_Operate + * @{ + */ +#define ETH_SECOND_FRAME_OPERATE_ENABLE ((uint32_t)0x00000004) +#define ETH_SECOND_FRAME_OPERATE_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_SECOND_FRAME_OPERATE(CMDCTRL) \ + (((CMDCTRL) == ETH_SECOND_FRAME_OPERATE_ENABLE) || ((CMDCTRL) == ETH_SECOND_FRAME_OPERATE_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Address_Aligned_Beats + * @{ + */ +#define ETH_ADDR_ALIGNED_BEATS_ENABLE ((uint32_t)0x02000000) +#define ETH_ADDR_ALIGNED_BEATS_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_ADDR_ALIGNED_BEATS(CMDCTRL) \ + (((CMDCTRL) == ETH_ADDR_ALIGNED_BEATS_ENABLE) || ((CMDCTRL) == ETH_ADDR_ALIGNED_BEATS_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Fixed_Burst + * @{ + */ +#define ETH_FIXED_BURST_ENABLE ((uint32_t)0x00010000) +#define ETH_FIXED_BURST_DISABLE ((uint32_t)0x00000000) +#define IS_ETH_FIXED_BURST(CMDCTRL) (((CMDCTRL) == ETH_FIXED_BURST_ENABLE) || ((CMDCTRL) == ETH_FIXED_BURST_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Rx_DMA_Burst_Length + * @{ + */ +#define ETH_RX_DMA_BURST_LEN_1BEAT \ + ((uint32_t)0x00020000) /*!< maximum number of beats to be transferred in one RxDMA transaction is 1 */ +#define ETH_RX_DMA_BURST_LEN_2BEAT \ + ((uint32_t)0x00040000) /*!< maximum number of beats to be transferred in one RxDMA transaction is 2 */ +#define ETH_RX_DMA_BURST_LEN_4BEAT \ + ((uint32_t)0x00080000) /*!< maximum number of beats to be transferred in one RxDMA transaction is 4 */ +#define ETH_RX_DMA_BURST_LEN_8BEAT \ + ((uint32_t)0x00100000) /*!< maximum number of beats to be transferred in one RxDMA transaction is 8 */ +#define ETH_RX_DMA_BURST_LEN_16BEAT \ + ((uint32_t)0x00200000) /*!< maximum number of beats to be transferred in one RxDMA transaction is 16 */ +#define ETH_RX_DMA_BURST_LEN_32BEAT \ + ((uint32_t)0x00400000) /*!< maximum number of beats to be transferred in one RxDMA transaction is 32 */ +#define ETH_RX_DMA_BURST_LEN_PBLX8_8BEAT \ + ((uint32_t)0x01020000) /*!< maximum number of beats to be transferred in one RxDMA transaction is 4 */ +#define ETH_RX_DMA_BURST_LEN_PBLX8_16BEAT \ + ((uint32_t)0x01040000) /*!< maximum number of beats to be transferred in one RxDMA transaction is 8 */ +#define ETH_RX_DMA_BURST_LEN_PBLX8_32BEAT \ + ((uint32_t)0x01080000) /*!< maximum number of beats to be transferred in one RxDMA transaction is 16 */ +#define ETH_RX_DMA_BURST_LEN_PBLX8_64BEAT \ + ((uint32_t)0x01100000) /*!< maximum number of beats to be transferred in one RxDMA transaction is 32 */ +#define ETH_RX_DMA_BURST_LEN_PBLX8_128BEAT \ + ((uint32_t)0x01200000) /*!< maximum number of beats to be transferred in one RxDMA transaction is 64 */ +#define ETH_RX_DMA_BURST_LEN_PBLX8_256BEAT \ + ((uint32_t)0x01400000) /*!< maximum number of beats to be transferred in one RxDMA transaction is 128 */ +#define IS_ETH_RX_DMA_BURST_LEN(LENGTH) \ + (((LENGTH) == ETH_RX_DMA_BURST_LEN_1BEAT) || ((LENGTH) == ETH_RX_DMA_BURST_LEN_2BEAT) \ + || ((LENGTH) == ETH_RX_DMA_BURST_LEN_4BEAT) || ((LENGTH) == ETH_RX_DMA_BURST_LEN_8BEAT) \ + || ((LENGTH) == ETH_RX_DMA_BURST_LEN_16BEAT) || ((LENGTH) == ETH_RX_DMA_BURST_LEN_32BEAT) \ + || ((LENGTH) == ETH_RX_DMA_BURST_LEN_PBLX8_8BEAT) || ((LENGTH) == ETH_RX_DMA_BURST_LEN_PBLX8_16BEAT) \ + || ((LENGTH) == ETH_RX_DMA_BURST_LEN_PBLX8_32BEAT) || ((LENGTH) == ETH_RX_DMA_BURST_LEN_PBLX8_64BEAT) \ + || ((LENGTH) == ETH_RX_DMA_BURST_LEN_PBLX8_128BEAT) || ((LENGTH) == ETH_RX_DMA_BURST_LEN_PBLX8_256BEAT)) + +/** + * @} + */ + +/** @addtogroup ETH_Tx_DMA_Burst_Length + * @{ + */ +#define ETH_TX_DMA_BURST_LEN_1BEAT \ + ((uint32_t)0x00000100) /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 1 */ +#define ETH_TX_DMA_BURST_LEN_2BEAT \ + ((uint32_t)0x00000200) /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 2 */ +#define ETH_TX_DMA_BURST_LEN_4BEAT \ + ((uint32_t)0x00000400) /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 4 */ +#define ETH_TX_DMA_BURST_LEN_8BEAT \ + ((uint32_t)0x00000800) /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 8 */ +#define ETH_TX_DMA_BURST_LEN_16BEAT \ + ((uint32_t)0x00001000) /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 16 */ +#define ETH_TX_DMA_BURST_LEN_32BEAT \ + ((uint32_t)0x00002000) /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 32 */ +#define ETH_TX_DMA_BURST_LEN_PBLX8_8BEAT \ + ((uint32_t)0x01000100) /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 4 */ +#define ETH_TX_DMA_BURST_LEN_PBLX8_16BEAT \ + ((uint32_t)0x01000200) /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 8 */ +#define ETH_TX_DMA_BURST_LEN_PBLX8_32BEAT \ + ((uint32_t)0x01000400) /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 16 */ +#define ETH_TX_DMA_BURST_LEN_PBLX8_64BEAT \ + ((uint32_t)0x01000800) /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 32 */ +#define ETH_TX_DMA_BURST_LEN_PBLX8_128BEAT \ + ((uint32_t)0x01001000) /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 64 */ +#define ETH_TX_DMA_BURST_LEN_PBLX8_256BEAT \ + ((uint32_t)0x01002000) /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 128 */ +#define IS_ETH_TX_DMA_BURST_LEN(LENGTH) \ + (((LENGTH) == ETH_TX_DMA_BURST_LEN_1BEAT) || ((LENGTH) == ETH_TX_DMA_BURST_LEN_2BEAT) \ + || ((LENGTH) == ETH_TX_DMA_BURST_LEN_4BEAT) || ((LENGTH) == ETH_TX_DMA_BURST_LEN_8BEAT) \ + || ((LENGTH) == ETH_TX_DMA_BURST_LEN_16BEAT) || ((LENGTH) == ETH_TX_DMA_BURST_LEN_32BEAT) \ + || ((LENGTH) == ETH_TX_DMA_BURST_LEN_PBLX8_8BEAT) || ((LENGTH) == ETH_TX_DMA_BURST_LEN_PBLX8_16BEAT) \ + || ((LENGTH) == ETH_TX_DMA_BURST_LEN_PBLX8_32BEAT) || ((LENGTH) == ETH_TX_DMA_BURST_LEN_PBLX8_64BEAT) \ + || ((LENGTH) == ETH_TX_DMA_BURST_LEN_PBLX8_128BEAT) || ((LENGTH) == ETH_TX_DMA_BURST_LEN_PBLX8_256BEAT)) + +#define IS_ETH_DMA_DESC_SKIP_LEN(LENGTH) ((LENGTH) <= 0x1F) + +/** + * @} + */ + +/** @addtogroup ETH_DMA_Arbitration + * @{ + */ +#define ETH_DMA_ARBITRATION_ROUND_ROBIN_RXTX_1_1 ((uint32_t)0x00000000) +#define ETH_DMA_ARBITRATION_ROUND_ROBIN_RXTX_2_1 ((uint32_t)0x00004000) +#define ETH_DMA_ARBITRATION_ROUND_ROBIN_RXTX_3_1 ((uint32_t)0x00008000) +#define ETH_DMA_ARBITRATION_ROUND_ROBIN_RXTX_4_1 ((uint32_t)0x0000C000) +#define ETH_DMA_ARBITRATION_RX_PRIOR_TX ((uint32_t)0x00000002) +#define IS_ETH_DMA_ARBITRATION_ROUND_ROBIN_RXTX(RATIO) \ + (((RATIO) == ETH_DMA_ARBITRATION_ROUND_ROBIN_RXTX_1_1) || ((RATIO) == ETH_DMA_ARBITRATION_ROUND_ROBIN_RXTX_2_1) \ + || ((RATIO) == ETH_DMA_ARBITRATION_ROUND_ROBIN_RXTX_3_1) || ((RATIO) == ETH_DMA_ARBITRATION_ROUND_ROBIN_RXTX_4_1) \ + || ((RATIO) == ETH_DMA_ARBITRATION_RX_PRIOR_TX)) +/** + * @} + */ + +/** @addtogroup ETH_DMA_Flags + * @{ + */ +#define ETH_DMA_FLAG_TST ((uint32_t)0x20000000) /*!< Time-stamp trigger interrupt (on DMA) */ +#define ETH_DMA_FLAG_PMT ((uint32_t)0x10000000) /*!< PMT interrupt (on DMA) */ +#define ETH_DMA_FLAG_MMC ((uint32_t)0x08000000) /*!< MMC interrupt (on DMA) */ +#define ETH_DMA_FLAG_DATA_TRANSFER_ERROR ((uint32_t)0x00800000) /*!< Error bits 0-Rx DMA, 1-Tx DMA */ +#define ETH_DMA_FLAG_READ_WRITE_ERROR ((uint32_t)0x01000000) /*!< Error bits 0-write trnsf, 1-read transfr */ +#define ETH_DMA_FLAG_ACCESS_ERROR ((uint32_t)0x02000000) /*!< Error bits 0-data buffer, 1-desc. access */ +#define ETH_DMA_FLAG_NIS ((uint32_t)0x00010000) /*!< Normal interrupt summary flag */ +#define ETH_DMA_FLAG_AIS ((uint32_t)0x00008000) /*!< Abnormal interrupt summary flag */ +#define ETH_DMA_FLAG_EARLY_RX ((uint32_t)0x00004000) /*!< Early receive flag */ +#define ETH_DMA_FLAG_FATAL_BUS_ERROR ((uint32_t)0x00002000) /*!< Fatal bus error flag */ +#define ETH_DMA_FLAG_EARLY_TX ((uint32_t)0x00000400) /*!< Early transmit flag */ +#define ETH_DMA_FLAG_RX_WDG_TIMEOUT ((uint32_t)0x00000200) /*!< Receive watchdog timeout flag */ +#define ETH_DMA_FLAG_RX_PROC_STOP ((uint32_t)0x00000100) /*!< Receive process stopped flag */ +#define ETH_DMA_FLAG_RX_BUF_UA ((uint32_t)0x00000080) /*!< Receive buffer unavailable flag */ +#define ETH_DMA_FLAG_RX ((uint32_t)0x00000040) /*!< Receive flag */ +#define ETH_DMA_FLAG_TX_UNDERFLOW ((uint32_t)0x00000020) /*!< Underflow flag */ +#define ETH_DMA_FLAG_RX_OVERFLOW ((uint32_t)0x00000010) /*!< Overflow flag */ +#define ETH_DMA_FLAG_TX_JABBER_TIMEOUT ((uint32_t)0x00000008) /*!< Transmit jabber timeout flag */ +#define ETH_DMA_FLAG_TX_BUF_UA ((uint32_t)0x00000004) /*!< Transmit buffer unavailable flag */ +#define ETH_DMA_FLAG_TX_PROC_STOP ((uint32_t)0x00000002) /*!< Transmit process stopped flag */ +#define ETH_DMA_FLAG_TX ((uint32_t)0x00000001) /*!< Transmit flag */ + +#define IS_ETH_DMA_FLAG(FLAG) ((((FLAG) & (uint32_t)0xFFFE1800) == 0x00) && ((FLAG) != 0x00)) +#define IS_ETH_DMA_GET_FLAG(FLAG) \ + (((FLAG) == ETH_DMA_FLAG_TST) || ((FLAG) == ETH_DMA_FLAG_PMT) || ((FLAG) == ETH_DMA_FLAG_MMC) \ + || ((FLAG) == ETH_DMA_FLAG_DATA_TRANSFER_ERROR) || ((FLAG) == ETH_DMA_FLAG_READ_WRITE_ERROR) \ + || ((FLAG) == ETH_DMA_FLAG_ACCESS_ERROR) || ((FLAG) == ETH_DMA_FLAG_NIS) || ((FLAG) == ETH_DMA_FLAG_AIS) \ + || ((FLAG) == ETH_DMA_FLAG_EARLY_RX) || ((FLAG) == ETH_DMA_FLAG_FATAL_BUS_ERROR) \ + || ((FLAG) == ETH_DMA_FLAG_EARLY_TX) || ((FLAG) == ETH_DMA_FLAG_RX_WDG_TIMEOUT) \ + || ((FLAG) == ETH_DMA_FLAG_RX_PROC_STOP) || ((FLAG) == ETH_DMA_FLAG_RX_BUF_UA) || ((FLAG) == ETH_DMA_FLAG_RX) \ + || ((FLAG) == ETH_DMA_FLAG_TX_UNDERFLOW) || ((FLAG) == ETH_DMA_FLAG_RX_OVERFLOW) \ + || ((FLAG) == ETH_DMA_FLAG_TX_JABBER_TIMEOUT) || ((FLAG) == ETH_DMA_FLAG_TX_BUF_UA) \ + || ((FLAG) == ETH_DMA_FLAG_TX_PROC_STOP) || ((FLAG) == ETH_DMA_FLAG_TX)) +/** + * @} + */ + +/** @addtogroup ETH_DMA_Interrupts + * @{ + */ +#define ETH_DMA_INT_TST ((uint32_t)0x20000000) /*!< Time-stamp trigger interrupt (on DMA) */ +#define ETH_DMA_INT_PMT ((uint32_t)0x10000000) /*!< PMT interrupt (on DMA) */ +#define ETH_DMA_INT_MMC ((uint32_t)0x08000000) /*!< MMC interrupt (on DMA) */ +#define ETH_DMA_INT_NIS ((uint32_t)0x00010000) /*!< Normal interrupt summary */ +#define ETH_DMA_INT_AIS ((uint32_t)0x00008000) /*!< Abnormal interrupt summary */ +#define ETH_DMA_INT_EARLY_RX ((uint32_t)0x00004000) /*!< Early receive interrupt */ +#define ETH_DMA_INT_FATAL_BUS_ERROR ((uint32_t)0x00002000) /*!< Fatal bus error interrupt */ +#define ETH_DMA_INT_EARLY_TX ((uint32_t)0x00000400) /*!< Early transmit interrupt */ +#define ETH_DMA_INT_RX_WDG_TIMEOUT ((uint32_t)0x00000200) /*!< Receive watchdog timeout interrupt */ +#define ETH_DMA_INT_RX_PROC_STOP ((uint32_t)0x00000100) /*!< Receive process stopped interrupt */ +#define ETH_DMA_INT_RX_BUF_UA ((uint32_t)0x00000080) /*!< Receive buffer unavailable interrupt */ +#define ETH_DMA_INT_RX ((uint32_t)0x00000040) /*!< Receive interrupt */ +#define ETH_DMA_INT_TX_UNDERFLOW ((uint32_t)0x00000020) /*!< Underflow interrupt */ +#define ETH_DMA_INT_RX_OVERFLOW ((uint32_t)0x00000010) /*!< Overflow interrupt */ +#define ETH_DMA_INT_TX_JABBER_TIMEOUT ((uint32_t)0x00000008) /*!< Transmit jabber timeout interrupt */ +#define ETH_DMA_INT_TX_BUF_UA ((uint32_t)0x00000004) /*!< Transmit buffer unavailable interrupt */ +#define ETH_DMA_INT_TX_PROC_STOP ((uint32_t)0x00000002) /*!< Transmit process stopped interrupt */ +#define ETH_DMA_INT_TX ((uint32_t)0x00000001) /*!< Transmit interrupt */ + +#define IS_ETH_DMA_INT(IT) ((((IT) & (uint32_t)0xFFFE1800) == 0x00) && ((IT) != 0x00)) +#define IS_ETH_DMA_GET_INT(IT) \ + (((IT) == ETH_DMA_INT_TST) || ((IT) == ETH_DMA_INT_PMT) || ((IT) == ETH_DMA_INT_MMC) || ((IT) == ETH_DMA_INT_NIS) \ + || ((IT) == ETH_DMA_INT_AIS) || ((IT) == ETH_DMA_INT_EARLY_RX) || ((IT) == ETH_DMA_INT_FATAL_BUS_ERROR) \ + || ((IT) == ETH_DMA_INT_EARLY_TX) || ((IT) == ETH_DMA_INT_RX_WDG_TIMEOUT) || ((IT) == ETH_DMA_INT_RX_PROC_STOP) \ + || ((IT) == ETH_DMA_INT_RX_BUF_UA) || ((IT) == ETH_DMA_INT_RX) || ((IT) == ETH_DMA_INT_TX_UNDERFLOW) \ + || ((IT) == ETH_DMA_INT_RX_OVERFLOW) || ((IT) == ETH_DMA_INT_TX_JABBER_TIMEOUT) \ + || ((IT) == ETH_DMA_INT_TX_BUF_UA) || ((IT) == ETH_DMA_INT_TX_PROC_STOP) || ((IT) == ETH_DMA_INT_TX)) + +/** + * @} + */ + +/** @addtogroup ETH_DMA_transmit_process_state_ + * @{ + */ +#define ETH_DMA_TX_PROC_STOPPED ((uint32_t)0x00000000) /*!< Stopped - Reset or Stop Tx Command issued */ +#define ETH_DMA_TX_PROC_FETCHING ((uint32_t)0x00100000) /*!< Running - fetching the Tx descriptor */ +#define ETH_DMA_TX_PROC_WAITING ((uint32_t)0x00200000) /*!< Running - waiting for status */ +#define ETH_DMA_TX_PROC_READING ((uint32_t)0x00300000) /*!< Running - reading the data from host memory */ +#define ETH_DMA_TX_PROC_SUSPENDED ((uint32_t)0x00600000) /*!< Suspended - Tx Desciptor unavailabe */ +#define ETH_DMA_TX_PROC_CLOSING ((uint32_t)0x00700000) /*!< Running - closing Rx descriptor */ + +/** + * @} + */ + +/** @addtogroup ETH_DMA_receive_process_state_ + * @{ + */ +#define ETH_DMA_RX_PROC_STOPPED ((uint32_t)0x00000000) /*!< Stopped - Reset or Stop Rx Command issued */ +#define ETH_DMA_RX_PROC_FETCHING ((uint32_t)0x00020000) /*!< Running - fetching the Rx descriptor */ +#define ETH_DMA_RX_PROC_WAITING ((uint32_t)0x00060000) /*!< Running - waiting for packet */ +#define ETH_DMA_RX_PROC_SUSPENDED ((uint32_t)0x00080000) /*!< Suspended - Rx Desciptor unavailable */ +#define ETH_DMA_RX_PROC_CLOSING ((uint32_t)0x000A0000) /*!< Running - closing descriptor */ +#define ETH_DMA_RX_PROC_QUEUING ((uint32_t)0x000E0000) /*!< Running - queuing the recieve frame into host memory */ + +/** + * @} + */ + +/** @addtogroup ETH_DMA_overflow_ + * @{ + */ +#define ETH_DMA_OVERFLOW_RX_FIFO_COUNTER ((uint32_t)0x10000000) /*!< Overflow bit for DATFIFO overflow counter */ +#define ETH_DMA_OVERFLOW_MISSED_FRAME_COUNTER ((uint32_t)0x00010000) /*!< Overflow bit for missed frame counter */ +#define IS_ETH_DMA_GET_OVERFLOW(OVERFLOW) \ + (((OVERFLOW) == ETH_DMA_OVERFLOW_RX_FIFO_COUNTER) || ((OVERFLOW) == ETH_DMA_OVERFLOW_MISSED_FRAME_COUNTER)) + +/** + * @} + */ + +/** @addtogroup ETH_PMT_Flags + * @{ + */ +#define ETH_PMT_FLAG_RWKUPFILTRST ((uint32_t)0x80000000) /*!< Wake-Up Frame Filter Register Poniter Reset */ +#define ETH_PMT_FLAG_RWKPRCVD ((uint32_t)0x00000040) /*!< Wake-Up Frame Received */ +#define ETH_PMT_FLAG_MGKPRCVD ((uint32_t)0x00000020) /*!< Magic Packet Received */ +#define IS_ETH_PMT_GET_FLAG(FLAG) (((FLAG) == ETH_PMT_FLAG_RWKPRCVD) || ((FLAG) == ETH_PMT_FLAG_MGKPRCVD)) + +/** + * @} + */ + +/** @addtogroup ETH_MMC_Tx_Interrupts + * @{ + */ +#define ETH_MMC_INT_TXGFRMIS ((uint32_t)0x00200000) /*!< When Tx good frame counter reaches half the maximum value */ +#define ETH_MMC_INT_TXMCOLGFIS \ + ((uint32_t)0x00008000) /*!< When Tx good multi col counter reaches half the maximum value */ +#define ETH_MMC_INT_TXSCOLGFIS \ + ((uint32_t)0x00004000) /*!< When Tx good single col counter reaches half the maximum value */ + +/** + * @} + */ + +/** @addtogroup ETH_MMC_Rx_Interrupts + * @{ + */ +#define ETH_MMC_INT_RXUCGFIS \ + ((uint32_t)0x10020000) /*!< When Rx good unicast frames counter reaches half the maximum value */ +#define ETH_MMC_INT_RXALGNERFIS \ + ((uint32_t)0x10000040) /*!< When Rx alignment error counter reaches half the maximum value */ +#define ETH_MMC_INT_RXCRCERFIS ((uint32_t)0x10000020) /*!< When Rx crc error counter reaches half the maximum value */ +#define IS_ETH_MMC_INT(IT) \ + (((((IT) & (uint32_t)0xFFDF3FFF) == 0x00) || (((IT) & (uint32_t)0xEFFDFF9F) == 0x00)) && ((IT) != 0x00)) +#define IS_ETH_MMC_GET_INT(IT) \ + (((IT) == ETH_MMC_INT_TXGFRMIS) || ((IT) == ETH_MMC_INT_TXMCOLGFIS) || ((IT) == ETH_MMC_INT_TXSCOLGFIS) \ + || ((IT) == ETH_MMC_INT_RXUCGFIS) || ((IT) == ETH_MMC_INT_RXALGNERFIS) || ((IT) == ETH_MMC_INT_RXCRCERFIS)) +/** + * @} + */ + +/** @addtogroup ETH_MMC_Registers + * @{ + */ +#define ETH_MMCCTRL ((uint32_t)0x00000100) /*!< MMC CTRL register */ +#define ETH_MMCRXINT ((uint32_t)0x00000104) /*!< MMC RIR register */ +#define ETH_MMCTXINT ((uint32_t)0x00000108) /*!< MMC TIR register */ +#define ETH_MMCRXINTMSK ((uint32_t)0x0000010C) /*!< MMC RIMR register */ +#define ETH_MMCTXINTMSK ((uint32_t)0x00000110) /*!< MMC TIMR register */ +#define ETH_MMCTXGFASCCNT ((uint32_t)0x0000014C) /*!< MMC TGFSCCR register */ +#define ETH_MMCTXGFAMSCCNT ((uint32_t)0x00000150) /*!< MMC TGFMSCCR register */ +#define ETH_MMCTXGFCNT ((uint32_t)0x00000168) /*!< MMC TGFCR register */ +#define ETH_MMCRXFCECNT ((uint32_t)0x00000194) /*!< MMC RFCECR register */ +#define ETH_MMCRXFAECNT ((uint32_t)0x00000198) /*!< MMC RFAECR register */ +#define ETH_MMCRXGUFCNT ((uint32_t)0x000001C4) /*!< MMC RGUFCR register */ + +#define IS_ETH_MMC_REGISTER(REG) \ + (((REG) == ETH_MMCCTRL) || ((REG) == ETH_MMCRXINT) || ((REG) == ETH_MMCTXINT) || ((REG) == ETH_MMCRXINTMSK) \ + || ((REG) == ETH_MMCTXINTMSK) || ((REG) == ETH_MMCTXGFASCCNT) || ((REG) == ETH_MMCTXGFAMSCCNT) \ + || ((REG) == ETH_MMCTXGFCNT) || ((REG) == ETH_MMCRXFCECNT) || ((REG) == ETH_MMCRXFAECNT) \ + || ((REG) == ETH_MMCRXGUFCNT)) + +/** + * @} + */ + +/** @addtogroup ETH_PTP_time_update_method + * @{ + */ +#define ETH_PTP_FINE_UPDATE ((uint32_t)0x00000001) /*!< Fine Update method */ +#define ETH_PTP_COARSE_UPDATE ((uint32_t)0x00000000) /*!< Coarse Update method */ +#define IS_ETH_PTP_UPDATE(UPDATE) (((UPDATE) == ETH_PTP_FINE_UPDATE) || ((UPDATE) == ETH_PTP_COARSE_UPDATE)) + +/** + * @} + */ + +/** @addtogroup ETH_PTP_Flags + * @{ + */ +#define ETH_PTP_FLAG_TSADDREG ((uint32_t)0x00000020) /*!< Addend Register Update */ +#define ETH_PTP_FLAG_TSTRIG ((uint32_t)0x00000010) /*!< Time Stamp Interrupt Trigger */ +#define ETH_PTP_FLAG_TSUPDT ((uint32_t)0x00000008) /*!< Time Stamp Update */ +#define ETH_PTP_FLAG_TSINIT ((uint32_t)0x00000004) /*!< Time Stamp Initialize */ +#define IS_ETH_PTP_GET_FLAG(FLAG) \ + (((FLAG) == ETH_PTP_FLAG_TSADDREG) || ((FLAG) == ETH_PTP_FLAG_TSTRIG) || ((FLAG) == ETH_PTP_FLAG_TSUPDT) \ + || ((FLAG) == ETH_PTP_FLAG_TSINIT)) + +#define IS_ETH_PTP_SUBSECOND_INCREMENT(SUBSECOND) ((SUBSECOND) <= 0xFF) + +/** + * @} + */ + +/** @addtogroup ETH_PTP_time_sign + * @{ + */ +#define ETH_PTP_POSITIVE_TIME ((uint32_t)0x00000000) /*!< Positive time value */ +#define ETH_PTP_NEGATIVE_TIME ((uint32_t)0x80000000) /*!< Negative time value */ +#define IS_ETH_PTP_TIME_SIGN(SIGN) (((SIGN) == ETH_PTP_POSITIVE_TIME) || ((SIGN) == ETH_PTP_NEGATIVE_TIME)) + +#define IS_ETH_PTP_TIME_STAMP_UPDATE_SUBSECOND(SUBSECOND) ((SUBSECOND) <= 0x7FFFFFFF) + +#define ETH_PTPTSCTRL ((uint32_t)0x00000700) /*!< PTP TSCR register */ +#define ETH_PTPSSINC ((uint32_t)0x00000704) /*!< PTP SSIR register */ +#define ETH_PTPSEC ((uint32_t)0x00000708) /*!< PTP TSHR register */ +#define ETH_PTPNS ((uint32_t)0x0000070C) /*!< PTP TSLR register */ +#define ETH_PTPSECUP ((uint32_t)0x00000710) /*!< PTP TSHUR register */ +#define ETH_PTPNSUP ((uint32_t)0x00000714) /*!< PTP TSLUR register */ +#define ETH_PTPTSADD ((uint32_t)0x00000718) /*!< PTP TSAR register */ +#define ETH_PTPTTSEC ((uint32_t)0x0000071C) /*!< PTP TTHR register */ +#define ETH_PTPTTNS ((uint32_t)0x00000720) /* PTP TTLR register */ +#define IS_ETH_PTP_REGISTER(REG) \ + (((REG) == ETH_PTPTSCTRL) || ((REG) == ETH_PTPSSINC) || ((REG) == ETH_PTPSEC) || ((REG) == ETH_PTPNS) \ + || ((REG) == ETH_PTPSECUP) || ((REG) == ETH_PTPNSUP) || ((REG) == ETH_PTPTSADD) || ((REG) == ETH_PTPTTSEC) \ + || ((REG) == ETH_PTPTTNS)) + +/** + * @} + */ + +/** + * @} + */ +/** @addtogroup ETH_Exported_Macros + * @{ + */ +/** + * @} + */ + +/* ETHERNET errors */ +#define ETH_ERROR ((uint32_t)0) +#define ETH_SUCCESS ((uint32_t)1) + +/** + * @brief the function prototype of initialize PHY. + * @param ETH_InitStruct init struct of ETH MAC peripheral. + * @return whether initialization succeed: + * - ETH_ERROR initialization fail + * - ETH_SUCCESS initialization succeed + */ +typedef uint32_t (*ETH_InitPHY)(ETH_InitType* ETH_InitStruct); + +/** @addtogroup ETH_Exported_Functions + * @{ + */ +void ETH_DeInit(void); + +uint32_t ETH_Init(ETH_InitType* ETH_InitStruct, ETH_InitPHY callable); +void ETH_InitStruct(ETH_InitType* ETH_InitStruct); +void ETH_SoftwareReset(void); +FlagStatus ETH_GetSoftwareResetStatus(void); +void ETH_EnableTxRx(void); +uint32_t ETH_TxPacket(u8* ppkt, u16 FrameLength); +uint32_t ETH_RxPacket(u8* ppkt, uint8_t checkErr); +uint32_t ETH_GetRxPacketSize(void); +void ETH_DropRxPacket(void); + +#define ETH_INTERFACE_RMII 0 +#define ETH_INTERFACE_MII 1 + +void ETH_ConfigGpio(uint8_t ETH_Interface, uint8_t remap); + +/* PHY */ +uint16_t ETH_ReadPhyRegister(u16 PHYAddress, u16 PHYReg); +uint32_t ETH_WritePhyRegister(u16 PHYAddress, u16 PHYReg, u16 PHYValue); +uint32_t ETH_EnablePhyLoopBack(u16 PHYAddress, FunctionalState Cmd); + +/* MAC */ +void ETH_EnableMacTx(FunctionalState Cmd); +void ETH_EnableMacRx(FunctionalState Cmd); +FlagStatus ETH_GetFlowCtrlBusyStatus(void); +void ETH_GeneratePauseCtrlFrame(void); +void ETH_EnableBackPressureActivation(FunctionalState Cmd); +FlagStatus ETH_GetMacFlagStatus(uint32_t ETH_MAC_FLAG); +INTStatus ETH_GetMacIntStatus(uint32_t ETH_MAC_IT); +void ETH_EnableMacInt(uint32_t ETH_MAC_IT, FunctionalState Cmd); +void ETH_SetMacAddr(uint32_t MacAddr, u8* Addr); +void ETH_GetMacAddr(uint32_t MacAddr, u8* Addr); +void ETH_EnableMacAddrPerfectFilter(uint32_t MacAddr, FunctionalState Cmd); +void ETH_ConfigMacAddrFilter(uint32_t MacAddr, uint32_t Filter); +void ETH_ConfigMacAddrMaskBytesFilter(uint32_t MacAddr, uint32_t MaskByte); + +/* DMA Tx/Rx descriptors */ +void ETH_ConfigDmaTxDescInChainMode(ETH_DMADescType* DMATxDescTab, u8* TxBuff, uint32_t BufSize, uint32_t TxBuffCount); +void ETH_ConfigDmaTxDescInRingMode(ETH_DMADescType* DMATxDescTab, + u8* TxBuff1, + u8* TxBuff2, + uint32_t BufSize, + uint32_t TxBuffCount); +FlagStatus ETH_GetDmaTxDescFlagStatus(ETH_DMADescType* DMATxDesc, uint32_t ETH_DMATxDescFlag); +uint32_t ETH_GetDmaTxDescCollisionCount(ETH_DMADescType* DMATxDesc); +void ETH_SetDmaTxDescOwn(ETH_DMADescType* DMATxDesc); +void ETH_EnableDmaTxDescTransmitInt(ETH_DMADescType* DMATxDesc, FunctionalState Cmd); +void ETH_ConfigDmaTxDescFrameSegment(ETH_DMADescType* DMATxDesc, uint32_t DMATxDesc_FrameSegment); +void ETH_ConfigDmaTxDescChecksumInsertion(ETH_DMADescType* DMATxDesc, uint32_t DMATxDesc_Checksum); +void ETH_EnableDmaTxDescCrc(ETH_DMADescType* DMATxDesc, FunctionalState Cmd); +void ETH_EnableDmaTxDescEndOfRing(ETH_DMADescType* DMATxDesc, FunctionalState Cmd); +void ETH_EnableDmaTxDescSecondAddrChained(ETH_DMADescType* DMATxDesc, FunctionalState Cmd); +void ETH_EnableDmaTxDescShortFramePadding(ETH_DMADescType* DMATxDesc, FunctionalState Cmd); +void ETH_EnableDmaTxDescTimeStamp(ETH_DMADescType* DMATxDesc, FunctionalState Cmd); +void ETH_ConfigDmaTxDescBufSize(ETH_DMADescType* DMATxDesc, uint32_t BufferSize1, uint32_t BufferSize2); +void ETH_ConfigDmaRxDescInChainMode(ETH_DMADescType* DMARxDescTab, u8* RxBuff, uint32_t BufSize, uint32_t RxBuffCount); +void ETH_ConfigDmaRxDescInRingMode(ETH_DMADescType* DMARxDescTab, + u8* RxBuff1, + u8* RxBuff2, + uint32_t BuffSize, + uint32_t RxBuffCount); +FlagStatus ETH_GetDmaRxDescFlagStatus(ETH_DMADescType* DMARxDesc, uint32_t ETH_DMARxDescFlag); +void ETH_SetDmaRxDescOwn(ETH_DMADescType* DMARxDesc); +uint32_t ETH_GetDmaRxDescFrameLen(__IO ETH_DMADescType* DMARxDesc); +void ETH_EnableDmaRxDescReceiveInt(ETH_DMADescType* DMARxDesc, FunctionalState Cmd); +void ETH_EnableDmaRxDescEndOfRing(ETH_DMADescType* DMARxDesc, FunctionalState Cmd); +void ETH_EnableDmaRxDescSecondAddrChained(ETH_DMADescType* DMARxDesc, FunctionalState Cmd); +uint32_t ETH_GetDmaRxDescBufSize(ETH_DMADescType* DMARxDesc, uint32_t DMARxDesc_Buffer); + +/* DMA */ +FlagStatus ETH_GetDmaFlagStatus(uint32_t ETH_DMA_FLAG); +void ETH_ClrDmaFlag(uint32_t ETH_DMA_FLAG); +INTStatus ETH_GetDmaIntStatus(uint32_t ETH_DMA_IT); +void ETH_ClrDmaIntPendingBit(uint32_t ETH_DMA_IT); +uint32_t ETH_GetTxProcState(void); +uint32_t ETH_GetRxProcState(void); +void ETH_FlushTxFifo(void); +FlagStatus ETH_GetFlushTxFifoStatus(void); +void ETH_EnableDmaTx(FunctionalState Cmd); +void ETH_EnableDmaRx(FunctionalState Cmd); +void ETH_EnableDmaInt(uint32_t ETH_DMA_IT, FunctionalState Cmd); +FlagStatus ETH_GetDmaOverflowStatus(uint32_t ETH_DMA_Overflow); +uint32_t ETH_GetRxOverflowMissedFrameCounter(void); +uint32_t ETH_GetBufUnavailableMissedFrameCounter(void); +uint32_t ETH_GetCurrentTxDescAddr(void); +uint32_t ETH_GetCurrentRxDescAddr(void); +uint32_t ETH_GetCurrentTxBufAddr(void); +uint32_t ETH_GetCurrentRxBufAddr(void); +void ETH_ResumeDmaTx(void); +void ETH_ResumeDmaRx(void); + +/* PMT */ +void ETH_ResetWakeUpFrameFilter(void); +void ETH_SetWakeUpFrameFilter(uint32_t* Buffer); +void ETH_EnableGlobalUnicastWakeUp(FunctionalState Cmd); +FlagStatus ETH_GetPmtFlagStatus(uint32_t ETH_PMT_FLAG); +void ETH_EnableWakeUpFrameDetection(FunctionalState Cmd); +void ETH_EnableMagicPacketDetection(FunctionalState Cmd); +void ETH_EnablePowerDown(FunctionalState Cmd); + +/* MMC */ +void ETH_EnableMmcCounterFreeze(FunctionalState Cmd); +void ETH_EnableMmcResetOnRead(FunctionalState Cmd); +void ETH_EnableMmcCounterRollover(FunctionalState Cmd); +void ETH_ResetMmcCounters(void); +void ETH_EnableMmcInt(uint32_t ETH_MMC_IT, FunctionalState Cmd); +INTStatus ETH_GetMmcIntStatus(uint32_t ETH_MMC_IT); +uint32_t ETH_GetMmcRegisterValue(uint32_t ETH_MMCReg); + +/* PTP */ +uint32_t ETH_TxPtpPacket(u8* ppkt, u16 FrameLength, uint32_t* PTPTxTab); +uint32_t ETH_RxPtpPacket(u8* ppkt, uint32_t* PTPRxTab); +void ETH_ConfigDmaPtpTxDescInChainMode(ETH_DMADescType* DMATxDescTab, + ETH_DMADescType* DMAPTPTxDescTab, + u8* TxBuff, + uint32_t TxBuffCount); +void ETH_ConfigDmaPtpRxDescInChainMode(ETH_DMADescType* DMARxDescTab, + ETH_DMADescType* DMAPTPRxDescTab, + u8* RxBuff, + uint32_t RxBuffCount); +void ETH_UpdatePtpTimeStampAddend(void); +void ETH_EnablePtpTimeStampIntTrigger(void); +void ETH_UpdatePtpTimeStamp(void); +void ETH_InitPtpTimeStamp(void); +void ETH_ConfigPtpUpdateMethod(uint32_t UpdateMethod); +void ETH_StartPTPTimeStamp(FunctionalState Cmd); +FlagStatus ETH_GetPtpFlagStatus(uint32_t ETH_PTP_FLAG); +void ETH_SetPtpSubSecondInc(uint32_t SubSecondValue); +void ETH_SetPtpTimeStampUpdate(uint32_t Sign, uint32_t SecondValue, uint32_t SubSecondValue); +void ETH_SetPtpTimeStampAddend(uint32_t Value); +void ETH_SetPtpTargetTime(uint32_t HighValue, uint32_t LowValue); +uint32_t ETH_GetPtpRegisterValue(uint32_t ETH_PTPReg); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __N32G45X_ETH_H__ */ +/** + * @} + */ + +/** + * @} + */ diff --git a/inc/n32g45x_exti.h b/inc/n32g45x_exti.h new file mode 100644 index 0000000..88c1bb7 --- /dev/null +++ b/inc/n32g45x_exti.h @@ -0,0 +1,206 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_exti.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_EXTI_H__ +#define __N32G45X_EXTI_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup EXTI + * @{ + */ + +/** @addtogroup EXTI_Exported_Types + * @{ + */ + +/** + * @brief EXTI mode enumeration + */ + +typedef enum +{ + EXTI_Mode_Interrupt = 0x00, + EXTI_Mode_Event = 0x04 +} EXTI_ModeType; + +#define IS_EXTI_MODE(MODE) (((MODE) == EXTI_Mode_Interrupt) || ((MODE) == EXTI_Mode_Event)) + +/** + * @brief EXTI Trigger enumeration + */ + +typedef enum +{ + EXTI_Trigger_Rising = 0x08, + EXTI_Trigger_Falling = 0x0C, + EXTI_Trigger_Rising_Falling = 0x10 +} EXTI_TriggerType; + +#define IS_EXTI_TRIGGER(TRIGGER) \ + (((TRIGGER) == EXTI_Trigger_Rising) || ((TRIGGER) == EXTI_Trigger_Falling) \ + || ((TRIGGER) == EXTI_Trigger_Rising_Falling)) +/** + * @brief EXTI Init Structure definition + */ + +typedef struct +{ + uint32_t EXTI_Line; /*!< Specifies the EXTI lines to be enabled or disabled. + This parameter can be any combination of @ref EXTI_Lines */ + + EXTI_ModeType EXTI_Mode; /*!< Specifies the mode for the EXTI lines. + This parameter can be a value of @ref EXTI_ModeType */ + + EXTI_TriggerType EXTI_Trigger; /*!< Specifies the trigger signal active edge for the EXTI lines. + This parameter can be a value of @ref EXTI_ModeType */ + + FunctionalState EXTI_LineCmd; /*!< Specifies the new state of the selected EXTI lines. + This parameter can be set either to ENABLE or DISABLE */ +} EXTI_InitType; + +/** + * @} + */ + +/** @addtogroup EXTI_Exported_Constants + * @{ + */ + +/** @addtogroup EXTI_Lines + * @{ + */ + +#define EXTI_LINE0 ((uint32_t)0x00001) /*!< External interrupt line 0 */ +#define EXTI_LINE1 ((uint32_t)0x00002) /*!< External interrupt line 1 */ +#define EXTI_LINE2 ((uint32_t)0x00004) /*!< External interrupt line 2 */ +#define EXTI_LINE3 ((uint32_t)0x00008) /*!< External interrupt line 3 */ +#define EXTI_LINE4 ((uint32_t)0x00010) /*!< External interrupt line 4 */ +#define EXTI_LINE5 ((uint32_t)0x00020) /*!< External interrupt line 5 */ +#define EXTI_LINE6 ((uint32_t)0x00040) /*!< External interrupt line 6 */ +#define EXTI_LINE7 ((uint32_t)0x00080) /*!< External interrupt line 7 */ +#define EXTI_LINE8 ((uint32_t)0x00100) /*!< External interrupt line 8 */ +#define EXTI_LINE9 ((uint32_t)0x00200) /*!< External interrupt line 9 */ +#define EXTI_LINE10 ((uint32_t)0x00400) /*!< External interrupt line 10 */ +#define EXTI_LINE11 ((uint32_t)0x00800) /*!< External interrupt line 11 */ +#define EXTI_LINE12 ((uint32_t)0x01000) /*!< External interrupt line 12 */ +#define EXTI_LINE13 ((uint32_t)0x02000) /*!< External interrupt line 13 */ +#define EXTI_LINE14 ((uint32_t)0x04000) /*!< External interrupt line 14 */ +#define EXTI_LINE15 ((uint32_t)0x08000) /*!< External interrupt line 15 */ +#define EXTI_LINE16 ((uint32_t)0x10000) /*!< External interrupt line 16 Connected to the PVD Output */ +#define EXTI_LINE17 ((uint32_t)0x20000) /*!< External interrupt line 17 Connected to the RTC Alarm event */ +#define EXTI_LINE18 ((uint32_t)0x40000) /*!< External interrupt line 18 Connected to the USB Device/USB OTG FS Wakeup from suspend event */ +#define EXTI_LINE19 ((uint32_t)0x80000) /*!< External interrupt line 19 Connected to the Ethernet Wakeup event */ +#define EXTI_LINE20 ((uint32_t)0x100000) /*!< External interrupt line 20 Connected to the RTC Wakeup event */ +#define EXTI_LINE21 ((uint32_t)0x200000) /*!< External interrupt line 21 Connected to the TSC event */ + +#define IS_EXTI_LINE(LINE) ((((LINE) & (uint32_t)0xFFC00000) == 0x00) && ((LINE) != (uint16_t)0x00)) +#define IS_GET_EXTI_LINE(LINE) \ + (((LINE) == EXTI_LINE0) || ((LINE) == EXTI_LINE1) || ((LINE) == EXTI_LINE2) || ((LINE) == EXTI_LINE3) \ + || ((LINE) == EXTI_LINE4) || ((LINE) == EXTI_LINE5) || ((LINE) == EXTI_LINE6) || ((LINE) == EXTI_LINE7) \ + || ((LINE) == EXTI_LINE8) || ((LINE) == EXTI_LINE9) || ((LINE) == EXTI_LINE10) || ((LINE) == EXTI_LINE11) \ + || ((LINE) == EXTI_LINE12) || ((LINE) == EXTI_LINE13) || ((LINE) == EXTI_LINE14) || ((LINE) == EXTI_LINE15) \ + || ((LINE) == EXTI_LINE16) || ((LINE) == EXTI_LINE17) || ((LINE) == EXTI_LINE18) || ((LINE) == EXTI_LINE19) \ + || ((LINE) == EXTI_LINE20) || ((LINE) == EXTI_LINE21)) + +/** + * @} + */ + +/** @addtogroup EXTI_TSSEL_Line + * @{ + */ + + +#define IS_EXTI_TSSEL_LINE(LINE) \ + (((LINE) == EXTI_TSSEL_LINE0) || ((LINE) == EXTI_TSSEL_LINE1) || ((LINE) == EXTI_TSSEL_LINE2) \ + || ((LINE) == EXTI_TSSEL_LINE3) || ((LINE) == EXTI_TSSEL_LINE4) || ((LINE) == EXTI_TSSEL_LINE5) \ + || ((LINE) == EXTI_TSSEL_LINE6) || ((LINE) == EXTI_TSSEL_LINE7) || ((LINE) == EXTI_TSSEL_LINE8) \ + || ((LINE) == EXTI_TSSEL_LINE9) || ((LINE) == EXTI_TSSEL_LINE10) || ((LINE) == EXTI_TSSEL_LINE11) \ + || ((LINE) == EXTI_TSSEL_LINE12) || ((LINE) == EXTI_TSSEL_LINE13) || ((LINE) == EXTI_TSSEL_LINE14) \ + || ((LINE) == EXTI_TSSEL_LINE15)) +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup EXTI_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup EXTI_Exported_Functions + * @{ + */ + +void EXTI_DeInit(void); +void EXTI_InitPeripheral(EXTI_InitType* EXTI_InitStruct); +void EXTI_InitStruct(EXTI_InitType* EXTI_InitStruct); +void EXTI_TriggerSWInt(uint32_t EXTI_Line); +FlagStatus EXTI_GetStatusFlag(uint32_t EXTI_Line); +void EXTI_ClrStatusFlag(uint32_t EXTI_Line); +INTStatus EXTI_GetITStatus(uint32_t EXTI_Line); +void EXTI_ClrITPendBit(uint32_t EXTI_Line); +void EXTI_RTCTimeStampSel(uint32_t EXTI_TSSEL_Line); + +#ifdef __cplusplus +} +#endif + +#endif /* __N32G45X_EXTI_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/inc/n32g45x_flash.h b/inc/n32g45x_flash.h new file mode 100644 index 0000000..c2771fd --- /dev/null +++ b/inc/n32g45x_flash.h @@ -0,0 +1,375 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_flash.h + * @author Nations + * @version v1.0.2 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_FLASH_H__ +#define __N32G45X_FLASH_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup FLASH + * @{ + */ + +/** @addtogroup FLASH_Exported_Types + * @{ + */ + +/** + * @brief FLASH Status + */ + +typedef enum +{ + FLASH_BUSY = 1, + FLASH_RESERVED, + FLASH_ERR_PG, + FLASH_ERR_PV, + FLASH_ERR_WRP, + FLASH_COMPL, + FLASH_ERR_EV, + FLASH_ERR_RDP2, + FLASH_ERR_ADD, + FLASH_TIMEOUT +} FLASH_STS; + +typedef enum +{ + FLASH_SMP1 = 0, + FLASH_SMP2 +} FLASH_SMPSEL; + +/** + * @} + */ + +/** @addtogroup FLASH_Exported_Constants + * @{ + */ + +/** @addtogroup Flash_Latency + * @{ + */ + +#define FLASH_LATENCY_0 ((uint32_t)0x00000000) /*!< FLASH Zero Latency cycle */ +#define FLASH_LATENCY_1 ((uint32_t)0x00000001) /*!< FLASH One Latency cycle */ +#define FLASH_LATENCY_2 ((uint32_t)0x00000002) /*!< FLASH Two Latency cycles */ +#define FLASH_LATENCY_3 ((uint32_t)0x00000003) /*!< FLASH Three Latency cycles */ +#define FLASH_LATENCY_4 ((uint32_t)0x00000004) /*!< FLASH Four Latency cycles */ +#define IS_FLASH_LATENCY(LATENCY) \ + (((LATENCY) == FLASH_LATENCY_0) || ((LATENCY) == FLASH_LATENCY_1) || ((LATENCY) == FLASH_LATENCY_2) \ + || ((LATENCY) == FLASH_LATENCY_3) || ((LATENCY) == FLASH_LATENCY_4)) +/** + * @} + */ + +/** @addtogroup Prefetch_Buffer_Enable_Disable + * @{ + */ + +#define FLASH_PrefetchBuf_EN ((uint32_t)0x00000010) /*!< FLASH Prefetch Buffer Enable */ +#define FLASH_PrefetchBuf_DIS ((uint32_t)0x00000000) /*!< FLASH Prefetch Buffer Disable */ +#define IS_FLASH_PREFETCHBUF_STATE(STATE) (((STATE) == FLASH_PrefetchBuf_EN) || ((STATE) == FLASH_PrefetchBuf_DIS)) +/** + * @} + */ + +/** @addtogroup iCache_Enable_Disable + * @{ + */ + +#define FLASH_iCache_EN ((uint32_t)0x00000080) /*!< FLASH iCache Enable */ +#define FLASH_iCache_DIS ((uint32_t)0x00000000) /*!< FLASH iCache Disable */ +#define IS_FLASH_ICACHE_STATE(STATE) (((STATE) == FLASH_iCache_EN) || ((STATE) == FLASH_iCache_DIS)) +/** + * @} + */ + +/** @addtogroup SMPSEL_SMP1_SMP2 + * @{ + */ + +#define FLASH_SMPSEL_SMP1 ((uint32_t)0x00000000) /*!< FLASH SMPSEL SMP1 */ +#define FLASH_SMPSEL_SMP2 ((uint32_t)0x00000100) /*!< FLASH SMPSEL SMP2 */ +#define IS_FLASH_SMPSEL_STATE(STATE) (((STATE) == FLASH_SMPSEL_SMP1) || ((STATE) == FLASH_SMPSEL_SMP2)) +/** + * @} + */ + +/* Values to be used with N32G45X devices */ +#define FLASH_WRP_Pages0to1 \ + ((uint32_t)0x00000001) /*!< N32G45X devices: \ + Write protection of page 0 to 1 */ +#define FLASH_WRP_Pages2to3 \ + ((uint32_t)0x00000002) /*!< N32G45X devices: \ + Write protection of page 2 to 3 */ +#define FLASH_WRP_Pages4to5 \ + ((uint32_t)0x00000004) /*!< N32G45X devices: \ + Write protection of page 4 to 5 */ +#define FLASH_WRP_Pages6to7 \ + ((uint32_t)0x00000008) /*!< N32G45X devices: \ + Write protection of page 6 to 7 */ +#define FLASH_WRP_Pages8to9 \ + ((uint32_t)0x00000010) /*!< N32G45X devices: \ + Write protection of page 8 to 9 */ +#define FLASH_WRP_Pages10to11 \ + ((uint32_t)0x00000020) /*!< N32G45X devices: \ + Write protection of page 10 to 11 */ +#define FLASH_WRP_Pages12to13 \ + ((uint32_t)0x00000040) /*!< N32G45X devices: \ + Write protection of page 12 to 13 */ +#define FLASH_WRP_Pages14to15 \ + ((uint32_t)0x00000080) /*!< N32G45X devices: \ + Write protection of page 14 to 15 */ +#define FLASH_WRP_Pages16to17 \ + ((uint32_t)0x00000100) /*!< N32G45X devices: \ + Write protection of page 16 to 17 */ +#define FLASH_WRP_Pages18to19 \ + ((uint32_t)0x00000200) /*!< N32G45X devices: \ + Write protection of page 18 to 19 */ +#define FLASH_WRP_Pages20to21 \ + ((uint32_t)0x00000400) /*!< N32G45X devices: \ + Write protection of page 20 to 21 */ +#define FLASH_WRP_Pages22to23 \ + ((uint32_t)0x00000800) /*!< N32G45X devices: \ + Write protection of page 22 to 23 */ +#define FLASH_WRP_Pages24to25 \ + ((uint32_t)0x00001000) /*!< N32G45X devices: \ + Write protection of page 24 to 25 */ +#define FLASH_WRP_Pages26to27 \ + ((uint32_t)0x00002000) /*!< N32G45X devices: \ + Write protection of page 26 to 27 */ +#define FLASH_WRP_Pages28to29 \ + ((uint32_t)0x00004000) /*!< N32G45X devices: \ + Write protection of page 28 to 29 */ +#define FLASH_WRP_Pages30to31 \ + ((uint32_t)0x00008000) /*!< N32G45X devices: \ + Write protection of page 30 to 31 */ +#define FLASH_WRP_Pages32to33 \ + ((uint32_t)0x00010000) /*!< N32G45X devices: \ + Write protection of page 32 to 33 */ +#define FLASH_WRP_Pages34to35 \ + ((uint32_t)0x00020000) /*!< N32G45X devices: \ + Write protection of page 34 to 35 */ +#define FLASH_WRP_Pages36to37 \ + ((uint32_t)0x00040000) /*!< N32G45X devices: \ + Write protection of page 36 to 37 */ +#define FLASH_WRP_Pages38to39 \ + ((uint32_t)0x00080000) /*!< N32G45X devices: \ + Write protection of page 38 to 39 */ +#define FLASH_WRP_Pages40to41 \ + ((uint32_t)0x00100000) /*!< N32G45X devices: \ + Write protection of page 40 to 41 */ +#define FLASH_WRP_Pages42to43 \ + ((uint32_t)0x00200000) /*!< N32G45X devices: \ + Write protection of page 42 to 43 */ +#define FLASH_WRP_Pages44to45 \ + ((uint32_t)0x00400000) /*!< N32G45X devices: \ + Write protection of page 44 to 45 */ +#define FLASH_WRP_Pages46to47 \ + ((uint32_t)0x00800000) /*!< N32G45X devices: \ + Write protection of page 46 to 47 */ +#define FLASH_WRP_Pages48to49 \ + ((uint32_t)0x01000000) /*!< N32G45X devices: \ + Write protection of page 48 to 49 */ +#define FLASH_WRP_Pages50to51 \ + ((uint32_t)0x02000000) /*!< N32G45X devices: \ + Write protection of page 50 to 51 */ +#define FLASH_WRP_Pages52to53 \ + ((uint32_t)0x04000000) /*!< N32G45X devices: \ + Write protection of page 52 to 53 */ +#define FLASH_WRP_Pages54to55 \ + ((uint32_t)0x08000000) /*!< N32G45X devices: \ + Write protection of page 54 to 55 */ +#define FLASH_WRP_Pages56to57 \ + ((uint32_t)0x10000000) /*!< N32G45X devices: \ + Write protection of page 56 to 57 */ +#define FLASH_WRP_Pages58to59 \ + ((uint32_t)0x20000000) /*!< N32G45X devices: \ + Write protection of page 58 to 59 */ +#define FLASH_WRP_Pages60to61 \ + ((uint32_t)0x40000000) /*!< N32G45X devices: \ + Write protection of page 60 to 61 */ +#define FLASH_WRP_Pages62to127 \ + ((uint32_t)0x80000000) /*!< N32G45X - 256KB devices: Write protection of page 62 to 127 */ +#define FLASH_WRP_Pages62to255 \ + ((uint32_t)0x80000000) /*!< N32G45X - 512KB devices: Write protection of page 62 to 255 */ + +#define FLASH_WRP_AllPages ((uint32_t)0xFFFFFFFF) /*!< Write protection of all Pages */ + +#define IS_FLASH_WRP_PAGE(PAGE) (((PAGE) != 0x00000000)) + +#define IS_FLASH_ADDRESS(ADDRESS) (((ADDRESS) >= 0x08000000) && ((ADDRESS) < 0x0807FFFF)) + +#define IS_OB_DATA_ADDRESS(ADDRESS) ((ADDRESS) == 0x1FFFF804) + +/** + * @} + */ + +/** @addtogroup Option_Bytes_IWatchdog + * @{ + */ + +#define OB_IWDG_SW ((uint16_t)0x0001) /*!< Software IWDG selected */ +#define OB_IWDG_HW ((uint16_t)0x0000) /*!< Hardware IWDG selected */ +#define IS_OB_IWDG_SOURCE(SOURCE) (((SOURCE) == OB_IWDG_SW) || ((SOURCE) == OB_IWDG_HW)) + +/** + * @} + */ + +/** @addtogroup Option_Bytes_nRST_STOP + * @{ + */ + +#define OB_STOP0_NORST ((uint16_t)0x0002) /*!< No reset generated when entering in STOP */ +#define OB_STOP0_RST ((uint16_t)0x0000) /*!< Reset generated when entering in STOP */ +#define IS_OB_STOP0_SOURCE(SOURCE) (((SOURCE) == OB_STOP0_NORST) || ((SOURCE) == OB_STOP0_RST)) + +/** + * @} + */ + +/** @addtogroup Option_Bytes_nRST_STDBY + * @{ + */ + +#define OB_STDBY_NORST ((uint16_t)0x0004) /*!< No reset generated when entering in STANDBY */ +#define OB_STDBY_RST ((uint16_t)0x0000) /*!< Reset generated when entering in STANDBY */ +#define IS_OB_STDBY_SOURCE(SOURCE) (((SOURCE) == OB_STDBY_NORST) || ((SOURCE) == OB_STDBY_RST)) + +/** + * @} + */ +/** @addtogroup FLASH_Interrupts + * @{ + */ +#define FLASH_INT_ERRIE ((uint32_t)0x00000400) /*!< PGERR WRPERR ERROR error interrupt source */ +#define FLASH_INT_FERR ((uint32_t)0x00000800) /*!< EVERR PVERR interrupt source */ +#define FLASH_INT_EOP ((uint32_t)0x00001000) /*!< End of FLASH Operation Interrupt source */ + +#define IS_FLASH_INT(IT) ((((IT) & (uint32_t)0xFFFFE3FF) == 0x00000000) && (((IT) != 0x00000000))) + +/** + * @} + */ + +/** @addtogroup FLASH_Flags + * @{ + */ +#define FLASH_FLAG_BUSY ((uint32_t)0x00000001) /*!< FLASH Busy flag */ +#define FLASH_FLAG_PGERR ((uint32_t)0x00000004) /*!< FLASH Program error flag */ +#define FLASH_FLAG_PVERR ((uint32_t)0x00000008) /*!< FLASH Program Verify ERROR flag after program */ +#define FLASH_FLAG_WRPERR ((uint32_t)0x00000010) /*!< FLASH Write protected error flag */ +#define FLASH_FLAG_EOP ((uint32_t)0x00000020) /*!< FLASH End of Operation flag */ +#define FLASH_FLAG_EVERR ((uint32_t)0x00000040) /*!< FLASH Erase Verify ERROR flag after page erase */ +#define FLASH_FLAG_OBERR ((uint32_t)0x00000001) /*!< FLASH Option Byte error flag */ + +#define IS_FLASH_CLEAR_FLAG(FLAG) ((((FLAG) & 0xFFFFFF83) == 0x00) && (FLAG != 0x00)) + +#define IS_FLASH_GET_FLAG(FLAG) \ + (((FLAG) == FLASH_FLAG_BUSY) || ((FLAG) == FLASH_FLAG_PGERR) || ((FLAG) == FLASH_FLAG_PVERR) \ + || ((FLAG) == FLASH_FLAG_WRPERR) || ((FLAG) == FLASH_FLAG_EOP) || ((FLAG) == FLASH_FLAG_EVERR) \ + || ((FLAG) == FLASH_FLAG_OBERR)) + +/** + * @} + */ + +/** @addtogroup FLASH_STS_CLRFLAG + * @{ + */ +#define FLASH_STS_CLRFLAG (FLASH_FLAG_PGERR | FLASH_FLAG_PVERR | FLASH_FLAG_WRPERR | FLASH_FLAG_EOP |FLASH_FLAG_EVERR) + +/** + * @} + */ + +/** @addtogroup FLASH_Exported_Functions + * @{ + */ + +/*------------ Functions used for N32G45X devices -----*/ +void FLASH_SetLatency(uint32_t FLASH_Latency); +void FLASH_PrefetchBufSet(uint32_t FLASH_PrefetchBuf); +void FLASH_iCacheRST(void); +void FLASH_iCacheCmd(uint32_t FLASH_iCache); +void FLASH_Unlock(void); +void FLASH_Lock(void); +FLASH_STS FLASH_EraseOnePage(uint32_t Page_Address); +FLASH_STS FLASH_MassErase(void); +FLASH_STS FLASH_EraseOB(void); +FLASH_STS FLASH_ProgramWord(uint32_t Address, uint32_t Data); +FLASH_STS FLASH_ProgramOBData(uint32_t Address, uint32_t Data); +FLASH_STS FLASH_EnWriteProtection(uint32_t FLASH_Pages); +FLASH_STS FLASH_ReadOutProtectionL1(FunctionalState Cmd); +FLASH_STS FLASH_ReadOutProtectionL2_ENABLE(void); +FLASH_STS FLASH_ConfigUserOB(uint16_t OB_IWDG, uint16_t OB_STOP, uint16_t OB_STDBY); +uint32_t FLASH_GetUserOB(void); +uint32_t FLASH_GetWriteProtectionOB(void); +FlagStatus FLASH_GetReadOutProtectionSTS(void); +FlagStatus FLASH_GetReadOutProtectionL2STS(void); +FlagStatus FLASH_GetPrefetchBufSTS(void); +void FLASH_SetSMPSELStatus(uint32_t FLASH_smpsel); +FLASH_SMPSEL FLASH_GetSMPSELStatus(void); +void FLASH_INTConfig(uint32_t FLASH_INT, FunctionalState Cmd); +FlagStatus FLASH_GetFlagSTS(uint32_t FLASH_FLAG); +void FLASH_ClearFlag(uint32_t FLASH_FLAG); +FLASH_STS FLASH_GetSTS(void); +FLASH_STS FLASH_WaitForLastOpt(uint32_t Timeout); + +#ifdef __cplusplus +} +#endif + +#endif /* __N32G45X_FLASH_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/inc/n32g45x_gpio.h b/inc/n32g45x_gpio.h new file mode 100644 index 0000000..8b23d21 --- /dev/null +++ b/inc/n32g45x_gpio.h @@ -0,0 +1,463 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_gpio.h + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_GPIO_H__ +#define __N32G45X_GPIO_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup GPIO + * @{ + */ + +/** @addtogroup GPIO_Exported_Types + * @{ + */ + +#define IS_GPIO_ALL_PERIPH(PERIPH) \ + (((PERIPH) == GPIOA) || ((PERIPH) == GPIOB) || ((PERIPH) == GPIOC) || ((PERIPH) == GPIOD) || ((PERIPH) == GPIOE) \ + || ((PERIPH) == GPIOF) || ((PERIPH) == GPIOG)) + +/** + * @brief Output Maximum frequency selection + */ + +typedef enum +{ + GPIO_INPUT = 0, + GPIO_Speed_2MHz = 1, + GPIO_Speed_10MHz, + GPIO_Speed_50MHz +} GPIO_SpeedType; +#define IS_GPIO_SPEED(SPEED) \ + (((SPEED) == GPIO_INPUT) || ((SPEED) == GPIO_Speed_10MHz) || ((SPEED) == GPIO_Speed_2MHz) \ + || ((SPEED) == GPIO_Speed_50MHz)) + +/** + * @brief Configuration Mode enumeration + */ + +typedef enum +{ + GPIO_Mode_AIN = 0x0, + GPIO_Mode_IN_FLOATING = 0x04, + GPIO_Mode_IPD = 0x28, + GPIO_Mode_IPU = 0x48, + GPIO_Mode_Out_OD = 0x14, + GPIO_Mode_Out_PP = 0x10, + GPIO_Mode_AF_OD = 0x1C, + GPIO_Mode_AF_PP = 0x18 +} GPIO_ModeType; + +#define IS_GPIO_MODE(MODE) \ + (((MODE) == GPIO_Mode_AIN) || ((MODE) == GPIO_Mode_IN_FLOATING) || ((MODE) == GPIO_Mode_IPD) \ + || ((MODE) == GPIO_Mode_IPU) || ((MODE) == GPIO_Mode_Out_OD) || ((MODE) == GPIO_Mode_Out_PP) \ + || ((MODE) == GPIO_Mode_AF_OD) || ((MODE) == GPIO_Mode_AF_PP)) + +/** + * @brief GPIO Init structure definition + */ + +typedef struct +{ + uint16_t Pin; /*!< Specifies the GPIO pins to be configured. + This parameter can be any value of @ref GPIO_pins_define */ + + GPIO_SpeedType GPIO_Speed; /*!< Specifies the speed for the selected pins. + This parameter can be a value of @ref GPIO_SpeedType */ + + GPIO_ModeType GPIO_Mode; /*!< Specifies the operating mode for the selected pins. + This parameter can be a value of @ref GPIO_ModeType */ +} GPIO_InitType; + +/** + * @brief Bit_SET and Bit_RESET enumeration + */ + +typedef enum +{ + Bit_RESET = 0, + Bit_SET +} Bit_OperateType; + +#define IS_GPIO_BIT_OPERATE(OPERATE) (((OPERATE) == Bit_RESET) || ((OPERATE) == Bit_SET)) + +/** + * @} + */ + +/** @addtogroup GPIO_Exported_Constants + * @{ + */ + +/** @addtogroup GPIO_pins_define + * @{ + */ + +#define GPIO_PIN_0 ((uint16_t)0x0001) /*!< Pin 0 selected */ +#define GPIO_PIN_1 ((uint16_t)0x0002) /*!< Pin 1 selected */ +#define GPIO_PIN_2 ((uint16_t)0x0004) /*!< Pin 2 selected */ +#define GPIO_PIN_3 ((uint16_t)0x0008) /*!< Pin 3 selected */ +#define GPIO_PIN_4 ((uint16_t)0x0010) /*!< Pin 4 selected */ +#define GPIO_PIN_5 ((uint16_t)0x0020) /*!< Pin 5 selected */ +#define GPIO_PIN_6 ((uint16_t)0x0040) /*!< Pin 6 selected */ +#define GPIO_PIN_7 ((uint16_t)0x0080) /*!< Pin 7 selected */ +#define GPIO_PIN_8 ((uint16_t)0x0100) /*!< Pin 8 selected */ +#define GPIO_PIN_9 ((uint16_t)0x0200) /*!< Pin 9 selected */ +#define GPIO_PIN_10 ((uint16_t)0x0400) /*!< Pin 10 selected */ +#define GPIO_PIN_11 ((uint16_t)0x0800) /*!< Pin 11 selected */ +#define GPIO_PIN_12 ((uint16_t)0x1000) /*!< Pin 12 selected */ +#define GPIO_PIN_13 ((uint16_t)0x2000) /*!< Pin 13 selected */ +#define GPIO_PIN_14 ((uint16_t)0x4000) /*!< Pin 14 selected */ +#define GPIO_PIN_15 ((uint16_t)0x8000) /*!< Pin 15 selected */ +#define GPIO_PIN_ALL ((uint16_t)0xFFFF) /*!< All pins selected */ + +#define IS_GPIO_PIN(PIN) ((((PIN) & (uint16_t)0x00) == 0x00) && ((PIN) != (uint16_t)0x00)) + +#define IS_GET_GPIO_PIN(PIN) \ + (((PIN) == GPIO_PIN_0) || ((PIN) == GPIO_PIN_1) || ((PIN) == GPIO_PIN_2) || ((PIN) == GPIO_PIN_3) \ + || ((PIN) == GPIO_PIN_4) || ((PIN) == GPIO_PIN_5) || ((PIN) == GPIO_PIN_6) || ((PIN) == GPIO_PIN_7) \ + || ((PIN) == GPIO_PIN_8) || ((PIN) == GPIO_PIN_9) || ((PIN) == GPIO_PIN_10) || ((PIN) == GPIO_PIN_11) \ + || ((PIN) == GPIO_PIN_12) || ((PIN) == GPIO_PIN_13) || ((PIN) == GPIO_PIN_14) || ((PIN) == GPIO_PIN_15)) + +/** + * @} + */ + +/** @addtogroup GPIO_Remap_define + * @{ + */ + +#define GPIO_RMP_SPI1 ((uint32_t)0x00000001) /*!< SPI1 Alternate Function mapping */ +#define GPIO_RMP_I2C1 ((uint32_t)0x00000002) /*!< I2C1 Alternate Function mapping */ +#define GPIO_RMP_USART1 ((uint32_t)0x00000004) /*!< USART1 Alternate Function mapping */ +#define GPIO_RMP_USART2 ((uint32_t)0x00000008) /*!< USART2 Alternate Function mapping */ +#define GPIO_PART_RMP_USART3 ((uint32_t)0x00140010) /*!< USART3 Partial Alternate Function mapping */ +#define GPIO_ALL_RMP_USART3 ((uint32_t)0x00140030) /*!< USART3 Full Alternate Function mapping */ +#define GPIO_PART1_RMP_TIM1 ((uint32_t)0x00160040) /*!< TIM1 Partial Alternate Function mapping */ +#define GPIO_PART2_RMP_TIM1 ((uint32_t)0x00160080) /*!< TIM1 Partial Alternate Function mapping */ +#define GPIO_ALL_RMP_TIM1 ((uint32_t)0x001600C0) /*!< TIM1 Full Alternate Function mapping */ +#define GPIO_PartialRemap1_TIM2 ((uint32_t)0x00180100) /*!< TIM2 Partial1 Alternate Function mapping */ +#define GPIO_PART2_RMP_TIM2 ((uint32_t)0x00180200) /*!< TIM2 Partial2 Alternate Function mapping */ +#define GPIO_ALL_RMP_TIM2 ((uint32_t)0x00180300) /*!< TIM2 Full Alternate Function mapping */ +#define GPIO_PART1_RMP_TIM3 ((uint32_t)0x001A0800) /*!< TIM3 Partial Alternate Function mapping */ +#define GPIO_ALL_RMP_TIM3 ((uint32_t)0x001A0C00) /*!< TIM3 Full Alternate Function mapping */ +#define GPIO_RMP_TIM4 ((uint32_t)0x00001000) /*!< TIM4 Alternate Function mapping */ +#define GPIO_RMP1_CAN1 ((uint32_t)0x001D2000) /*!< CAN1 Alternate Function mapping */ +#define GPIO_RMP2_CAN1 ((uint32_t)0x001D4000) /*!< CAN1 Alternate Function mapping */ +#define GPIO_RMP3_CAN1 ((uint32_t)0x001D6000) /*!< CAN1 Alternate Function mapping */ +#define GPIO_RMP_PD01 ((uint32_t)0x00008000) /*!< PD01 Alternate Function mapping */ +#define GPIO_RMP_TIM5CH4 ((uint32_t)0x00200001) /*!< LSI connected to TIM5 Channel4 input capture for calibration */ +#define GPIO_RMP_ADC1_ETRI ((uint32_t)0x00200002) /*!< ADC1 External Trigger Injected Conversion remapping */ +#define GPIO_RMP_ADC1_ETRR ((uint32_t)0x00200004) /*!< ADC1 External Trigger Regular Conversion remapping */ +#define GPIO_RMP_ADC2_ETRI ((uint32_t)0x00200008) /*!< ADC2 External Trigger Injected Conversion remapping */ +#define GPIO_RMP_ADC2_ETRR ((uint32_t)0x00200010) /*!< ADC2 External Trigger Regular Conversion remapping */ +#define GPIO_RMP_MII_RMII_SEL ((uint32_t)0x00200080) /*!< MII_RMII_SEL remapping */ +#define GPIO_RMP_SW_JTAG_NO_NJTRST ((uint32_t)0x00300100) /*!< Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST */ +#define GPIO_RMP_SW_JTAG_SW_ENABLE ((uint32_t)0x00300200) /*!< JTAG-DP Disabled and SW-DP Enabled */ +#define GPIO_RMP_SW_JTAG_DISABLE ((uint32_t)0x00300400) /*!< Full SWJ Disabled (JTAG-DP + SW-DP) */ + +/* AFIO_RMP_CFG3 */ +#define GPIO_RMP_SDIO ((uint32_t)0x40000001) /*!< SDIO Alternate Function mapping */ +#define GPIO_RMP1_CAN2 ((uint32_t)0x40110002) /*!< CAN2 Alternate Function mapping */ +#define GPIO_RMP3_CAN2 ((uint32_t)0x40110006) /*!< CAN2 Alternate Function mapping */ +#define GPIO_RMP1_QSPI ((uint32_t)0x40140020) /*!< QSPI Alternate Function mapping */ +#define GPIO_RMP3_QSPI ((uint32_t)0x40140030) /*!< QSPI Alternate Function mapping */ +#define GPIO_RMP1_I2C2 ((uint32_t)0x40160040) /*!< I2C2 Alternate Function mapping */ +#define GPIO_RMP3_I2C2 ((uint32_t)0x401600C0) /*!< I2C2 Alternate Function mapping */ +#define GPIO_RMP2_I2C3 ((uint32_t)0x40180200) /*!< I2C3 Alternate Function mapping */ +#define GPIO_RMP3_I2C3 ((uint32_t)0x40180300) /*!< I2C3 Alternate Function mapping */ +#define GPIO_RMP1_I2C4 ((uint32_t)0x401A0400) /*!< I2C4 Alternate Function mapping */ +#define GPIO_RMP3_I2C4 ((uint32_t)0x401A0C00) /*!< I2C4 Alternate Function mapping */ +#define GPIO_RMP1_SPI2 ((uint32_t)0x401C1000) /*!< SPI2 Alternate Function mapping */ +#define GPIO_RMP2_SPI2 ((uint32_t)0x401C3000) /*!< SPI2 Alternate Function mapping */ +#define GPIO_RMP1_SPI3 ((uint32_t)0x401E4000) /*!< SPI3 Alternate Function mapping */ +#define GPIO_RMP2_SPI3 ((uint32_t)0x401E8000) /*!< SPI3 Alternate Function mapping */ +#define GPIO_RMP3_SPI3 ((uint32_t)0x401EC000) /*!< SPI3 Alternate Function mapping */ +#define GPIO_RMP1_ETH ((uint32_t)0x40300001) /*!< ETH Alternate Function mapping */ +#define GPIO_RMP2_ETH ((uint32_t)0x40300002) /*!< ETH Alternate Function mapping */ +#define GPIO_RMP3_ETH ((uint32_t)0x40300003) /*!< ETH Alternate Function mapping */ +#define GPIO_RMP1_SPI1 ((uint32_t)0x41200000) /*!< SPI1 Alternate Function mapping */ +#define GPIO_RMP2_SPI1 ((uint32_t)0x41200004) /*!< SPI1 Alternate Function mapping */ +#define GPIO_RMP3_SPI1 ((uint32_t)0x43200004) /*!< SPI1 Alternate Function mapping */ +#define GPIO_RMP1_USART2 ((uint32_t)0x44200000) /*!< USART2 Alternate Function mapping */ +#define GPIO_RMP2_USART2 ((uint32_t)0x44200008) /*!< USART2 Alternate Function mapping */ +#define GPIO_RMP3_USART2 ((uint32_t)0x46200008) /*!< USART2 Alternate Function mapping */ +#define GPIO_RMP1_UART4 ((uint32_t)0x40340010) /*!< UART4 Alternate Function mapping */ +#define GPIO_RMP2_UART4 ((uint32_t)0x40340020) /*!< UART4 Alternate Function mapping */ +#define GPIO_RMP3_UART4 ((uint32_t)0x40340030) /*!< UART4 Alternate Function mapping */ +#define GPIO_RMP1_UART5 ((uint32_t)0x40360040) /*!< UART5 Alternate Function mapping */ +#define GPIO_RMP2_UART5 ((uint32_t)0x40360080) /*!< UART5 Alternate Function mapping */ +#define GPIO_RMP3_UART5 ((uint32_t)0x403600C0) /*!< UART5 Alternate Function mapping */ +#define GPIO_RMP2_UART6 ((uint32_t)0x40380200) /*!< UART6 Alternate Function mapping */ +#define GPIO_RMP3_UART6 ((uint32_t)0x40380300) /*!< UART6 Alternate Function mapping */ +#define GPIO_RMP1_UART7 ((uint32_t)0x403A0400) /*!< UART7 Alternate Function mapping */ +#define GPIO_RMP3_UART7 ((uint32_t)0x403A0C00) /*!< UART7 Alternate Function mapping */ +#define GPIO_RMP1_TIM8 ((uint32_t)0x403E4000) /*!< TIM8 Alternate Function mapping */ +#define GPIO_RMP3_TIM8 ((uint32_t)0x403EC000) /*!< TIM8 Alternate Function mapping */ + +/* AFIO_RMP_CFG4 */ +#define GPIO_RMP1_COMP1 ((uint32_t)0x20100001) /*!< COMP1 Alternate Function mapping */ +#define GPIO_RMP2_COMP1 ((uint32_t)0x20100002) /*!< COMP1 Alternate Function mapping */ +#define GPIO_RMP3_COMP1 ((uint32_t)0x20100003) /*!< COMP1 Alternate Function mapping */ +#define GPIO_RMP1_COMP2 ((uint32_t)0x20120004) /*!< COMP2 Alternate Function mapping */ +#define GPIO_RMP2_COMP2 ((uint32_t)0x20120008) /*!< COMP2 Alternate Function mapping */ +#define GPIO_RMP3_COMP2 ((uint32_t)0x2012000C) /*!< COMP2 Alternate Function mapping */ +#define GPIO_RMP1_COMP3 ((uint32_t)0x20140010) /*!< COMP3 Alternate Function mapping */ +#define GPIO_RMP3_COMP3 ((uint32_t)0x20140030) /*!< COMP3 Alternate Function mapping */ +#define GPIO_RMP1_COMP4 ((uint32_t)0x20160040) /*!< COMP4 Alternate Function mapping */ +#define GPIO_RMP3_COMP4 ((uint32_t)0x201600C0) /*!< COMP4 Alternate Function mapping */ +#define GPIO_RMP1_COMP5 ((uint32_t)0x20180100) /*!< COMP5 Alternate Function mapping */ +#define GPIO_RMP2_COMP5 ((uint32_t)0x20180200) /*!< COMP5 Alternate Function mapping */ +#define GPIO_RMP3_COMP5 ((uint32_t)0x20180300) /*!< COMP5 Alternate Function mapping */ +#define GPIO_RMP1_COMP6 ((uint32_t)0x201A0400) /*!< COMP6 Alternate Function mapping */ +#define GPIO_RMP3_COMP6 ((uint32_t)0x201A0C00) /*!< COMP6 Alternate Function mapping */ +#define GPIO_RMP_COMP7 ((uint32_t)0x20001000) /*!< COMP7 Alternate Function mapping */ +#define GPIO_RMP_ADC3_ETRI ((uint32_t)0x20004000) /*!< ADC3_ETRGINJ Alternate Function mapping */ +#define GPIO_RMP_ADC3_ETRR ((uint32_t)0x20008000) /*!< ADC3_ETRGREG Alternate Function mapping */ +#define GPIO_RMP_ADC4_ETRI ((uint32_t)0x20200001) /*!< ADC4_ETRGINJ Alternate Function mapping */ +#define GPIO_RMP_ADC4_ETRR ((uint32_t)0x20200002) /*!< ADC4_ETRGREG Alternate Function mapping */ +#define GPIO_RMP_TSC_OUT_CTRL ((uint32_t)0x20200004) /*!< TSC_OUT_CTRL Alternate Function mapping */ +#define GPIO_RMP_QSPI_XIP_EN ((uint32_t)0x20200008) /*!< QSPI_XIP_EN Alternate Function mapping */ +#define GPIO_RMP1_DVP ((uint32_t)0x20340010) /*!< DVP Alternate Function mapping */ +#define GPIO_RMP3_DVP ((uint32_t)0x20340030) /*!< DVP Alternate Function mapping */ +#define GPIO_Remap_SPI1_NSS ((uint32_t)0x20200040) /*!< SPI1 NSS Alternate Function mapping */ +#define GPIO_Remap_SPI2_NSS ((uint32_t)0x20200080) /*!< SPI2 NSS Alternate Function mapping */ +#define GPIO_Remap_SPI3_NSS ((uint32_t)0x20200100) /*!< SPI3 NSS Alternate Function mapping */ +#define GPIO_Remap_QSPI_MISO ((uint32_t)0x20200200) /*!< QSPI MISO Alternate Function mapping */ + +/* AFIO_RMP_CFG5 */ +#define GPIO_Remap_DET_EN_EGB4 ((uint32_t)0x10200080) /*!< EGB4 Detect Alternate Function mapping*/ +#define GPIO_Remap_DET_EN_EGB3 ((uint32_t)0x10200040) /*!< EGB4 Detect Alternate Function mapping*/ +#define GPIO_Remap_DET_EN_EGB2 ((uint32_t)0x10200020) /*!< EGB4 Detect Alternate Function mapping*/ +#define GPIO_Remap_DET_EN_EGB1 ((uint32_t)0x10200010) /*!< EGB4 Detect Alternate Function mapping*/ +#define GPIO_Remap_DET_EN_EGBN4 ((uint32_t)0x10200008) /*!< EGBN4 Detect Alternate Function mapping*/ +#define GPIO_Remap_DET_EN_EGBN3 ((uint32_t)0x10200004) /*!< EGBN3 Detect Alternate Function mapping*/ +#define GPIO_Remap_DET_EN_EGBN2 ((uint32_t)0x10200002) /*!< EGBN2 Detect Alternate Function mapping*/ +#define GPIO_Remap_DET_EN_EGBN1 ((uint32_t)0x10200001) /*!< EGBN1 Detect Alternate Function mapping*/ +#define GPIO_Remap_DET_EN_ECLAMP4 ((uint32_t)0x10008000) /*!< ECLAMP4 Detect Alternate Function mapping*/ +#define GPIO_Remap_DET_EN_ECLAMP3 ((uint32_t)0x10004000) /*!< ECLAMP3 Detect Alternate Function mapping*/ +#define GPIO_Remap_DET_EN_ECLAMP2 ((uint32_t)0x10002000) /*!< ECLAMP2 Detect Alternate Function mapping*/ +#define GPIO_Remap_DET_EN_ECLAMP1 ((uint32_t)0x10001000) /*!< ECLAMP1 Detect Alternate Function mapping*/ +#define GPIO_Remap_RST_EN_EGB4 ((uint32_t)0x10000800) /*!< EGB4 Reset Alternate Function mapping*/ +#define GPIO_Remap_RST_EN_EGB3 ((uint32_t)0x10000400) /*!< EGB3 Reset Alternate Function mapping*/ +#define GPIO_Remap_RST_EN_EGB2 ((uint32_t)0x10000200) /*!< EGB2 Reset Alternate Function mapping*/ +#define GPIO_Remap_RST_EN_EGB1 ((uint32_t)0x10000100) /*!< EGB1 Reset Alternate Function mapping*/ +#define GPIO_Remap_RST_EN_EGBN4 ((uint32_t)0x10000080) /*!< EGBN4 Reset Alternate Function mapping*/ +#define GPIO_Remap_RST_EN_EGBN3 ((uint32_t)0x10000040) /*!< EGBN3 Reset Alternate Function mapping*/ +#define GPIO_Remap_RST_EN_EGBN2 ((uint32_t)0x10000020) /*!< EGBN2 Reset Alternate Function mapping*/ +#define GPIO_Remap_RST_EN_EGBN1 ((uint32_t)0x10000010) /*!< EGBN1 Reset Alternate Function mapping*/ +#define GPIO_Remap_RST_EN_ECLAMP4 ((uint32_t)0x10000008) /*!< ECLAMP4 Reset Alternate Function mapping*/ +#define GPIO_Remap_RST_EN_ECLAMP3 ((uint32_t)0x10000004) /*!< ECLAMP3 Reset Alternate Function mapping*/ +#define GPIO_Remap_RST_EN_ECLAMP2 ((uint32_t)0x10000002) /*!< ECLAMP2 Reset Alternate Function mapping*/ +#define GPIO_Remap_RST_EN_ECLAMP1 ((uint32_t)0x10000001) /*!< ECLAMP1 Reset Alternate Function mapping*/ + +#define IS_GPIO_REMAP(REMAP) \ + (((REMAP) == GPIO_RMP_SPI1) || ((REMAP) == GPIO_RMP_I2C1) || ((REMAP) == GPIO_RMP_USART1) \ + || ((REMAP) == GPIO_RMP_USART2) || ((REMAP) == GPIO_PART_RMP_USART3) || ((REMAP) == GPIO_ALL_RMP_USART3) \ + || ((REMAP) == GPIO_PART1_RMP_TIM1) || ((REMAP) == GPIO_ALL_RMP_TIM1) || ((REMAP) == GPIO_PartialRemap1_TIM2) \ + || ((REMAP) == GPIO_PART2_RMP_TIM2) || ((REMAP) == GPIO_ALL_RMP_TIM2) || ((REMAP) == GPIO_PART1_RMP_TIM3) \ + || ((REMAP) == GPIO_ALL_RMP_TIM3) || ((REMAP) == GPIO_RMP_TIM4) || ((REMAP) == GPIO_RMP1_CAN1) \ + || ((REMAP) == GPIO_RMP2_CAN1) || ((REMAP) == GPIO_RMP3_CAN1) || ((REMAP) == GPIO_RMP_PD01) || ((REMAP) == GPIO_RMP_TIM5CH4) \ + || ((REMAP) == GPIO_RMP_ADC1_ETRI) || ((REMAP) == GPIO_RMP_ADC1_ETRR) || ((REMAP) == GPIO_RMP_ADC2_ETRI) \ + || ((REMAP) == GPIO_RMP_ADC2_ETRR) || ((REMAP) == GPIO_RMP_SW_JTAG_NO_NJTRST) \ + || ((REMAP) == GPIO_RMP_SW_JTAG_SW_ENABLE) || ((REMAP) == GPIO_RMP_SW_JTAG_DISABLE) \ + || ((REMAP) == GPIO_RMP_SDIO) || ((REMAP) == GPIO_RMP1_CAN2) \ + || ((REMAP) == GPIO_RMP3_CAN2) || ((REMAP) == GPIO_RMP1_QSPI) || ((REMAP) == GPIO_RMP3_QSPI) \ + || ((REMAP) == GPIO_RMP1_I2C2) || ((REMAP) == GPIO_RMP3_I2C2) || ((REMAP) == GPIO_RMP2_I2C3) \ + || ((REMAP) == GPIO_RMP3_I2C3) || ((REMAP) == GPIO_RMP1_I2C4) || ((REMAP) == GPIO_RMP3_I2C4) \ + || ((REMAP) == GPIO_RMP1_SPI2) || ((REMAP) == GPIO_RMP2_SPI2) || ((REMAP) == GPIO_RMP1_SPI3) \ + || ((REMAP) == GPIO_RMP2_SPI3) || ((REMAP) == GPIO_RMP3_SPI3) || ((REMAP) == GPIO_RMP1_ETH) \ + || ((REMAP) == GPIO_RMP2_ETH) || ((REMAP) == GPIO_RMP3_ETH) || ((REMAP) == GPIO_RMP1_SPI1) \ + || ((REMAP) == GPIO_RMP2_SPI1) || ((REMAP) == GPIO_RMP3_SPI1) || ((REMAP) == GPIO_RMP1_USART2) \ + || ((REMAP) == GPIO_RMP2_USART2) || ((REMAP) == GPIO_RMP3_USART2) || ((REMAP) == GPIO_RMP1_UART4) \ + || ((REMAP) == GPIO_RMP2_UART4) || ((REMAP) == GPIO_RMP3_UART4) || ((REMAP) == GPIO_RMP1_UART5) \ + || ((REMAP) == GPIO_RMP2_UART5) || ((REMAP) == GPIO_RMP3_UART5) || ((REMAP) == GPIO_RMP2_UART6) \ + || ((REMAP) == GPIO_RMP3_UART6) || ((REMAP) == GPIO_RMP1_UART7) || ((REMAP) == GPIO_RMP3_UART7) \ + || ((REMAP) == GPIO_RMP1_TIM8) \ + || ((REMAP) == GPIO_RMP3_TIM8) || ((REMAP) == GPIO_RMP1_COMP1) || ((REMAP) == GPIO_RMP2_COMP1) \ + || ((REMAP) == GPIO_RMP3_COMP1) || ((REMAP) == GPIO_RMP1_COMP2) || ((REMAP) == GPIO_RMP2_COMP2) \ + || ((REMAP) == GPIO_RMP3_COMP2) || ((REMAP) == GPIO_RMP1_COMP3) || ((REMAP) == GPIO_RMP3_COMP3) \ + || ((REMAP) == GPIO_RMP1_COMP4) || ((REMAP) == GPIO_RMP3_COMP4) || ((REMAP) == GPIO_RMP1_COMP5) \ + || ((REMAP) == GPIO_RMP2_COMP5) || ((REMAP) == GPIO_RMP3_COMP5) || ((REMAP) == GPIO_RMP1_COMP6) \ + || ((REMAP) == GPIO_RMP3_COMP6) || ((REMAP) == GPIO_RMP_COMP7) || ((REMAP) == GPIO_RMP_ADC3_ETRI) \ + || ((REMAP) == GPIO_RMP_ADC3_ETRR) || ((REMAP) == GPIO_RMP_ADC4_ETRI) || ((REMAP) == GPIO_RMP_ADC4_ETRR) \ + || ((REMAP) == GPIO_RMP_TSC_OUT_CTRL) || ((REMAP) == GPIO_RMP_QSPI_XIP_EN) || ((REMAP) == GPIO_RMP1_DVP) \ + || ((REMAP) == GPIO_RMP3_DVP) || ((REMAP) == GPIO_Remap_SPI1_NSS) || ((REMAP) == GPIO_Remap_SPI2_NSS) \ + || ((REMAP) == GPIO_Remap_SPI3_NSS) || ((REMAP) == GPIO_Remap_QSPI_MISO) || ((REMAP) == GPIO_RMP_MII_RMII_SEL) \ + || ((REMAP) == GPIO_PART2_RMP_TIM1) || ((REMAP) == GPIO_Remap_DET_EN_EGB4) || ((REMAP) == GPIO_Remap_DET_EN_EGB3) \ + || ((REMAP) == GPIO_Remap_DET_EN_EGB2) || ((REMAP) == GPIO_Remap_DET_EN_EGB1) \ + || ((REMAP) == GPIO_Remap_DET_EN_EGBN4) || ((REMAP) == GPIO_Remap_DET_EN_EGBN3) \ + || ((REMAP) == GPIO_Remap_DET_EN_EGBN2) || ((REMAP) == GPIO_Remap_DET_EN_EGBN1) \ + || ((REMAP) == GPIO_Remap_DET_EN_ECLAMP4) || ((REMAP) == GPIO_Remap_DET_EN_ECLAMP3) \ + || ((REMAP) == GPIO_Remap_DET_EN_ECLAMP2) || ((REMAP) == GPIO_Remap_DET_EN_ECLAMP1) \ + || ((REMAP) == GPIO_Remap_RST_EN_EGB4) || ((REMAP) == GPIO_Remap_RST_EN_EGB3) \ + || ((REMAP) == GPIO_Remap_RST_EN_EGB2) || ((REMAP) == GPIO_Remap_RST_EN_EGB1) \ + || ((REMAP) == GPIO_Remap_RST_EN_EGBN4) || ((REMAP) == GPIO_Remap_RST_EN_EGBN3) \ + || ((REMAP) == GPIO_Remap_RST_EN_EGBN2) || ((REMAP) == GPIO_Remap_RST_EN_EGBN1) \ + || ((REMAP) == GPIO_Remap_RST_EN_ECLAMP4) || ((REMAP) == GPIO_Remap_RST_EN_ECLAMP3) \ + || ((REMAP) == GPIO_Remap_RST_EN_ECLAMP2) || ((REMAP) == GPIO_Remap_RST_EN_ECLAMP1)) + +/** + * @} + */ + +/** @addtogroup GPIO_Port_Sources + * @{ + */ + +#define GPIOA_PORT_SOURCE ((uint8_t)0x00) +#define GPIOB_PORT_SOURCE ((uint8_t)0x01) +#define GPIOC_PORT_SOURCE ((uint8_t)0x02) +#define GPIOD_PORT_SOURCE ((uint8_t)0x03) +#define GPIOE_PORT_SOURCE ((uint8_t)0x04) +#define GPIOF_PORT_SOURCE ((uint8_t)0x05) +#define GPIOG_PORT_SOURCE ((uint8_t)0x06) +#define IS_GPIO_EVENTOUT_PORT_SOURCE(PORTSOURCE) \ + (((PORTSOURCE) == GPIOA_PORT_SOURCE) || ((PORTSOURCE) == GPIOB_PORT_SOURCE) || ((PORTSOURCE) == GPIOC_PORT_SOURCE) \ + || ((PORTSOURCE) == GPIOD_PORT_SOURCE) || ((PORTSOURCE) == GPIOE_PORT_SOURCE)) + +#define IS_GPIO_EXTI_PORT_SOURCE(PORTSOURCE) \ + (((PORTSOURCE) == GPIOA_PORT_SOURCE) || ((PORTSOURCE) == GPIOB_PORT_SOURCE) || ((PORTSOURCE) == GPIOC_PORT_SOURCE) \ + || ((PORTSOURCE) == GPIOD_PORT_SOURCE) || ((PORTSOURCE) == GPIOE_PORT_SOURCE) \ + || ((PORTSOURCE) == GPIOF_PORT_SOURCE) || ((PORTSOURCE) == GPIOG_PORT_SOURCE)) + +/** + * @} + */ + +/** @addtogroup GPIO_Pin_sources + * @{ + */ + +#define GPIO_PIN_SOURCE0 ((uint8_t)0x00) +#define GPIO_PIN_SOURCE1 ((uint8_t)0x01) +#define GPIO_PIN_SOURCE2 ((uint8_t)0x02) +#define GPIO_PIN_SOURCE3 ((uint8_t)0x03) +#define GPIO_PIN_SOURCE4 ((uint8_t)0x04) +#define GPIO_PIN_SOURCE5 ((uint8_t)0x05) +#define GPIO_PIN_SOURCE6 ((uint8_t)0x06) +#define GPIO_PIN_SOURCE7 ((uint8_t)0x07) +#define GPIO_PIN_SOURCE8 ((uint8_t)0x08) +#define GPIO_PIN_SOURCE9 ((uint8_t)0x09) +#define GPIO_PIN_SOURCE10 ((uint8_t)0x0A) +#define GPIO_PIN_SOURCE11 ((uint8_t)0x0B) +#define GPIO_PIN_SOURCE12 ((uint8_t)0x0C) +#define GPIO_PIN_SOURCE13 ((uint8_t)0x0D) +#define GPIO_PIN_SOURCE14 ((uint8_t)0x0E) +#define GPIO_PIN_SOURCE15 ((uint8_t)0x0F) + +#define IS_GPIO_PIN_SOURCE(PINSOURCE) \ + (((PINSOURCE) == GPIO_PIN_SOURCE0) || ((PINSOURCE) == GPIO_PIN_SOURCE1) || ((PINSOURCE) == GPIO_PIN_SOURCE2) \ + || ((PINSOURCE) == GPIO_PIN_SOURCE3) || ((PINSOURCE) == GPIO_PIN_SOURCE4) || ((PINSOURCE) == GPIO_PIN_SOURCE5) \ + || ((PINSOURCE) == GPIO_PIN_SOURCE6) || ((PINSOURCE) == GPIO_PIN_SOURCE7) || ((PINSOURCE) == GPIO_PIN_SOURCE8) \ + || ((PINSOURCE) == GPIO_PIN_SOURCE9) || ((PINSOURCE) == GPIO_PIN_SOURCE10) || ((PINSOURCE) == GPIO_PIN_SOURCE11) \ + || ((PINSOURCE) == GPIO_PIN_SOURCE12) || ((PINSOURCE) == GPIO_PIN_SOURCE13) || ((PINSOURCE) == GPIO_PIN_SOURCE14) \ + || ((PINSOURCE) == GPIO_PIN_SOURCE15)) + +/** + * @} + */ + +/** @addtogroup Ethernet_Media_Interface + * @{ + */ +#define GPIO_ETH_MII_CFG ((uint32_t)0x00000000) +#define GPIO_ETH_RMII_CFG ((uint32_t)0x00800000) + +#define IS_GPIO_ETH_MEDIA_INTERFACE(INTERFACE) (((INTERFACE) == GPIO_ETH_MII_CFG) || ((INTERFACE) == GPIO_ETH_RMII_CFG)) + +/** + * @} + */ +/** + * @} + */ + +/** @addtogroup GPIO_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup GPIO_Exported_Functions + * @{ + */ + +void GPIO_DeInit(GPIO_Module* GPIOx); +void GPIO_AFIOInitDefault(void); +void GPIO_InitPeripheral(GPIO_Module* GPIOx, GPIO_InitType* GPIO_InitStruct); +void GPIO_InitStruct(GPIO_InitType* GPIO_InitStruct); +uint8_t GPIO_ReadInputDataBit(GPIO_Module* GPIOx, uint16_t Pin); +uint16_t GPIO_ReadInputData(GPIO_Module* GPIOx); +uint8_t GPIO_ReadOutputDataBit(GPIO_Module* GPIOx, uint16_t Pin); +uint16_t GPIO_ReadOutputData(GPIO_Module* GPIOx); +void GPIO_SetBits(GPIO_Module* GPIOx, uint16_t Pin); +void GPIO_ResetBits(GPIO_Module* GPIOx, uint16_t Pin); +void GPIO_WriteBit(GPIO_Module* GPIOx, uint16_t Pin, Bit_OperateType BitCmd); +void GPIO_Write(GPIO_Module* GPIOx, uint16_t PortVal); +void GPIO_ConfigPinLock(GPIO_Module* GPIOx, uint16_t Pin); +void GPIO_ConfigEventOutput(uint8_t PortSource, uint8_t PinSource); +void GPIO_CtrlEventOutput(FunctionalState Cmd); +void GPIO_ConfigPinRemap(uint32_t RmpPin, FunctionalState Cmd); +void GPIO_ConfigEXTILine(uint8_t PortSource, uint8_t PinSource); +void GPIO_ETH_ConfigMediaInterface(uint32_t ETH_ConfigSel); +void GPIO_SetBitsHigh16(GPIO_Module* GPIOx, uint32_t Pin); + +#ifdef __cplusplus +} +#endif + +#endif /* __N32G45X_GPIO_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/inc/n32g45x_i2c.h b/inc/n32g45x_i2c.h new file mode 100644 index 0000000..d92df0a --- /dev/null +++ b/inc/n32g45x_i2c.h @@ -0,0 +1,672 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_i2c.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_I2C_H__ +#define __N32G45X_I2C_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup I2C + * @{ + */ + +/** @addtogroup I2C_Exported_Types + * @{ + */ + +/** + * @brief I2C Init structure definition + */ + +typedef struct +{ + uint32_t ClkSpeed; /*!< Specifies the clock frequency. + This parameter must be set to a value lower than 400kHz */ + + uint16_t BusMode; /*!< Specifies the I2C mode. + This parameter can be a value of @ref I2C_BusMode */ + + uint16_t FmDutyCycle; /*!< Specifies the I2C fast mode duty cycle. + This parameter can be a value of @ref I2C_duty_cycle_in_fast_mode */ + + uint16_t OwnAddr1; /*!< Specifies the first device own address. + This parameter can be a 7-bit or 10-bit address. */ + + uint16_t AckEnable; /*!< Enables or disables the acknowledgement. + This parameter can be a value of @ref I2C_acknowledgement */ + + uint16_t AddrMode; /*!< Specifies if 7-bit or 10-bit address is acknowledged. + This parameter can be a value of @ref I2C_acknowledged_address */ +} I2C_InitType; + +/** + * @} + */ + +/** @addtogroup I2C_Exported_Constants + * @{ + */ + +#define IS_I2C_PERIPH(PERIPH) (((PERIPH) == I2C1) || ((PERIPH) == I2C2) || ((PERIPH) == I2C3) || ((PERIPH) == I2C4)) +/** @addtogroup I2C_BusMode + * @{ + */ + +#define I2C_BUSMODE_I2C ((uint16_t)0x0000) +#define I2C_BUSMODE_SMBDEVICE ((uint16_t)0x0002) +#define I2C_BUSMODE_SMBHOST ((uint16_t)0x000A) +#define IS_I2C_BUS_MODE(MODE) \ + (((MODE) == I2C_BUSMODE_I2C) || ((MODE) == I2C_BUSMODE_SMBDEVICE) || ((MODE) == I2C_BUSMODE_SMBHOST)) +/** + * @} + */ + +/** @addtogroup I2C_duty_cycle_in_fast_mode + * @{ + */ + +#define I2C_FMDUTYCYCLE_16_9 ((uint16_t)0x4000) /*!< I2C fast mode Tlow/Thigh = 16/9 */ +#define I2C_FMDUTYCYCLE_2 ((uint16_t)0xBFFF) /*!< I2C fast mode Tlow/Thigh = 2 */ +#define IS_I2C_FM_DUTY_CYCLE(CYCLE) (((CYCLE) == I2C_FMDUTYCYCLE_16_9) || ((CYCLE) == I2C_FMDUTYCYCLE_2)) +/** + * @} + */ + +/** @addtogroup I2C_acknowledgement + * @{ + */ + +#define I2C_ACKEN ((uint16_t)0x0400) +#define I2C_ACKDIS ((uint16_t)0x0000) +#define IS_I2C_ACK_STATE(STATE) (((STATE) == I2C_ACKEN) || ((STATE) == I2C_ACKDIS)) +/** + * @} + */ + +/** @addtogroup I2C_transfer_direction + * @{ + */ + +#define I2C_DIRECTION_SEND ((uint8_t)0x00) +#define I2C_DIRECTION_RECV ((uint8_t)0x01) +#define IS_I2C_DIRECTION(DIRECTION) (((DIRECTION) == I2C_DIRECTION_SEND) || ((DIRECTION) == I2C_DIRECTION_RECV)) +/** + * @} + */ + +/** @addtogroup I2C_acknowledged_address + * @{ + */ + +#define I2C_ADDR_MODE_7BIT ((uint16_t)0x4000) +#define I2C_ADDR_MODE_10BIT ((uint16_t)0xC000) +#define IS_I2C_ADDR_MODE(ADDRESS) (((ADDRESS) == I2C_ADDR_MODE_7BIT) || ((ADDRESS) == I2C_ADDR_MODE_10BIT)) +/** + * @} + */ + +/** @addtogroup I2C_registers + * @{ + */ + +#define I2C_REG_CTRL1 ((uint8_t)0x00) +#define I2C_REG_CTRL2 ((uint8_t)0x04) +#define I2C_REG_OADDR1 ((uint8_t)0x08) +#define I2C_REG_OADDR2 ((uint8_t)0x0C) +#define I2C_REG_DAT ((uint8_t)0x10) +#define I2C_REG_STS1 ((uint8_t)0x14) +#define I2C_REG_STS2 ((uint8_t)0x18) +#define I2C_REG_CLKCTRL ((uint8_t)0x1C) +#define I2C_REG_TMRISE ((uint8_t)0x20) +#define IS_I2C_REG(REGISTER) \ + (((REGISTER) == I2C_REG_CTRL1) || ((REGISTER) == I2C_REG_CTRL2) || ((REGISTER) == I2C_REG_OADDR1) \ + || ((REGISTER) == I2C_REG_OADDR2) || ((REGISTER) == I2C_REG_DAT) || ((REGISTER) == I2C_REG_STS1) \ + || ((REGISTER) == I2C_REG_STS2) || ((REGISTER) == I2C_REG_CLKCTRL) || ((REGISTER) == I2C_REG_TMRISE)) +/** + * @} + */ + +/** @addtogroup I2C_SMBus_alert_pin_level + * @{ + */ + +#define I2C_SMBALERT_LOW ((uint16_t)0x2000) +#define I2C_SMBALERT_HIGH ((uint16_t)0xDFFF) +#define IS_I2C_SMB_ALERT(ALERT) (((ALERT) == I2C_SMBALERT_LOW) || ((ALERT) == I2C_SMBALERT_HIGH)) +/** + * @} + */ + +/** @addtogroup I2C_PEC_position + * @{ + */ + +#define I2C_PEC_POS_NEXT ((uint16_t)0x0800) +#define I2C_PEC_POS_CURRENT ((uint16_t)0xF7FF) +#define IS_I2C_PEC_POS(POSITION) (((POSITION) == I2C_PEC_POS_NEXT) || ((POSITION) == I2C_PEC_POS_CURRENT)) +/** + * @} + */ + +/** @addtogroup I2C_NCAK_position + * @{ + */ + +#define I2C_NACK_POS_NEXT ((uint16_t)0x0800) +#define I2C_NACK_POS_CURRENT ((uint16_t)0xF7FF) +#define IS_I2C_NACK_POS(POSITION) (((POSITION) == I2C_NACK_POS_NEXT) || ((POSITION) == I2C_NACK_POS_CURRENT)) +/** + * @} + */ + +/** @addtogroup I2C_interrupts_definition + * @{ + */ + +#define I2C_INT_BUF ((uint16_t)0x0400) +#define I2C_INT_EVENT ((uint16_t)0x0200) +#define I2C_INT_ERR ((uint16_t)0x0100) +#define IS_I2C_CFG_INT(IT) ((((IT) & (uint16_t)0xF8FF) == 0x00) && ((IT) != 0x00)) +/** + * @} + */ + +/** @addtogroup I2C_interrupts_definition + * @{ + */ + +#define I2C_INT_SMBALERT ((uint32_t)0x01008000) +#define I2C_INT_TIMOUT ((uint32_t)0x01004000) +#define I2C_INT_PECERR ((uint32_t)0x01001000) +#define I2C_INT_OVERRUN ((uint32_t)0x01000800) +#define I2C_INT_ACKFAIL ((uint32_t)0x01000400) +#define I2C_INT_ARLOST ((uint32_t)0x01000200) +#define I2C_INT_BUSERR ((uint32_t)0x01000100) +#define I2C_INT_TXDATE ((uint32_t)0x06000080) +#define I2C_INT_RXDATNE ((uint32_t)0x06000040) +#define I2C_INT_STOPF ((uint32_t)0x02000010) +#define I2C_INT_ADDR10F ((uint32_t)0x02000008) +#define I2C_INT_BYTEF ((uint32_t)0x02000004) +#define I2C_INT_ADDRF ((uint32_t)0x02000002) +#define I2C_INT_STARTBF ((uint32_t)0x02000001) + +#define IS_I2C_CLR_INT(IT) ((((IT) & (uint16_t)0x20FF) == 0x00) && ((IT) != (uint16_t)0x00)) + +#define IS_I2C_GET_INT(IT) \ + (((IT) == I2C_INT_SMBALERT) || ((IT) == I2C_INT_TIMOUT) || ((IT) == I2C_INT_PECERR) || ((IT) == I2C_INT_OVERRUN) \ + || ((IT) == I2C_INT_ACKFAIL) || ((IT) == I2C_INT_ARLOST) || ((IT) == I2C_INT_BUSERR) || ((IT) == I2C_INT_TXDATE) \ + || ((IT) == I2C_INT_RXDATNE) || ((IT) == I2C_INT_STOPF) || ((IT) == I2C_INT_ADDR10F) || ((IT) == I2C_INT_BYTEF) \ + || ((IT) == I2C_INT_ADDRF) || ((IT) == I2C_INT_STARTBF)) +/** + * @} + */ + +/** @addtogroup I2C_flags_definition + * @{ + */ + +/** + * @brief STS2 register flags + */ + +#define I2C_FLAG_DUALFLAG ((uint32_t)0x00800000) +#define I2C_FLAG_SMBHADDR ((uint32_t)0x00400000) +#define I2C_FLAG_SMBDADDR ((uint32_t)0x00200000) +#define I2C_FLAG_GCALLADDR ((uint32_t)0x00100000) +#define I2C_FLAG_TRF ((uint32_t)0x00040000) +#define I2C_FLAG_BUSY ((uint32_t)0x00020000) +#define I2C_FLAG_MSMODE ((uint32_t)0x00010000) + +/** + * @brief STS1 register flags + */ + +#define I2C_FLAG_SMBALERT ((uint32_t)0x10008000) +#define I2C_FLAG_TIMOUT ((uint32_t)0x10004000) +#define I2C_FLAG_PECERR ((uint32_t)0x10001000) +#define I2C_FLAG_OVERRUN ((uint32_t)0x10000800) +#define I2C_FLAG_ACKFAIL ((uint32_t)0x10000400) +#define I2C_FLAG_ARLOST ((uint32_t)0x10000200) +#define I2C_FLAG_BUSERR ((uint32_t)0x10000100) +#define I2C_FLAG_TXDATE ((uint32_t)0x10000080) +#define I2C_FLAG_RXDATNE ((uint32_t)0x10000040) +#define I2C_FLAG_STOPF ((uint32_t)0x10000010) +#define I2C_FLAG_ADDR10F ((uint32_t)0x10000008) +#define I2C_FLAG_BYTEF ((uint32_t)0x10000004) +#define I2C_FLAG_ADDRF ((uint32_t)0x10000002) +#define I2C_FLAG_STARTBF ((uint32_t)0x10000001) + +#define IS_I2C_CLR_FLAG(FLAG) ((((FLAG) & (uint16_t)0x20FF) == 0x00) && ((FLAG) != (uint16_t)0x00)) + +#define IS_I2C_GET_FLAG(FLAG) \ + (((FLAG) == I2C_FLAG_DUALFLAG) || ((FLAG) == I2C_FLAG_SMBHADDR) || ((FLAG) == I2C_FLAG_SMBDADDR) \ + || ((FLAG) == I2C_FLAG_GCALLADDR) || ((FLAG) == I2C_FLAG_TRF) || ((FLAG) == I2C_FLAG_BUSY) \ + || ((FLAG) == I2C_FLAG_MSMODE) || ((FLAG) == I2C_FLAG_SMBALERT) || ((FLAG) == I2C_FLAG_TIMOUT) \ + || ((FLAG) == I2C_FLAG_PECERR) || ((FLAG) == I2C_FLAG_OVERRUN) || ((FLAG) == I2C_FLAG_ACKFAIL) \ + || ((FLAG) == I2C_FLAG_ARLOST) || ((FLAG) == I2C_FLAG_BUSERR) || ((FLAG) == I2C_FLAG_TXDATE) \ + || ((FLAG) == I2C_FLAG_RXDATNE) || ((FLAG) == I2C_FLAG_STOPF) || ((FLAG) == I2C_FLAG_ADDR10F) \ + || ((FLAG) == I2C_FLAG_BYTEF) || ((FLAG) == I2C_FLAG_ADDRF) || ((FLAG) == I2C_FLAG_STARTBF)) +/** + * @} + */ + +/** @addtogroup I2C_Events + * @{ + */ + +/*======================================== + + I2C Master Events (Events grouped in order of communication) + ==========================================*/ +/** + * @brief Communication start + * + * After sending the START condition (I2C_GenerateStart() function) the master + * has to wait for this event. It means that the Start condition has been correctly + * released on the I2C bus (the bus is free, no other devices is communicating). + * + */ +/* Master mode */ +#define I2C_ROLE_MASTER ((uint32_t)0x00010000) /* MSMODE */ +/* --EV5 */ +#define I2C_EVT_MASTER_MODE_FLAG ((uint32_t)0x00030001) /* BUSY, MSMODE and STARTBF flag */ + +/** + * @brief Address Acknowledge + * + * After checking on EV5 (start condition correctly released on the bus), the + * master sends the address of the slave(s) with which it will communicate + * (I2C_SendAddr7bit() function, it also determines the direction of the communication: + * Master transmitter or Receiver). Then the master has to wait that a slave acknowledges + * his address. If an acknowledge is sent on the bus, one of the following events will + * be set: + * + * 1) In case of Master Receiver (7-bit addressing): the I2C_EVT_MASTER_RXMODE_FLAG + * event is set. + * + * 2) In case of Master Transmitter (7-bit addressing): the I2C_EVT_MASTER_TXMODE_FLAG + * is set + * + * 3) In case of 10-Bit addressing mode, the master (just after generating the START + * and checking on EV5) has to send the header of 10-bit addressing mode (I2C_SendData() + * function). Then master should wait on EV9. It means that the 10-bit addressing + * header has been correctly sent on the bus. Then master should send the second part of + * the 10-bit address (LSB) using the function I2C_SendAddr7bit(). Then master + * should wait for event EV6. + * + */ + +/* --EV6 */ +#define I2C_EVT_MASTER_TXMODE_FLAG ((uint32_t)0x00070082) /* BUSY, MSMODE, ADDRF, TXDATE and TRF flags */ +#define I2C_EVT_MASTER_RXMODE_FLAG ((uint32_t)0x00030002) /* BUSY, MSMODE and ADDRF flags */ +/* --EV9 */ +#define I2C_EVT_MASTER_MODE_ADDRESS10_FLAG ((uint32_t)0x00030008) /* BUSY, MSMODE and ADD10RF flags */ + +/** + * @brief Communication events + * + * If a communication is established (START condition generated and slave address + * acknowledged) then the master has to check on one of the following events for + * communication procedures: + * + * 1) Master Receiver mode: The master has to wait on the event EV7 then to read + * the data received from the slave (I2C_RecvData() function). + * + * 2) Master Transmitter mode: The master has to send data (I2C_SendData() + * function) then to wait on event EV8 or EV8_2. + * These two events are similar: + * - EV8 means that the data has been written in the data register and is + * being shifted out. + * - EV8_2 means that the data has been physically shifted out and output + * on the bus. + * In most cases, using EV8 is sufficient for the application. + * Using EV8_2 leads to a slower communication but ensure more reliable test. + * EV8_2 is also more suitable than EV8 for testing on the last data transmission + * (before Stop condition generation). + * + * @note In case the user software does not guarantee that this event EV7 is + * managed before the current byte end of transfer, then user may check on EV7 + * and BSF flag at the same time (ie. (I2C_EVT_MASTER_DATA_RECVD_FLAG | I2C_FLAG_BYTEF)). + * In this case the communication may be slower. + * + */ + +/* Master RECEIVER mode -----------------------------*/ +/* --EV7 */ +#define I2C_EVT_MASTER_DATA_RECVD_FLAG ((uint32_t)0x00030040) /* BUSY, MSMODE and RXDATNE flags */ +/* EV7x shifter register full */ +#define I2C_EVT_MASTER_SFT_DATA_RECVD_FLAG ((uint32_t)0x00030044) /* BUSY, MSMODE, BSF and RXDATNE flags */ + +/* Master TRANSMITTER mode --------------------------*/ +/* --EV8 */ +#define I2C_EVT_MASTER_DATA_SENDING ((uint32_t)0x00070080) /* TRF, BUSY, MSMODE, TXDATE flags */ +/* --EV8_2 */ +#define I2C_EVT_MASTER_DATA_SENDED ((uint32_t)0x00070084) /* TRF, BUSY, MSMODE, TXDATE and BSF flags */ + +/*======================================== + + I2C Slave Events (Events grouped in order of communication) + ==========================================*/ + +/** + * @brief Communication start events + * + * Wait on one of these events at the start of the communication. It means that + * the I2C peripheral detected a Start condition on the bus (generated by master + * device) followed by the peripheral address. The peripheral generates an ACK + * condition on the bus (if the acknowledge feature is enabled through function + * I2C_ConfigAck()) and the events listed above are set : + * + * 1) In normal case (only one address managed by the slave), when the address + * sent by the master matches the own address of the peripheral (configured by + * OwnAddr1 field) the I2C_EVENT_SLAVE_XXX_ADDRESS_MATCHED event is set + * (where XXX could be TRANSMITTER or RECEIVER). + * + * 2) In case the address sent by the master matches the second address of the + * peripheral (configured by the function I2C_ConfigOwnAddr2() and enabled + * by the function I2C_EnableDualAddr()) the events I2C_EVENT_SLAVE_XXX_SECONDADDRESS_MATCHED + * (where XXX could be TRANSMITTER or RECEIVER) are set. + * + * 3) In case the address sent by the master is General Call (address 0x00) and + * if the General Call is enabled for the peripheral (using function I2C_EnableGeneralCall()) + * the following event is set I2C_EVT_SLAVE_GCALLADDR_MATCHED. + * + */ + +/* --EV1 (all the events below are variants of EV1) */ +/* 1) Case of One Single Address managed by the slave */ +#define I2C_EVT_SLAVE_RECV_ADDR_MATCHED ((uint32_t)0x00020002) /* BUSY and ADDRF flags */ +#define I2C_EVT_SLAVE_SEND_ADDR_MATCHED ((uint32_t)0x00060082) /* TRF, BUSY, TXDATE and ADDRF flags */ + +/* 2) Case of Dual address managed by the slave */ +#define I2C_EVT_SLAVE_RECV_ADDR2_MATCHED ((uint32_t)0x00820000) /* DUALF and BUSY flags */ +#define I2C_EVT_SLAVE_SEND_ADDR2_MATCHED ((uint32_t)0x00860080) /* DUALF, TRF, BUSY and TXDATE flags */ + +/* 3) Case of General Call enabled for the slave */ +#define I2C_EVT_SLAVE_GCALLADDR_MATCHED ((uint32_t)0x00120000) /* GENCALL and BUSY flags */ + +/** + * @brief Communication events + * + * Wait on one of these events when EV1 has already been checked and: + * + * - Slave RECEIVER mode: + * - EV2: When the application is expecting a data byte to be received. + * - EV4: When the application is expecting the end of the communication: master + * sends a stop condition and data transmission is stopped. + * + * - Slave Transmitter mode: + * - EV3: When a byte has been transmitted by the slave and the application is expecting + * the end of the byte transmission. The two events I2C_EVT_SLAVE_DATA_SENDED and + * I2C_EVT_SLAVE_DATA_SENDING are similar. The second one can optionally be + * used when the user software doesn't guarantee the EV3 is managed before the + * current byte end of transfer. + * - EV3_2: When the master sends a NACK in order to tell slave that data transmission + * shall end (before sending the STOP condition). In this case slave has to stop sending + * data bytes and expect a Stop condition on the bus. + * + * @note In case the user software does not guarantee that the event EV2 is + * managed before the current byte end of transfer, then user may check on EV2 + * and BSF flag at the same time (ie. (I2C_EVT_SLAVE_DATA_RECVD | I2C_FLAG_BYTEF)). + * In this case the communication may be slower. + * + */ + +/* Slave RECEIVER mode --------------------------*/ +/* --EV2 */ +#define I2C_EVT_SLAVE_DATA_RECVD ((uint32_t)0x00020040) /* BUSY and RXDATNE flags */ +/* --EV2x */ +#define I2C_EVT_SLAVE_DATA_RECVD_NOBUSY ((uint32_t)0x00000040) /* no BUSY and RXDATNE flags */ +/* --EV4 */ +#define I2C_EVT_SLAVE_STOP_RECVD ((uint32_t)0x00000010) /* STOPF flag */ + +/* Slave TRANSMITTER mode -----------------------*/ +/* --EV3 */ +#define I2C_EVT_SLAVE_DATA_SENDED ((uint32_t)0x00060084) /* TRF, BUSY, TXDATE and BSF flags */ +#define I2C_EVT_SLAVE_DATA_SENDING ((uint32_t)0x00060080) /* TRF, BUSY and TXDATE flags */ +/* --EV3_2 */ +#define I2C_EVT_SLAVE_ACK_MISS ((uint32_t)0x00000400) /* AF flag */ + +/*=========================== End of Events Description ==========================================*/ + +#define IS_I2C_EVT(EVENT) \ + (((EVENT) == I2C_EVT_SLAVE_SEND_ADDR_MATCHED) || ((EVENT) == I2C_EVT_SLAVE_RECV_ADDR_MATCHED) \ + || ((EVENT) == I2C_EVT_SLAVE_SEND_ADDR2_MATCHED) || ((EVENT) == I2C_EVT_SLAVE_RECV_ADDR2_MATCHED) \ + || ((EVENT) == I2C_EVT_SLAVE_GCALLADDR_MATCHED) || ((EVENT) == I2C_EVT_SLAVE_DATA_RECVD) \ + || ((EVENT) == (I2C_EVT_SLAVE_DATA_RECVD | I2C_FLAG_DUALFLAG)) \ + || ((EVENT) == (I2C_EVT_SLAVE_DATA_RECVD | I2C_FLAG_GCALLADDR)) || ((EVENT) == I2C_EVT_SLAVE_DATA_SENDED) \ + || ((EVENT) == (I2C_EVT_SLAVE_DATA_SENDED | I2C_FLAG_DUALFLAG)) \ + || ((EVENT) == (I2C_EVT_SLAVE_DATA_SENDED | I2C_FLAG_GCALLADDR)) || ((EVENT) == I2C_EVT_SLAVE_STOP_RECVD) \ + || ((EVENT) == I2C_EVT_MASTER_MODE_FLAG) || ((EVENT) == I2C_EVT_MASTER_TXMODE_FLAG) \ + || ((EVENT) == I2C_EVT_MASTER_RXMODE_FLAG) || ((EVENT) == I2C_EVT_MASTER_DATA_RECVD_FLAG) \ + || ((EVENT) == I2C_EVT_MASTER_DATA_SENDED) || ((EVENT) == I2C_EVT_MASTER_DATA_SENDING) \ + || ((EVENT) == I2C_EVT_MASTER_MODE_ADDRESS10_FLAG) || ((EVENT) == I2C_EVT_SLAVE_ACK_MISS) \ + || ((EVENT) == I2C_EVT_MASTER_SFT_DATA_RECVD_FLAG) || ((EVENT) == I2C_EVT_SLAVE_DATA_RECVD_NOBUSY)) +/** + * @} + */ + +/** @addtogroup I2C_own_address1 + * @{ + */ + +#define IS_I2C_OWN_ADDR1(ADDRESS1) ((ADDRESS1) <= 0x3FF) +/** + * @} + */ + +/** @addtogroup I2C_clock_speed + * @{ + */ + +//#define IS_I2C_CLK_SPEED(SPEED) (((SPEED) >= 0x1) && ((SPEED) <= 400000)) +#define IS_I2C_CLK_SPEED(SPEED) (((SPEED) >= 0x1) && ((SPEED) <= 1000000)) + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup I2C_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup I2C_Exported_Functions + * @{ + */ + +void I2C_DeInit(I2C_Module* I2Cx); +void I2C_Init(I2C_Module* I2Cx, I2C_InitType* I2C_InitStruct); +void I2C_InitStruct(I2C_InitType* I2C_InitStruct); +void I2C_Enable(I2C_Module* I2Cx, FunctionalState Cmd); +void I2C_EnableDMA(I2C_Module* I2Cx, FunctionalState Cmd); +void I2C_EnableDmaLastSend(I2C_Module* I2Cx, FunctionalState Cmd); +void I2C_GenerateStart(I2C_Module* I2Cx, FunctionalState Cmd); +void I2C_GenerateStop(I2C_Module* I2Cx, FunctionalState Cmd); +void I2C_ConfigAck(I2C_Module* I2Cx, FunctionalState Cmd); +void I2C_ConfigOwnAddr2(I2C_Module* I2Cx, uint8_t Address); +void I2C_EnableDualAddr(I2C_Module* I2Cx, FunctionalState Cmd); +void I2C_EnableGeneralCall(I2C_Module* I2Cx, FunctionalState Cmd); +void I2C_ConfigInt(I2C_Module* I2Cx, uint16_t I2C_IT, FunctionalState Cmd); +void I2C_SendData(I2C_Module* I2Cx, uint8_t Data); +uint8_t I2C_RecvData(I2C_Module* I2Cx); +void I2C_SendAddr7bit(I2C_Module* I2Cx, uint8_t Address, uint8_t I2C_Direction); +uint16_t I2C_GetRegister(I2C_Module* I2Cx, uint8_t I2C_Register); +void I2C_EnableSoftwareReset(I2C_Module* I2Cx, FunctionalState Cmd); +void I2C_ConfigNackLocation(I2C_Module* I2Cx, uint16_t I2C_NACKPosition); +void I2C_ConfigSmbusAlert(I2C_Module* I2Cx, uint16_t I2C_SMBusAlert); +void I2C_SendPEC(I2C_Module* I2Cx, FunctionalState Cmd); +void I2C_ConfigPecLocation(I2C_Module* I2Cx, uint16_t I2C_PECPosition); +void I2C_ComputePec(I2C_Module* I2Cx, FunctionalState Cmd); +uint8_t I2C_GetPec(I2C_Module* I2Cx); +void I2C_EnableArp(I2C_Module* I2Cx, FunctionalState Cmd); +void I2C_EnableExtendClk(I2C_Module* I2Cx, FunctionalState Cmd); +void I2C_ConfigFastModeDutyCycle(I2C_Module* I2Cx, uint16_t FmDutyCycle); + +/** + * @brief + **************************************************************************************** + * + * I2C State Monitoring Functions + * + **************************************************************************************** + * This I2C driver provides three different ways for I2C state monitoring + * depending on the application requirements and constraints: + * + * + * 1) Basic state monitoring: + * Using I2C_CheckEvent() function: + * It compares the status registers (STS1 and STS2) content to a given event + * (can be the combination of one or more flags). + * It returns SUCCESS if the current status includes the given flags + * and returns ERROR if one or more flags are missing in the current status. + * - When to use: + * - This function is suitable for most applications as well as for startup + * activity since the events are fully described in the product reference manual + * (RM0008). + * - It is also suitable for users who need to define their own events. + * - Limitations: + * - If an error occurs (ie. error flags are set besides to the monitored flags), + * the I2C_CheckEvent() function may return SUCCESS despite the communication + * hold or corrupted real state. + * In this case, it is advised to use error interrupts to monitor the error + * events and handle them in the interrupt IRQ handler. + * + * @note + * For error management, it is advised to use the following functions: + * - I2C_ConfigInt() to configure and enable the error interrupts (I2C_INT_ERR). + * - I2Cx_ER_IRQHandler() which is called when the error interrupt occurs. + * Where x is the peripheral instance (I2C1, I2C2 ...) + * - I2C_GetFlag() or I2C_GetIntStatus() to be called into I2Cx_ER_IRQHandler() + * in order to determine which error occurred. + * - I2C_ClrFlag() or I2C_ClrIntPendingBit() and/or I2C_EnableSoftwareReset() + * and/or I2C_GenerateStop() in order to clear the error flag and source, + * and return to correct communication status. + * + * + * 2) Advanced state monitoring: + * Using the function I2C_GetLastEvent() which returns the image of both status + * registers in a single word (uint32_t) (Status Register 2 value is shifted left + * by 16 bits and concatenated to Status Register 1). + * - When to use: + * - This function is suitable for the same applications above but it allows to + * overcome the limitations of I2C_GetFlag() function (see below). + * The returned value could be compared to events already defined in the + * library (n32g45x_i2c.h) or to custom values defined by user. + * - This function is suitable when multiple flags are monitored at the same time. + * - At the opposite of I2C_CheckEvent() function, this function allows user to + * choose when an event is accepted (when all events flags are set and no + * other flags are set or just when the needed flags are set like + * I2C_CheckEvent() function). + * - Limitations: + * - User may need to define his own events. + * - Same remark concerning the error management is applicable for this + * function if user decides to check only regular communication flags (and + * ignores error flags). + * + * + * 3) Flag-based state monitoring: + * Using the function I2C_GetFlag() which simply returns the status of + * one single flag (ie. I2C_FLAG_RXDATNE ...). + * - When to use: + * - This function could be used for specific applications or in debug phase. + * - It is suitable when only one flag checking is needed (most I2C events + * are monitored through multiple flags). + * - Limitations: + * - When calling this function, the Status register is accessed. Some flags are + * cleared when the status register is accessed. So checking the status + * of one Flag, may clear other ones. + * - Function may need to be called twice or more in order to monitor one + * single event. + * + */ + +/** + * + * 1) Basic state monitoring + ******************************************************************************* + */ +ErrorStatus I2C_CheckEvent(I2C_Module* I2Cx, uint32_t I2C_EVENT); +/** + * + * 2) Advanced state monitoring + ******************************************************************************* + */ +uint32_t I2C_GetLastEvent(I2C_Module* I2Cx); +/** + * + * 3) Flag-based state monitoring + ******************************************************************************* + */ +FlagStatus I2C_GetFlag(I2C_Module* I2Cx, uint32_t I2C_FLAG); +/** + * + ******************************************************************************* + */ + +void I2C_ClrFlag(I2C_Module* I2Cx, uint32_t I2C_FLAG); +INTStatus I2C_GetIntStatus(I2C_Module* I2Cx, uint32_t I2C_IT); +void I2C_ClrIntPendingBit(I2C_Module* I2Cx, uint32_t I2C_IT); + +#ifdef __cplusplus +} +#endif + +#endif /*__N32G45X_I2C_H */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/inc/n32g45x_iwdg.h b/inc/n32g45x_iwdg.h new file mode 100644 index 0000000..9ace2b5 --- /dev/null +++ b/inc/n32g45x_iwdg.h @@ -0,0 +1,145 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_iwdg.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_IWDG_H__ +#define __N32G45X_IWDG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup IWDG + * @{ + */ + +/** @addtogroup IWDG_Exported_Types + * @{ + */ + +/** + * @} + */ + +/** @addtogroup IWDG_Exported_Constants + * @{ + */ + +/** @addtogroup IWDG_WriteAccess + * @{ + */ + +#define IWDG_WRITE_ENABLE ((uint16_t)0x5555) +#define IWDG_WRITE_DISABLE ((uint16_t)0x0000) +#define IS_IWDG_WRITE(ACCESS) (((ACCESS) == IWDG_WRITE_ENABLE) || ((ACCESS) == IWDG_WRITE_DISABLE)) +/** + * @} + */ + +/** @addtogroup IWDG_prescaler + * @{ + */ + +#define IWDG_PRESCALER_DIV4 ((uint8_t)0x00) +#define IWDG_PRESCALER_DIV8 ((uint8_t)0x01) +#define IWDG_PRESCALER_DIV16 ((uint8_t)0x02) +#define IWDG_PRESCALER_DIV32 ((uint8_t)0x03) +#define IWDG_PRESCALER_DIV64 ((uint8_t)0x04) +#define IWDG_PRESCALER_DIV128 ((uint8_t)0x05) +#define IWDG_PRESCALER_DIV256 ((uint8_t)0x06) +#define IS_IWDG_PRESCALER_DIV(PRESCALER) \ + (((PRESCALER) == IWDG_PRESCALER_DIV4) || ((PRESCALER) == IWDG_PRESCALER_DIV8) \ + || ((PRESCALER) == IWDG_PRESCALER_DIV16) || ((PRESCALER) == IWDG_PRESCALER_DIV32) \ + || ((PRESCALER) == IWDG_PRESCALER_DIV64) || ((PRESCALER) == IWDG_PRESCALER_DIV128) \ + || ((PRESCALER) == IWDG_PRESCALER_DIV256)) +/** + * @} + */ + +/** @addtogroup IWDG_Flag + * @{ + */ + +#define IWDG_PVU_FLAG ((uint16_t)0x0001) +#define IWDG_CRVU_FLAG ((uint16_t)0x0002) +#define IS_IWDG_FLAG(FLAG) (((FLAG) == IWDG_PVU_FLAG) || ((FLAG) == IWDG_CRVU_FLAG)) +#define IS_IWDG_RELOAD(RELOAD) ((RELOAD) <= 0xFFF) +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup IWDG_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup IWDG_Exported_Functions + * @{ + */ + +void IWDG_WriteConfig(uint16_t IWDG_WriteAccess); +void IWDG_SetPrescalerDiv(uint8_t IWDG_Prescaler); +void IWDG_CntReload(uint16_t Reload); +void IWDG_ReloadKey(void); +void IWDG_Enable(void); +FlagStatus IWDG_GetStatus(uint16_t IWDG_FLAG); + +#ifdef __cplusplus +} +#endif + +#endif /* __N32G45X_IWDG_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/inc/n32g45x_opamp.h b/inc/n32g45x_opamp.h new file mode 100644 index 0000000..8273c7d --- /dev/null +++ b/inc/n32g45x_opamp.h @@ -0,0 +1,213 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_opamp.h + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_OPAMPMP_H__ +#define __N32G45X_OPAMPMP_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" +#include + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup OPAMP + * @{ + */ + +/** @addtogroup OPAMP_Exported_Constants + * @{ + */ +typedef enum +{ + OPAMP1 = 0, + OPAMP2 = 4, + OPAMP3 = 8, + OPAMP4 = 12, +} OPAMPX; + +// OPAMP_CS +typedef enum +{ + OPAMP1_CS_VPSSEL_PA1 = (0x00L << 19), + OPAMP1_CS_VPSSEL_PA3 = (0x01L << 19), + OPAMP1_CS_VPSSEL_DAC2_PA5 = (0x02L << 19), + OPAMP1_CS_VPSSEL_PA7 = (0x03L << 19), + OPAMP2_CS_VPSSEL_PA7 = (0x00L << 19), + OPAMP2_CS_VPSSEL_PB0 = (0x01L << 19), + OPAMP2_CS_VPSSEL_PE8 = (0x02L << 19), + OPAMP3_CS_VPSSEL_PC9 = (0x00L << 19), + OPAMP3_CS_VPSSEL_PA1 = (0x01L << 19), + OPAMP3_CS_VPSSEL_DAC2_PA5 = (0x02L << 19), + OPAMP3_CS_VPSSEL_PC3 = (0x03L << 19), + OPAMP4_CS_VPSSEL_PC3 = (0x00L << 19), + OPAMP4_CS_VPSSEL_DAC1_PA4 = (0x01L << 19), + OPAMP4_CS_VPSSEL_PC5 = (0x02L << 19), +} OPAMP_CS_VPSSEL; +typedef enum +{ + OPAMP1_CS_VMSSEL_PA3 = (0x00L << 17), + OPAMP1_CS_VMSSEL_PA2 = (0x01L << 17), + OPAMPx_CS_VMSSEL_FLOAT = (0x03L << 17), + OPAMP2_CS_VMSSEL_PA2 = (0x00L << 17), + OPAMP2_CS_VMSSEL_PA5 = (0x01L << 17), + OPAMP3_CS_VMSSEL_PC4 = (0x00L << 17), + OPAMP3_CS_VMSSEL_PB10 = (0x01L << 17), + OPAMP4_CS_VMSSEL_PB10 = (0x00L << 17), + OPAMP4_CS_VMSSEL_PC9 = (0x01L << 17), + OPAMP4_CS_VMSSEL_PD8 = (0x02L << 17), +} OPAMP_CS_VMSSEL; + +typedef enum +{ + OPAMP1_CS_VPSEL_PA1 = (0x00L << 8), + OPAMP1_CS_VPSEL_PA3 = (0x01L << 8), + OPAMP1_CS_VPSEL_DAC2_PA5 = (0x02L << 8), + OPAMP1_CS_VPSEL_PA7 = (0x03L << 8), + OPAMP2_CS_VPSEL_PA7 = (0x00L << 8), + OPAMP2_CS_VPSEL_PB0 = (0x01L << 8), + OPAMP2_CS_VPSEL_PE8 = (0x02L << 8), + OPAMP3_CS_VPSEL_PC9 = (0x00L << 8), + OPAMP3_CS_VPSEL_PA1 = (0x01L << 8), + OPAMP3_CS_VPSEL_DAC2_PA5 = (0x02L << 8), + OPAMP3_CS_VPSEL_PC3 = (0x03L << 8), + OPAMP4_CS_VPSEL_PC3 = (0x00L << 8), + OPAMP4_CS_VPSEL_DAC1_PA4 = (0x01L << 8), + OPAMP4_CS_VPSEL_PC5 = (0x02L << 8), +} OPAMP_CS_VPSEL; +typedef enum +{ + OPAMP1_CS_VMSEL_PA3 = (0x00L << 6), + OPAMP1_CS_VMSEL_PA2 = (0x01L << 6), + OPAMPx_CS_VMSEL_FLOAT = (0x03L << 6), + OPAMP2_CS_VMSEL_PA2 = (0x00L << 6), + OPAMP2_CS_VMSEL_PA5 = (0x01L << 6), + OPAMP3_CS_VMSEL_PC4 = (0x00L << 6), + OPAMP3_CS_VMSEL_PB10 = (0x01L << 6), + OPAMP4_CS_VMSEL_PB10 = (0x00L << 6), + OPAMP4_CS_VMSEL_PC9 = (0x01L << 6), + OPAMP4_CS_VMSEL_PD8 = (0x02L << 6), +} OPAMP_CS_VMSEL; +typedef enum +{ + OPAMP_CS_PGA_GAIN_2 = (0x00 << 3), + OPAMP_CS_PGA_GAIN_4 = (0x01 << 3), + OPAMP_CS_PGA_GAIN_8 = (0x02 << 3), + OPAMP_CS_PGA_GAIN_16 = (0x03 << 3), + OPAMP_CS_PGA_GAIN_32 = (0x04 << 3), +} OPAMP_CS_PGA_GAIN; +typedef enum +{ + OPAMP_CS_EXT_OPAMP = (0x00 << 1), + OPAMP_CS_PGA_EN = (0x02 << 1), + OPAMP_CS_FOLLOW = (0x03 << 1), +} OPAMP_CS_MOD; + +// bit mask +#define OPAMP_CS_EN_MASK (0x01L << 0) +#define OPAMP_CS_MOD_MASK (0x03L << 1) +#define OPAMP_CS_PGA_GAIN_MASK (0x07L << 3) +#define OPAMP_CS_VMSEL_MASK (0x03L << 6) +#define OPAMP_CS_VPSEL_MASK (0x07L << 8) +#define OPAMP_CS_CALON_MASK (0x01L << 11) +#define OPAMP_CS_TSTREF_MASK (0x01L << 13) +#define OPAMP_CS_CALOUT_MASK (0x01L << 14) +#define OPAMP_CS_RANGE_MASK (0x01L << 15) +#define OPAMP_CS_TCMEN_MASK (0x01L << 16) +#define OPAMP_CS_VMSEL_SECOND_MASK (0x03L << 17) +#define OPAMP_CS_VPSEL_SECOND_MASK (0x07L << 19) +/** @addtogroup OPAMP_LOCK + * @{ + */ +#define OPAMP_LOCK_1 0x01L +#define OPAMP_LOCK_2 0x02L +#define OPAMP_LOCK_3 0x04L +#define OPAMP_LOCK_4 0x08L +/** + * @} + */ +/** + * @} + */ + +/** + * @brief OPAMP Init structure definition + */ + +typedef struct +{ + FunctionalState TimeAutoMuxEn; /*call ENABLE or DISABLE */ + + FunctionalState HighVolRangeEn; /*call ENABLE or DISABLE ,low range VDDA < 2.4V,high range VDDA >= 2.4V*/ + + OPAMP_CS_PGA_GAIN Gain; /*see @EM_PGA_GAIN */ + + OPAMP_CS_MOD Mod; /*see @EM_OPAMP_MOD*/ +} OPAMP_InitType; + +/** @addtogroup OPAMP_Exported_Functions + * @{ + */ + +void OPAMP_DeInit(void); +void OPAMP_StructInit(OPAMP_InitType* OPAMP_InitStruct); +void OPAMP_Init(OPAMPX OPAMPx, OPAMP_InitType* OPAMP_InitStruct); +void OPAMP_Enable(OPAMPX OPAMPx, FunctionalState en); +void OPAMP_SetPgaGain(OPAMPX OPAMPx, OPAMP_CS_PGA_GAIN Gain); +void OPAMP_SetVpSecondSel(OPAMPX OPAMPx, OPAMP_CS_VPSSEL VpSSel); +void OPAMP_SetVmSecondSel(OPAMPX OPAMPx, OPAMP_CS_VMSSEL VmSSel); +void OPAMP_SetVpSel(OPAMPX OPAMPx, OPAMP_CS_VPSEL VpSel); +void OPAMP_SetVmSel(OPAMPX OPAMPx, OPAMP_CS_VMSEL VmSel); +bool OPAMP_IsCalOutHigh(OPAMPX OPAMPx); +void OPAMP_CalibrationEnable(OPAMPX OPAMPx, FunctionalState en); +void OPAMP_SetLock(uint32_t Lock); // see @OPAMP_LOCK +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /*__N32G45X_ADC_H */ + /** + * @} + */ + /** + * @} + */ diff --git a/inc/n32g45x_pwr.h b/inc/n32g45x_pwr.h new file mode 100644 index 0000000..7ee2e96 --- /dev/null +++ b/inc/n32g45x_pwr.h @@ -0,0 +1,179 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_pwr.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_PWR_H__ +#define __N32G45X_PWR_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup PWR + * @{ + */ + +/** @addtogroup PWR_Exported_Types + * @{ + */ + +/** + * @} + */ + +/** @addtogroup PWR_Exported_Constants + * @{ + */ + +/** @addtogroup PVD_detection_level + * @{ + */ + +#define PWR_PVDRANGRE_2V2 ((uint32_t)0x00000000) +#define PWR_PVDRANGRE_2V3 ((uint32_t)0x00000020) +#define PWR_PVDRANGRE_2V4 ((uint32_t)0x00000040) +#define PWR_PVDRANGRE_2V5 ((uint32_t)0x00000060) +#define PWR_PVDRANGRE_2V6 ((uint32_t)0x00000080) +#define PWR_PVDRANGRE_2V7 ((uint32_t)0x000000A0) +#define PWR_PVDRANGRE_2V8 ((uint32_t)0x000000C0) +#define PWR_PVDRANGRE_2V9 ((uint32_t)0x000000E0) + +#define PWR_PVDRANGE_1V78 ((uint32_t)0x00000200) +#define PWR_PVDRANGE_1V88 ((uint32_t)0x00000220) +#define PWR_PVDRANGE_1V98 ((uint32_t)0x00000240) +#define PWR_PVDRANGE_2V08 ((uint32_t)0x00000260) +#define PWR_PVDRANGE_3V06 ((uint32_t)0x00000280) +#define PWR_PVDRANGE_3V24 ((uint32_t)0x000002A0) +#define PWR_PVDRANGE_3V42 ((uint32_t)0x000002C0) +#define PWR_PVDRANGE_3V60 ((uint32_t)0x000002E0) +#define IS_PWR_PVD_LEVEL(LEVEL) \ + (((LEVEL) == PWR_PVDRANGRE_2V2) || ((LEVEL) == PWR_PVDRANGRE_2V3) || ((LEVEL) == PWR_PVDRANGRE_2V4) \ + || ((LEVEL) == PWR_PVDRANGRE_2V5) || ((LEVEL) == PWR_PVDRANGRE_2V6) || ((LEVEL) == PWR_PVDRANGRE_2V7) \ + || ((LEVEL) == PWR_PVDRANGRE_2V8) || ((LEVEL) == PWR_PVDRANGRE_2V9) || ((LEVEL) == PWR_PVDRANGE_1V78) \ + || ((LEVEL) == PWR_PVDRANGE_1V88) || ((LEVEL) == PWR_PVDRANGE_1V98) || ((LEVEL) == PWR_PVDRANGE_2V08) \ + || ((LEVEL) == PWR_PVDRANGE_3V06) || ((LEVEL) == PWR_PVDRANGE_3V24) || ((LEVEL) == PWR_PVDRANGE_3V42) \ + || ((LEVEL) == PWR_PVDRANGE_3V60)) + +/** + * @} + */ + +/** @addtogroup Regulator_state_is_STOP_mode + * @{ + */ + +#define PWR_REGULATOR_ON ((uint32_t)0x00000000) +#define PWR_REGULATOR_LOWPOWER ((uint32_t)0x00000001) +#define IS_PWR_REGULATOR(REGULATOR) (((REGULATOR) == PWR_REGULATOR_ON) || ((REGULATOR) == PWR_REGULATOR_LOWPOWER)) +/** + * @} + */ + +/** @addtogroup STOP_mode_entry + * @{ + */ + +#define PWR_STOPENTRY_WFI ((uint8_t)0x01) +#define PWR_STOPENTRY_WFE ((uint8_t)0x02) +#define IS_PWR_STOP_ENTRY(ENTRY) (((ENTRY) == PWR_STOPENTRY_WFI) || ((ENTRY) == PWR_STOPENTRY_WFE)) + +/** + * @} + */ + +/** @addtogroup PWR_Flag + * @{ + */ + +#define PWR_WU_FLAG ((uint32_t)0x00000001) +#define PWR_SB_FLAG ((uint32_t)0x00000002) +#define PWR_PVDO_FLAG ((uint32_t)0x00000004) +#define PWR_VBATF_FLAG ((uint32_t)0x00000008) +#define IS_PWR_GET_FLAG(FLAG) \ + (((FLAG) == PWR_WU_FLAG) || ((FLAG) == PWR_SB_FLAG) || ((FLAG) == PWR_PVDO_FLAG) || ((FLAG) == PWR_VBATF_FLAG)) + +#define IS_PWR_CLEAR_FLAG(FLAG) (((FLAG) == PWR_WU_FLAG) || ((FLAG) == PWR_SB_FLAG) || ((FLAG) == PWR_VBATF_FLAG)) +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup PWR_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup PWR_Exported_Functions + * @{ + */ + +void PWR_DeInit(void); +void PWR_BackupAccessEnable(FunctionalState Cmd); +void PWR_PvdEnable(FunctionalState Cmd); +void PWR_PvdRangeConfig(uint32_t PWR_PVDLevel); +void PWR_WakeUpPinEnable(FunctionalState Cmd); +void PWR_EnterStopState(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry); +void PWR_EnterSLEEPMode(uint8_t SLEEPONEXIT, uint8_t PWR_STOPEntry); +void PWR_EnterSTOP2Mode(uint8_t PWR_STOPEntry); +void PWR_EnterStandbyState(void); +FlagStatus PWR_GetFlagStatus(uint32_t PWR_FLAG); +void PWR_ClearFlag(uint32_t PWR_FLAG); + +#ifdef __cplusplus +} +#endif + +#endif /* __N32G45X_PWR_H__ */ + /** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/inc/n32g45x_qspi.h b/inc/n32g45x_qspi.h new file mode 100644 index 0000000..914e426 --- /dev/null +++ b/inc/n32g45x_qspi.h @@ -0,0 +1,333 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_qspi.h + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_QSPI_H__ +#define __N32G45X_QSPI_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" +#include +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup QSPI + * @brief QSPI driver modules + * @{ + */ +//////////////////////////////////////////////////////////////////////////////////////////////////// +typedef enum +{ + STANDARD_SPI_FORMAT_SEL = 0, + DUAL_SPI_FORMAT_SEL, + QUAD_SPI_FORMAT_SEL, + XIP_SPI_FORMAT_SEL +} QSPI_FORMAT_SEL; + +typedef enum +{ + TX_AND_RX = 0, + TX_ONLY, + RX_ONLY +} QSPI_DATA_DIR; + +typedef enum +{ + QSPI_NSS_PORTA_SEL, + QSPI_NSS_PORTC_SEL, + QSPI_NSS_PORTF_SEL +} QSPI_NSS_PORT_SEL; + +typedef enum +{ + QSPI_NULL = 0, + QSPI_SUCCESS, +} QSPI_STATUS; +//////////////////////////////////////////////////////////////////////////////////////////////////// +typedef struct +{ + /*QSPI_CTRL0*/ + uint32_t DFS; + uint32_t FRF; + uint32_t SCPH; + uint32_t SCPOL; + uint32_t TMOD; + uint32_t SSTE; + uint32_t CFS; + uint32_t SPI_FRF; + + /*QSPI_CTRL1*/ + uint32_t NDF; + + /*QSPI_MW_CTRL*/ + uint32_t MWMOD; + uint32_t MC_DIR; + uint32_t MHS_EN; + + /*QSPI_BAUD*/ + uint32_t CLK_DIV; + + /*QSPI_TXFT*/ + uint32_t TXFT; + + /*QSPI_RXFT*/ + uint32_t RXFT; + + /*QSPI_TXFN*/ + uint32_t TXFN; + + /*QSPI_RXFN*/ + uint32_t RXFN; + + /*QSPI_RS_DELAY*/ + uint32_t SDCN; + uint32_t SES; + + /*QSPI_ENH_CTRL0*/ + uint32_t ENHANCED_TRANS_TYPE; + uint32_t ENHANCED_ADDR_LEN; + uint32_t ENHANCED_MD_BIT_EN; + uint32_t ENHANCED_INST_L; + uint32_t ENHANCED_WAIT_CYCLES; + uint32_t ENHANCED_SPI_DDR_EN; + uint32_t ENHANCED_INST_DDR_EN; + uint32_t ENHANCED_XIP_DFS_HC; + uint32_t ENHANCED_XIP_INST_EN; + uint32_t ENHANCED_XIP_CT_EN; + uint32_t ENHANCED_XIP_MBL; + uint32_t ENHANCED_CLK_STRETCH_EN; + + /*QSPI_DDR_TXDE*/ + uint32_t TXDE; + + /*QSPI_XIP_MODE*/ + uint32_t XIP_MD_BITS; + + /*QSPI_XIP_INCR_TOC*/ + uint32_t ITOC; + + /*QSPI_XIP_WRAP_TOC*/ + uint32_t WTOC; + + /*QSPI_XIP_CTRL*/ + uint32_t XIP_FRF; + uint32_t XIP_TRANS_TYPE; + uint32_t XIP_ADDR_LEN; + uint32_t XIP_INST_L; + uint32_t XIP_MD_BITS_EN; + uint32_t XIP_WAIT_CYCLES; + uint32_t XIP_DFS_HC; + uint32_t XIP_DDR_EN; + uint32_t XIP_INST_DDR_EN; + uint32_t XIP_INST_EN; + uint32_t XIP_CT_EN; + uint32_t XIP_MBL; + + /*QSPI_XIP_TOUT*/ + uint32_t XTOUT; + +} QSPI_InitType; +//////////////////////////////////////////////////////////////////////////////////////////////////// +#define QSPI_TIME_OUT_CNT 200 + +#define IS_QSPI_SPI_FRF(SPI_FRF) \ + (((SPI_FRF) == QSPI_CTRL0_SPI_FRF_STANDARD_FORMAT) || ((SPI_FRF) == QSPI_CTRL0_SPI_FRF_DUAL_FORMAT) || ((SPI_FRF) == QSPI_CTRL0_SPI_FRF_QUAD_FORMAT)) + +#define IS_QSPI_CFS(CFS) ((((CFS) >= QSPI_CTRL0_CFS_2_BIT) && ((CFS) <= QSPI_CTRL0_CFS_16_BIT)) || ((CFS) == QSPI_CTRL0_CFS_1_BIT)) + +#define IS_QSPI_SSTE(SSTE) (((SSTE) == QSPI_CTRL0_SSTE_EN) || ((SSTE) == 0)) + +#define IS_QSPI_TMOD(TMOD) \ + (((TMOD) == QSPI_CTRL0_TMOD_TX_AND_RX) || ((TMOD) == QSPI_CTRL0_TMOD_TX_ONLY) || ((TMOD) == QSPI_CTRL0_TMOD_RX_ONLY) || ((TMOD) == QSPI_CTRL0_TMOD_EEPROM_READ)) + +#define IS_QSPI_SCPOL(SCPOL) (((SCPOL) == QSPI_CTRL0_SCPOL_LOW) || ((SCPOL) == QSPI_CTRL0_SCPOL_HIGH)) + +#define IS_QSPI_SCPH(SCPH) (((SCPH) == QSPI_CTRL0_SCPH_FIRST_EDGE) || ((SCPH) == QSPI_CTRL0_SCPH_SECOND_EDGE)) + +#define IS_QSPI_FRF(FRF) (((FRF) == QSPI_CTRL0_FRF_MOTOROLA) || ((FRF) == QSPI_CTRL0_FRF_TI) || ((FRF) == QSPI_CTRL0_FRF_MICROWIRE)) + +#define IS_QSPI_DFS(DFS) (((DFS) >= QSPI_CTRL0_DFS_4_BIT) && ((DFS) <= QSPI_CTRL0_DFS_32_BIT)) + + +#define IS_QSPI_NDF(NDF) (((NDF) <= 0xFFFF)) + +#define IS_QSPI_MWMOD(MWMOD) (((MWMOD) == QSPI_MW_CTRL_MWMOD_UNSEQUENTIAL) || ((MWMOD) == QSPI_MW_CTRL_MWMOD_SEQUENTIAL)) + +#define IS_QSPI_MC_DIR(MC_DIR) (((MC_DIR) == QSPI_MW_CTRL_MC_DIR_RX) || ((MC_DIR) == QSPI_MW_CTRL_MC_DIR_TX)) + +#define IS_QSPI_MHS_EN(MHS_EN) (((MHS_EN) == QSPI_MW_CTRL_MHS_EN) || ((MHS_EN) == 0)) + +#define IS_QSPI_CLK_DIV(CLK_DIV) (((CLK_DIV) <= 0xFFFF)) + +#define IS_QSPI_TXFT(TXFT) (((TXFT) <= 0x1FFFFF)) + +#define IS_QSPI_RXFT(RXFT) (((RXFT) <= 0x1F)) + +#define IS_QSPI_TXFN(TXFN) (((TXFN) <= 0x3F)) + +#define IS_QSPI_RXFN(RXFN) (((RXFN) <= 0x3F)) + +#define IS_QSPI_DMA_CTRL(DMA_CTRL) (((DMA_CTRL) == QSPI_DMA_CTRL_TX_DMA_EN) || ((DMA_CTRL) == QSPI_DMA_CTRL_RX_DMA_EN)) + +#define IS_QSPI_DMATDL_CTRL(DMATDL_CTRL) (((DMATDL_CTRL) <= 0x3F)) + +#define IS_QSPI_DMARDL_CTRL(DMARDL_CTRL) (((DMARDL_CTRL) <= 0x3F)) + +#define IS_QSPI_SES(SES) (((SES) == QSPI_RS_DELAY_SES_RISING_EDGE) || ((SES) == QSPI_RS_DELAY_SES_FALLING_EDGE)) + +#define IS_QSPI_SDCN(SDCN) (((SDCN) <= 0xFF)) + +#define IS_QSPI_ENH_CLK_STRETCH_EN(ENH_CLK_STRETCH_EN) (((ENH_CLK_STRETCH_EN) == QSPI_ENH_CTRL0_CLK_STRETCH_EN) || ((ENH_CLK_STRETCH_EN) == 0)) + +#define IS_QSPI_ENH_XIP_MBL(ENH_XIP_MBL) \ + (((ENH_XIP_MBL) == QSPI_ENH_CTRL0_XIP_MBL_2_BIT) || ((ENH_XIP_MBL) == QSPI_ENH_CTRL0_XIP_MBL_4_BIT) || \ + ((ENH_XIP_MBL) == QSPI_ENH_CTRL0_XIP_MBL_8_BIT) || ((ENH_XIP_MBL) == QSPI_ENH_CTRL0_XIP_MBL_16_BIT)) + +#define IS_QSPI_ENH_XIP_CT_EN(ENH_XIP_CT_EN) (((ENH_XIP_CT_EN) == QSPI_ENH_CTRL0_XIP_CT_EN) || ((ENH_XIP_CT_EN) == 0)) + +#define IS_QSPI_ENH_XIP_INST_EN(ENH_XIP_INST_EN) (((ENH_XIP_INST_EN) == QSPI_ENH_CTRL0_XIP_INST_EN) || ((ENH_XIP_INST_EN) == 0)) + +#define IS_QSPI_ENH_XIP_DFS_HC(ENH_XIP_DFS_HC) (((ENH_XIP_DFS_HC) == QSPI_ENH_CTRL0_XIP_DFS_HC) || ((ENH_XIP_DFS_HC) == 0)) + +#define IS_QSPI_ENH_INST_DDR_EN(ENH_INST_DDR_EN) (((ENH_INST_DDR_EN) == QSPI_ENH_CTRL0_INST_DDR_EN) || ((ENH_INST_DDR_EN) == 0)) + +#define IS_QSPI_ENH_SPI_DDR_EN(ENH_SPI_DDR_EN) (((ENH_SPI_DDR_EN) == QSPI_ENH_CTRL0_SPI_DDR_EN) || ((ENH_SPI_DDR_EN) == 0)) + +#define IS_QSPI_ENH_WAIT_CYCLES(ENH_WAIT_CYCLES) ((((ENH_WAIT_CYCLES) >= QSPI_ENH_CTRL0_WAIT_1CYCLES) && ((ENH_WAIT_CYCLES) <= QSPI_ENH_CTRL0_WAIT_31CYCLES)) || \ + ((ENH_WAIT_CYCLES) == 0)) + +#define IS_QSPI_ENH_INST_L(ENH_INST_L) \ + (((ENH_INST_L) == QSPI_ENH_CTRL0_INST_L_0_LINE) || ((ENH_INST_L) == QSPI_ENH_CTRL0_INST_L_4_LINE) || \ + ((ENH_INST_L) == QSPI_ENH_CTRL0_INST_L_8_LINE) || ((ENH_INST_L) == QSPI_ENH_CTRL0_INST_L_16_LINE)) + +#define IS_QSPI_ENH_MD_BIT_EN(ENH_MD_BIT_EN) (((ENH_MD_BIT_EN) == QSPI_ENH_CTRL0_MD_BIT_EN) || ((ENH_MD_BIT_EN) == 0)) + +#define IS_QSPI_ENH_ADDR_LEN(ENH_ADDR_LEN) ((((ENH_ADDR_LEN) >= QSPI_ENH_CTRL0_ADDR_LEN_4_BIT) && ((ENH_ADDR_LEN) <= QSPI_ENH_CTRL0_ADDR_LEN_60_BIT)) || \ + ((ENH_ADDR_LEN) == 0)) + +#define IS_QSPI_ENH_TRANS_TYPE(ENH_TRANS_TYPE) (((ENH_TRANS_TYPE) == QSPI_ENH_CTRL0_TRANS_TYPE_STANDARD) || \ + ((ENH_TRANS_TYPE) == QSPI_ENH_CTRL0_TRANS_TYPE_ADDRESS_BY_FRF) || \ + ((ENH_TRANS_TYPE) == QSPI_ENH_CTRL0_TRANS_TYPE_ALL_BY_FRF)) + + +#define IS_QSPI_DDR_TXDE(DDR_TXDE) (((DDR_TXDE) <= 0xFF)) + +#define IS_QSPI_XIP_MODE(XIP_MODE) (((XIP_MODE) <= 0xFFFF)) + +#define IS_QSPI_XIP_INCR_TOC(XIP_INCR_TOC) (((XIP_INCR_TOC) <= 0xFFFF)) + +#define IS_QSPI_XIP_WRAP_TOC(XIP_WRAP_TOC) (((XIP_WRAP_TOC) <= 0xFFFF)) + +#define IS_QSPI_XIP_TOUT(XIP_TOUT) (((XIP_TOUT) <= 0xFF)) + +#define IS_QSPI_XIP_MBL(XIP_MBL) \ + (((XIP_MBL) == QSPI_XIP_CTRL_XIP_MBL_LEN_2_BIT) || ((XIP_MBL) == QSPI_XIP_CTRL_XIP_MBL_LEN_4_BIT) || \ + ((XIP_MBL) == QSPI_XIP_CTRL_XIP_MBL_LEN_8_BIT) || ((XIP_MBL) == QSPI_XIP_CTRL_XIP_MBL_LEN_16_BIT)) + +#define IS_QSPI_XIP_CT_EN(XIP_CT_EN) (((XIP_CT_EN) == QSPI_XIP_CTRL_XIP_CT_EN) || ((XIP_CT_EN) == 0)) + +#define IS_QSPI_XIP_INST_EN(XIP_INST_EN) (((XIP_INST_EN) == QSPI_XIP_CTRL_XIP_INST_EN) || ((XIP_INST_EN) == 0)) + +#define IS_QSPI_INST_DDR_EN(INST_DDR_EN) (((INST_DDR_EN) == QSPI_XIP_CTRL_XIP_INST_EN) || ((INST_DDR_EN) == 0)) + +#define IS_QSPI_DDR_EN(DDR_EN) (((DDR_EN) == QSPI_XIP_CTRL_DDR_EN) || ((DDR_EN) == 0)) + +#define IS_QSPI_XIP_DFS_HC(XIP_DFS_HC) (((XIP_DFS_HC) == QSPI_XIP_CTRL_DFS_HC) || ((XIP_DFS_HC) == 0)) + +#define IS_QSPI_XIP_WAIT_CYCLES(XIP_WAIT_CYCLES) ((((XIP_WAIT_CYCLES) >= QSPI_XIP_CTRL_WAIT_1CYCLES) && ((XIP_WAIT_CYCLES) <= QSPI_XIP_CTRL_WAIT_31CYCLES)) || \ + ((XIP_WAIT_CYCLES) == 0)) + +#define IS_QSPI_XIP_MD_BIT_EN(XIP_MD_BIT_EN) (((XIP_MD_BIT_EN) == QSPI_XIP_CTRL_MD_BIT_EN) || ((XIP_MD_BIT_EN) == 0)) + +#define IS_QSPI_XIP_INST_L(XIP_INST_L) \ + (((XIP_INST_L) == QSPI_XIP_CTRL_INST_L_0_LINE) || ((XIP_INST_L) == QSPI_XIP_CTRL_INST_L_4_LINE) || \ + ((XIP_INST_L) == QSPI_XIP_CTRL_INST_L_8_LINE) || ((XIP_INST_L) == QSPI_XIP_CTRL_INST_L_16_LINE)) + +#define IS_QSPI_XIP_ADDR_LEN(XIP_ADDR_LEN) ((((XIP_ADDR_LEN) >= QSPI_XIP_CTRL_ADDR_4BIT) && ((XIP_ADDR_LEN) <= QSPI_XIP_CTRL_ADDR_60BIT)) || \ + ((XIP_ADDR_LEN) == 0)) + +#define IS_QSPI_XIP_TRANS_TYPE(XIP_TRANS_TYPE) (((XIP_TRANS_TYPE) == QSPI_XIP_CTRL_TRANS_TYPE_STANDARD_SPI) || \ + ((XIP_TRANS_TYPE) == QSPI_XIP_CTRL_TRANS_TYPE_ADDRESS_BY_XIP_FRF) || \ + ((XIP_TRANS_TYPE) == QSPI_XIP_CTRL_TRANS_TYPE_INSTRUCT_BY_XIP_FRF)) + +#define IS_QSPI_XIP_FRF(XIP_FRF) (((XIP_FRF) == QSPI_XIP_CTRL_FRF_2_LINE) || ((XIP_FRF) == QSPI_XIP_CTRL_FRF_4_LINE) || ((XIP_FRF) == 0)) + + + + + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +void QSPI_Cmd(bool cmd); +void QSPI_XIP_Cmd(bool cmd); +void QSPI_DeInit(void); +void QspiInitConfig(QSPI_InitType* QSPI_InitStruct); +void QSPI_GPIO(QSPI_NSS_PORT_SEL qspi_nss_port_sel, bool IO1_Input, bool IO3_Output); +void QSPI_DMA_CTRL_Config(uint8_t TxRx,uint8_t TxDataLevel,uint8_t RxDataLevel); +uint16_t QSPI_GetITStatus(uint16_t FLAG); +void QSPI_ClearITFLAG(uint16_t FLAG); +void QSPI_XIP_ClearITFLAG(uint16_t FLAG); +bool GetQspiBusyStatus(void); +bool GetQspiTxDataBusyStatus(void); +bool GetQspiTxDataEmptyStatus(void); +bool GetQspiRxHaveDataStatus(void); +bool GetQspiRxDataFullStatus(void); +bool GetQspiTransmitErrorStatus(void); +bool GetQspiDataConflictErrorStatus(void); +void QspiSendWord(uint32_t SendData); +uint32_t QspiReadWord(void); +uint32_t QspiGetDataPointer(void); +uint32_t QspiReadRxFifoNum(void); +void ClrFifo(void); +uint32_t GetFifoData(uint32_t* pData, uint32_t Len); +void QspiSendAndGetWords(uint32_t* pSrcData, uint32_t* pDstData, uint32_t cnt); +uint32_t QspiSendWordAndGetWords(uint32_t WrData, uint32_t* pRdData, uint8_t LastRd); + + +#ifdef __cplusplus +} +#endif + +#endif /*__N32G45X_QSPI_H__ */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/inc/n32g45x_rcc.h b/inc/n32g45x_rcc.h new file mode 100644 index 0000000..3552074 --- /dev/null +++ b/inc/n32g45x_rcc.h @@ -0,0 +1,708 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_rcc.h + * @author Nations + * @version v1.0.2 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_RCC_H__ +#define __N32G45X_RCC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup RCC + * @{ + */ + +/** @addtogroup RCC_Exported_Types + * @{ + */ + +typedef struct +{ + uint32_t SysclkFreq; /*!< returns SYSCLK clock frequency expressed in Hz */ + uint32_t HclkFreq; /*!< returns HCLK clock frequency expressed in Hz */ + uint32_t Pclk1Freq; /*!< returns PCLK1 clock frequency expressed in Hz */ + uint32_t Pclk2Freq; /*!< returns PCLK2 clock frequency expressed in Hz */ + uint32_t AdcPllClkFreq; /*!< returns ADCPLLCLK clock frequency expressed in Hz */ + uint32_t AdcHclkFreq; /*!< returns ADCHCLK clock frequency expressed in Hz */ +} RCC_ClocksType; + +/** + * @} + */ + +/** @addtogroup RCC_Exported_Constants + * @{ + */ + +/** @addtogroup HSE_configuration + * @{ + */ + +#define RCC_HSE_DISABLE ((uint32_t)0x00000000) +#define RCC_HSE_ENABLE ((uint32_t)0x00010000) +#define RCC_HSE_BYPASS ((uint32_t)0x00040000) +#define IS_RCC_HSE(HSE) (((HSE) == RCC_HSE_DISABLE) || ((HSE) == RCC_HSE_ENABLE) || ((HSE) == RCC_HSE_BYPASS)) + +/** + * @} + */ + +/** @addtogroup PLL_entry_clock_source + * @{ + */ + +#define RCC_PLL_SRC_HSI_DIV2 ((uint32_t)0x00000000) + +#define RCC_PLL_SRC_HSE_DIV1 ((uint32_t)0x00010000) +#define RCC_PLL_SRC_HSE_DIV2 ((uint32_t)0x00030000) +#define IS_RCC_PLL_SRC(SOURCE) \ + (((SOURCE) == RCC_PLL_SRC_HSI_DIV2) || ((SOURCE) == RCC_PLL_SRC_HSE_DIV1) || ((SOURCE) == RCC_PLL_SRC_HSE_DIV2)) + +/** + * @} + */ + +/** @addtogroup PLL_multiplication_factor + * @{ + */ +#define RCC_PLL_MUL_2 ((uint32_t)0x00000000) +#define RCC_PLL_MUL_3 ((uint32_t)0x00040000) +#define RCC_PLL_MUL_4 ((uint32_t)0x00080000) +#define RCC_PLL_MUL_5 ((uint32_t)0x000C0000) +#define RCC_PLL_MUL_6 ((uint32_t)0x00100000) +#define RCC_PLL_MUL_7 ((uint32_t)0x00140000) +#define RCC_PLL_MUL_8 ((uint32_t)0x00180000) +#define RCC_PLL_MUL_9 ((uint32_t)0x001C0000) +#define RCC_PLL_MUL_10 ((uint32_t)0x00200000) +#define RCC_PLL_MUL_11 ((uint32_t)0x00240000) +#define RCC_PLL_MUL_12 ((uint32_t)0x00280000) +#define RCC_PLL_MUL_13 ((uint32_t)0x002C0000) +#define RCC_PLL_MUL_14 ((uint32_t)0x00300000) +#define RCC_PLL_MUL_15 ((uint32_t)0x00340000) +#define RCC_PLL_MUL_16 ((uint32_t)0x00380000) +#define RCC_PLL_MUL_17 ((uint32_t)0x08000000) +#define RCC_PLL_MUL_18 ((uint32_t)0x08040000) +#define RCC_PLL_MUL_19 ((uint32_t)0x08080000) +#define RCC_PLL_MUL_20 ((uint32_t)0x080C0000) +#define RCC_PLL_MUL_21 ((uint32_t)0x08100000) +#define RCC_PLL_MUL_22 ((uint32_t)0x08140000) +#define RCC_PLL_MUL_23 ((uint32_t)0x08180000) +#define RCC_PLL_MUL_24 ((uint32_t)0x081C0000) +#define RCC_PLL_MUL_25 ((uint32_t)0x08200000) +#define RCC_PLL_MUL_26 ((uint32_t)0x08240000) +#define RCC_PLL_MUL_27 ((uint32_t)0x08280000) +#define RCC_PLL_MUL_28 ((uint32_t)0x082C0000) +#define RCC_PLL_MUL_29 ((uint32_t)0x08300000) +#define RCC_PLL_MUL_30 ((uint32_t)0x08340000) +#define RCC_PLL_MUL_31 ((uint32_t)0x08380000) +#define RCC_PLL_MUL_32 ((uint32_t)0x083C0000) +#define IS_RCC_PLL_MUL(MUL) \ + (((MUL) == RCC_PLL_MUL_2) || ((MUL) == RCC_PLL_MUL_3) || ((MUL) == RCC_PLL_MUL_4) || ((MUL) == RCC_PLL_MUL_5) \ + || ((MUL) == RCC_PLL_MUL_6) || ((MUL) == RCC_PLL_MUL_7) || ((MUL) == RCC_PLL_MUL_8) || ((MUL) == RCC_PLL_MUL_9) \ + || ((MUL) == RCC_PLL_MUL_10) || ((MUL) == RCC_PLL_MUL_11) || ((MUL) == RCC_PLL_MUL_12) \ + || ((MUL) == RCC_PLL_MUL_13) || ((MUL) == RCC_PLL_MUL_14) || ((MUL) == RCC_PLL_MUL_15) \ + || ((MUL) == RCC_PLL_MUL_16) || ((MUL) == RCC_PLL_MUL_17) || ((MUL) == RCC_PLL_MUL_18) \ + || ((MUL) == RCC_PLL_MUL_19) || ((MUL) == RCC_PLL_MUL_20) || ((MUL) == RCC_PLL_MUL_21) \ + || ((MUL) == RCC_PLL_MUL_22) || ((MUL) == RCC_PLL_MUL_23) || ((MUL) == RCC_PLL_MUL_24) \ + || ((MUL) == RCC_PLL_MUL_25) || ((MUL) == RCC_PLL_MUL_26) || ((MUL) == RCC_PLL_MUL_27) \ + || ((MUL) == RCC_PLL_MUL_28) || ((MUL) == RCC_PLL_MUL_29) || ((MUL) == RCC_PLL_MUL_30) \ + || ((MUL) == RCC_PLL_MUL_31) || ((MUL) == RCC_PLL_MUL_32)) + +/** + * @} + */ + +/** @addtogroup System_clock_source + * @{ + */ + +#define RCC_SYSCLK_SRC_HSI ((uint32_t)0x00000000) +#define RCC_SYSCLK_SRC_HSE ((uint32_t)0x00000001) +#define RCC_SYSCLK_SRC_PLLCLK ((uint32_t)0x00000002) +#define IS_RCC_SYSCLK_SRC(SOURCE) \ + (((SOURCE) == RCC_SYSCLK_SRC_HSI) || ((SOURCE) == RCC_SYSCLK_SRC_HSE) || ((SOURCE) == RCC_SYSCLK_SRC_PLLCLK)) +/** + * @} + */ + +/** @addtogroup AHB_clock_source + * @{ + */ + +#define RCC_SYSCLK_DIV1 ((uint32_t)0x00000000) +#define RCC_SYSCLK_DIV2 ((uint32_t)0x00000080) +#define RCC_SYSCLK_DIV4 ((uint32_t)0x00000090) +#define RCC_SYSCLK_DIV8 ((uint32_t)0x000000A0) +#define RCC_SYSCLK_DIV16 ((uint32_t)0x000000B0) +#define RCC_SYSCLK_DIV64 ((uint32_t)0x000000C0) +#define RCC_SYSCLK_DIV128 ((uint32_t)0x000000D0) +#define RCC_SYSCLK_DIV256 ((uint32_t)0x000000E0) +#define RCC_SYSCLK_DIV512 ((uint32_t)0x000000F0) +#define IS_RCC_SYSCLK_DIV(HCLK) \ + (((HCLK) == RCC_SYSCLK_DIV1) || ((HCLK) == RCC_SYSCLK_DIV2) || ((HCLK) == RCC_SYSCLK_DIV4) \ + || ((HCLK) == RCC_SYSCLK_DIV8) || ((HCLK) == RCC_SYSCLK_DIV16) || ((HCLK) == RCC_SYSCLK_DIV64) \ + || ((HCLK) == RCC_SYSCLK_DIV128) || ((HCLK) == RCC_SYSCLK_DIV256) || ((HCLK) == RCC_SYSCLK_DIV512)) +/** + * @} + */ + +/** @addtogroup APB1_APB2_clock_source + * @{ + */ + +#define RCC_HCLK_DIV1 ((uint32_t)0x00000000) +#define RCC_HCLK_DIV2 ((uint32_t)0x00000400) +#define RCC_HCLK_DIV4 ((uint32_t)0x00000500) +#define RCC_HCLK_DIV8 ((uint32_t)0x00000600) +#define RCC_HCLK_DIV16 ((uint32_t)0x00000700) +#define IS_RCC_HCLK_DIV(PCLK) \ + (((PCLK) == RCC_HCLK_DIV1) || ((PCLK) == RCC_HCLK_DIV2) || ((PCLK) == RCC_HCLK_DIV4) || ((PCLK) == RCC_HCLK_DIV8) \ + || ((PCLK) == RCC_HCLK_DIV16)) +/** + * @} + */ + +/** @addtogroup RCC_Interrupt_source + * @{ + */ + +#define RCC_INT_LSIRDIF ((uint8_t)0x01) +#define RCC_INT_LSERDIF ((uint8_t)0x02) +#define RCC_INT_HSIRDIF ((uint8_t)0x04) +#define RCC_INT_HSERDIF ((uint8_t)0x08) +#define RCC_INT_PLLRDIF ((uint8_t)0x10) +#define RCC_INT_CLKSSIF ((uint8_t)0x80) + +#define IS_RCC_INT(IT) ((((IT) & (uint8_t)0xE0) == 0x00) && ((IT) != 0x00)) +#define IS_RCC_GET_INT(IT) \ + (((IT) == RCC_INT_LSIRDIF) || ((IT) == RCC_INT_LSERDIF) || ((IT) == RCC_INT_HSIRDIF) || ((IT) == RCC_INT_HSERDIF) \ + || ((IT) == RCC_INT_PLLRDIF) || ((IT) == RCC_INT_CLKSSIF)) +#define IS_RCC_CLR_INT(IT) ((((IT) & (uint8_t)0x60) == 0x00) && ((IT) != 0x00)) + +/** + * @} + */ + +/** @addtogroup USB_Device_clock_source + * @{ + */ + +#define RCC_USBCLK_SRC_PLLCLK_DIV1_5 ((uint8_t)0x00) +#define RCC_USBCLK_SRC_PLLCLK_DIV1 ((uint8_t)0x01) +#define RCC_USBCLK_SRC_PLLCLK_DIV2 ((uint8_t)0x02) +#define RCC_USBCLK_SRC_PLLCLK_DIV3 ((uint8_t)0x03) + +#define IS_RCC_USBCLK_SRC(SOURCE) \ + (((SOURCE) == RCC_USBCLK_SRC_PLLCLK_DIV1_5) || ((SOURCE) == RCC_USBCLK_SRC_PLLCLK_DIV1) \ + || ((SOURCE) == RCC_USBCLK_SRC_PLLCLK_DIV2) || ((SOURCE) == RCC_USBCLK_SRC_PLLCLK_DIV3)) +/** + * @} + */ + +/** @addtogroup ADC_clock_source + * @{ + */ + +#define RCC_PCLK2_DIV2 ((uint32_t)0x00000000) +#define RCC_PCLK2_DIV4 ((uint32_t)0x00004000) +#define RCC_PCLK2_DIV6 ((uint32_t)0x00008000) +#define RCC_PCLK2_DIV8 ((uint32_t)0x0000C000) +#define IS_RCC_PCLK2_DIV(ADCCLK) \ + (((ADCCLK) == RCC_PCLK2_DIV2) || ((ADCCLK) == RCC_PCLK2_DIV4) || ((ADCCLK) == RCC_PCLK2_DIV6) \ + || ((ADCCLK) == RCC_PCLK2_DIV8)) + +/** + * @} + */ + +/** @addtogroup RCC_CFGR2_Config + * @{ + */ +#define RCC_TIM18CLK_SRC_TIM18CLK ((uint32_t)0x00000000) +#define RCC_TIM18CLK_SRC_SYSCLK ((uint32_t)0x20000000) +#define IS_RCC_TIM18CLKSRC(TIM18CLK) \ + (((TIM18CLK) == RCC_TIM18CLK_SRC_TIM18CLK) || ((TIM18CLK) == RCC_TIM18CLK_SRC_SYSCLK)) + +#define RCC_RNGCCLK_SYSCLK_DIV1 ((uint32_t)0x00000000) +#define RCC_RNGCCLK_SYSCLK_DIV2 ((uint32_t)0x01000000) +#define RCC_RNGCCLK_SYSCLK_DIV3 ((uint32_t)0x02000000) +#define RCC_RNGCCLK_SYSCLK_DIV4 ((uint32_t)0x03000000) +#define RCC_RNGCCLK_SYSCLK_DIV5 ((uint32_t)0x04000000) +#define RCC_RNGCCLK_SYSCLK_DIV6 ((uint32_t)0x05000000) +#define RCC_RNGCCLK_SYSCLK_DIV7 ((uint32_t)0x06000000) +#define RCC_RNGCCLK_SYSCLK_DIV8 ((uint32_t)0x07000000) +#define RCC_RNGCCLK_SYSCLK_DIV9 ((uint32_t)0x08000000) +#define RCC_RNGCCLK_SYSCLK_DIV10 ((uint32_t)0x09000000) +#define RCC_RNGCCLK_SYSCLK_DIV11 ((uint32_t)0x0A000000) +#define RCC_RNGCCLK_SYSCLK_DIV12 ((uint32_t)0x0B000000) +#define RCC_RNGCCLK_SYSCLK_DIV13 ((uint32_t)0x0C000000) +#define RCC_RNGCCLK_SYSCLK_DIV14 ((uint32_t)0x0D000000) +#define RCC_RNGCCLK_SYSCLK_DIV15 ((uint32_t)0x0E000000) +#define RCC_RNGCCLK_SYSCLK_DIV16 ((uint32_t)0x0F000000) +#define RCC_RNGCCLK_SYSCLK_DIV17 ((uint32_t)0x10000000) +#define RCC_RNGCCLK_SYSCLK_DIV18 ((uint32_t)0x11000000) +#define RCC_RNGCCLK_SYSCLK_DIV19 ((uint32_t)0x12000000) +#define RCC_RNGCCLK_SYSCLK_DIV20 ((uint32_t)0x13000000) +#define RCC_RNGCCLK_SYSCLK_DIV21 ((uint32_t)0x14000000) +#define RCC_RNGCCLK_SYSCLK_DIV22 ((uint32_t)0x15000000) +#define RCC_RNGCCLK_SYSCLK_DIV23 ((uint32_t)0x16000000) +#define RCC_RNGCCLK_SYSCLK_DIV24 ((uint32_t)0x17000000) +#define RCC_RNGCCLK_SYSCLK_DIV25 ((uint32_t)0x18000000) +#define RCC_RNGCCLK_SYSCLK_DIV26 ((uint32_t)0x19000000) +#define RCC_RNGCCLK_SYSCLK_DIV27 ((uint32_t)0x1A000000) +#define RCC_RNGCCLK_SYSCLK_DIV28 ((uint32_t)0x1B000000) +#define RCC_RNGCCLK_SYSCLK_DIV29 ((uint32_t)0x1C000000) +#define RCC_RNGCCLK_SYSCLK_DIV30 ((uint32_t)0x1D000000) +#define RCC_RNGCCLK_SYSCLK_DIV31 ((uint32_t)0x1E000000) +#define RCC_RNGCCLK_SYSCLK_DIV32 ((uint32_t)0x1F000000) +#define IS_RCC_RNGCCLKPRE(DIV) \ + (((DIV) == RCC_RNGCCLK_SYSCLK_DIV1) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV2) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV3) \ + || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV4) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV5) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV6) \ + || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV7) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV8) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV9) \ + || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV10) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV11) \ + || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV12) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV13) \ + || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV14) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV15) \ + || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV16) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV17) \ + || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV18) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV19) \ + || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV20) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV21) \ + || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV22) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV23) \ + || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV24) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV25) \ + || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV26) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV27) \ + || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV28) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV29) \ + || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV30) || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV31) \ + || ((DIV) == RCC_RNGCCLK_SYSCLK_DIV32)) + +#define RCC_ADC1MCLK_SRC_HSI ((uint32_t)0x00000000) +#define RCC_ADC1MCLK_SRC_HSE ((uint32_t)0x00000400) +#define IS_RCC_ADC1MCLKSRC(ADC1MCLK) (((ADC1MCLK) == RCC_ADC1MCLK_SRC_HSI) || ((ADC1MCLK) == RCC_ADC1MCLK_SRC_HSE)) + +#define RCC_ADC1MCLK_DIV1 ((uint32_t)0x00000000) +#define RCC_ADC1MCLK_DIV2 ((uint32_t)0x00000800) +#define RCC_ADC1MCLK_DIV3 ((uint32_t)0x00001000) +#define RCC_ADC1MCLK_DIV4 ((uint32_t)0x00001800) +#define RCC_ADC1MCLK_DIV5 ((uint32_t)0x00002000) +#define RCC_ADC1MCLK_DIV6 ((uint32_t)0x00002800) +#define RCC_ADC1MCLK_DIV7 ((uint32_t)0x00003000) +#define RCC_ADC1MCLK_DIV8 ((uint32_t)0x00003800) +#define RCC_ADC1MCLK_DIV9 ((uint32_t)0x00004000) +#define RCC_ADC1MCLK_DIV10 ((uint32_t)0x00004800) +#define RCC_ADC1MCLK_DIV11 ((uint32_t)0x00005000) +#define RCC_ADC1MCLK_DIV12 ((uint32_t)0x00005800) +#define RCC_ADC1MCLK_DIV13 ((uint32_t)0x00006000) +#define RCC_ADC1MCLK_DIV14 ((uint32_t)0x00006800) +#define RCC_ADC1MCLK_DIV15 ((uint32_t)0x00007000) +#define RCC_ADC1MCLK_DIV16 ((uint32_t)0x00007800) +#define RCC_ADC1MCLK_DIV17 ((uint32_t)0x00008000) +#define RCC_ADC1MCLK_DIV18 ((uint32_t)0x00008800) +#define RCC_ADC1MCLK_DIV19 ((uint32_t)0x00009000) +#define RCC_ADC1MCLK_DIV20 ((uint32_t)0x00009800) +#define RCC_ADC1MCLK_DIV21 ((uint32_t)0x0000A000) +#define RCC_ADC1MCLK_DIV22 ((uint32_t)0x0000A800) +#define RCC_ADC1MCLK_DIV23 ((uint32_t)0x0000B000) +#define RCC_ADC1MCLK_DIV24 ((uint32_t)0x0000B800) +#define RCC_ADC1MCLK_DIV25 ((uint32_t)0x0000C000) +#define RCC_ADC1MCLK_DIV26 ((uint32_t)0x0000C800) +#define RCC_ADC1MCLK_DIV27 ((uint32_t)0x0000D000) +#define RCC_ADC1MCLK_DIV28 ((uint32_t)0x0000D800) +#define RCC_ADC1MCLK_DIV29 ((uint32_t)0x0000E000) +#define RCC_ADC1MCLK_DIV30 ((uint32_t)0x0000E800) +#define RCC_ADC1MCLK_DIV31 ((uint32_t)0x0000F000) +#define RCC_ADC1MCLK_DIV32 ((uint32_t)0x0000F800) +#define IS_RCC_ADC1MCLKPRE(DIV) \ + (((DIV) == RCC_ADC1MCLK_DIV1) || ((DIV) == RCC_ADC1MCLK_DIV2) || ((DIV) == RCC_ADC1MCLK_DIV3) \ + || ((DIV) == RCC_ADC1MCLK_DIV4) || ((DIV) == RCC_ADC1MCLK_DIV5) || ((DIV) == RCC_ADC1MCLK_DIV6) \ + || ((DIV) == RCC_ADC1MCLK_DIV7) || ((DIV) == RCC_ADC1MCLK_DIV8) || ((DIV) == RCC_ADC1MCLK_DIV9) \ + || ((DIV) == RCC_ADC1MCLK_DIV10) || ((DIV) == RCC_ADC1MCLK_DIV11) || ((DIV) == RCC_ADC1MCLK_DIV12) \ + || ((DIV) == RCC_ADC1MCLK_DIV13) || ((DIV) == RCC_ADC1MCLK_DIV14) || ((DIV) == RCC_ADC1MCLK_DIV15) \ + || ((DIV) == RCC_ADC1MCLK_DIV16) || ((DIV) == RCC_ADC1MCLK_DIV17) || ((DIV) == RCC_ADC1MCLK_DIV18) \ + || ((DIV) == RCC_ADC1MCLK_DIV19) || ((DIV) == RCC_ADC1MCLK_DIV20) || ((DIV) == RCC_ADC1MCLK_DIV21) \ + || ((DIV) == RCC_ADC1MCLK_DIV22) || ((DIV) == RCC_ADC1MCLK_DIV23) || ((DIV) == RCC_ADC1MCLK_DIV24) \ + || ((DIV) == RCC_ADC1MCLK_DIV25) || ((DIV) == RCC_ADC1MCLK_DIV26) || ((DIV) == RCC_ADC1MCLK_DIV27) \ + || ((DIV) == RCC_ADC1MCLK_DIV28) || ((DIV) == RCC_ADC1MCLK_DIV29) || ((DIV) == RCC_ADC1MCLK_DIV30) \ + || ((DIV) == RCC_ADC1MCLK_DIV31) || ((DIV) == RCC_ADC1MCLK_DIV32)) + +#define RCC_ADCPLLCLK_DISABLE ((uint32_t)0xFFFFFEFF) +#define RCC_ADCPLLCLK_DIV1 ((uint32_t)0x00000100) +#define RCC_ADCPLLCLK_DIV2 ((uint32_t)0x00000110) +#define RCC_ADCPLLCLK_DIV4 ((uint32_t)0x00000120) +#define RCC_ADCPLLCLK_DIV6 ((uint32_t)0x00000130) +#define RCC_ADCPLLCLK_DIV8 ((uint32_t)0x00000140) +#define RCC_ADCPLLCLK_DIV10 ((uint32_t)0x00000150) +#define RCC_ADCPLLCLK_DIV12 ((uint32_t)0x00000160) +#define RCC_ADCPLLCLK_DIV16 ((uint32_t)0x00000170) +#define RCC_ADCPLLCLK_DIV32 ((uint32_t)0x00000180) +#define RCC_ADCPLLCLK_DIV64 ((uint32_t)0x00000190) +#define RCC_ADCPLLCLK_DIV128 ((uint32_t)0x000001A0) +#define RCC_ADCPLLCLK_DIV256 ((uint32_t)0x000001B0) +#define RCC_ADCPLLCLK_DIV_OTHERS ((uint32_t)0x000001C0) +#define IS_RCC_ADCPLLCLKPRE(DIV) \ + (((DIV) == RCC_ADCPLLCLK_DIV1) || ((DIV) == RCC_ADCPLLCLK_DIV2) || ((DIV) == RCC_ADCPLLCLK_DIV4) \ + || ((DIV) == RCC_ADCPLLCLK_DIV6) || ((DIV) == RCC_ADCPLLCLK_DIV8) || ((DIV) == RCC_ADCPLLCLK_DIV10) \ + || ((DIV) == RCC_ADCPLLCLK_DIV12) || ((DIV) == RCC_ADCPLLCLK_DIV16) || ((DIV) == RCC_ADCPLLCLK_DIV32) \ + || ((DIV) == RCC_ADCPLLCLK_DIV64) || ((DIV) == RCC_ADCPLLCLK_DIV128) || ((DIV) == RCC_ADCPLLCLK_DIV256) \ + || ((DIV) == RCC_ADC1MCLK_DIV15) || ((DIV) == RCC_ADCPLLCLK_DIV16) \ + || (((DIV)&RCC_ADCPLLCLK_DIV_OTHERS) == 0x000001C0)) + +#define RCC_ADCHCLK_DIV1 ((uint32_t)0x00000000) +#define RCC_ADCHCLK_DIV2 ((uint32_t)0x00000001) +#define RCC_ADCHCLK_DIV4 ((uint32_t)0x00000002) +#define RCC_ADCHCLK_DIV6 ((uint32_t)0x00000003) +#define RCC_ADCHCLK_DIV8 ((uint32_t)0x00000004) +#define RCC_ADCHCLK_DIV10 ((uint32_t)0x00000005) +#define RCC_ADCHCLK_DIV12 ((uint32_t)0x00000006) +#define RCC_ADCHCLK_DIV16 ((uint32_t)0x00000007) +#define RCC_ADCHCLK_DIV32 ((uint32_t)0x00000008) +#define RCC_ADCHCLK_DIV_OTHERS ((uint32_t)0x00000008) +#define IS_RCC_ADCHCLKPRE(DIV) \ + (((DIV) == RCC_ADCHCLK_DIV1) || ((DIV) == RCC_ADCHCLK_DIV2) || ((DIV) == RCC_ADCHCLK_DIV4) \ + || ((DIV) == RCC_ADCHCLK_DIV6) || ((DIV) == RCC_ADCHCLK_DIV8) || ((DIV) == RCC_ADCHCLK_DIV10) \ + || ((DIV) == RCC_ADCHCLK_DIV12) || ((DIV) == RCC_ADCHCLK_DIV16) || ((DIV) == RCC_ADCHCLK_DIV32) \ + || (((DIV)&RCC_ADCHCLK_DIV_OTHERS) != 0x00)) +/** + * @} + */ + +/** @addtogroup RCC_CFGR3_Config + * @{ + */ +#define RCC_BOR_RST_ENABLE ((uint32_t)0x00000040) + +#define RCC_TRNG1MCLK_ENABLE ((uint32_t)0x00040000) +#define RCC_TRNG1MCLK_DISABLE ((uint32_t)0xFFFBFFFF) + +#define RCC_TRNG1MCLK_SRC_HSI ((uint32_t)0x00000000) +#define RCC_TRNG1MCLK_SRC_HSE ((uint32_t)0x00020000) +#define IS_RCC_TRNG1MCLK_SRC(TRNG1MCLK) \ + (((TRNG1MCLK) == RCC_TRNG1MCLK_SRC_HSI) || ((TRNG1MCLK) == RCC_TRNG1MCLK_SRC_HSE)) + +#define RCC_TRNG1MCLK_DIV2 ((uint32_t)0x00000800) +#define RCC_TRNG1MCLK_DIV4 ((uint32_t)0x00001800) +#define RCC_TRNG1MCLK_DIV6 ((uint32_t)0x00002800) +#define RCC_TRNG1MCLK_DIV8 ((uint32_t)0x00003800) +#define RCC_TRNG1MCLK_DIV10 ((uint32_t)0x00004800) +#define RCC_TRNG1MCLK_DIV12 ((uint32_t)0x00005800) +#define RCC_TRNG1MCLK_DIV14 ((uint32_t)0x00006800) +#define RCC_TRNG1MCLK_DIV16 ((uint32_t)0x00007800) +#define RCC_TRNG1MCLK_DIV18 ((uint32_t)0x00008800) +#define RCC_TRNG1MCLK_DIV20 ((uint32_t)0x00009800) +#define RCC_TRNG1MCLK_DIV22 ((uint32_t)0x0000A800) +#define RCC_TRNG1MCLK_DIV24 ((uint32_t)0x0000B800) +#define RCC_TRNG1MCLK_DIV26 ((uint32_t)0x0000C800) +#define RCC_TRNG1MCLK_DIV28 ((uint32_t)0x0000D800) +#define RCC_TRNG1MCLK_DIV30 ((uint32_t)0x0000E800) +#define RCC_TRNG1MCLK_DIV32 ((uint32_t)0x0000F800) +#define IS_RCC_TRNG1MCLKPRE(VAL) \ + (((VAL) == RCC_TRNG1MCLK_DIV2) || ((VAL) == RCC_TRNG1MCLK_DIV4) || ((VAL) == RCC_TRNG1MCLK_DIV6) \ + || ((VAL) == RCC_TRNG1MCLK_DIV8) || ((VAL) == RCC_TRNG1MCLK_DIV10) || ((VAL) == RCC_TRNG1MCLK_DIV12) \ + || ((VAL) == RCC_TRNG1MCLK_DIV14) || ((VAL) == RCC_TRNG1MCLK_DIV16) || ((VAL) == RCC_TRNG1MCLK_DIV18) \ + || ((VAL) == RCC_TRNG1MCLK_DIV20) || ((VAL) == RCC_TRNG1MCLK_DIV22) || ((VAL) == RCC_TRNG1MCLK_DIV24) \ + || ((VAL) == RCC_TRNG1MCLK_DIV26) || ((VAL) == RCC_TRNG1MCLK_DIV28) || ((VAL) == RCC_TRNG1MCLK_DIV30) \ + || ((VAL) == RCC_TRNG1MCLK_DIV32)) + +/** + * @} + */ + +/** @addtogroup LSE_configuration + * @{ + */ + +#define RCC_LSE_DISABLE ((uint8_t)0x00) +#define RCC_LSE_ENABLE ((uint8_t)0x01) +#define RCC_LSE_BYPASS ((uint8_t)0x04) +#define IS_RCC_LSE(LSE) (((LSE) == RCC_LSE_DISABLE) || ((LSE) == RCC_LSE_ENABLE) || ((LSE) == RCC_LSE_BYPASS)) +/** + * @} + */ + +/** @addtogroup RTC_clock_source + * @{ + */ + +#define RCC_RTCCLK_SRC_LSE ((uint32_t)0x00000100) +#define RCC_RTCCLK_SRC_LSI ((uint32_t)0x00000200) +#define RCC_RTCCLK_SRC_HSE_DIV128 ((uint32_t)0x00000300) +#define IS_RCC_RTCCLK_SRC(SOURCE) \ + (((SOURCE) == RCC_RTCCLK_SRC_LSE) || ((SOURCE) == RCC_RTCCLK_SRC_LSI) || ((SOURCE) == RCC_RTCCLK_SRC_HSE_DIV128)) +/** + * @} + */ + +/** @addtogroup AHB_peripheral + * @{ + */ + +#define RCC_AHB_PERIPH_DMA1 ((uint32_t)0x00000001) +#define RCC_AHB_PERIPH_DMA2 ((uint32_t)0x00000002) +#define RCC_AHB_PERIPH_SRAM ((uint32_t)0x00000004) +#define RCC_AHB_PERIPH_FLITF ((uint32_t)0x00000010) +#define RCC_AHB_PERIPH_CRC ((uint32_t)0x00000040) +#define RCC_AHB_PERIPH_RNGC ((uint32_t)0x00000200) +#define RCC_AHB_PERIPH_SDIO ((uint32_t)0x00000400) +#define RCC_AHB_PERIPH_SAC ((uint32_t)0x00000800) +#define RCC_AHB_PERIPH_ADC1 ((uint32_t)0x00001000) +#define RCC_AHB_PERIPH_ADC2 ((uint32_t)0x00002000) +#define RCC_AHB_PERIPH_ADC3 ((uint32_t)0x00004000) +#define RCC_AHB_PERIPH_ADC4 ((uint32_t)0x00008000) +#define RCC_AHB_PERIPH_ETHMAC ((uint32_t)0x00010000) +#define RCC_AHB_PERIPH_QSPI ((uint32_t)0x00020000) + +#define IS_RCC_AHB_PERIPH(PERIPH) ((((PERIPH)&0xFFFC02A8) == 0x00) && ((PERIPH) != 0x00)) + +/** + * @} + */ + +/** @addtogroup APB2_peripheral + * @{ + */ + +#define RCC_APB2_PERIPH_AFIO ((uint32_t)0x00000001) +#define RCC_APB2_PERIPH_GPIOA ((uint32_t)0x00000004) +#define RCC_APB2_PERIPH_GPIOB ((uint32_t)0x00000008) +#define RCC_APB2_PERIPH_GPIOC ((uint32_t)0x00000010) +#define RCC_APB2_PERIPH_GPIOD ((uint32_t)0x00000020) +#define RCC_APB2_PERIPH_GPIOE ((uint32_t)0x00000040) +#define RCC_APB2_PERIPH_GPIOF ((uint32_t)0x00000080) +#define RCC_APB2_PERIPH_GPIOG ((uint32_t)0x00000100) +#define RCC_APB2_PERIPH_TIM1 ((uint32_t)0x00000800) +#define RCC_APB2_PERIPH_SPI1 ((uint32_t)0x00001000) +#define RCC_APB2_PERIPH_TIM8 ((uint32_t)0x00002000) +#define RCC_APB2_PERIPH_USART1 ((uint32_t)0x00004000) +#define RCC_APB2_PERIPH_DVP ((uint32_t)0x00010000) +#define RCC_APB2_PERIPH_UART6 ((uint32_t)0x00020000) +#define RCC_APB2_PERIPH_UART7 ((uint32_t)0x00040000) +#define RCC_APB2_PERIPH_I2C3 ((uint32_t)0x00080000) +#define RCC_APB2_PERIPH_I2C4 ((uint32_t)0x00100000) + +#define IS_RCC_APB2_PERIPH(PERIPH) ((((PERIPH)&0xFFE08602) == 0x00) && ((PERIPH) != 0x00)) +/** + * @} + */ + +/** @addtogroup APB1_peripheral + * @{ + */ + +#define RCC_APB1_PERIPH_TIM2 ((uint32_t)0x00000001) +#define RCC_APB1_PERIPH_TIM3 ((uint32_t)0x00000002) +#define RCC_APB1_PERIPH_TIM4 ((uint32_t)0x00000004) +#define RCC_APB1_PERIPH_TIM5 ((uint32_t)0x00000008) +#define RCC_APB1_PERIPH_TIM6 ((uint32_t)0x00000010) +#define RCC_APB1_PERIPH_TIM7 ((uint32_t)0x00000020) +#define RCC_APB1_PERIPH_COMP ((uint32_t)0x00000040) +#define RCC_APB1_PERIPH_COMP_FILT ((uint32_t)0x00000080) +#define RCC_APB1_PERIPH_TSC ((uint32_t)0x00000400) +#define RCC_APB1_PERIPH_WWDG ((uint32_t)0x00000800) +#define RCC_APB1_PERIPH_SPI2 ((uint32_t)0x00004000) +#define RCC_APB1_PERIPH_SPI3 ((uint32_t)0x00008000) +#define RCC_APB1_PERIPH_USART2 ((uint32_t)0x00020000) +#define RCC_APB1_PERIPH_USART3 ((uint32_t)0x00040000) +#define RCC_APB1_PERIPH_UART4 ((uint32_t)0x00080000) +#define RCC_APB1_PERIPH_UART5 ((uint32_t)0x00100000) +#define RCC_APB1_PERIPH_I2C1 ((uint32_t)0x00200000) +#define RCC_APB1_PERIPH_I2C2 ((uint32_t)0x00400000) +#define RCC_APB1_PERIPH_USB ((uint32_t)0x00800000) +#define RCC_APB1_PERIPH_CAN1 ((uint32_t)0x02000000) +#define RCC_APB1_PERIPH_CAN2 ((uint32_t)0x04000000) +#define RCC_APB1_PERIPH_BKP ((uint32_t)0x08000000) +#define RCC_APB1_PERIPH_PWR ((uint32_t)0x10000000) +#define RCC_APB1_PERIPH_DAC ((uint32_t)0x20000000) +#define RCC_APB1_PERIPH_OPAMP ((uint32_t)0x80000000) + +#define IS_RCC_APB1_PERIPH(PERIPH) ((((PERIPH)&0x41013300) == 0x00) && ((PERIPH) != 0x00)) + +/** + * @} + */ + +#define RCC_MCO_PLLCLK_DIV2 ((uint32_t)0x20000000) +#define RCC_MCO_PLLCLK_DIV3 ((uint32_t)0x30000000) +#define RCC_MCO_PLLCLK_DIV4 ((uint32_t)0x40000000) +#define RCC_MCO_PLLCLK_DIV5 ((uint32_t)0x50000000) +#define RCC_MCO_PLLCLK_DIV6 ((uint32_t)0x60000000) +#define RCC_MCO_PLLCLK_DIV7 ((uint32_t)0x70000000) +#define RCC_MCO_PLLCLK_DIV8 ((uint32_t)0x80000000) +#define RCC_MCO_PLLCLK_DIV9 ((uint32_t)0x90000000) +#define RCC_MCO_PLLCLK_DIV10 ((uint32_t)0xA0000000) +#define RCC_MCO_PLLCLK_DIV11 ((uint32_t)0xB0000000) +#define RCC_MCO_PLLCLK_DIV12 ((uint32_t)0xC0000000) +#define RCC_MCO_PLLCLK_DIV13 ((uint32_t)0xD0000000) +#define RCC_MCO_PLLCLK_DIV14 ((uint32_t)0xE0000000) +#define RCC_MCO_PLLCLK_DIV15 ((uint32_t)0xF0000000) +#define IS_RCC_MCOPLLCLKPRE(DIV) \ + (((DIV) == RCC_MCO_PLLCLK_DIV2) || ((DIV) == RCC_MCO_PLLCLK_DIV3) || ((DIV) == RCC_MCO_PLLCLK_DIV4) \ + || ((DIV) == RCC_MCO_PLLCLK_DIV5) || ((DIV) == RCC_MCO_PLLCLK_DIV6) || ((DIV) == RCC_MCO_PLLCLK_DIV7) \ + || ((DIV) == RCC_MCO_PLLCLK_DIV8) || ((DIV) == RCC_MCO_PLLCLK_DIV9) || ((DIV) == RCC_MCO_PLLCLK_DIV10) \ + || ((DIV) == RCC_MCO_PLLCLK_DIV11) || ((DIV) == RCC_MCO_PLLCLK_DIV12) || ((DIV) == RCC_MCO_PLLCLK_DIV13) \ + || ((DIV) == RCC_MCO_PLLCLK_DIV14) || ((DIV) == RCC_MCO_PLLCLK_DIV15)) + +/** @addtogroup Clock_source_to_output_on_MCO_pin + * @{ + */ + +#define RCC_MCO_NOCLK ((uint8_t)0x00) +#define RCC_MCO_SYSCLK ((uint8_t)0x04) +#define RCC_MCO_HSI ((uint8_t)0x05) +#define RCC_MCO_HSE ((uint8_t)0x06) +#define RCC_MCO_PLLCLK ((uint8_t)0x07) + +#define IS_RCC_MCO(MCO) \ + (((MCO) == RCC_MCO_NOCLK) || ((MCO) == RCC_MCO_HSI) || ((MCO) == RCC_MCO_SYSCLK) || ((MCO) == RCC_MCO_HSE) \ + || ((MCO) == RCC_MCO_PLLCLK)) + +/** + * @} + */ + +/** @addtogroup RCC_Flag + * @{ + */ +#define RCC_FLAG_HSIRD ((uint8_t)0x21) +#define RCC_FLAG_HSERD ((uint8_t)0x31) +#define RCC_FLAG_PLLRD ((uint8_t)0x39) +#define RCC_FLAG_LSERD ((uint8_t)0x41) +#define RCC_FLAG_LSIRD ((uint8_t)0x61) +#define RCC_FLAG_BORRST ((uint8_t)0x73) +#define RCC_FLAG_RETEMC ((uint8_t)0x74) +#define RCC_FLAG_BKPEMC ((uint8_t)0x75) +#define RCC_FLAG_RAMRST ((uint8_t)0x77) +#define RCC_FLAG_MMURST ((uint8_t)0x79) +#define RCC_FLAG_PINRST ((uint8_t)0x7A) +#define RCC_FLAG_PORRST ((uint8_t)0x7B) +#define RCC_FLAG_SFTRST ((uint8_t)0x7C) +#define RCC_FLAG_IWDGRST ((uint8_t)0x7D) +#define RCC_FLAG_WWDGRST ((uint8_t)0x7E) +#define RCC_FLAG_LPWRRST ((uint8_t)0x7F) + +#define IS_RCC_FLAG(FLAG) \ + (((FLAG) == RCC_FLAG_HSIRD) || ((FLAG) == RCC_FLAG_HSERD) || ((FLAG) == RCC_FLAG_PLLRD) \ + || ((FLAG) == RCC_FLAG_LSERD) || ((FLAG) == RCC_FLAG_LSIRD) || ((FLAG) == RCC_FLAG_BORRST) \ + || ((FLAG) == RCC_FLAG_RETEMC) || ((FLAG) == RCC_FLAG_BKPEMC) || ((FLAG) == RCC_FLAG_RAMRST) \ + || ((FLAG) == RCC_FLAG_MMURST) || ((FLAG) == RCC_FLAG_PINRST) || ((FLAG) == RCC_FLAG_PORRST) \ + || ((FLAG) == RCC_FLAG_SFTRST) || ((FLAG) == RCC_FLAG_IWDGRST) || ((FLAG) == RCC_FLAG_WWDGRST) \ + || ((FLAG) == RCC_FLAG_LPWRRST)) + +#define IS_RCC_CALIB_VALUE(VALUE) ((VALUE) <= 0x1F) +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup RCC_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup RCC_Exported_Functions + * @{ + */ + +void RCC_DeInit(void); +void RCC_ConfigHse(uint32_t RCC_HSE); +ErrorStatus RCC_WaitHseStable(void); +void RCC_SetHsiCalibValue(uint8_t HSICalibrationValue); +void RCC_EnableHsi(FunctionalState Cmd); +void RCC_ConfigPll(uint32_t RCC_PLLSource, uint32_t RCC_PLLMul); +void RCC_EnablePll(FunctionalState Cmd); + +void RCC_ConfigSysclk(uint32_t RCC_SYSCLKSource); +uint8_t RCC_GetSysclkSrc(void); +void RCC_ConfigHclk(uint32_t RCC_SYSCLK); +void RCC_ConfigPclk1(uint32_t RCC_HCLK); +void RCC_ConfigPclk2(uint32_t RCC_HCLK); +void RCC_ConfigInt(uint8_t RccInt, FunctionalState Cmd); + +void RCC_ConfigUsbClk(uint32_t RCC_USBCLKSource); + +void RCC_ConfigTim18Clk(uint32_t RCC_TIM18CLKSource); +void RCC_ConfigRngcClk(uint32_t RCC_RNGCCLKPrescaler); + +void RCC_ConfigAdc1mClk(uint32_t RCC_ADC1MCLKSource, uint32_t RCC_ADC1MPrescaler); +void RCC_ConfigAdcPllClk(uint32_t RCC_ADCPLLCLKPrescaler, FunctionalState Cmd); +void RCC_ConfigAdcHclk(uint32_t RCC_ADCHCLKPrescaler); + +void RCC_ConfigTrng1mClk(uint32_t RCC_TRNG1MCLKSource, uint32_t RCC_TRNG1MPrescaler); +void RCC_EnableTrng1mClk(FunctionalState Cmd); + +void RCC_ConfigLse(uint8_t RCC_LSE); +void RCC_EnableLsi(FunctionalState Cmd); +void RCC_ConfigRtcClk(uint32_t RCC_RTCCLKSource); +void RCC_EnableRtcClk(FunctionalState Cmd); +void RCC_GetClocksFreqValue(RCC_ClocksType* RCC_Clocks); +void RCC_EnableAHBPeriphClk(uint32_t RCC_AHBPeriph, FunctionalState Cmd); +void RCC_EnableAPB2PeriphClk(uint32_t RCC_APB2Periph, FunctionalState Cmd); +void RCC_EnableAPB1PeriphClk(uint32_t RCC_APB1Periph, FunctionalState Cmd); + +void RCC_EnableAHBPeriphReset(uint32_t RCC_AHBPeriph, FunctionalState Cmd); +void RCC_EnableAPB2PeriphReset(uint32_t RCC_APB2Periph, FunctionalState Cmd); +void RCC_EnableAPB1PeriphReset(uint32_t RCC_APB1Periph, FunctionalState Cmd); +void RCC_EnableBORReset(FunctionalState Cmd); +void RCC_EnableBackupReset(FunctionalState Cmd); +void RCC_EnableClockSecuritySystem(FunctionalState Cmd); +void RCC_ConfigMcoPllClk(uint32_t RCC_MCOPLLCLKPrescaler); +void RCC_ConfigMco(uint8_t RCC_MCO); +FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG); +void RCC_ClrFlag(void); +INTStatus RCC_GetIntStatus(uint8_t RccInt); +void RCC_ClrIntPendingBit(uint8_t RccInt); + +#ifdef __cplusplus +} +#endif + +#endif /* __N32G45X_RCC_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/inc/n32g45x_rtc.h b/inc/n32g45x_rtc.h new file mode 100644 index 0000000..8e8d94a --- /dev/null +++ b/inc/n32g45x_rtc.h @@ -0,0 +1,662 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_rtc.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_RTC_H__ +#define __N32G45X_RTC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup RTC + * @{ + */ + +/** + * @brief RTC Init structures definition + */ +typedef struct +{ + uint32_t RTC_HourFormat; /*!< Specifies the RTC Hour Format. + This parameter can be a value of @ref RTC_Hour_Formats */ + + uint32_t RTC_AsynchPrediv; /*!< Specifies the RTC Asynchronous Predivider value. + This parameter must be set to a value lower than 0x7F */ + + uint32_t RTC_SynchPrediv; /*!< Specifies the RTC Synchronous Predivider value. + This parameter must be set to a value lower than 0x7FFF */ +} RTC_InitType; + +/** + * @brief RTC Time structure definition + */ +typedef struct +{ + uint8_t Hours; /*!< Specifies the RTC Time Hour. + This parameter must be set to a value in the 0-12 range + if the RTC_12HOUR_FORMAT is selected or 0-23 range if + the RTC_24HOUR_FORMAT is selected. */ + + uint8_t Minutes; /*!< Specifies the RTC Time Minutes. + This parameter must be set to a value in the 0-59 range. */ + + uint8_t Seconds; /*!< Specifies the RTC Time Seconds. + This parameter must be set to a value in the 0-59 range. */ + + uint8_t H12; /*!< Specifies the RTC AM/PM Time. + This parameter can be a value of @ref RTC_AM_PM_Definitions */ +} RTC_TimeType; + +/** + * @brief RTC Date structure definition + */ +typedef struct +{ + uint8_t WeekDay; /*!< Specifies the RTC Date WeekDay. + This parameter can be a value of @ref RTC_WeekDay_Definitions */ + + uint8_t Month; /*!< Specifies the RTC Date Month (in BCD format). + This parameter can be a value of @ref RTC_Month_Date_Definitions */ + + uint8_t Date; /*!< Specifies the RTC Date. + This parameter must be set to a value in the 1-31 range. */ + + uint8_t Year; /*!< Specifies the RTC Date Year. + This parameter must be set to a value in the 0-99 range. */ +} RTC_DateType; + +/** + * @brief RTC Alarm structure definition + */ +typedef struct +{ + RTC_TimeType AlarmTime; /*!< Specifies the RTC Alarm Time members. */ + + uint32_t AlarmMask; /*!< Specifies the RTC Alarm Masks. + This parameter can be a value of @ref RTC_AlarmMask_Definitions */ + + uint32_t DateWeekMode; /*!< Specifies the RTC Alarm is on Date or WeekDay. + This parameter can be a value of @ref RTC_AlarmDateWeekDay_Definitions */ + + uint8_t DateWeekValue; /*!< Specifies the RTC Alarm Date/WeekDay. + If the Alarm Date is selected, this parameter + must be set to a value in the 1-31 range. + If the Alarm WeekDay is selected, this + parameter can be a value of @ref RTC_WeekDay_Definitions */ +} RTC_AlarmType; + +/** @addtogroup RTC_Exported_Constants + * @{ + */ + +/** @addtogroup RTC_Hour_Formats + * @{ + */ +#define RTC_24HOUR_FORMAT ((uint32_t)0x00000000) +#define RTC_12HOUR_FORMAT ((uint32_t)0x00000040) +#define IS_RTC_HOUR_FORMAT(FORMAT) (((FORMAT) == RTC_12HOUR_FORMAT) || ((FORMAT) == RTC_24HOUR_FORMAT)) +/** + * @} + */ + +/** @addtogroup RTC_Asynchronous_Predivider + * @{ + */ +#define IS_RTC_PREDIV_ASYNCH(PREDIV) ((PREDIV) <= 0x7F) + +/** + * @} + */ + +/** @addtogroup RTC_Synchronous_Predivider + * @{ + */ +#define IS_RTC_PREDIV_SYNCH(PREDIV) ((PREDIV) <= 0x7FFF) + +/** + * @} + */ + +/** @addtogroup RTC_Time_Definitions + * @{ + */ +#define IS_RTC_12HOUR(HOUR) (((HOUR) > 0) && ((HOUR) <= 12)) +#define IS_RTC_24HOUR(HOUR) ((HOUR) <= 23) +#define IS_RTC_MINUTES(MINUTES) ((MINUTES) <= 59) +#define IS_RTC_SECONDS(SECONDS) ((SECONDS) <= 59) + +/** + * @} + */ + +/** @addtogroup RTC_AM_PM_Definitions + * @{ + */ +#define RTC_AM_H12 ((uint8_t)0x00) +#define RTC_PM_H12 ((uint8_t)0x40) +#define IS_RTC_H12(PM) (((PM) == RTC_AM_H12) || ((PM) == RTC_PM_H12)) + +/** + * @} + */ + +/** @addtogroup RTC_Year_Date_Definitions + * @{ + */ +#define IS_RTC_YEAR(YEAR) ((YEAR) <= 99) + +/** + * @} + */ + +/** @addtogroup RTC_Month_Date_Definitions + * @{ + */ + +/* Coded in BCD format */ +#define RTC_MONTH_JANUARY ((uint8_t)0x01) +#define RTC_MONTH_FEBRURY ((uint8_t)0x02) +#define RTC_MONTH_MARCH ((uint8_t)0x03) +#define RTC_MONTH_APRIL ((uint8_t)0x04) +#define RTC_MONTH_MAY ((uint8_t)0x05) +#define RTC_MONTH_JUNE ((uint8_t)0x06) +#define RTC_MONTH_JULY ((uint8_t)0x07) +#define RTC_MONTH_AUGUST ((uint8_t)0x08) +#define RTC_MONTH_SEPTEMBER ((uint8_t)0x09) +#define RTC_MONTH_OCTOBER ((uint8_t)0x10) +#define RTC_MONTH_NOVEMBER ((uint8_t)0x11) +#define RTC_MONTH_DECEMBER ((uint8_t)0x12) +#define IS_RTC_MONTH(MONTH) (((MONTH) >= 1) && ((MONTH) <= 12)) +#define IS_RTC_DATE(DATE) (((DATE) >= 1) && ((DATE) <= 31)) + +/** + * @} + */ + +/** @addtogroup RTC_WeekDay_Definitions + * @{ + */ + +#define RTC_WEEKDAY_MONDAY ((uint8_t)0x01) +#define RTC_WEEKDAY_TUESDAY ((uint8_t)0x02) +#define RTC_WEEKDAY_WEDNESDAY ((uint8_t)0x03) +#define RTC_WEEKDAY_THURSDAY ((uint8_t)0x04) +#define RTC_WEEKDAY_FRIDAY ((uint8_t)0x05) +#define RTC_WEEKDAY_SATURDAY ((uint8_t)0x06) +#define RTC_WEEKDAY_SUNDAY ((uint8_t)0x07) +#define IS_RTC_WEEKDAY(WEEKDAY) \ + (((WEEKDAY) == RTC_WEEKDAY_MONDAY) || ((WEEKDAY) == RTC_WEEKDAY_TUESDAY) || ((WEEKDAY) == RTC_WEEKDAY_WEDNESDAY) \ + || ((WEEKDAY) == RTC_WEEKDAY_THURSDAY) || ((WEEKDAY) == RTC_WEEKDAY_FRIDAY) \ + || ((WEEKDAY) == RTC_WEEKDAY_SATURDAY) || ((WEEKDAY) == RTC_WEEKDAY_SUNDAY)) +/** + * @} + */ + +/** @addtogroup RTC_Alarm_Definitions + * @{ + */ +#define IS_RTC_ALARM_WEEKDAY_DATE(DATE) (((DATE) > 0) && ((DATE) <= 31)) +#define IS_RTC_ALARM_WEEKDAY_WEEKDAY(WEEKDAY) \ + (((WEEKDAY) == RTC_WEEKDAY_MONDAY) || ((WEEKDAY) == RTC_WEEKDAY_TUESDAY) || ((WEEKDAY) == RTC_WEEKDAY_WEDNESDAY) \ + || ((WEEKDAY) == RTC_WEEKDAY_THURSDAY) || ((WEEKDAY) == RTC_WEEKDAY_FRIDAY) \ + || ((WEEKDAY) == RTC_WEEKDAY_SATURDAY) || ((WEEKDAY) == RTC_WEEKDAY_SUNDAY)) + +/** + * @} + */ + +/** @addtogroup RTC_AlarmDateWeekDay_Definitions + * @{ + */ +#define RTC_ALARM_SEL_WEEKDAY_DATE ((uint32_t)0x00000000) +#define RTC_ALARM_SEL_WEEKDAY_WEEKDAY ((uint32_t)0x40000000) + +#define IS_RTC_ALARM_WEEKDAY_SEL(SEL) \ + (((SEL) == RTC_ALARM_SEL_WEEKDAY_DATE) || ((SEL) == RTC_ALARM_SEL_WEEKDAY_WEEKDAY)) + +/** + * @} + */ + +/** @addtogroup RTC_AlarmMask_Definitions + * @{ + */ +#define RTC_ALARMMASK_NONE ((uint32_t)0x00000000) +#define RTC_ALARMMASK_WEEKDAY ((uint32_t)0x80000000) +#define RTC_ALARMMASK_HOURS ((uint32_t)0x00800000) +#define RTC_ALARMMASK_MINUTES ((uint32_t)0x00008000) +#define RTC_ALARMMASK_SECONDS ((uint32_t)0x00000080) +#define RTC_ALARMMASK_ALL ((uint32_t)0x80808080) +#define IS_ALARM_MASK(INTEN) (((INTEN)&0x7F7F7F7F) == (uint32_t)RESET) + +/** + * @} + */ + +/** @addtogroup RTC_Alarms_Definitions + * @{ + */ +#define RTC_A_ALARM ((uint32_t)0x00000100) +#define RTC_B_ALARM ((uint32_t)0x00000200) +#define IS_RTC_ALARM_SEL(ALARM) (((ALARM) == RTC_A_ALARM) || ((ALARM) == RTC_B_ALARM)) +#define IS_RTC_ALARM_ENABLE(ALARM) (((ALARM) & (RTC_A_ALARM | RTC_B_ALARM)) != (uint32_t)RESET) + +/** + * @} + */ + +/** @addtogroup RTC_Alarm_Sub_Seconds_Masks_Definitions + * @{ + */ +#define RTC_SUBS_MASK_ALL \ + ((uint32_t)0x00000000) /*!< All Alarm SS fields are masked. \ + There is no comparison on sub seconds \ + for Alarm */ +#define RTC_SUBS_MASK_SS14_1 \ + ((uint32_t)0x01000000) /*!< SS[14:1] are don't care in Alarm \ + comparison. Only SS[0] is compared. */ +#define RTC_SUBS_MASK_SS14_2 \ + ((uint32_t)0x02000000) /*!< SS[14:2] are don't care in Alarm \ + comparison. Only SS[1:0] are compared */ +#define RTC_SUBS_MASK_SS14_3 \ + ((uint32_t)0x03000000) /*!< SS[14:3] are don't care in Alarm \ + comparison. Only SS[2:0] are compared */ +#define RTC_SUBS_MASK_SS14_4 \ + ((uint32_t)0x04000000) /*!< SS[14:4] are don't care in Alarm \ + comparison. Only SS[3:0] are compared */ +#define RTC_SUBS_MASK_SS14_5 \ + ((uint32_t)0x05000000) /*!< SS[14:5] are don't care in Alarm \ + comparison. Only SS[4:0] are compared */ +#define RTC_SUBS_MASK_SS14_6 \ + ((uint32_t)0x06000000) /*!< SS[14:6] are don't care in Alarm \ + comparison. Only SS[5:0] are compared */ +#define RTC_SUBS_MASK_SS14_7 \ + ((uint32_t)0x07000000) /*!< SS[14:7] are don't care in Alarm \ + comparison. Only SS[6:0] are compared */ +#define RTC_SUBS_MASK_SS14_8 \ + ((uint32_t)0x08000000) /*!< SS[14:8] are don't care in Alarm \ + comparison. Only SS[7:0] are compared */ +#define RTC_SUBS_MASK_SS14_9 \ + ((uint32_t)0x09000000) /*!< SS[14:9] are don't care in Alarm \ + comparison. Only SS[8:0] are compared */ +#define RTC_SUBS_MASK_SS14_10 \ + ((uint32_t)0x0A000000) /*!< SS[14:10] are don't care in Alarm \ + comparison. Only SS[9:0] are compared */ +#define RTC_SUBS_MASK_SS14_11 \ + ((uint32_t)0x0B000000) /*!< SS[14:11] are don't care in Alarm \ + comparison. Only SS[10:0] are compared */ +#define RTC_SUBS_MASK_SS14_12 \ + ((uint32_t)0x0C000000) /*!< SS[14:12] are don't care in Alarm \ + comparison.Only SS[11:0] are compared */ +#define RTC_SUBS_MASK_SS14_13 \ + ((uint32_t)0x0D000000) /*!< SS[14:13] are don't care in Alarm \ + comparison. Only SS[12:0] are compared */ +#define RTC_SUBS_MASK_SS14_14 \ + ((uint32_t)0x0E000000) /*!< SS[14] is don't care in Alarm \ + comparison.Only SS[13:0] are compared */ +#define RTC_SUBS_MASK_NONE \ + ((uint32_t)0x0F000000) /*!< SS[14:0] are compared and must match \ + to activate alarm. */ +#define IS_RTC_ALARM_SUB_SECOND_MASK_MODE(INTEN) \ + (((INTEN) == RTC_SUBS_MASK_ALL) || ((INTEN) == RTC_SUBS_MASK_SS14_1) || ((INTEN) == RTC_SUBS_MASK_SS14_2) \ + || ((INTEN) == RTC_SUBS_MASK_SS14_3) || ((INTEN) == RTC_SUBS_MASK_SS14_4) || ((INTEN) == RTC_SUBS_MASK_SS14_5) \ + || ((INTEN) == RTC_SUBS_MASK_SS14_6) || ((INTEN) == RTC_SUBS_MASK_SS14_7) || ((INTEN) == RTC_SUBS_MASK_SS14_8) \ + || ((INTEN) == RTC_SUBS_MASK_SS14_9) || ((INTEN) == RTC_SUBS_MASK_SS14_10) || ((INTEN) == RTC_SUBS_MASK_SS14_11) \ + || ((INTEN) == RTC_SUBS_MASK_SS14_12) || ((INTEN) == RTC_SUBS_MASK_SS14_13) || ((INTEN) == RTC_SUBS_MASK_SS14_14) \ + || ((INTEN) == RTC_SUBS_MASK_NONE)) +/** + * @} + */ + +/** @addtogroup RTC_Alarm_Sub_Seconds_Value + * @{ + */ + +#define IS_RTC_ALARM_SUB_SECOND_VALUE(VALUE) ((VALUE) <= 0x00007FFF) + +/** + * @} + */ + +/** @addtogroup RTC_Wakeup_Timer_Definitions + * @{ + */ +#define RTC_WKUPCLK_RTCCLK_DIV16 ((uint32_t)0x00000000) +#define RTC_WKUPCLK_RTCCLK_DIV8 ((uint32_t)0x00000001) +#define RTC_WKUPCLK_RTCCLK_DIV4 ((uint32_t)0x00000002) +#define RTC_WKUPCLK_RTCCLK_DIV2 ((uint32_t)0x00000003) +#define RTC_WKUPCLK_CK_SPRE_16BITS ((uint32_t)0x00000004) + +#define IS_RTC_WKUP_CLOCK(CLOCK) \ + (((CLOCK) == RTC_WKUPCLK_RTCCLK_DIV16) || ((CLOCK) == RTC_WKUPCLK_RTCCLK_DIV8) \ + || ((CLOCK) == RTC_WKUPCLK_RTCCLK_DIV4) || ((CLOCK) == RTC_WKUPCLK_RTCCLK_DIV2) \ + || ((CLOCK) == RTC_WKUPCLK_CK_SPRE_16BITS)) +#define IS_RTC_WKUP_COUNTER(COUNTER) ((COUNTER) <= 0xFFFF) +/** + * @} + */ + +/** @addtogroup RTC_Time_Stamp_Edges_definitions + * @{ + */ +#define RTC_TIMESTAMP_EDGE_RISING ((uint32_t)0x00000000) +#define RTC_TIMESTAMP_EDGE_FALLING ((uint32_t)0x00000008) +#define IS_RTC_TIMESTAMP_EDGE_MODE(EDGE) \ + (((EDGE) == RTC_TIMESTAMP_EDGE_RISING) || ((EDGE) == RTC_TIMESTAMP_EDGE_FALLING)) +/** + * @} + */ + +/** @addtogroup RTC_Output_selection_Definitions + * @{ + */ +#define RTC_OUTPUT_DIS ((uint32_t)0x00000000) +#define RTC_OUTPUT_ALA ((uint32_t)0x00200000) +#define RTC_OUTPUT_ALB ((uint32_t)0x00400000) +#define RTC_OUTPUT_WKUP ((uint32_t)0x00600000) + +#define IS_RTC_OUTPUT_MODE(OUTPUT) \ + (((OUTPUT) == RTC_OUTPUT_DIS) || ((OUTPUT) == RTC_OUTPUT_ALA) || ((OUTPUT) == RTC_OUTPUT_ALB) \ + || ((OUTPUT) == RTC_OUTPUT_WKUP)) + +/** + * @} + */ + +/** @addtogroup RTC_Output_Polarity_Definitions + * @{ + */ +#define RTC_OUTPOL_HIGH ((uint32_t)0x00000000) +#define RTC_OUTPOL_LOW ((uint32_t)0x00100000) +#define IS_RTC_OUTPUT_POL(POL) (((POL) == RTC_OUTPOL_HIGH) || ((POL) == RTC_OUTPOL_LOW)) +/** + * @} + */ + + +/** @addtogroup RTC_Calib_Output_selection_Definitions + * @{ + */ +#define RTC_CALIB_OUTPUT_256HZ ((uint32_t)0x00000000) +#define RTC_CALIB_OUTPUT_1HZ ((uint32_t)0x00080000) +#define IS_RTC_CALIB_OUTPUT(OUTPUT) (((OUTPUT) == RTC_CALIB_OUTPUT_256HZ) || ((OUTPUT) == RTC_CALIB_OUTPUT_1HZ)) +/** + * @} + */ + +/** @addtogroup RTC_Smooth_calib_period_Definitions + * @{ + */ +#define SMOOTH_CALIB_32SEC \ + ((uint32_t)0x00000000) /*!< if RTCCLK = 32768 Hz, Smooth calibation \ + period is 32s, else 2exp20 RTCCLK seconds */ +#define SMOOTH_CALIB_16SEC \ + ((uint32_t)0x00002000) /*!< if RTCCLK = 32768 Hz, Smooth calibation \ + period is 16s, else 2exp19 RTCCLK seconds */ +#define SMOOTH_CALIB_8SEC \ + ((uint32_t)0x00004000) /*!< if RTCCLK = 32768 Hz, Smooth calibation \ + period is 8s, else 2exp18 RTCCLK seconds */ +#define IS_RTC_SMOOTH_CALIB_PERIOD_SEL(PERIOD) \ + (((PERIOD) == SMOOTH_CALIB_32SEC) || ((PERIOD) == SMOOTH_CALIB_16SEC) || ((PERIOD) == SMOOTH_CALIB_8SEC)) + +/** + * @} + */ + +/** @addtogroup RTC_Smooth_calib_Plus_pulses_Definitions + * @{ + */ +#define RTC_SMOOTH_CALIB_PLUS_PULSES_SET \ + ((uint32_t)0x00008000) /*!< The number of RTCCLK pulses added \ + during a X -second window = Y - CALM[8:0]. \ + with Y = 512, 256, 128 when X = 32, 16, 8 */ +#define RTC_SMOOTH_CALIB_PLUS_PULSES__RESET \ + ((uint32_t)0x00000000) /*!< The number of RTCCLK pulses subbstited \ + during a 32-second window = CALM[8:0]. */ +#define IS_RTC_SMOOTH_CALIB_PLUS(PLUS) \ + (((PLUS) == RTC_SMOOTH_CALIB_PLUS_PULSES_SET) || ((PLUS) == RTC_SMOOTH_CALIB_PLUS_PULSES__RESET)) + +/** + * @} + */ + +/** @addtogroup RTC_Smooth_calib_Minus_pulses_Definitions + * @{ + */ +#define IS_RTC_SMOOTH_CALIB_MINUS(VALUE) ((VALUE) <= 0x000001FF) + +/** + * @} + */ + +/** @addtogroup RTC_DayLightSaving_Definitions + * @{ + */ +#define RTC_DAYLIGHT_SAVING_SUB1H ((uint32_t)0x00020000) +#define RTC_DAYLIGHT_SAVING_ADD1H ((uint32_t)0x00010000) +#define IS_RTC_DAYLIGHT_SAVING(SAVE) (((SAVE) == RTC_DAYLIGHT_SAVING_SUB1H) || ((SAVE) == RTC_DAYLIGHT_SAVING_ADD1H)) + +#define RTC_STORE_OPERATION_RESET ((uint32_t)0x00000000) +#define RTC_STORE_OPERATION_SET ((uint32_t)0x00040000) +#define IS_RTC_STORE_OPERATION(OPERATION) \ + (((OPERATION) == RTC_STORE_OPERATION_RESET) || ((OPERATION) == RTC_STORE_OPERATION_SET)) +/** + * @} + */ + +/** @addtogroup RTC_Output_Type_ALARM_OUT + * @{ + */ +#define RTC_OUTPUT_OPENDRAIN ((uint32_t)0x00000000) +#define RTC_OUTPUT_PUSHPULL ((uint32_t)0x00000001) +#define IS_RTC_OUTPUT_TYPE(TYPE) (((TYPE) == RTC_OUTPUT_OPENDRAIN) || ((TYPE) == RTC_OUTPUT_PUSHPULL)) + +/** + * @} + */ +/** @addtogroup RTC_Add_Fraction_Of_Second_Value + * @{ + */ +#define RTC_SHIFT_SUB1S_DISABLE ((uint32_t)0x00000000) +#define RTC_SHIFT_SUB1S_ENABLE ((uint32_t)0x80000000) +#define IS_RTC_SHIFT_SUB1S(SEL) (((SEL) == RTC_SHIFT_SUB1S_DISABLE) || ((SEL) == RTC_SHIFT_SUB1S_ENABLE)) +/** + * @} + */ +/** @addtogroup RTC_Substract_1_Second_Parameter_Definitions + * @{ + */ +#define IS_RTC_SHIFT_ADFS(FS) ((FS) <= 0x00007FFF) + +/** + * @} + */ + +/** @addtogroup RTC_Input_parameter_format_definitions + * @{ + */ +#define RTC_FORMAT_BIN ((uint32_t)0x000000000) +#define RTC_FORMAT_BCD ((uint32_t)0x000000001) +#define IS_RTC_FORMAT(FORMAT) (((FORMAT) == RTC_FORMAT_BIN) || ((FORMAT) == RTC_FORMAT_BCD)) + +/** + * @} + */ + +/** @addtogroup RTC_Flags_Definitions + * @{ + */ +#define RTC_FLAG_RECPF ((uint32_t)0x00010000) +#define RTC_FLAG_TISOVF ((uint32_t)0x00001000) +#define RTC_FLAG_TISF ((uint32_t)0x00000800) +#define RTC_FLAG_WTF ((uint32_t)0x00000400) +#define RTC_FLAG_ALBF ((uint32_t)0x00000200) +#define RTC_FLAG_ALAF ((uint32_t)0x00000100) +#define RTC_FLAG_INITF ((uint32_t)0x00000040) +#define RTC_FLAG_RSYF ((uint32_t)0x00000020) +#define RTC_FLAG_INITSF ((uint32_t)0x00000010) +#define RTC_FLAG_SHOPF ((uint32_t)0x00000008) +#define RTC_FLAG_WTWF ((uint32_t)0x00000004) +#define RTC_FLAG_ALBWF ((uint32_t)0x00000002) +#define RTC_FLAG_ALAWF ((uint32_t)0x00000001) +#define IS_RTC_GET_FLAG(FLAG) \ + (((FLAG) == RTC_FLAG_TISOVF) || ((FLAG) == RTC_FLAG_TISF) || ((FLAG) == RTC_FLAG_WTF) || ((FLAG) == RTC_FLAG_ALBF) \ + || ((FLAG) == RTC_FLAG_ALAF) || ((FLAG) == RTC_FLAG_INITF) || ((FLAG) == RTC_FLAG_RSYF) \ + || ((FLAG) == RTC_FLAG_WTWF) || ((FLAG) == RTC_FLAG_ALBWF) || ((FLAG) == RTC_FLAG_ALAWF) \ + || ((FLAG) == RTC_FLAG_RECPF) || ((FLAG) == RTC_FLAG_SHOPF) || ((FLAG) == RTC_FLAG_INITSF)) +#define IS_RTC_CLEAR_FLAG(FLAG) (((FLAG) != (uint32_t)RESET) && (((FLAG)&0x00011fff) == (uint32_t)SET)) + +/** + * @} + */ + +/** @addtogroup RTC_Interrupts_Definitions + * @{ + */ + +#define RTC_INT_WUT ((uint32_t)0x00004000) +#define RTC_INT_ALRB ((uint32_t)0x00002000) +#define RTC_INT_ALRA ((uint32_t)0x00001000) + +#define IS_RTC_CONFIG_INT(IT) (((IT) != (uint32_t)RESET) && (((IT)&0xFFFF0FFB) == (uint32_t)RESET)) +#define IS_RTC_GET_INT(IT) \ + (((IT) == RTC_INT_WUT) || ((IT) == RTC_INT_ALRB) || ((IT) == RTC_INT_ALRA)) +#define IS_RTC_CLEAR_INT(IT) (((IT) != (uint32_t)RESET) && (((IT)&0x00007000) == (uint32_t)SET)) + +/** + * @} + */ + +/** @addtogroup RTC_Legacy + * @{ + */ +#define RTC_DigitalCalibConfig RTC_CoarseCalibConfig +#define RTC_DigitalCalibCmd RTC_CoarseCalibCmd + +/** + * @} + */ + +/** + * @} + */ + +/* Function used to set the RTC configuration to the default reset state *****/ +ErrorStatus RTC_DeInit(void); + +/* Initialization and Configuration functions *********************************/ +ErrorStatus RTC_Init(RTC_InitType* RTC_InitStruct); +void RTC_StructInit(RTC_InitType* RTC_InitStruct); +void RTC_EnableWriteProtection(FunctionalState Cmd); +ErrorStatus RTC_EnterInitMode(void); +void RTC_ExitInitMode(void); +ErrorStatus RTC_WaitForSynchro(void); +ErrorStatus RTC_EnableRefClock(FunctionalState Cmd); +void RTC_EnableBypassShadow(FunctionalState Cmd); + +/* Time and Date configuration functions **************************************/ +ErrorStatus RTC_ConfigTime(uint32_t RTC_Format, RTC_TimeType* RTC_TimeStruct); +void RTC_TimeStructInit(RTC_TimeType* RTC_TimeStruct); +void RTC_GetTime(uint32_t RTC_Format, RTC_TimeType* RTC_TimeStruct); +uint32_t RTC_GetSubSecond(void); +ErrorStatus RTC_SetDate(uint32_t RTC_Format, RTC_DateType* RTC_DateStruct); +void RTC_DateStructInit(RTC_DateType* RTC_DateStruct); +void RTC_GetDate(uint32_t RTC_Format, RTC_DateType* RTC_DateStruct); + +/* Alarms (Alarm A and Alarm B) configuration functions **********************/ +void RTC_SetAlarm(uint32_t RTC_Format, uint32_t RTC_Alarm, RTC_AlarmType* RTC_AlarmStruct); +void RTC_AlarmStructInit(RTC_AlarmType* RTC_AlarmStruct); +void RTC_GetAlarm(uint32_t RTC_Format, uint32_t RTC_Alarm, RTC_AlarmType* RTC_AlarmStruct); +ErrorStatus RTC_EnableAlarm(uint32_t RTC_Alarm, FunctionalState Cmd); +void RTC_ConfigAlarmSubSecond(uint32_t RTC_Alarm, uint32_t RTC_AlarmSubSecondValue, uint32_t RTC_AlarmSubSecondMask); +uint32_t RTC_GetAlarmSubSecond(uint32_t RTC_Alarm); + +/* WakeUp Timer configuration functions ***************************************/ +void RTC_ConfigWakeUpClock(uint32_t RTC_WakeUpClock); +void RTC_SetWakeUpCounter(uint32_t RTC_WakeUpCounter); +uint32_t RTC_GetWakeUpCounter(void); +ErrorStatus RTC_EnableWakeUp(FunctionalState Cmd); + +/* Daylight Saving configuration functions ************************************/ +void RTC_ConfigDayLightSaving(uint32_t RTC_DayLightSaving, uint32_t RTC_StoreOperation); +uint32_t RTC_GetStoreOperation(void); + +/* Output pin Configuration function ******************************************/ +void RTC_ConfigOutput(uint32_t RTC_Output, uint32_t RTC_OutputPolarity); + +/* Coarse and Smooth Calibration configuration functions **********************/ +void RTC_EnableCalibOutput(FunctionalState Cmd); +void RTC_ConfigCalibOutput(uint32_t RTC_CalibOutput); +ErrorStatus RTC_ConfigSmoothCalib(uint32_t RTC_SmoothCalibPeriod, + uint32_t RTC_SmoothCalibPlusPulses, + uint32_t RTC_SmouthCalibMinusPulsesValue); + +/* TimeStamp configuration functions ******************************************/ +void RTC_EnableTimeStamp(uint32_t RTC_TimeStampEdge, FunctionalState Cmd); +void RTC_GetTimeStamp(uint32_t RTC_Format, RTC_TimeType* RTC_StampTimeStruct, RTC_DateType* RTC_StampDateStruct); +uint32_t RTC_GetTimeStampSubSecond(void); + +/* Output Type Config configuration functions *********************************/ +void RTC_ConfigOutputType(uint32_t RTC_OutputType); + +/* RTC_Shift_control_synchonisation_functions *********************************/ +ErrorStatus RTC_ConfigSynchroShift(uint32_t RTC_ShiftAddFS, uint32_t RTC_ShiftSub1s); + +/* Interrupts and flags management functions **********************************/ +void RTC_ConfigInt(uint32_t RTC_INT, FunctionalState Cmd); +FlagStatus RTC_GetFlagStatus(uint32_t RTC_FLAG); +void RTC_ClrFlag(uint32_t RTC_FLAG); +INTStatus RTC_GetITStatus(uint32_t RTC_INT); +void RTC_ClrIntPendingBit(uint32_t RTC_INT); +/* WakeUp TSC function **********************************/ +void RTC_EnableWakeUpTsc(uint32_t count); +#ifdef __cplusplus +} +#endif + +#endif /*__N32G45X_RTC_H__ */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/inc/n32g45x_sdio.h b/inc/n32g45x_sdio.h new file mode 100644 index 0000000..c70eb58 --- /dev/null +++ b/inc/n32g45x_sdio.h @@ -0,0 +1,494 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_sdio.h + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_SDIO_H__ +#define __N32G45X_SDIO_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup SDIO + * @{ + */ + +/** @addtogroup SDIO_Exported_Types + * @{ + */ + +typedef struct +{ + uint32_t ClkEdge; /*!< Specifies the clock transition on which the bit capture is made. + This parameter can be a value of @ref SDIO_Clock_Edge */ + + uint32_t ClkBypass; /*!< Specifies whether the SDIO Clock divider bypass is + enabled or disabled. + This parameter can be a value of @ref SDIO_Clock_Bypass */ + + uint32_t ClkPwrSave; /*!< Specifies whether SDIO Clock output is enabled or + disabled when the bus is idle. + This parameter can be a value of @ref SDIO_Clock_Power_Save */ + + uint32_t BusWidth; /*!< Specifies the SDIO bus width. + This parameter can be a value of @ref SDIO_Bus_Wide */ + + uint32_t HardwareClkCtrl; /*!< Specifies whether the SDIO hardware flow control is enabled or disabled. + This parameter can be a value of @ref SDIO_Hardware_Flow_Control */ + + uint8_t ClkDiv; /*!< Specifies the clock frequency of the SDIO controller. + This parameter can be a value between 0x00 and 0xFF. */ + +} SDIO_InitType; + +typedef struct +{ + uint32_t CmdArgument; /*!< Specifies the SDIO command argument which is sent + to a card as part of a command message. If a command + contains an argument, it must be loaded into this register + before writing the command to the command register */ + + uint32_t CmdIndex; /*!< Specifies the SDIO command index. It must be lower than 0x40. */ + + uint32_t ResponseType; /*!< Specifies the SDIO response type. + This parameter can be a value of @ref SDIO_Response_Type */ + + uint32_t WaitType; /*!< Specifies whether SDIO wait-for-interrupt request is enabled or disabled. + This parameter can be a value of @ref SDIO_Wait_Interrupt_State */ + + uint32_t CPSMConfig; /*!< Specifies whether SDIO Command path state machine (CPSM) + is enabled or disabled. + This parameter can be a value of @ref SDIO_CPSM_State */ +} SDIO_CmdInitType; + +typedef struct +{ + uint32_t DatTimeout; /*!< Specifies the data timeout period in card bus clock periods. */ + + uint32_t DatLen; /*!< Specifies the number of data bytes to be transferred. */ + + uint32_t DatBlkSize; /*!< Specifies the data block size for block transfer. + This parameter can be a value of @ref SDIO_Data_Block_Size */ + + uint32_t TransferDirection; /*!< Specifies the data transfer direction, whether the transfer + is a read or write. + This parameter can be a value of @ref SDIO_Transfer_Direction */ + + uint32_t TransferMode; /*!< Specifies whether data transfer is in stream or block mode. + This parameter can be a value of @ref SDIO_Transfer_Type */ + + uint32_t DPSMConfig; /*!< Specifies whether SDIO Data path state machine (DPSM) + is enabled or disabled. + This parameter can be a value of @ref SDIO_DPSM_State */ +} SDIO_DataInitType; + +/** + * @} + */ + +/** @addtogroup SDIO_Exported_Constants + * @{ + */ + +/** @addtogroup SDIO_Clock_Edge + * @{ + */ + +#define SDIO_CLKEDGE_RISING ((uint32_t)0x00000000) +#define SDIO_CLKEDGE_FALLING ((uint32_t)0x00002000) +#define IS_SDIO_CLK_EDGE(EDGE) (((EDGE) == SDIO_CLKEDGE_RISING) || ((EDGE) == SDIO_CLKEDGE_FALLING)) +/** + * @} + */ + +/** @addtogroup SDIO_Clock_Bypass + * @{ + */ + +#define SDIO_ClkBYPASS_DISABLE ((uint32_t)0x00000000) +#define SDIO_ClkBYPASS_ENABLE ((uint32_t)0x00000400) +#define IS_SDIO_CLK_BYPASS(BYPASS) (((BYPASS) == SDIO_ClkBYPASS_DISABLE) || ((BYPASS) == SDIO_ClkBYPASS_ENABLE)) +/** + * @} + */ + +/** @addtogroup SDIO_Clock_Power_Save + * @{ + */ + +#define SDIO_CLKPOWERSAVE_DISABLE ((uint32_t)0x00000000) +#define SDIO_CLKPOWERSAVE_ENABLE ((uint32_t)0x00000200) +#define IS_SDIO_CLK_POWER_SAVE(SAVE) (((SAVE) == SDIO_CLKPOWERSAVE_DISABLE) || ((SAVE) == SDIO_CLKPOWERSAVE_ENABLE)) +/** + * @} + */ + +/** @addtogroup SDIO_Bus_Wide + * @{ + */ + +#define SDIO_BUSWIDTH_1B ((uint32_t)0x00000000) +#define SDIO_BUSWIDTH_4B ((uint32_t)0x00000800) +#define SDIO_BUSWIDTH_8B ((uint32_t)0x00001000) +#define IS_SDIO_BUS_WIDTH(WIDE) \ + (((WIDE) == SDIO_BUSWIDTH_1B) || ((WIDE) == SDIO_BUSWIDTH_4B) || ((WIDE) == SDIO_BUSWIDTH_8B)) + +/** + * @} + */ + +/** @addtogroup SDIO_Hardware_Flow_Control + * @{ + */ + +#define SDIO_HARDWARE_CLKCTRL_DISABLE ((uint32_t)0x00000000) +#define SDIO_HARDWARE_CLKCTRL_ENABLE ((uint32_t)0x00004000) +#define IS_SDIO_HARDWARE_CLKCTRL(CONTROL) \ + (((CONTROL) == SDIO_HARDWARE_CLKCTRL_DISABLE) || ((CONTROL) == SDIO_HARDWARE_CLKCTRL_ENABLE)) +/** + * @} + */ + +/** @addtogroup SDIO_Power_State + * @{ + */ + +#define SDIO_POWER_CTRL_OFF ((uint32_t)0x00000000) +#define SDIO_POWER_CTRL_ON ((uint32_t)0x00000003) +#define IS_SDIO_POWER_CTRL(STATE) (((STATE) == SDIO_POWER_CTRL_OFF) || ((STATE) == SDIO_POWER_CTRL_ON)) +/** + * @} + */ + +/** @addtogroup SDIO_Interrupt_sources + * @{ + */ + +#define SDIO_INT_CCRCERR ((uint32_t)0x00000001) +#define SDIO_INT_DCRCERR ((uint32_t)0x00000002) +#define SDIO_INT_CMDTIMEOUT ((uint32_t)0x00000004) +#define SDIO_INT_DATTIMEOUT ((uint32_t)0x00000008) +#define SDIO_INT_TXURERR ((uint32_t)0x00000010) +#define SDIO_INT_RXORERR ((uint32_t)0x00000020) +#define SDIO_INT_CMDRESPRECV ((uint32_t)0x00000040) +#define SDIO_INT_CMDSEND ((uint32_t)0x00000080) +#define SDIO_INT_DATEND ((uint32_t)0x00000100) +#define SDIO_INT_SBERR ((uint32_t)0x00000200) +#define SDIO_INT_DATBLKEND ((uint32_t)0x00000400) +#define SDIO_INT_CMDRUN ((uint32_t)0x00000800) +#define SDIO_INT_TXRUN ((uint32_t)0x00001000) +#define SDIO_INT_RXRUN ((uint32_t)0x00002000) +#define SDIO_INT_TFIFOHE ((uint32_t)0x00004000) +#define SDIO_INT_RFIFOHF ((uint32_t)0x00008000) +#define SDIO_INT_TFIFOF ((uint32_t)0x00010000) +#define SDIO_INT_RFIFOF ((uint32_t)0x00020000) +#define SDIO_INT_TFIFOE ((uint32_t)0x00040000) +#define SDIO_INT_RFIFOE ((uint32_t)0x00080000) +#define SDIO_INT_TDATVALID ((uint32_t)0x00100000) +#define SDIO_INT_RDATVALID ((uint32_t)0x00200000) +#define SDIO_INT_SDIOINT ((uint32_t)0x00400000) +#define SDIO_INT_CEATAF ((uint32_t)0x00800000) +#define IS_SDIO_INT(IT) ((((IT) & (uint32_t)0xFF000000) == 0x00) && ((IT) != (uint32_t)0x00)) +/** + * @} + */ + +/** @addtogroup SDIO_Command_Index + * @{ + */ + +#define IS_SDIO_CMD_INDEX(INDEX) ((INDEX) < 0x40) +/** + * @} + */ + +/** @addtogroup SDIO_Response_Type + * @{ + */ + +#define SDIO_RESP_NO ((uint32_t)0x00000000) +#define SDIO_RESP_SHORT ((uint32_t)0x00000040) +#define SDIO_RESP_LONG ((uint32_t)0x000000C0) +#define IS_SDIO_RESP(RESPONSE) \ + (((RESPONSE) == SDIO_RESP_NO) || ((RESPONSE) == SDIO_RESP_SHORT) || ((RESPONSE) == SDIO_RESP_LONG)) +/** + * @} + */ + +/** @addtogroup SDIO_Wait_Interrupt_State + * @{ + */ + +#define SDIO_WAIT_NO ((uint32_t)0x00000000) /*!< SDIO No Wait, TimeOut is enabled */ +#define SDIO_WAIT_INT ((uint32_t)0x00000100) /*!< SDIO Wait Interrupt Request */ +#define SDIO_WAIT_PEND ((uint32_t)0x00000200) /*!< SDIO Wait End of transfer */ +#define IS_SDIO_WAIT(WAIT) (((WAIT) == SDIO_WAIT_NO) || ((WAIT) == SDIO_WAIT_INT) || ((WAIT) == SDIO_WAIT_PEND)) +/** + * @} + */ + +/** @addtogroup SDIO_CPSM_State + * @{ + */ + +#define SDIO_CPSM_DISABLE ((uint32_t)0x00000000) +#define SDIO_CPSM_ENABLE ((uint32_t)0x00000400) +#define IS_SDIO_CPSM(CPSM) (((CPSM) == SDIO_CPSM_ENABLE) || ((CPSM) == SDIO_CPSM_DISABLE)) +/** + * @} + */ + +/** @addtogroup SDIO_Response_Registers + * @{ + */ + +#define SDIO_RESPONSE_1 ((uint32_t)0x00000000) +#define SDIO_RESPONSE_2 ((uint32_t)0x00000004) +#define SDIO_RESPONSE_3 ((uint32_t)0x00000008) +#define SDIO_RESPONSE_4 ((uint32_t)0x0000000C) +#define IS_SDIO_RESPONSE(RESP) \ + (((RESP) == SDIO_RESPONSE_1) || ((RESP) == SDIO_RESPONSE_2) || ((RESP) == SDIO_RESPONSE_3) \ + || ((RESP) == SDIO_RESPONSE_4)) +/** + * @} + */ + +/** @addtogroup SDIO_Data_Length + * @{ + */ + +#define IS_SDIO_DAT_LEN(LENGTH) ((LENGTH) <= 0x01FFFFFF) +/** + * @} + */ + +/** @addtogroup SDIO_Data_Block_Size + * @{ + */ + +#define SDIO_DATBLK_SIZE_1B ((uint32_t)0x00000000) +#define SDIO_DATBLK_SIZE_2B ((uint32_t)0x00000010) +#define SDIO_DATBLK_SIZE_4B ((uint32_t)0x00000020) +#define SDIO_DATBLK_SIZE_8B ((uint32_t)0x00000030) +#define SDIO_DATBLK_SIZE_16B ((uint32_t)0x00000040) +#define SDIO_DATBLK_SIZE_32B ((uint32_t)0x00000050) +#define SDIO_DATBLK_SIZE_64B ((uint32_t)0x00000060) +#define SDIO_DATBLK_SIZE_128B ((uint32_t)0x00000070) +#define SDIO_DATBLK_SIZE_256B ((uint32_t)0x00000080) +#define SDIO_DATBLK_SIZE_512B ((uint32_t)0x00000090) +#define SDIO_DATBLK_SIZE_1024B ((uint32_t)0x000000A0) +#define SDIO_DATBLK_SIZE_2048B ((uint32_t)0x000000B0) +#define SDIO_DATBLK_SIZE_4096B ((uint32_t)0x000000C0) +#define SDIO_DATBLK_SIZE_8192B ((uint32_t)0x000000D0) +#define SDIO_DATBLK_SIZE_16384B ((uint32_t)0x000000E0) +#define IS_SDIO_BLK_SIZE(SIZE) \ + (((SIZE) == SDIO_DATBLK_SIZE_1B) || ((SIZE) == SDIO_DATBLK_SIZE_2B) || ((SIZE) == SDIO_DATBLK_SIZE_4B) \ + || ((SIZE) == SDIO_DATBLK_SIZE_8B) || ((SIZE) == SDIO_DATBLK_SIZE_16B) || ((SIZE) == SDIO_DATBLK_SIZE_32B) \ + || ((SIZE) == SDIO_DATBLK_SIZE_64B) || ((SIZE) == SDIO_DATBLK_SIZE_128B) || ((SIZE) == SDIO_DATBLK_SIZE_256B) \ + || ((SIZE) == SDIO_DATBLK_SIZE_512B) || ((SIZE) == SDIO_DATBLK_SIZE_1024B) || ((SIZE) == SDIO_DATBLK_SIZE_2048B) \ + || ((SIZE) == SDIO_DATBLK_SIZE_4096B) || ((SIZE) == SDIO_DATBLK_SIZE_8192B) \ + || ((SIZE) == SDIO_DATBLK_SIZE_16384B)) +/** + * @} + */ + +/** @addtogroup SDIO_Transfer_Direction + * @{ + */ + +#define SDIO_TRANSDIR_TOCARD ((uint32_t)0x00000000) +#define SDIO_TRANSDIR_TOSDIO ((uint32_t)0x00000002) +#define IS_SDIO_TRANSFER_DIRECTION(DIR) (((DIR) == SDIO_TRANSDIR_TOCARD) || ((DIR) == SDIO_TRANSDIR_TOSDIO)) +/** + * @} + */ + +/** @addtogroup SDIO_Transfer_Type + * @{ + */ + +#define SDIO_TRANSMODE_BLOCK ((uint32_t)0x00000000) +#define SDIO_TRANSMODE_STREAM ((uint32_t)0x00000004) +#define IS_SDIO_TRANS_MODE(MODE) (((MODE) == SDIO_TRANSMODE_STREAM) || ((MODE) == SDIO_TRANSMODE_BLOCK)) +/** + * @} + */ + +/** @addtogroup SDIO_DPSM_State + * @{ + */ + +#define SDIO_DPSM_DISABLE ((uint32_t)0x00000000) +#define SDIO_DPSM_ENABLE ((uint32_t)0x00000001) +#define IS_SDIO_DPSM(DPSM) (((DPSM) == SDIO_DPSM_ENABLE) || ((DPSM) == SDIO_DPSM_DISABLE)) +/** + * @} + */ + +/** @addtogroup SDIO_Flags + * @{ + */ + +#define SDIO_FLAG_CCRCERR ((uint32_t)0x00000001) +#define SDIO_FLAG_DCRCERR ((uint32_t)0x00000002) +#define SDIO_FLAG_CMDTIMEOUT ((uint32_t)0x00000004) +#define SDIO_FLAG_DATTIMEOUT ((uint32_t)0x00000008) +#define SDIO_FLAG_TXURERR ((uint32_t)0x00000010) +#define SDIO_FLAG_RXORERR ((uint32_t)0x00000020) +#define SDIO_FLAG_CMDRESPRECV ((uint32_t)0x00000040) +#define SDIO_FLAG_CMDSEND ((uint32_t)0x00000080) +#define SDIO_FLAG_DATEND ((uint32_t)0x00000100) +#define SDIO_FLAG_SBERR ((uint32_t)0x00000200) +#define SDIO_FLAG_DATBLKEND ((uint32_t)0x00000400) +#define SDIO_FLAG_CMDRUN ((uint32_t)0x00000800) +#define SDIO_FLAG_TXRUN ((uint32_t)0x00001000) +#define SDIO_FLAG_RXRUN ((uint32_t)0x00002000) +#define SDIO_FLAG_TFIFOHE ((uint32_t)0x00004000) +#define SDIO_FLAG_RFIFOHF ((uint32_t)0x00008000) +#define SDIO_FLAG_TFIFOF ((uint32_t)0x00010000) +#define SDIO_FLAG_RFIFOF ((uint32_t)0x00020000) +#define SDIO_FLAG_TFIFOE ((uint32_t)0x00040000) +#define SDIO_FLAG_RFIFOE ((uint32_t)0x00080000) +#define SDIO_FLAG_TDATVALID ((uint32_t)0x00100000) +#define SDIO_FLAG_RDATVALID ((uint32_t)0x00200000) +#define SDIO_FLAG_SDIOINT ((uint32_t)0x00400000) +#define SDIO_FLAG_CEATAF ((uint32_t)0x00800000) +#define IS_SDIO_FLAG(FLAG) \ + (((FLAG) == SDIO_FLAG_CCRCERR) || ((FLAG) == SDIO_FLAG_DCRCERR) || ((FLAG) == SDIO_FLAG_CMDTIMEOUT) \ + || ((FLAG) == SDIO_FLAG_DATTIMEOUT) || ((FLAG) == SDIO_FLAG_TXURERR) || ((FLAG) == SDIO_FLAG_RXORERR) \ + || ((FLAG) == SDIO_FLAG_CMDRESPRECV) || ((FLAG) == SDIO_FLAG_CMDSEND) || ((FLAG) == SDIO_FLAG_DATEND) \ + || ((FLAG) == SDIO_FLAG_SBERR) || ((FLAG) == SDIO_FLAG_DATBLKEND) || ((FLAG) == SDIO_FLAG_CMDRUN) \ + || ((FLAG) == SDIO_FLAG_TXRUN) || ((FLAG) == SDIO_FLAG_RXRUN) || ((FLAG) == SDIO_FLAG_TFIFOHE) \ + || ((FLAG) == SDIO_FLAG_RFIFOHF) || ((FLAG) == SDIO_FLAG_TFIFOF) || ((FLAG) == SDIO_FLAG_RFIFOF) \ + || ((FLAG) == SDIO_FLAG_TFIFOE) || ((FLAG) == SDIO_FLAG_RFIFOE) || ((FLAG) == SDIO_FLAG_TDATVALID) \ + || ((FLAG) == SDIO_FLAG_RDATVALID) || ((FLAG) == SDIO_FLAG_SDIOINT) || ((FLAG) == SDIO_FLAG_CEATAF)) + +#define IS_SDIO_CLR_FLAG(FLAG) ((((FLAG) & (uint32_t)0xFF3FF800) == 0x00) && ((FLAG) != (uint32_t)0x00)) + +#define IS_SDIO_GET_INT(IT) \ + (((IT) == SDIO_INT_CCRCERR) || ((IT) == SDIO_INT_DCRCERR) || ((IT) == SDIO_INT_CMDTIMEOUT) \ + || ((IT) == SDIO_INT_DATTIMEOUT) || ((IT) == SDIO_INT_TXURERR) || ((IT) == SDIO_INT_RXORERR) \ + || ((IT) == SDIO_INT_CMDRESPRECV) || ((IT) == SDIO_INT_CMDSEND) || ((IT) == SDIO_INT_DATEND) \ + || ((IT) == SDIO_INT_SBERR) || ((IT) == SDIO_INT_DATBLKEND) || ((IT) == SDIO_INT_CMDRUN) \ + || ((IT) == SDIO_INT_TXRUN) || ((IT) == SDIO_INT_RXRUN) || ((IT) == SDIO_INT_TFIFOHE) \ + || ((IT) == SDIO_INT_RFIFOHF) || ((IT) == SDIO_INT_TFIFOF) || ((IT) == SDIO_INT_RFIFOF) \ + || ((IT) == SDIO_INT_TFIFOE) || ((IT) == SDIO_INT_RFIFOE) || ((IT) == SDIO_INT_TDATVALID) \ + || ((IT) == SDIO_INT_RDATVALID) || ((IT) == SDIO_INT_SDIOINT) || ((IT) == SDIO_INT_CEATAF)) + +#define IS_SDIO_CLR_INT(IT) ((((IT) & (uint32_t)0xFF3FF800) == 0x00) && ((IT) != (uint32_t)0x00)) + +/** + * @} + */ + +/** @addtogroup SDIO_Read_Wait_Mode + * @{ + */ + +#define SDIO_RDWAIT_MODE_CLK ((uint32_t)0x00000001) +#define SDIO_RDWAIT_MODE_DAT2 ((uint32_t)0x00000000) +#define IS_SDIO_RDWAIT_MODE(MODE) (((MODE) == SDIO_RDWAIT_MODE_CLK) || ((MODE) == SDIO_RDWAIT_MODE_DAT2)) +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup SDIO_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup SDIO_Exported_Functions + * @{ + */ + +void SDIO_DeInit(void); +void SDIO_Init(SDIO_InitType* SDIO_InitStruct); +void SDIO_InitStruct(SDIO_InitType* SDIO_InitStruct); +void SDIO_EnableClock(FunctionalState Cmd); +void SDIO_SetPower(uint32_t SDIO_PowerState); +uint32_t SDIO_GetPower(void); +void SDIO_ConfigInt(uint32_t SDIO_IT, FunctionalState Cmd); +void SDIO_DMACmd(FunctionalState Cmd); +void SDIO_SendCmd(SDIO_CmdInitType* SDIO_CmdInitStruct); +void SDIO_InitCmdStruct(SDIO_CmdInitType* SDIO_CmdInitStruct); +uint8_t SDIO_GetCmdResp(void); +uint32_t SDIO_GetResp(uint32_t SDIO_RESP); +void SDIO_ConfigData(SDIO_DataInitType* SDIO_DataInitStruct); +void SDIO_InitDataStruct(SDIO_DataInitType* SDIO_DataInitStruct); +uint32_t SDIO_GetDataCountValue(void); +uint32_t SDIO_ReadData(void); +void SDIO_WriteData(uint32_t Data); +uint32_t SDIO_GetFifoCounter(void); +void SDIO_EnableReadWait(FunctionalState Cmd); +void SDIO_DisableReadWait(FunctionalState Cmd); +void SDIO_EnableSdioReadWaitMode(uint32_t SDIO_ReadWaitMode); +void SDIO_EnableSdioOperation(FunctionalState Cmd); +void SDIO_EnableSendSdioSuspend(FunctionalState Cmd); +void SDIO_EnableCommandCompletion(FunctionalState Cmd); +void SDIO_EnableCEATAInt(FunctionalState Cmd); +void SDIO_EnableSendCEATA(FunctionalState Cmd); +FlagStatus SDIO_GetFlag(uint32_t SDIO_FLAG); +void SDIO_ClrFlag(uint32_t SDIO_FLAG); +INTStatus SDIO_GetIntStatus(uint32_t SDIO_IT); +void SDIO_ClrIntPendingBit(uint32_t SDIO_IT); + +#ifdef __cplusplus +} +#endif + +#endif /* __N32G45X_SDIO_H__ */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/inc/n32g45x_spi.h b/inc/n32g45x_spi.h new file mode 100644 index 0000000..401fbe6 --- /dev/null +++ b/inc/n32g45x_spi.h @@ -0,0 +1,471 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_spi.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_SPI_H__ +#define __N32G45X_SPI_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup SPI + * @{ + */ + +/** @addtogroup SPI_Exported_Types + * @{ + */ + +/** + * @brief SPI Init structure definition + */ + +typedef struct +{ + uint16_t DataDirection; /*!< Specifies the SPI unidirectional or bidirectional data mode. + This parameter can be a value of @ref SPI_data_direction */ + + uint16_t SpiMode; /*!< Specifies the SPI operating mode. + This parameter can be a value of @ref SPI_mode */ + + uint16_t DataLen; /*!< Specifies the SPI data size. + This parameter can be a value of @ref SPI_data_size */ + + uint16_t CLKPOL; /*!< Specifies the serial clock steady state. + This parameter can be a value of @ref SPI_Clock_Polarity */ + + uint16_t CLKPHA; /*!< Specifies the clock active edge for the bit capture. + This parameter can be a value of @ref SPI_Clock_Phase */ + + uint16_t NSS; /*!< Specifies whether the NSS signal is managed by + hardware (NSS pin) or by software using the SSI bit. + This parameter can be a value of @ref SPI_Slave_Select_management */ + + uint16_t BaudRatePres; /*!< Specifies the Baud Rate prescaler value which will be + used to configure the transmit and receive SCK clock. + This parameter can be a value of @ref SPI_BaudRate_Prescaler. + @note The communication clock is derived from the master + clock. The slave clock does not need to be set. */ + + uint16_t FirstBit; /*!< Specifies whether data transfers start from MSB or LSB bit. + This parameter can be a value of @ref SPI_MSB_LSB_transmission */ + + uint16_t CRCPoly; /*!< Specifies the polynomial used for the CRC calculation. */ +} SPI_InitType; + +/** + * @brief I2S Init structure definition + */ + +typedef struct +{ + uint16_t I2sMode; /*!< Specifies the I2S operating mode. + This parameter can be a value of @ref I2sMode */ + + uint16_t Standard; /*!< Specifies the standard used for the I2S communication. + This parameter can be a value of @ref Standard */ + + uint16_t DataFormat; /*!< Specifies the data format for the I2S communication. + This parameter can be a value of @ref I2S_Data_Format */ + + uint16_t MCLKEnable; /*!< Specifies whether the I2S MCLK output is enabled or not. + This parameter can be a value of @ref I2S_MCLK_Output */ + + uint32_t AudioFrequency; /*!< Specifies the frequency selected for the I2S communication. + This parameter can be a value of @ref I2S_Audio_Frequency */ + + uint16_t CLKPOL; /*!< Specifies the idle state of the I2S clock. + This parameter can be a value of @ref I2S_Clock_Polarity */ +} I2S_InitType; + +/** + * @} + */ + +/** @addtogroup SPI_Exported_Constants + * @{ + */ + +#define IS_SPI_PERIPH(PERIPH) (((PERIPH) == SPI1) || ((PERIPH) == SPI2) || ((PERIPH) == SPI3)) + +#define IS_SPI_2OR3_PERIPH(PERIPH) (((PERIPH) == SPI2) || ((PERIPH) == SPI3)) + +/** @addtogroup SPI_data_direction + * @{ + */ + +#define SPI_DIR_DOUBLELINE_FULLDUPLEX ((uint16_t)0x0000) +#define SPI_DIR_DOUBLELINE_RONLY ((uint16_t)0x0400) +#define SPI_DIR_SINGLELINE_RX ((uint16_t)0x8000) +#define SPI_DIR_SINGLELINE_TX ((uint16_t)0xC000) +#define IS_SPI_DIR_MODE(MODE) \ + (((MODE) == SPI_DIR_DOUBLELINE_FULLDUPLEX) || ((MODE) == SPI_DIR_DOUBLELINE_RONLY) \ + || ((MODE) == SPI_DIR_SINGLELINE_RX) || ((MODE) == SPI_DIR_SINGLELINE_TX)) +/** + * @} + */ + +/** @addtogroup SPI_mode + * @{ + */ + +#define SPI_MODE_MASTER ((uint16_t)0x0104) +#define SPI_MODE_SLAVE ((uint16_t)0x0000) +#define IS_SPI_MODE(MODE) (((MODE) == SPI_MODE_MASTER) || ((MODE) == SPI_MODE_SLAVE)) +/** + * @} + */ + +/** @addtogroup SPI_data_size + * @{ + */ + +#define SPI_DATA_SIZE_16BITS ((uint16_t)0x0800) +#define SPI_DATA_SIZE_8BITS ((uint16_t)0x0000) +#define IS_SPI_DATASIZE(DATASIZE) (((DATASIZE) == SPI_DATA_SIZE_16BITS) || ((DATASIZE) == SPI_DATA_SIZE_8BITS)) +/** + * @} + */ + +/** @addtogroup SPI_Clock_Polarity + * @{ + */ + +#define SPI_CLKPOL_LOW ((uint16_t)0x0000) +#define SPI_CLKPOL_HIGH ((uint16_t)0x0002) +#define IS_SPI_CLKPOL(CPOL) (((CPOL) == SPI_CLKPOL_LOW) || ((CPOL) == SPI_CLKPOL_HIGH)) +/** + * @} + */ + +/** @addtogroup SPI_Clock_Phase + * @{ + */ + +#define SPI_CLKPHA_FIRST_EDGE ((uint16_t)0x0000) +#define SPI_CLKPHA_SECOND_EDGE ((uint16_t)0x0001) +#define IS_SPI_CLKPHA(CPHA) (((CPHA) == SPI_CLKPHA_FIRST_EDGE) || ((CPHA) == SPI_CLKPHA_SECOND_EDGE)) +/** + * @} + */ + +/** @addtogroup SPI_Slave_Select_management + * @{ + */ + +#define SPI_NSS_SOFT ((uint16_t)0x0200) +#define SPI_NSS_HARD ((uint16_t)0x0000) +#define IS_SPI_NSS(NSS) (((NSS) == SPI_NSS_SOFT) || ((NSS) == SPI_NSS_HARD)) +/** + * @} + */ + +/** @addtogroup SPI_BaudRate_Prescaler + * @{ + */ + +#define SPI_BR_PRESCALER_2 ((uint16_t)0x0000) +#define SPI_BR_PRESCALER_4 ((uint16_t)0x0008) +#define SPI_BR_PRESCALER_8 ((uint16_t)0x0010) +#define SPI_BR_PRESCALER_16 ((uint16_t)0x0018) +#define SPI_BR_PRESCALER_32 ((uint16_t)0x0020) +#define SPI_BR_PRESCALER_64 ((uint16_t)0x0028) +#define SPI_BR_PRESCALER_128 ((uint16_t)0x0030) +#define SPI_BR_PRESCALER_256 ((uint16_t)0x0038) +#define IS_SPI_BR_PRESCALER(PRESCALER) \ + (((PRESCALER) == SPI_BR_PRESCALER_2) || ((PRESCALER) == SPI_BR_PRESCALER_4) || ((PRESCALER) == SPI_BR_PRESCALER_8) \ + || ((PRESCALER) == SPI_BR_PRESCALER_16) || ((PRESCALER) == SPI_BR_PRESCALER_32) \ + || ((PRESCALER) == SPI_BR_PRESCALER_64) || ((PRESCALER) == SPI_BR_PRESCALER_128) \ + || ((PRESCALER) == SPI_BR_PRESCALER_256)) +/** + * @} + */ + +/** @addtogroup SPI_MSB_LSB_transmission + * @{ + */ + +#define SPI_FB_MSB ((uint16_t)0x0000) +#define SPI_FB_LSB ((uint16_t)0x0080) +#define IS_SPI_FIRST_BIT(BIT) (((BIT) == SPI_FB_MSB) || ((BIT) == SPI_FB_LSB)) +/** + * @} + */ + +/** @addtogroup I2sMode + * @{ + */ + +#define I2S_MODE_SlAVE_TX ((uint16_t)0x0000) +#define I2S_MODE_SlAVE_RX ((uint16_t)0x0100) +#define I2S_MODE_MASTER_TX ((uint16_t)0x0200) +#define I2S_MODE_MASTER_RX ((uint16_t)0x0300) +#define IS_I2S_MODE(MODE) \ + (((MODE) == I2S_MODE_SlAVE_TX) || ((MODE) == I2S_MODE_SlAVE_RX) || ((MODE) == I2S_MODE_MASTER_TX) \ + || ((MODE) == I2S_MODE_MASTER_RX)) +/** + * @} + */ + +/** @addtogroup Standard + * @{ + */ + +#define I2S_STD_PHILLIPS ((uint16_t)0x0000) +#define I2S_STD_MSB_ALIGN ((uint16_t)0x0010) +#define I2S_STD_LSB_ALIGN ((uint16_t)0x0020) +#define I2S_STD_PCM_SHORTFRAME ((uint16_t)0x0030) +#define I2S_STD_PCM_LONGFRAME ((uint16_t)0x00B0) +#define IS_I2S_STANDARD(STANDARD) \ + (((STANDARD) == I2S_STD_PHILLIPS) || ((STANDARD) == I2S_STD_MSB_ALIGN) || ((STANDARD) == I2S_STD_LSB_ALIGN) \ + || ((STANDARD) == I2S_STD_PCM_SHORTFRAME) || ((STANDARD) == I2S_STD_PCM_LONGFRAME)) +/** + * @} + */ + +/** @addtogroup I2S_Data_Format + * @{ + */ + +#define I2S_DATA_FMT_16BITS ((uint16_t)0x0000) +#define I2S_DATA_FMT_16BITS_EXTENDED ((uint16_t)0x0001) +#define I2S_DATA_FMT_24BITS ((uint16_t)0x0003) +#define I2S_DATA_FMT_32BITS ((uint16_t)0x0005) +#define IS_I2S_DATA_FMT(FORMAT) \ + (((FORMAT) == I2S_DATA_FMT_16BITS) || ((FORMAT) == I2S_DATA_FMT_16BITS_EXTENDED) \ + || ((FORMAT) == I2S_DATA_FMT_24BITS) || ((FORMAT) == I2S_DATA_FMT_32BITS)) +/** + * @} + */ + +/** @addtogroup I2S_MCLK_Output + * @{ + */ + +#define I2S_MCLK_ENABLE ((uint16_t)0x0200) +#define I2S_MCLK_DISABLE ((uint16_t)0x0000) +#define IS_I2S_MCLK_ENABLE(OUTPUT) (((OUTPUT) == I2S_MCLK_ENABLE) || ((OUTPUT) == I2S_MCLK_DISABLE)) +/** + * @} + */ + +/** @addtogroup I2S_Audio_Frequency + * @{ + */ + +#define I2S_AUDIO_FREQ_192K ((uint32_t)192000) +#define I2S_AUDIO_FREQ_96K ((uint32_t)96000) +#define I2S_AUDIO_FREQ_48K ((uint32_t)48000) +#define I2S_AUDIO_FREQ_44K ((uint32_t)44100) +#define I2S_AUDIO_FREQ_32K ((uint32_t)32000) +#define I2S_AUDIO_FREQ_22K ((uint32_t)22050) +#define I2S_AUDIO_FREQ_16K ((uint32_t)16000) +#define I2S_AUDIO_FREQ_11K ((uint32_t)11025) +#define I2S_AUDIO_FREQ_8K ((uint32_t)8000) +#define I2S_AUDIO_FREQ_DEFAULT ((uint32_t)2) + +#define IS_I2S_AUDIO_FREQ(FREQ) \ + ((((FREQ) >= I2S_AUDIO_FREQ_8K) && ((FREQ) <= I2S_AUDIO_FREQ_192K)) || ((FREQ) == I2S_AUDIO_FREQ_DEFAULT)) +/** + * @} + */ + +/** @addtogroup I2S_Clock_Polarity + * @{ + */ + +#define I2S_CLKPOL_LOW ((uint16_t)0x0000) +#define I2S_CLKPOL_HIGH ((uint16_t)0x0008) +#define IS_I2S_CLKPOL(CPOL) (((CPOL) == I2S_CLKPOL_LOW) || ((CPOL) == I2S_CLKPOL_HIGH)) +/** + * @} + */ + +/** @addtogroup SPI_I2S_DMA_transfer_requests + * @{ + */ + +#define SPI_I2S_DMA_TX ((uint16_t)0x0002) +#define SPI_I2S_DMA_RX ((uint16_t)0x0001) +#define IS_SPI_I2S_DMA(DMAREQ) ((((DMAREQ) & (uint16_t)0xFFFC) == 0x00) && ((DMAREQ) != 0x00)) +/** + * @} + */ + +/** @addtogroup SPI_NSS_internal_software_management + * @{ + */ + +#define SPI_NSS_HIGH ((uint16_t)0x0100) +#define SPI_NSS_LOW ((uint16_t)0xFEFF) +#define IS_SPI_NSS_LEVEL(INTERNAL) (((INTERNAL) == SPI_NSS_HIGH) || ((INTERNAL) == SPI_NSS_LOW)) +/** + * @} + */ + +/** @addtogroup SPI_CRC_Transmit_Receive + * @{ + */ + +#define SPI_CRC_TX ((uint8_t)0x00) +#define SPI_CRC_RX ((uint8_t)0x01) +#define IS_SPI_CRC(CRC) (((CRC) == SPI_CRC_TX) || ((CRC) == SPI_CRC_RX)) +/** + * @} + */ + +/** @addtogroup SPI_direction_transmit_receive + * @{ + */ + +#define SPI_BIDIRECTION_RX ((uint16_t)0xBFFF) +#define SPI_BIDIRECTION_TX ((uint16_t)0x4000) +#define IS_SPI_BIDIRECTION(DIRECTION) (((DIRECTION) == SPI_BIDIRECTION_RX) || ((DIRECTION) == SPI_BIDIRECTION_TX)) +/** + * @} + */ + +/** @addtogroup SPI_I2S_interrupts_definition + * @{ + */ + +#define SPI_I2S_INT_TE ((uint8_t)0x71) +#define SPI_I2S_INT_RNE ((uint8_t)0x60) +#define SPI_I2S_INT_ERR ((uint8_t)0x50) +#define IS_SPI_I2S_CONFIG_INT(IT) (((IT) == SPI_I2S_INT_TE) || ((IT) == SPI_I2S_INT_RNE) || ((IT) == SPI_I2S_INT_ERR)) +#define SPI_I2S_INT_OVER ((uint8_t)0x56) +#define SPI_INT_MODERR ((uint8_t)0x55) +#define SPI_INT_CRCERR ((uint8_t)0x54) +#define I2S_INT_UNDER ((uint8_t)0x53) +#define IS_SPI_I2S_CLR_INT(IT) (((IT) == SPI_INT_CRCERR)) +#define IS_SPI_I2S_GET_INT(IT) \ + (((IT) == SPI_I2S_INT_RNE) || ((IT) == SPI_I2S_INT_TE) || ((IT) == I2S_INT_UNDER) || ((IT) == SPI_INT_CRCERR) \ + || ((IT) == SPI_INT_MODERR) || ((IT) == SPI_I2S_INT_OVER)) +/** + * @} + */ + +/** @addtogroup SPI_I2S_flags_definition + * @{ + */ + +#define SPI_I2S_RNE_FLAG ((uint16_t)0x0001) +#define SPI_I2S_TE_FLAG ((uint16_t)0x0002) +#define I2S_CHSIDE_FLAG ((uint16_t)0x0004) +#define I2S_UNDER_FLAG ((uint16_t)0x0008) +#define SPI_CRCERR_FLAG ((uint16_t)0x0010) +#define SPI_MODERR_FLAG ((uint16_t)0x0020) +#define SPI_I2S_OVER_FLAG ((uint16_t)0x0040) +#define SPI_I2S_BUSY_FLAG ((uint16_t)0x0080) +#define IS_SPI_I2S_CLR_FLAG(FLAG) (((FLAG) == SPI_CRCERR_FLAG)) +#define IS_SPI_I2S_GET_FLAG(FLAG) \ + (((FLAG) == SPI_I2S_BUSY_FLAG) || ((FLAG) == SPI_I2S_OVER_FLAG) || ((FLAG) == SPI_MODERR_FLAG) \ + || ((FLAG) == SPI_CRCERR_FLAG) || ((FLAG) == I2S_UNDER_FLAG) || ((FLAG) == I2S_CHSIDE_FLAG) \ + || ((FLAG) == SPI_I2S_TE_FLAG) || ((FLAG) == SPI_I2S_RNE_FLAG)) +/** + * @} + */ + +/** @addtogroup SPI_CRC_polynomial + * @{ + */ + +#define IS_SPI_CRC_POLYNOMIAL(POLYNOMIAL) ((POLYNOMIAL) >= 0x1) +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup SPI_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup SPI_Exported_Functions + * @{ + */ + +void SPI_I2S_DeInit(SPI_Module* SPIx); +void SPI_Init(SPI_Module* SPIx, SPI_InitType* SPI_InitStruct); +void I2S_Init(SPI_Module* SPIx, I2S_InitType* I2S_InitStruct); +void SPI_InitStruct(SPI_InitType* SPI_InitStruct); +void I2S_InitStruct(I2S_InitType* I2S_InitStruct); +void SPI_Enable(SPI_Module* SPIx, FunctionalState Cmd); +void I2S_Enable(SPI_Module* SPIx, FunctionalState Cmd); +void SPI_I2S_EnableInt(SPI_Module* SPIx, uint8_t SPI_I2S_IT, FunctionalState Cmd); +void SPI_I2S_EnableDma(SPI_Module* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState Cmd); +void SPI_I2S_TransmitData(SPI_Module* SPIx, uint16_t Data); +uint16_t SPI_I2S_ReceiveData(SPI_Module* SPIx); +void SPI_SetNssLevel(SPI_Module* SPIx, uint16_t SPI_NSSInternalSoft); +void SPI_SSOutputEnable(SPI_Module* SPIx, FunctionalState Cmd); +void SPI_ConfigDataLen(SPI_Module* SPIx, uint16_t DataLen); +void SPI_TransmitCrcNext(SPI_Module* SPIx); +void SPI_EnableCalculateCrc(SPI_Module* SPIx, FunctionalState Cmd); +uint16_t SPI_GetCRCDat(SPI_Module* SPIx, uint8_t SPI_CRC); +uint16_t SPI_GetCRCPoly(SPI_Module* SPIx); +void SPI_ConfigBidirectionalMode(SPI_Module* SPIx, uint16_t DataDirection); +FlagStatus SPI_I2S_GetStatus(SPI_Module* SPIx, uint16_t SPI_I2S_FLAG); +void SPI_I2S_ClrCRCErrFlag(SPI_Module* SPIx, uint16_t SPI_I2S_FLAG); +INTStatus SPI_I2S_GetIntStatus(SPI_Module* SPIx, uint8_t SPI_I2S_IT); +void SPI_I2S_ClrITPendingBit(SPI_Module* SPIx, uint8_t SPI_I2S_IT); + +#ifdef __cplusplus +} +#endif + +#endif /*__N32G45X_SPI_H__ */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/inc/n32g45x_tim.h b/inc/n32g45x_tim.h new file mode 100644 index 0000000..5da1c9c --- /dev/null +++ b/inc/n32g45x_tim.h @@ -0,0 +1,1114 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_tim.h + * @author Nations + * @version v1.0.3 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_TIM_H__ +#define __N32G45X_TIM_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" +#include "stdbool.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup TIM + * @{ + */ + +/** @addtogroup TIM_Exported_Types + * @{ + */ + +/** + * @brief TIM Time Base Init structure definition + * @note This structure is used with all TIMx except for TIM6 and TIM7. + */ + +typedef struct +{ + uint16_t Prescaler; /*!< Specifies the prescaler value used to divide the TIM clock. + This parameter can be a number between 0x0000 and 0xFFFF */ + + uint16_t CntMode; /*!< Specifies the counter mode. + This parameter can be a value of @ref TIM_Counter_Mode */ + + uint16_t Period; /*!< Specifies the period value to be loaded into the active + Auto-Reload Register at the next update event. + This parameter must be a number between 0x0000 and 0xFFFF. */ + + uint16_t ClkDiv; /*!< Specifies the clock division. + This parameter can be a value of @ref TIM_Clock_Division_CKD */ + + uint8_t RepetCnt; /*!< Specifies the repetition counter value. Each time the REPCNT downcounter + reaches zero, an update event is generated and counting restarts + from the REPCNT value (N). + This means in PWM mode that (N+1) corresponds to: + - the number of PWM periods in edge-aligned mode + - the number of half PWM period in center-aligned mode + This parameter must be a number between 0x00 and 0xFF. + @note This parameter is valid only for TIM1 and TIM8. */ + + bool CapCh1FromCompEn; /*!< channel 1 select capture in from comp if 1, from IOM if 0 + Tim1,Tim8,Tim2,Tim3,Tim4,Tim5 valid*/ + bool CapCh2FromCompEn; /*!< channel 2 select capture in from comp if 1, from IOM if 0 + Tim2,Tim3,Tim4,Tim5 valid*/ + bool CapCh3FromCompEn; /*!< channel 3 select capture in from comp if 1, from IOM if 0 + Tim2,Tim3,Tim4,Tim5 valid*/ + bool CapCh4FromCompEn; /*!< channel 4 select capture in from comp if 1, from IOM if 0 + Tim2,Tim3,Tim4 valid*/ + bool CapEtrClrFromCompEn; /*!< etr clearref select from comp if 1, from ETR IOM if 0 + Tim2,Tim3,Tim4 valid*/ + bool CapEtrSelFromTscEn; /*!< etr select from TSC if 1, from IOM if 0 + Tim2,Tim4 valid*/ +} TIM_TimeBaseInitType; + +/** + * @brief TIM Output Compare Init structure definition + */ + +typedef struct +{ + uint16_t OcMode; /*!< Specifies the TIM mode. + This parameter can be a value of @ref TIM_Output_Compare_and_PWM_modes */ + + uint16_t OutputState; /*!< Specifies the TIM Output Compare state. + This parameter can be a value of @ref TIM_Output_Compare_state */ + + uint16_t OutputNState; /*!< Specifies the TIM complementary Output Compare state. + This parameter can be a value of @ref TIM_Output_Compare_N_state + @note This parameter is valid only for TIM1 and TIM8. */ + + uint16_t Pulse; /*!< Specifies the pulse value to be loaded into the Capture Compare Register. + This parameter can be a number between 0x0000 and 0xFFFF */ + + uint16_t OcPolarity; /*!< Specifies the output polarity. + This parameter can be a value of @ref TIM_Output_Compare_Polarity */ + + uint16_t OcNPolarity; /*!< Specifies the complementary output polarity. + This parameter can be a value of @ref TIM_Output_Compare_N_Polarity + @note This parameter is valid only for TIM1 and TIM8. */ + + uint16_t OcIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state. + This parameter can be a value of @ref TIM_Output_Compare_Idle_State + @note This parameter is valid only for TIM1 and TIM8. */ + + uint16_t OcNIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state. + This parameter can be a value of @ref TIM_Output_Compare_N_Idle_State + @note This parameter is valid only for TIM1 and TIM8. */ +} OCInitType; + +/** + * @brief TIM Input Capture Init structure definition + */ + +typedef struct +{ + uint16_t Channel; /*!< Specifies the TIM channel. + This parameter can be a value of @ref Channel */ + + uint16_t IcPolarity; /*!< Specifies the active edge of the input signal. + This parameter can be a value of @ref TIM_Input_Capture_Polarity */ + + uint16_t IcSelection; /*!< Specifies the input. + This parameter can be a value of @ref TIM_Input_Capture_Selection */ + + uint16_t IcPrescaler; /*!< Specifies the Input Capture Prescaler. + This parameter can be a value of @ref TIM_Input_Capture_Prescaler */ + + uint16_t IcFilter; /*!< Specifies the input capture filter. + This parameter can be a number between 0x0 and 0xF */ +} TIM_ICInitType; + +/** + * @brief BKDT structure definition + * @note This structure is used only with TIM1 and TIM8. + */ + +typedef struct +{ + uint16_t OssrState; /*!< Specifies the Off-State selection used in Run mode. + This parameter can be a value of @ref OSSR_Off_State_Selection_for_Run_mode_state */ + + uint16_t OssiState; /*!< Specifies the Off-State used in Idle state. + This parameter can be a value of @ref OSSI_Off_State_Selection_for_Idle_mode_state */ + + uint16_t LockLevel; /*!< Specifies the LOCK level parameters. + This parameter can be a value of @ref Lock_level */ + + uint16_t DeadTime; /*!< Specifies the delay time between the switching-off and the + switching-on of the outputs. + This parameter can be a number between 0x00 and 0xFF */ + + uint16_t Break; /*!< Specifies whether the TIM Break input is enabled or not. + This parameter can be a value of @ref Break_Input_enable_disable */ + + uint16_t BreakPolarity; /*!< Specifies the TIM Break Input pin polarity. + This parameter can be a value of @ref Break_Polarity */ + + uint16_t AutomaticOutput; /*!< Specifies whether the TIM Automatic Output feature is enabled or not. + This parameter can be a value of @ref TIM_AOE_Bit_Set_Reset */ + bool IomBreakEn; /*!< EXTENDMODE valid, open iom as break in*/ + bool LockUpBreakEn; /*!< EXTENDMODE valid, open lockup(haldfault) as break in*/ + bool PvdBreakEn; /*!< EXTENDMODE valid, open pvd(sys voltage too high or too low) as break in*/ +} TIM_BDTRInitType; + +/** @addtogroup TIM_Exported_constants + * @{ + */ + +#define IsTimAllModule(PERIPH) \ + (((PERIPH) == TIM1) || ((PERIPH) == TIM2) || ((PERIPH) == TIM3) || ((PERIPH) == TIM4) || ((PERIPH) == TIM5) \ + || ((PERIPH) == TIM6) || ((PERIPH) == TIM7) || ((PERIPH) == TIM8)) + +/* LIST1: TIM 1 and 8 */ +#define IsTimList1Module(PERIPH) (((PERIPH) == TIM1) || ((PERIPH) == TIM8)) + +/* LIST2: TIM 1, 8 */ +#define IsTimList2Module(PERIPH) (((PERIPH) == TIM1) || ((PERIPH) == TIM8)) + +/* LIST3: TIM 1, 2, 3, 4, 5 and 8 */ +#define IsTimList3Module(PERIPH) \ + (((PERIPH) == TIM1) || ((PERIPH) == TIM2) || ((PERIPH) == TIM3) || ((PERIPH) == TIM4) || ((PERIPH) == TIM5) \ + || ((PERIPH) == TIM8)) + +/* LIST4: TIM 1, 2, 3, 4, 5, 8 */ +#define IsTimList4Module(PERIPH) \ + (((PERIPH) == TIM1) || ((PERIPH) == TIM2) || ((PERIPH) == TIM3) || ((PERIPH) == TIM4) || ((PERIPH) == TIM5) \ + || ((PERIPH) == TIM8)) + +/* LIST5: TIM 1, 2, 3, 4, 5, 8 */ +#define IsTimList5Module(PERIPH) \ + (((PERIPH) == TIM1) || ((PERIPH) == TIM2) || ((PERIPH) == TIM3) || ((PERIPH) == TIM4) || ((PERIPH) == TIM5) \ + || ((PERIPH) == TIM8)) + +/* LIST6: TIM 1, 2, 3, 4, 5, 8 */ +#define IsTimList6Module(PERIPH) \ + (((PERIPH) == TIM1) || ((PERIPH) == TIM2) || ((PERIPH) == TIM3) || ((PERIPH) == TIM4) || ((PERIPH) == TIM5) \ + || ((PERIPH) == TIM8)) + +/* LIST7: TIM 1, 2, 3, 4, 5, 6, 7, 8 */ +#define IsTimList7Module(PERIPH) \ + (((PERIPH) == TIM1) || ((PERIPH) == TIM2) || ((PERIPH) == TIM3) || ((PERIPH) == TIM4) || ((PERIPH) == TIM5) \ + || ((PERIPH) == TIM6) || ((PERIPH) == TIM7) || ((PERIPH) == TIM8)) + +/* LIST8: TIM 1, 2, 3, 4, 5, 8 */ +#define IsTimList8Module(PERIPH) \ + (((PERIPH) == TIM1) || ((PERIPH) == TIM2) || ((PERIPH) == TIM3) || ((PERIPH) == TIM4) || ((PERIPH) == TIM5) \ + || ((PERIPH) == TIM8)) + +/* LIST9: TIM 1, 2, 3, 4, 5, 6, 7, 8 */ +#define IsTimList9Module(PERIPH) \ + (((PERIPH) == TIM1) || ((PERIPH) == TIM2) || ((PERIPH) == TIM3) || ((PERIPH) == TIM4) || ((PERIPH) == TIM5) \ + || ((PERIPH) == TIM6) || ((PERIPH) == TIM7) || ((PERIPH) == TIM8)) + +/** + * @} + */ + +/** @addtogroup TIM_Output_Compare_and_PWM_modes + * @{ + */ + +#define TIM_OCMODE_TIMING ((uint16_t)0x0000) +#define TIM_OCMODE_ACTIVE ((uint16_t)0x0010) +#define TIM_OCMODE_INACTIVE ((uint16_t)0x0020) +#define TIM_OCMODE_TOGGLE ((uint16_t)0x0030) +#define TIM_OCMODE_PWM1 ((uint16_t)0x0060) +#define TIM_OCMODE_PWM2 ((uint16_t)0x0070) +#define IsTimOcMode(MODE) \ + (((MODE) == TIM_OCMODE_TIMING) || ((MODE) == TIM_OCMODE_ACTIVE) || ((MODE) == TIM_OCMODE_INACTIVE) \ + || ((MODE) == TIM_OCMODE_TOGGLE) || ((MODE) == TIM_OCMODE_PWM1) || ((MODE) == TIM_OCMODE_PWM2)) +#define IsTimOc(MODE) \ + (((MODE) == TIM_OCMODE_TIMING) || ((MODE) == TIM_OCMODE_ACTIVE) || ((MODE) == TIM_OCMODE_INACTIVE) \ + || ((MODE) == TIM_OCMODE_TOGGLE) || ((MODE) == TIM_OCMODE_PWM1) || ((MODE) == TIM_OCMODE_PWM2) \ + || ((MODE) == TIM_FORCED_ACTION_ACTIVE) || ((MODE) == TIM_FORCED_ACTION_INACTIVE)) +/** + * @} + */ + +/** @addtogroup TIM_One_Pulse_Mode + * @{ + */ + +#define TIM_OPMODE_SINGLE ((uint16_t)0x0008) +#define TIM_OPMODE_REPET ((uint16_t)0x0000) +#define IsTimOpMOde(MODE) (((MODE) == TIM_OPMODE_SINGLE) || ((MODE) == TIM_OPMODE_REPET)) +/** + * @} + */ + +/** @addtogroup Channel + * @{ + */ + +#define TIM_CH_1 ((uint16_t)0x0000) +#define TIM_CH_2 ((uint16_t)0x0004) +#define TIM_CH_3 ((uint16_t)0x0008) +#define TIM_CH_4 ((uint16_t)0x000C) +#define IsTimCh(CHANNEL) \ + (((CHANNEL) == TIM_CH_1) || ((CHANNEL) == TIM_CH_2) || ((CHANNEL) == TIM_CH_3) || ((CHANNEL) == TIM_CH_4)) +#define IsTimPwmInCh(CHANNEL) (((CHANNEL) == TIM_CH_1) || ((CHANNEL) == TIM_CH_2)) +#define IsTimComplementaryCh(CHANNEL) (((CHANNEL) == TIM_CH_1) || ((CHANNEL) == TIM_CH_2) || ((CHANNEL) == TIM_CH_3)) +/** + * @} + */ + +/** @addtogroup TIM_Clock_Division_CKD + * @{ + */ + +#define TIM_CLK_DIV1 ((uint16_t)0x0000) +#define TIM_CLK_DIV2 ((uint16_t)0x0100) +#define TIM_CLK_DIV4 ((uint16_t)0x0200) +#define IsTimClkDiv(DIV) (((DIV) == TIM_CLK_DIV1) || ((DIV) == TIM_CLK_DIV2) || ((DIV) == TIM_CLK_DIV4)) +/** + * @} + */ + +/** @addtogroup TIM_Counter_Mode + * @{ + */ + +#define TIM_CNT_MODE_UP ((uint16_t)0x0000) +#define TIM_CNT_MODE_DOWN ((uint16_t)0x0010) +#define TIM_CNT_MODE_CENTER_ALIGN1 ((uint16_t)0x0020) +#define TIM_CNT_MODE_CENTER_ALIGN2 ((uint16_t)0x0040) +#define TIM_CNT_MODE_CENTER_ALIGN3 ((uint16_t)0x0060) +#define IsTimCntMode(MODE) \ + (((MODE) == TIM_CNT_MODE_UP) || ((MODE) == TIM_CNT_MODE_DOWN) || ((MODE) == TIM_CNT_MODE_CENTER_ALIGN1) \ + || ((MODE) == TIM_CNT_MODE_CENTER_ALIGN2) || ((MODE) == TIM_CNT_MODE_CENTER_ALIGN3)) +/** + * @} + */ + +/** @addtogroup TIM_Output_Compare_Polarity + * @{ + */ + +#define TIM_OC_POLARITY_HIGH ((uint16_t)0x0000) +#define TIM_OC_POLARITY_LOW ((uint16_t)0x0002) +#define IsTimOcPolarity(POLARITY) (((POLARITY) == TIM_OC_POLARITY_HIGH) || ((POLARITY) == TIM_OC_POLARITY_LOW)) +/** + * @} + */ + +/** @addtogroup TIM_Output_Compare_N_Polarity + * @{ + */ + +#define TIM_OCN_POLARITY_HIGH ((uint16_t)0x0000) +#define TIM_OCN_POLARITY_LOW ((uint16_t)0x0008) +#define IsTimOcnPolarity(POLARITY) (((POLARITY) == TIM_OCN_POLARITY_HIGH) || ((POLARITY) == TIM_OCN_POLARITY_LOW)) +/** + * @} + */ + +/** @addtogroup TIM_Output_Compare_state + * @{ + */ + +#define TIM_OUTPUT_STATE_DISABLE ((uint16_t)0x0000) +#define TIM_OUTPUT_STATE_ENABLE ((uint16_t)0x0001) +#define IsTimOutputState(STATE) (((STATE) == TIM_OUTPUT_STATE_DISABLE) || ((STATE) == TIM_OUTPUT_STATE_ENABLE)) +/** + * @} + */ + +/** @addtogroup TIM_Output_Compare_N_state + * @{ + */ + +#define TIM_OUTPUT_NSTATE_DISABLE ((uint16_t)0x0000) +#define TIM_OUTPUT_NSTATE_ENABLE ((uint16_t)0x0004) +#define IsTimOutputNState(STATE) (((STATE) == TIM_OUTPUT_NSTATE_DISABLE) || ((STATE) == TIM_OUTPUT_NSTATE_ENABLE)) +/** + * @} + */ + +/** @addtogroup TIM_Capture_Compare_state + * @{ + */ + +#define TIM_CAP_CMP_ENABLE ((uint16_t)0x0001) +#define TIM_CAP_CMP_DISABLE ((uint16_t)0x0000) +#define IsTimCapCmpState(CCX) (((CCX) == TIM_CAP_CMP_ENABLE) || ((CCX) == TIM_CAP_CMP_DISABLE)) +/** + * @} + */ + +/** @addtogroup TIM_Capture_Compare_N_state + * @{ + */ + +#define TIM_CAP_CMP_N_ENABLE ((uint16_t)0x0004) +#define TIM_CAP_CMP_N_DISABLE ((uint16_t)0x0000) +#define IsTimCapCmpNState(CCXN) (((CCXN) == TIM_CAP_CMP_N_ENABLE) || ((CCXN) == TIM_CAP_CMP_N_DISABLE)) +/** + * @} + */ + +/** @addtogroup Break_Input_enable_disable + * @{ + */ + +#define TIM_BREAK_IN_ENABLE ((uint16_t)0x1000) +#define TIM_BREAK_IN_DISABLE ((uint16_t)0x0000) +#define IsTimBreakInState(STATE) (((STATE) == TIM_BREAK_IN_ENABLE) || ((STATE) == TIM_BREAK_IN_DISABLE)) +/** + * @} + */ + +/** @addtogroup Break_Polarity + * @{ + */ + +#define TIM_BREAK_POLARITY_LOW ((uint16_t)0x0000) +#define TIM_BREAK_POLARITY_HIGH ((uint16_t)0x2000) +#define IsTimBreakPalarity(POLARITY) (((POLARITY) == TIM_BREAK_POLARITY_LOW) || ((POLARITY) == TIM_BREAK_POLARITY_HIGH)) +/** + * @} + */ + +/** @addtogroup TIM_AOE_Bit_Set_Reset + * @{ + */ + +#define TIM_AUTO_OUTPUT_ENABLE ((uint16_t)0x4000) +#define TIM_AUTO_OUTPUT_DISABLE ((uint16_t)0x0000) +#define IsTimAutoOutputState(STATE) (((STATE) == TIM_AUTO_OUTPUT_ENABLE) || ((STATE) == TIM_AUTO_OUTPUT_DISABLE)) +/** + * @} + */ + +/** @addtogroup Lock_level + * @{ + */ + +#define TIM_LOCK_LEVEL_OFF ((uint16_t)0x0000) +#define TIM_LOCK_LEVEL_1 ((uint16_t)0x0100) +#define TIM_LOCK_LEVEL_2 ((uint16_t)0x0200) +#define TIM_LOCK_LEVEL_3 ((uint16_t)0x0300) +#define IsTimLockLevel(LEVEL) \ + (((LEVEL) == TIM_LOCK_LEVEL_OFF) || ((LEVEL) == TIM_LOCK_LEVEL_1) || ((LEVEL) == TIM_LOCK_LEVEL_2) \ + || ((LEVEL) == TIM_LOCK_LEVEL_3)) +/** + * @} + */ + +/** @addtogroup OSSI_Off_State_Selection_for_Idle_mode_state + * @{ + */ + +#define TIM_OSSI_STATE_ENABLE ((uint16_t)0x0400) +#define TIM_OSSI_STATE_DISABLE ((uint16_t)0x0000) +#define IsTimOssiState(STATE) (((STATE) == TIM_OSSI_STATE_ENABLE) || ((STATE) == TIM_OSSI_STATE_DISABLE)) +/** + * @} + */ + +/** @addtogroup OSSR_Off_State_Selection_for_Run_mode_state + * @{ + */ + +#define TIM_OSSR_STATE_ENABLE ((uint16_t)0x0800) +#define TIM_OSSR_STATE_DISABLE ((uint16_t)0x0000) +#define IsTimOssrState(STATE) (((STATE) == TIM_OSSR_STATE_ENABLE) || ((STATE) == TIM_OSSR_STATE_DISABLE)) +/** + * @} + */ + +/** @addtogroup TIM_Output_Compare_Idle_State + * @{ + */ + +#define TIM_OC_IDLE_STATE_SET ((uint16_t)0x0100) +#define TIM_OC_IDLE_STATE_RESET ((uint16_t)0x0000) +#define IsTimOcIdleState(STATE) (((STATE) == TIM_OC_IDLE_STATE_SET) || ((STATE) == TIM_OC_IDLE_STATE_RESET)) +/** + * @} + */ + +/** @addtogroup TIM_Output_Compare_N_Idle_State + * @{ + */ + +#define TIM_OCN_IDLE_STATE_SET ((uint16_t)0x0200) +#define TIM_OCN_IDLE_STATE_RESET ((uint16_t)0x0000) +#define IsTimOcnIdleState(STATE) (((STATE) == TIM_OCN_IDLE_STATE_SET) || ((STATE) == TIM_OCN_IDLE_STATE_RESET)) +/** + * @} + */ + +/** @addtogroup TIM_Input_Capture_Polarity + * @{ + */ + +#define TIM_IC_POLARITY_RISING ((uint16_t)0x0000) +#define TIM_IC_POLARITY_FALLING ((uint16_t)0x0002) +#define TIM_IC_POLARITY_BOTHEDGE ((uint16_t)0x000A) +#define IsTimIcPalaritySingleEdge(POLARITY) \ + (((POLARITY) == TIM_IC_POLARITY_RISING) || ((POLARITY) == TIM_IC_POLARITY_FALLING)) +#define IsTimIcPolarityAnyEdge(POLARITY) \ + (((POLARITY) == TIM_IC_POLARITY_RISING) || ((POLARITY) == TIM_IC_POLARITY_FALLING) \ + || ((POLARITY) == TIM_IC_POLARITY_BOTHEDGE)) +/** + * @} + */ + +/** @addtogroup TIM_Input_Capture_Selection + * @{ + */ + +#define TIM_IC_SELECTION_DIRECTTI \ + ((uint16_t)0x0001) /*!< TIM Input 1, 2, 3 or 4 is selected to be \ + connected to IC1, IC2, IC3 or IC4, respectively */ +#define TIM_IC_SELECTION_INDIRECTTI \ + ((uint16_t)0x0002) /*!< TIM Input 1, 2, 3 or 4 is selected to be \ + connected to IC2, IC1, IC4 or IC3, respectively. */ +#define TIM_IC_SELECTION_TRC ((uint16_t)0x0003) /*!< TIM Input 1, 2, 3 or 4 is selected to be connected to TRC. */ +#define IsTimIcSelection(SELECTION) \ + (((SELECTION) == TIM_IC_SELECTION_DIRECTTI) || ((SELECTION) == TIM_IC_SELECTION_INDIRECTTI) \ + || ((SELECTION) == TIM_IC_SELECTION_TRC)) +/** + * @} + */ + +/** @addtogroup TIM_Input_Capture_Prescaler + * @{ + */ + +#define TIM_IC_PSC_DIV1 ((uint16_t)0x0000) /*!< Capture performed each time an edge is detected on the capture input. \ + */ +#define TIM_IC_PSC_DIV2 ((uint16_t)0x0004) /*!< Capture performed once every 2 events. */ +#define TIM_IC_PSC_DIV4 ((uint16_t)0x0008) /*!< Capture performed once every 4 events. */ +#define TIM_IC_PSC_DIV8 ((uint16_t)0x000C) /*!< Capture performed once every 8 events. */ +#define IsTimIcPrescaler(PRESCALER) \ + (((PRESCALER) == TIM_IC_PSC_DIV1) || ((PRESCALER) == TIM_IC_PSC_DIV2) || ((PRESCALER) == TIM_IC_PSC_DIV4) \ + || ((PRESCALER) == TIM_IC_PSC_DIV8)) +/** + * @} + */ + +/** @addtogroup TIM_interrupt_sources + * @{ + */ + +#define TIM_INT_UPDATE ((uint16_t)0x0001) +#define TIM_INT_CC1 ((uint16_t)0x0002) +#define TIM_INT_CC2 ((uint16_t)0x0004) +#define TIM_INT_CC3 ((uint16_t)0x0008) +#define TIM_INT_CC4 ((uint16_t)0x0010) +#define TIM_INT_COM ((uint16_t)0x0020) +#define TIM_INT_TRIG ((uint16_t)0x0040) +#define TIM_INT_BREAK ((uint16_t)0x0080) +#define IsTimInt(IT) ((((IT) & (uint16_t)0xFF00) == 0x0000) && ((IT) != 0x0000)) + +#define IsTimGetInt(IT) \ + (((IT) == TIM_INT_UPDATE) || ((IT) == TIM_INT_CC1) || ((IT) == TIM_INT_CC2) || ((IT) == TIM_INT_CC3) \ + || ((IT) == TIM_INT_CC4) || ((IT) == TIM_INT_COM) || ((IT) == TIM_INT_TRIG) || ((IT) == TIM_INT_BREAK)) +/** + * @} + */ + +/** @addtogroup TIM_DMA_Base_address + * @{ + */ + +#define TIM_DMABASE_CTRL1 ((uint16_t)0x0000) +#define TIM_DMABASE_CTRL2 ((uint16_t)0x0001) +#define TIM_DMABASE_SMCTRL ((uint16_t)0x0002) +#define TIM_DMABASE_DMAINTEN ((uint16_t)0x0003) +#define TIM_DMABASE_STS ((uint16_t)0x0004) +#define TIM_DMABASE_EVTGEN ((uint16_t)0x0005) +#define TIM_DMABASE_CAPCMPMOD1 ((uint16_t)0x0006) +#define TIM_DMABASE_CAPCMPMOD2 ((uint16_t)0x0007) +#define TIM_DMABASE_CAPCMPEN ((uint16_t)0x0008) +#define TIM_DMABASE_CNT ((uint16_t)0x0009) +#define TIM_DMABASE_PSC ((uint16_t)0x000A) +#define TIM_DMABASE_AR ((uint16_t)0x000B) +#define TIM_DMABASE_REPCNT ((uint16_t)0x000C) +#define TIM_DMABASE_CAPCMPDAT1 ((uint16_t)0x000D) +#define TIM_DMABASE_CAPCMPDAT2 ((uint16_t)0x000E) +#define TIM_DMABASE_CAPCMPDAT3 ((uint16_t)0x000F) +#define TIM_DMABASE_CAPCMPDAT4 ((uint16_t)0x0010) +#define TIM_DMABASE_BKDT ((uint16_t)0x0011) +#define TIM_DMABASE_DMACTRL ((uint16_t)0x0012) +#define TIM_DMABASE_CAPCMPMOD3 ((uint16_t)0x0013) +#define TIM_DMABASE_CAPCMPDAT5 ((uint16_t)0x0014) +#define TIM_DMABASE_CAPCMPDAT6 ((uint16_t)0x0015) + +#define IsTimDmaBase(BASE) \ + (((BASE) == TIM_DMABASE_CTRL1) || ((BASE) == TIM_DMABASE_CTRL2) || ((BASE) == TIM_DMABASE_SMCTRL) \ + || ((BASE) == TIM_DMABASE_DMAINTEN) || ((BASE) == TIM_DMABASE_STS) || ((BASE) == TIM_DMABASE_EVTGEN) \ + || ((BASE) == TIM_DMABASE_CAPCMPMOD1) || ((BASE) == TIM_DMABASE_CAPCMPMOD2) || ((BASE) == TIM_DMABASE_CAPCMPMOD3) \ + || ((BASE) == TIM_DMABASE_CAPCMPEN) || ((BASE) == TIM_DMABASE_CNT) || ((BASE) == TIM_DMABASE_PSC) \ + || ((BASE) == TIM_DMABASE_AR) || ((BASE) == TIM_DMABASE_REPCNT) || ((BASE) == TIM_DMABASE_CAPCMPDAT1) \ + || ((BASE) == TIM_DMABASE_CAPCMPDAT2) || ((BASE) == TIM_DMABASE_CAPCMPDAT3) || ((BASE) == TIM_DMABASE_CAPCMPDAT4) \ + || ((BASE) == TIM_DMABASE_CAPCMPDAT5) || ((BASE) == TIM_DMABASE_CAPCMPDAT6) || ((BASE) == TIM_DMABASE_BKDT) \ + || ((BASE) == TIM_DMABASE_DMACTRL)) +/** + * @} + */ + +/** @addtogroup TIM_DMA_Burst_Length + * @{ + */ + +#define TIM_DMABURST_LENGTH_1TRANSFER ((uint16_t)0x0000) +#define TIM_DMABURST_LENGTH_2TRANSFERS ((uint16_t)0x0100) +#define TIM_DMABURST_LENGTH_3TRANSFERS ((uint16_t)0x0200) +#define TIM_DMABURST_LENGTH_4TRANSFERS ((uint16_t)0x0300) +#define TIM_DMABURST_LENGTH_5TRANSFERS ((uint16_t)0x0400) +#define TIM_DMABURST_LENGTH_6TRANSFERS ((uint16_t)0x0500) +#define TIM_DMABURST_LENGTH_7TRANSFERS ((uint16_t)0x0600) +#define TIM_DMABURST_LENGTH_8TRANSFERS ((uint16_t)0x0700) +#define TIM_DMABURST_LENGTH_9TRANSFERS ((uint16_t)0x0800) +#define TIM_DMABURST_LENGTH_10TRANSFERS ((uint16_t)0x0900) +#define TIM_DMABURST_LENGTH_11TRANSFERS ((uint16_t)0x0A00) +#define TIM_DMABURST_LENGTH_12TRANSFERS ((uint16_t)0x0B00) +#define TIM_DMABURST_LENGTH_13TRANSFERS ((uint16_t)0x0C00) +#define TIM_DMABURST_LENGTH_14TRANSFERS ((uint16_t)0x0D00) +#define TIM_DMABURST_LENGTH_15TRANSFERS ((uint16_t)0x0E00) +#define TIM_DMABURST_LENGTH_16TRANSFERS ((uint16_t)0x0F00) +#define TIM_DMABURST_LENGTH_17TRANSFERS ((uint16_t)0x1000) +#define TIM_DMABURST_LENGTH_18TRANSFERS ((uint16_t)0x1100) +#define TIM_DMABURST_LENGTH_19TRANSFERS ((uint16_t)0x1200) +#define TIM_DMABURST_LENGTH_20TRANSFERS ((uint16_t)0x1300) +#define TIM_DMABURST_LENGTH_21TRANSFERS ((uint16_t)0x1400) +#define IsTimDmaLength(LENGTH) \ + (((LENGTH) == TIM_DMABURST_LENGTH_1TRANSFER) || ((LENGTH) == TIM_DMABURST_LENGTH_2TRANSFERS) \ + || ((LENGTH) == TIM_DMABURST_LENGTH_3TRANSFERS) || ((LENGTH) == TIM_DMABURST_LENGTH_4TRANSFERS) \ + || ((LENGTH) == TIM_DMABURST_LENGTH_5TRANSFERS) || ((LENGTH) == TIM_DMABURST_LENGTH_6TRANSFERS) \ + || ((LENGTH) == TIM_DMABURST_LENGTH_7TRANSFERS) || ((LENGTH) == TIM_DMABURST_LENGTH_8TRANSFERS) \ + || ((LENGTH) == TIM_DMABURST_LENGTH_9TRANSFERS) || ((LENGTH) == TIM_DMABURST_LENGTH_10TRANSFERS) \ + || ((LENGTH) == TIM_DMABURST_LENGTH_11TRANSFERS) || ((LENGTH) == TIM_DMABURST_LENGTH_12TRANSFERS) \ + || ((LENGTH) == TIM_DMABURST_LENGTH_13TRANSFERS) || ((LENGTH) == TIM_DMABURST_LENGTH_14TRANSFERS) \ + || ((LENGTH) == TIM_DMABURST_LENGTH_15TRANSFERS) || ((LENGTH) == TIM_DMABURST_LENGTH_16TRANSFERS) \ + || ((LENGTH) == TIM_DMABURST_LENGTH_17TRANSFERS) || ((LENGTH) == TIM_DMABURST_LENGTH_18TRANSFERS) \ + || ((LENGTH) == TIM_DMABURST_LENGTH_19TRANSFERS) || ((LENGTH) == TIM_DMABURST_LENGTH_20TRANSFERS) \ + || ((LENGTH) == TIM_DMABURST_LENGTH_21TRANSFERS)) +/** + * @} + */ + +/** @addtogroup TIM_DMA_sources + * @{ + */ + +#define TIM_DMA_UPDATE ((uint16_t)0x0100) +#define TIM_DMA_CC1 ((uint16_t)0x0200) +#define TIM_DMA_CC2 ((uint16_t)0x0400) +#define TIM_DMA_CC3 ((uint16_t)0x0800) +#define TIM_DMA_CC4 ((uint16_t)0x1000) +#define TIM_DMA_COM ((uint16_t)0x2000) +#define TIM_DMA_TRIG ((uint16_t)0x4000) +#define IsTimDmaSrc(SOURCE) ((((SOURCE) & (uint16_t)0x80FF) == 0x0000) && ((SOURCE) != 0x0000)) + +/** + * @} + */ + +/** @addtogroup TIM_External_Trigger_Prescaler + * @{ + */ + +#define TIM_EXT_TRG_PSC_OFF ((uint16_t)0x0000) +#define TIM_EXT_TRG_PSC_DIV2 ((uint16_t)0x1000) +#define TIM_EXT_TRG_PSC_DIV4 ((uint16_t)0x2000) +#define TIM_EXT_TRG_PSC_DIV8 ((uint16_t)0x3000) +#define IsTimExtPreDiv(PRESCALER) \ + (((PRESCALER) == TIM_EXT_TRG_PSC_OFF) || ((PRESCALER) == TIM_EXT_TRG_PSC_DIV2) \ + || ((PRESCALER) == TIM_EXT_TRG_PSC_DIV4) || ((PRESCALER) == TIM_EXT_TRG_PSC_DIV8)) +/** + * @} + */ + +/** @addtogroup TIM_Internal_Trigger_Selection + * @{ + */ + +#define TIM_TRIG_SEL_IN_TR0 ((uint16_t)0x0000) +#define TIM_TRIG_SEL_IN_TR1 ((uint16_t)0x0010) +#define TIM_TRIG_SEL_IN_TR2 ((uint16_t)0x0020) +#define TIM_TRIG_SEL_IN_TR3 ((uint16_t)0x0030) +#define TIM_TRIG_SEL_TI1F_ED ((uint16_t)0x0040) +#define TIM_TRIG_SEL_TI1FP1 ((uint16_t)0x0050) +#define TIM_TRIG_SEL_TI2FP2 ((uint16_t)0x0060) +#define TIM_TRIG_SEL_ETRF ((uint16_t)0x0070) +#define IsTimTrigSel(SELECTION) \ + (((SELECTION) == TIM_TRIG_SEL_IN_TR0) || ((SELECTION) == TIM_TRIG_SEL_IN_TR1) \ + || ((SELECTION) == TIM_TRIG_SEL_IN_TR2) || ((SELECTION) == TIM_TRIG_SEL_IN_TR3) \ + || ((SELECTION) == TIM_TRIG_SEL_TI1F_ED) || ((SELECTION) == TIM_TRIG_SEL_TI1FP1) \ + || ((SELECTION) == TIM_TRIG_SEL_TI2FP2) || ((SELECTION) == TIM_TRIG_SEL_ETRF)) +#define IsTimInterTrigSel(SELECTION) \ + (((SELECTION) == TIM_TRIG_SEL_IN_TR0) || ((SELECTION) == TIM_TRIG_SEL_IN_TR1) \ + || ((SELECTION) == TIM_TRIG_SEL_IN_TR2) || ((SELECTION) == TIM_TRIG_SEL_IN_TR3)) +/** + * @} + */ + +/** @addtogroup TIM_TIx_External_Clock_Source + * @{ + */ + +#define TIM_EXT_CLK_SRC_TI1 ((uint16_t)0x0050) +#define TIM_EXT_CLK_SRC_TI2 ((uint16_t)0x0060) +#define TIM_EXT_CLK_SRC_TI1ED ((uint16_t)0x0040) +#define IsTimExtClkSrc(SOURCE) \ + (((SOURCE) == TIM_EXT_CLK_SRC_TI1) || ((SOURCE) == TIM_EXT_CLK_SRC_TI2) || ((SOURCE) == TIM_EXT_CLK_SRC_TI1ED)) +/** + * @} + */ + +/** @addtogroup TIM_External_Trigger_Polarity + * @{ + */ +#define TIM_EXT_TRIG_POLARITY_INVERTED ((uint16_t)0x8000) +#define TIM_EXT_TRIG_POLARITY_NONINVERTED ((uint16_t)0x0000) +#define IsTimExtTrigPolarity(POLARITY) \ + (((POLARITY) == TIM_EXT_TRIG_POLARITY_INVERTED) || ((POLARITY) == TIM_EXT_TRIG_POLARITY_NONINVERTED)) +/** + * @} + */ + +/** @addtogroup TIM_Prescaler_Reload_Mode + * @{ + */ + +#define TIM_PSC_RELOAD_MODE_UPDATE ((uint16_t)0x0000) +#define TIM_PSC_RELOAD_MODE_IMMEDIATE ((uint16_t)0x0001) +#define IsTimPscReloadMode(RELOAD) \ + (((RELOAD) == TIM_PSC_RELOAD_MODE_UPDATE) || ((RELOAD) == TIM_PSC_RELOAD_MODE_IMMEDIATE)) +/** + * @} + */ + +/** @addtogroup TIM_Forced_Action + * @{ + */ + +#define TIM_FORCED_ACTION_ACTIVE ((uint16_t)0x0050) +#define TIM_FORCED_ACTION_INACTIVE ((uint16_t)0x0040) +#define IsTimForceActive(OPERATE) (((OPERATE) == TIM_FORCED_ACTION_ACTIVE) || ((OPERATE) == TIM_FORCED_ACTION_INACTIVE)) +/** + * @} + */ + +/** @addtogroup TIM_Encoder_Mode + * @{ + */ + +#define TIM_ENCODE_MODE_TI1 ((uint16_t)0x0001) +#define TIM_ENCODE_MODE_TI2 ((uint16_t)0x0002) +#define TIM_ENCODE_MODE_TI12 ((uint16_t)0x0003) +#define IsTimEncodeMode(MODE) \ + (((MODE) == TIM_ENCODE_MODE_TI1) || ((MODE) == TIM_ENCODE_MODE_TI2) || ((MODE) == TIM_ENCODE_MODE_TI12)) +/** + * @} + */ + +/** @addtogroup TIM_Event_Source + * @{ + */ + +#define TIM_EVT_SRC_UPDATE ((uint16_t)0x0001) +#define TIM_EVT_SRC_CC1 ((uint16_t)0x0002) +#define TIM_EVT_SRC_CC2 ((uint16_t)0x0004) +#define TIM_EVT_SRC_CC3 ((uint16_t)0x0008) +#define TIM_EVT_SRC_CC4 ((uint16_t)0x0010) +#define TIM_EVT_SRC_COM ((uint16_t)0x0020) +#define TIM_EVT_SRC_TRIG ((uint16_t)0x0040) +#define TIM_EVT_SRC_BREAK ((uint16_t)0x0080) +#define IsTimEvtSrc(SOURCE) ((((SOURCE) & (uint16_t)0xFF00) == 0x0000) && ((SOURCE) != 0x0000)) + +/** + * @} + */ + +/** @addtogroup TIM_Update_Source + * @{ + */ + +#define TIM_UPDATE_SRC_GLOBAL \ + ((uint16_t)0x0000) /*!< Source of update is the counter overflow/underflow \ + or the setting of UG bit, or an update generation \ + through the slave mode controller. */ +#define TIM_UPDATE_SRC_REGULAr ((uint16_t)0x0001) /*!< Source of update is counter overflow/underflow. */ +#define IsTimUpdateSrc(SOURCE) (((SOURCE) == TIM_UPDATE_SRC_GLOBAL) || ((SOURCE) == TIM_UPDATE_SRC_REGULAr)) +/** + * @} + */ + +/** @addtogroup TIM_Output_Compare_Preload_State + * @{ + */ + +#define TIM_OC_PRE_LOAD_ENABLE ((uint16_t)0x0008) +#define TIM_OC_PRE_LOAD_DISABLE ((uint16_t)0x0000) +#define IsTimOcPreLoadState(STATE) (((STATE) == TIM_OC_PRE_LOAD_ENABLE) || ((STATE) == TIM_OC_PRE_LOAD_DISABLE)) +/** + * @} + */ + +/** @addtogroup TIM_Output_Compare_Fast_State + * @{ + */ + +#define TIM_OC_FAST_ENABLE ((uint16_t)0x0004) +#define TIM_OC_FAST_DISABLE ((uint16_t)0x0000) +#define IsTimOcFastState(STATE) (((STATE) == TIM_OC_FAST_ENABLE) || ((STATE) == TIM_OC_FAST_DISABLE)) + +/** + * @} + */ + +/** @addtogroup TIM_Output_Compare_Clear_State + * @{ + */ + +#define TIM_OC_CLR_ENABLE ((uint16_t)0x0080) +#define TIM_OC_CLR_DISABLE ((uint16_t)0x0000) +#define IsTimOcClrState(STATE) (((STATE) == TIM_OC_CLR_ENABLE) || ((STATE) == TIM_OC_CLR_DISABLE)) +/** + * @} + */ + +/** @addtogroup TIM_Trigger_Output_Source + * @{ + */ + +#define TIM_TRGO_SRC_RESET ((uint16_t)0x0000) +#define TIM_TRGO_SRC_ENABLE ((uint16_t)0x0010) +#define TIM_TRGO_SRC_UPDATE ((uint16_t)0x0020) +#define TIM_TRGO_SRC_OC1 ((uint16_t)0x0030) +#define TIM_TRGO_SRC_OC1REF ((uint16_t)0x0040) +#define TIM_TRGO_SRC_OC2REF ((uint16_t)0x0050) +#define TIM_TRGO_SRC_OC3REF ((uint16_t)0x0060) +#define TIM_TRGO_SRC_OC4REF ((uint16_t)0x0070) +#define IsTimTrgoSrc(SOURCE) \ + (((SOURCE) == TIM_TRGO_SRC_RESET) || ((SOURCE) == TIM_TRGO_SRC_ENABLE) || ((SOURCE) == TIM_TRGO_SRC_UPDATE) \ + || ((SOURCE) == TIM_TRGO_SRC_OC1) || ((SOURCE) == TIM_TRGO_SRC_OC1REF) || ((SOURCE) == TIM_TRGO_SRC_OC2REF) \ + || ((SOURCE) == TIM_TRGO_SRC_OC3REF) || ((SOURCE) == TIM_TRGO_SRC_OC4REF)) +/** + * @} + */ + +/** @defgroup ETR selection + * @{ + */ +#define TIM_ETR_Seletct_ExtGpio ((uint16_t)0x0000) +#define TIM_ETR_Seletct_innerTsc ((uint16_t)0x0100) +/** + * @} + */ + +/** @addtogroup TIM_Slave_Mode + * @{ + */ + +#define TIM_SLAVE_MODE_RESET ((uint16_t)0x0004) +#define TIM_SLAVE_MODE_GATED ((uint16_t)0x0005) +#define TIM_SLAVE_MODE_TRIG ((uint16_t)0x0006) +#define TIM_SLAVE_MODE_EXT1 ((uint16_t)0x0007) +#define IsTimSlaveMode(MODE) \ + (((MODE) == TIM_SLAVE_MODE_RESET) || ((MODE) == TIM_SLAVE_MODE_GATED) || ((MODE) == TIM_SLAVE_MODE_TRIG) \ + || ((MODE) == TIM_SLAVE_MODE_EXT1)) +/** + * @} + */ + +/** @addtogroup TIM_Master_Slave_Mode + * @{ + */ + +#define TIM_MASTER_SLAVE_MODE_ENABLE ((uint16_t)0x0080) +#define TIM_MASTER_SLAVE_MODE_DISABLE ((uint16_t)0x0000) +#define IsTimMasterSlaveMode(STATE) \ + (((STATE) == TIM_MASTER_SLAVE_MODE_ENABLE) || ((STATE) == TIM_MASTER_SLAVE_MODE_DISABLE)) +/** + * @} + */ + +/** @addtogroup TIM_Flags + * @{ + */ + +#define TIM_FLAG_UPDATE ((uint32_t)0x0001) +#define TIM_FLAG_CC1 ((uint32_t)0x0002) +#define TIM_FLAG_CC2 ((uint32_t)0x0004) +#define TIM_FLAG_CC3 ((uint32_t)0x0008) +#define TIM_FLAG_CC4 ((uint32_t)0x0010) +#define TIM_FLAG_COM ((uint32_t)0x0020) +#define TIM_FLAG_TRIG ((uint32_t)0x0040) +#define TIM_FLAG_BREAK ((uint32_t)0x0080) +#define TIM_FLAG_CC1OF ((uint32_t)0x0200) +#define TIM_FLAG_CC2OF ((uint32_t)0x0400) +#define TIM_FLAG_CC3OF ((uint32_t)0x0800) +#define TIM_FLAG_CC4OF ((uint32_t)0x1000) +#define TIM_FLAG_CC5 ((uint32_t)0x010000) +#define TIM_FLAG_CC6 ((uint32_t)0x020000) + +#define IsTimGetFlag(FLAG) \ + (((FLAG) == TIM_FLAG_UPDATE) || ((FLAG) == TIM_FLAG_CC1) || ((FLAG) == TIM_FLAG_CC2) || ((FLAG) == TIM_FLAG_CC3) \ + || ((FLAG) == TIM_FLAG_CC4) || ((FLAG) == TIM_FLAG_COM) || ((FLAG) == TIM_FLAG_TRIG) \ + || ((FLAG) == TIM_FLAG_BREAK) || ((FLAG) == TIM_FLAG_CC1OF) || ((FLAG) == TIM_FLAG_CC2OF) \ + || ((FLAG) == TIM_FLAG_CC3OF) || ((FLAG) == TIM_FLAG_CC4OF) || ((FLAG) == TIM_FLAG_CC5) \ + || ((FLAG) == TIM_FLAG_CC6)) + +#define IsTimClrFlag(TIM_FLAG) ((((TIM_FLAG) & (uint16_t)0xE100) == 0x0000) && ((TIM_FLAG) != 0x0000)) +/** + * @} + */ + +/** @addtogroup TIM_Input_Capture_Filer_Value + * @{ + */ + +#define IsTimInCapFilter(ICFILTER) ((ICFILTER) <= 0xF) +/** + * @} + */ + +/** @addtogroup TIM_External_Trigger_Filter + * @{ + */ + +#define IsTimExtTrigFilter(EXTFILTER) ((EXTFILTER) <= 0xF) +/** + * @} + */ + +#define TIM_CC1EN ((uint32_t)1<<0) +#define TIM_CC1NEN ((uint32_t)1<<2) +#define TIM_CC2EN ((uint32_t)1<<4) +#define TIM_CC2NEN ((uint32_t)1<<6) +#define TIM_CC3EN ((uint32_t)1<<8) +#define TIM_CC3NEN ((uint32_t)1<<10) +#define TIM_CC4EN ((uint32_t)1<<12) +#define TIM_CC5EN ((uint32_t)1<<16) +#define TIM_CC6EN ((uint32_t)1<<20) + +#define IsAdvancedTimCCENFlag(FLAG) \ + (((FLAG) == TIM_CC1EN) || ((FLAG) == TIM_CC1NEN) || ((FLAG) == TIM_CC2EN) || ((FLAG) == TIM_CC2NEN) \ + || ((FLAG) == TIM_CC3EN) || ((FLAG) == TIM_CC3NEN) \ + || ((FLAG) == TIM_CC4EN) || ((FLAG) == TIM_CC5EN) || ((FLAG) == TIM_CC6EN) ) +#define IsGeneralTimCCENFlag(FLAG) \ + (((FLAG) == TIM_CC1EN) || ((FLAG) == TIM_CC2EN) \ + || ((FLAG) == TIM_CC3EN) \ + || ((FLAG) == TIM_CC4EN) ) + +/** @addtogroup TIM_Legacy + * @{ + */ + +#define TIM_DMA_BURST_LEN_1BYTE TIM_DMABURST_LENGTH_1TRANSFER +#define TIM_DMA_BURST_LEN_2BYTES TIM_DMABURST_LENGTH_2TRANSFERS +#define TIM_DMA_BURST_LEN_3BYTES TIM_DMABURST_LENGTH_3TRANSFERS +#define TIM_DMA_BURST_LEN_4BYTES TIM_DMABURST_LENGTH_4TRANSFERS +#define TIM_DMA_BURST_LEN_5BYTES TIM_DMABURST_LENGTH_5TRANSFERS +#define TIM_DMA_BURST_LEN_6BYTES TIM_DMABURST_LENGTH_6TRANSFERS +#define TIM_DMA_BURST_LEN_7BYTES TIM_DMABURST_LENGTH_7TRANSFERS +#define TIM_DMA_BURST_LEN_8BYTES TIM_DMABURST_LENGTH_8TRANSFERS +#define TIM_DMA_BURST_LEN_9BYTES TIM_DMABURST_LENGTH_9TRANSFERS +#define TIM_DMA_BURST_LEN_10BYTES TIM_DMABURST_LENGTH_10TRANSFERS +#define TIM_DMA_BURST_LEN_11BYTES TIM_DMABURST_LENGTH_11TRANSFERS +#define TIM_DMA_BURST_LEN_12BYTES TIM_DMABURST_LENGTH_12TRANSFERS +#define TIM_DMA_BURST_LEN_13BYTES TIM_DMABURST_LENGTH_13TRANSFERS +#define TIM_DMA_BURST_LEN_14BYTES TIM_DMABURST_LENGTH_14TRANSFERS +#define TIM_DMA_BURST_LEN_15BYTES TIM_DMABURST_LENGTH_15TRANSFERS +#define TIM_DMA_BURST_LEN_16BYTES TIM_DMABURST_LENGTH_16TRANSFERS +#define TIM_DMA_BURST_LEN_17BYTES TIM_DMABURST_LENGTH_17TRANSFERS +#define TIM_DMA_BURST_LEN_18BYTES TIM_DMABURST_LENGTH_18TRANSFERS +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup TIM_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup TIM_Exported_Functions + * @{ + */ + +void TIM_DeInit(TIM_Module* TIMx); +void TIM_InitTimeBase(TIM_Module* TIMx, TIM_TimeBaseInitType* TIM_TimeBaseInitStruct); +void TIM_InitOc1(TIM_Module* TIMx, OCInitType* TIM_OCInitStruct); +void TIM_InitOc2(TIM_Module* TIMx, OCInitType* TIM_OCInitStruct); +void TIM_InitOc3(TIM_Module* TIMx, OCInitType* TIM_OCInitStruct); +void TIM_InitOc4(TIM_Module* TIMx, OCInitType* TIM_OCInitStruct); +void TIM_InitOc5(TIM_Module* TIMx, OCInitType* TIM_OCInitStruct); +void TIM_InitOc6(TIM_Module* TIMx, OCInitType* TIM_OCInitStruct); +void TIM_ICInit(TIM_Module* TIMx, TIM_ICInitType* TIM_ICInitStruct); +void TIM_ConfigPwmIc(TIM_Module* TIMx, TIM_ICInitType* TIM_ICInitStruct); +void TIM_ConfigBkdt(TIM_Module* TIMx, TIM_BDTRInitType* TIM_BDTRInitStruct); +void TIM_InitTimBaseStruct(TIM_TimeBaseInitType* TIM_TimeBaseInitStruct); +void TIM_InitOcStruct(OCInitType* TIM_OCInitStruct); +void TIM_InitIcStruct(TIM_ICInitType* TIM_ICInitStruct); +void TIM_InitBkdtStruct(TIM_BDTRInitType* TIM_BDTRInitStruct); +void TIM_Enable(TIM_Module* TIMx, FunctionalState Cmd); +void TIM_EnableCtrlPwmOutputs(TIM_Module* TIMx, FunctionalState Cmd); +void TIM_ConfigInt(TIM_Module* TIMx, uint16_t TIM_IT, FunctionalState Cmd); +void TIM_GenerateEvent(TIM_Module* TIMx, uint16_t TIM_EventSource); +void TIM_ConfigDma(TIM_Module* TIMx, uint16_t TIM_DMABase, uint16_t TIM_DMABurstLength); +void TIM_EnableDma(TIM_Module* TIMx, uint16_t TIM_DMASource, FunctionalState Cmd); +void TIM_ConfigInternalClk(TIM_Module* TIMx); +void TIM_ConfigInternalTrigToExt(TIM_Module* TIMx, uint16_t TIM_InputTriggerSource); +void TIM_ConfigExtTrigAsClk(TIM_Module* TIMx, + uint16_t TIM_TIxExternalCLKSource, + uint16_t IcPolarity, + uint16_t ICFilter); +void TIM_ConfigExtClkMode1(TIM_Module* TIMx, + uint16_t TIM_ExtTRGPrescaler, + uint16_t TIM_ExtTRGPolarity, + uint16_t ExtTRGFilter); +void TIM_ConfigExtClkMode2(TIM_Module* TIMx, + uint16_t TIM_ExtTRGPrescaler, + uint16_t TIM_ExtTRGPolarity, + uint16_t ExtTRGFilter); +void TIM_ConfigExtTrig(TIM_Module* TIMx, + uint16_t TIM_ExtTRGPrescaler, + uint16_t TIM_ExtTRGPolarity, + uint16_t ExtTRGFilter); +void TIM_ConfigPrescaler(TIM_Module* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode); +void TIM_ConfigCntMode(TIM_Module* TIMx, uint16_t CntMode); +void TIM_SelectInputTrig(TIM_Module* TIMx, uint16_t TIM_InputTriggerSource); +void TIM_ConfigEncoderInterface(TIM_Module* TIMx, + uint16_t TIM_EncoderMode, + uint16_t TIM_IC1Polarity, + uint16_t TIM_IC2Polarity); +void TIM_ConfigForcedOc1(TIM_Module* TIMx, uint16_t TIM_ForcedAction); +void TIM_ConfigForcedOc2(TIM_Module* TIMx, uint16_t TIM_ForcedAction); +void TIM_ConfigForcedOc3(TIM_Module* TIMx, uint16_t TIM_ForcedAction); +void TIM_ConfigForcedOc4(TIM_Module* TIMx, uint16_t TIM_ForcedAction); +void TIM_ConfigForcedOc5(TIM_Module* TIMx, uint16_t TIM_ForcedAction); +void TIM_ConfigForcedOc6(TIM_Module* TIMx, uint16_t TIM_ForcedAction); +void TIM_ConfigArPreload(TIM_Module* TIMx, FunctionalState Cmd); +void TIM_SelectComEvt(TIM_Module* TIMx, FunctionalState Cmd); +void TIM_SelectCapCmpDmaSrc(TIM_Module* TIMx, FunctionalState Cmd); +void TIM_EnableCapCmpPreloadControl(TIM_Module* TIMx, FunctionalState Cmd); +void TIM_ConfigOc1Preload(TIM_Module* TIMx, uint16_t TIM_OCPreload); +void TIM_ConfigOc2Preload(TIM_Module* TIMx, uint16_t TIM_OCPreload); +void TIM_ConfigOc3Preload(TIM_Module* TIMx, uint16_t TIM_OCPreload); +void TIM_ConfigOc4Preload(TIM_Module* TIMx, uint16_t TIM_OCPreload); +void TIM_ConfigOc5Preload(TIM_Module* TIMx, uint16_t TIM_OCPreload); +void TIM_ConfigOc6Preload(TIM_Module* TIMx, uint16_t TIM_OCPreload); +void TIM_ConfigOc1Fast(TIM_Module* TIMx, uint16_t TIM_OCFast); +void TIM_ConfigOc2Fast(TIM_Module* TIMx, uint16_t TIM_OCFast); +void TIM_ConfigOc3Fast(TIM_Module* TIMx, uint16_t TIM_OCFast); +void TIM_ConfigOc4Fast(TIM_Module* TIMx, uint16_t TIM_OCFast); +void TIM_ConfigOc5Fast(TIM_Module* TIMx, uint16_t TIM_OCFast); +void TIM_ConfigOc6Fast(TIM_Module* TIMx, uint16_t TIM_OCFast); +void TIM_ClrOc1Ref(TIM_Module* TIMx, uint16_t TIM_OCClear); +void TIM_ClrOc2Ref(TIM_Module* TIMx, uint16_t TIM_OCClear); +void TIM_ClrOc3Ref(TIM_Module* TIMx, uint16_t TIM_OCClear); +void TIM_ClrOc4Ref(TIM_Module* TIMx, uint16_t TIM_OCClear); +void TIM_ClrOc5Ref(TIM_Module* TIMx, uint16_t TIM_OCClear); +void TIM_ClrOc6Ref(TIM_Module* TIMx, uint16_t TIM_OCClear); +void TIM_ConfigOc1Polarity(TIM_Module* TIMx, uint16_t OcPolarity); +void TIM_ConfigOc1NPolarity(TIM_Module* TIMx, uint16_t OcNPolarity); +void TIM_ConfigOc2Polarity(TIM_Module* TIMx, uint16_t OcPolarity); +void TIM_ConfigOc2NPolarity(TIM_Module* TIMx, uint16_t OcNPolarity); +void TIM_ConfigOc3Polarity(TIM_Module* TIMx, uint16_t OcPolarity); +void TIM_ConfigOc3NPolarity(TIM_Module* TIMx, uint16_t OcNPolarity); +void TIM_ConfigOc4Polarity(TIM_Module* TIMx, uint16_t OcPolarity); +void TIM_ConfigOc5Polarity(TIM_Module* TIMx, uint16_t OcPolarity); +void TIM_ConfigOc6Polarity(TIM_Module* TIMx, uint16_t OcPolarity); +void TIM_EnableCapCmpCh(TIM_Module* TIMx, uint16_t Channel, uint32_t TIM_CCx); +void TIM_EnableCapCmpChN(TIM_Module* TIMx, uint16_t Channel, uint32_t TIM_CCxN); +void TIM_SelectOcMode(TIM_Module* TIMx, uint16_t Channel, uint16_t OcMode); +void TIM_EnableUpdateEvt(TIM_Module* TIMx, FunctionalState Cmd); +void TIM_ConfigUpdateRequestIntSrc(TIM_Module* TIMx, uint16_t TIM_UpdateSource); +void TIM_SelectHallSensor(TIM_Module* TIMx, FunctionalState Cmd); +void TIM_SelectOnePulseMode(TIM_Module* TIMx, uint16_t TIM_OPMode); +void TIM_SelectOutputTrig(TIM_Module* TIMx, uint16_t TIM_TRGOSource); +void TIM_SelectExtSignalSource(TIM_Module* TIMx, uint16_t ExtSigalSource); +void TIM_SelectSlaveMode(TIM_Module* TIMx, uint16_t TIM_SlaveMode); +void TIM_SelectMasterSlaveMode(TIM_Module* TIMx, uint16_t TIM_MasterSlaveMode); +void TIM_SetCnt(TIM_Module* TIMx, uint16_t Counter); +void TIM_SetAutoReload(TIM_Module* TIMx, uint16_t Autoreload); +void TIM_SetCmp1(TIM_Module* TIMx, uint16_t Compare1); +void TIM_SetCmp2(TIM_Module* TIMx, uint16_t Compare2); +void TIM_SetCmp3(TIM_Module* TIMx, uint16_t Compare3); +void TIM_SetCmp4(TIM_Module* TIMx, uint16_t Compare4); +void TIM_SetCmp5(TIM_Module* TIMx, uint16_t Compare5); +void TIM_SetCmp6(TIM_Module* TIMx, uint16_t Compare6); +void TIM_SetInCap1Prescaler(TIM_Module* TIMx, uint16_t TIM_ICPSC); +void TIM_SetInCap2Prescaler(TIM_Module* TIMx, uint16_t TIM_ICPSC); +void TIM_SetInCap3Prescaler(TIM_Module* TIMx, uint16_t TIM_ICPSC); +void TIM_SetInCap4Prescaler(TIM_Module* TIMx, uint16_t TIM_ICPSC); +void TIM_SetClkDiv(TIM_Module* TIMx, uint16_t TIM_CKD); +uint16_t TIM_GetCap1(TIM_Module* TIMx); +uint16_t TIM_GetCap2(TIM_Module* TIMx); +uint16_t TIM_GetCap3(TIM_Module* TIMx); +uint16_t TIM_GetCap4(TIM_Module* TIMx); +uint16_t TIM_GetCap5(TIM_Module* TIMx); +uint16_t TIM_GetCap6(TIM_Module* TIMx); +uint16_t TIM_GetCnt(TIM_Module* TIMx); +uint16_t TIM_GetPrescaler(TIM_Module* TIMx); +uint16_t TIM_GetAutoReload(TIM_Module* TIMx); +FlagStatus TIM_GetCCENStatus(TIM_Module* TIMx, uint32_t TIM_CCEN); +FlagStatus TIM_GetFlagStatus(TIM_Module* TIMx, uint32_t TIM_FLAG); +void TIM_ClearFlag(TIM_Module* TIMx, uint32_t TIM_FLAG); +INTStatus TIM_GetIntStatus(TIM_Module* TIMx, uint32_t TIM_IT); +void TIM_ClrIntPendingBit(TIM_Module* TIMx, uint32_t TIM_IT); + +#ifdef __cplusplus +} +#endif + +#endif /*__N32G45X_TIM_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/inc/n32g45x_tsc.h b/inc/n32g45x_tsc.h new file mode 100644 index 0000000..ad009b8 --- /dev/null +++ b/inc/n32g45x_tsc.h @@ -0,0 +1,576 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_tsc.h + * @author Nations + * @version v1.0.3 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_TSC_H__ +#define __N32G45X_TSC_H__ + +#ifdef __cplusplus + extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup TSC + * @{ + */ + +/** + * @brief TSC error code + */ + typedef enum { + TSC_ERROR_OK = 0x00U, /*!< No error */ + TSC_ERROR_CLOCK = 0x01U, /*!< clock config error */ + TSC_ERROR_PARAMETER = 0x02U, /*!< parameter error */ + TSC_ERROR_HW_MODE = 0x02U, /*!< Exit hw mode timeout */ + + }TSC_ErrorTypeDef; + /** + * @ + */ + +/** + * @brief TSC clock source + */ +#define TSC_CLK_SRC_LSI (0x00000000) /*!< LSI*/ +#define TSC_CLK_SRC_LSE (RCC_LSE_ENABLE) /*!< LSE */ +#define TSC_CLK_SRC_LSE_BYPASS (RCC_LSE_BYPASS) /*!< LSE bypass */ +/** + * @ + */ + + +/** + * @defgroup Detect_Period + */ +#define TSC_DET_PERIOD_8 (0x00000000U) /*!< DET_PERIOD[3:0] = 8/TSC_CLOCK */ +#define TSC_DET_PERIOD_16 (0x01UL << TSC_CTRL_DET_PERIOD_SHIFT) /*!< 0x00000001U DET_PERIOD[3:0] = 16/TSC_CLOCK */ +#define TSC_DET_PERIOD_24 (0x02UL << TSC_CTRL_DET_PERIOD_SHIFT) /*!< 0x00000002U DET_PERIOD[3:0] = 24/TSC_CLOCK */ +#define TSC_DET_PERIOD_32 (0x03UL << TSC_CTRL_DET_PERIOD_SHIFT) /*!< 0x00000003U DET_PERIOD[3:0] = 32/TSC_CLOCK(default) */ +#define TSC_DET_PERIOD_40 (0x04UL << TSC_CTRL_DET_PERIOD_SHIFT) /*!< 0x00000004U DET_PERIOD[3:0] = 40/TSC_CLOCK */ +#define TSC_DET_PERIOD_48 (0x05UL << TSC_CTRL_DET_PERIOD_SHIFT) /*!< 0x00000005U DET_PERIOD[3:0] = 48/TSC_CLOCK */ +#define TSC_DET_PERIOD_56 (0x06UL << TSC_CTRL_DET_PERIOD_SHIFT) /*!< 0x00000006U DET_PERIOD[3:0] = 56/TSC_CLOCK */ +#define TSC_DET_PERIOD_64 (0x07UL << TSC_CTRL_DET_PERIOD_SHIFT) /*!< 0x00000007U DET_PERIOD[3:0] = 64/TSC_CLOCK */ +#define TSC_DET_PERIOD_72 (0x08UL << TSC_CTRL_DET_PERIOD_SHIFT) /*!< 0x00000008U DET_PERIOD[3:0] = 72/TSC_CLOCK */ +#define TSC_DET_PERIOD_80 (0x09UL << TSC_CTRL_DET_PERIOD_SHIFT) /*!< 0x00000009U DET_PERIOD[3:0] = 80/TSC_CLOCK */ +#define TSC_DET_PERIOD_88 (0x0AUL << TSC_CTRL_DET_PERIOD_SHIFT) /*!< 0x0000000AU DET_PERIOD[3:0] = 88/TSC_CLOCK */ +#define TSC_DET_PERIOD_96 (0x0BUL << TSC_CTRL_DET_PERIOD_SHIFT) /*!< 0x0000000BU DET_PERIOD[3:0] = 96/TSC_CLOCK */ +#define TSC_DET_PERIOD_104 (0x0CUL << TSC_CTRL_DET_PERIOD_SHIFT) /*!< 0x0000000CU DET_PERIOD[3:0] = 104/TSC_CLOCK */ + +#define TSC_DET_PERIOD_8_32KHZ ((uint8_t)TSC_DET_PERIOD_8) +#define TSC_DET_PERIOD_16_32KHZ ((uint8_t)TSC_DET_PERIOD_16) +#define TSC_DET_PERIOD_24_32KHZ ((uint8_t)TSC_DET_PERIOD_24) +#define TSC_DET_PERIOD_32_32KHZ ((uint8_t)TSC_DET_PERIOD_32) +#define TSC_DET_PERIOD_40_32KHZ ((uint8_t)TSC_DET_PERIOD_40) +#define TSC_DET_PERIOD_48_32KHZ ((uint8_t)TSC_DET_PERIOD_48) +#define TSC_DET_PERIOD_56_32KHZ ((uint8_t)TSC_DET_PERIOD_56) +#define TSC_DET_PERIOD_64_32KHZ ((uint8_t)TSC_DET_PERIOD_64) +#define TSC_DET_PERIOD_72_32KHZ ((uint8_t)TSC_DET_PERIOD_72) +#define TSC_DET_PERIOD_80_32KHZ ((uint8_t)TSC_DET_PERIOD_80) +#define TSC_DET_PERIOD_88_32KHZ ((uint8_t)TSC_DET_PERIOD_88) +#define TSC_DET_PERIOD_96_32KHZ ((uint8_t)TSC_DET_PERIOD_96) +#define TSC_DET_PERIOD_104_32KHZ ((uint8_t)TSC_DET_PERIOD_104) +/** + * @ + */ + +/** + * @defgroup Detect_Filter + */ +#define TSC_DET_FILTER_1 (0x00000000U) /*!< DET_FILTER[3:0] = 1 sample */ +#define TSC_DET_FILTER_2 (0x01UL << TSC_CTRL_DET_FILTER_SHIFT) /*!< 0x00000010U DET_FILTER[3:0] = 2 samples */ +#define TSC_DET_FILTER_3 (0x02UL << TSC_CTRL_DET_FILTER_SHIFT) /*!< 0x00000020U DET_FILTER[3:0] = 3 samples */ +#define TSC_DET_FILTER_4 (0x03UL << TSC_CTRL_DET_FILTER_SHIFT) /*!< 0x00000030U DET_FILTER[3:0] = 4 samples */ + +#define TSC_HW_DET_FILTER_1 ((uint8_t)TSC_DET_FILTER_1) +#define TSC_HW_DET_FILTER_2 ((uint8_t)TSC_DET_FILTER_2) +#define TSC_HW_DET_FILTER_3 ((uint8_t)TSC_DET_FILTER_3) +#define TSC_HW_DET_FILTER_4 ((uint8_t)TSC_DET_FILTER_4) + +/** + * @ + */ + +/** + * @defgroup HW_Detect_Mode + */ +#define TSC_HW_DET_MODE_DISABLE (0x00000000U) /*!< Hardware detect mode disable */ +#define TSC_HW_DET_MODE_ENABLE (0x01UL << TSC_CTRL_HW_DET_MODE_SHIFT) /*!< 0x00000040U Hardware detect mode enable */ + +#define TSC_HW_DET_ENABLE TSC_HW_DET_MODE_ENABLE +/** + * @ + */ + +/** + * @defgroup Detect_Type + */ +#define TSC_DET_TYPE_MASK (TSC_CTRL_LESS_DET_SEL_MASK|TSC_CTRL_GREAT_DET_SEL_MASK) +#define TSC_DET_TYPE_SHIFT (TSC_CTRL_LESS_DET_SEL_SHIFT) + +#define TSC_DET_TYPE_NONE (0UL) /*!< 0x00000000U Disable detect */ +#define TSC_DET_TYPE_LESS (0x01UL << TSC_DET_TYPE_SHIFT) /*!< 0x00000100U Less detect enable */ +#define TSC_DET_TYPE_GREAT (0x02UL << TSC_DET_TYPE_SHIFT) /*!< 0x00000200U Great detect enable */ +#define TSC_DET_TYPE_PERIOD (0x03UL << TSC_DET_TYPE_SHIFT) /*!< 0x00000300U Both great and less detct enable */ +/** + * @ + */ + +/** + * @defgroup TSC_Interrupt + */ +#define TSC_IT_DET_ENABLE (TSC_CTRL_DET_INTEN) /*!< Enable TSC detect interrupt */ +#define TSC_IT_DET_DISABLE (0UL) /*!< Disable TSC detect interrupt */ +/** + * @ + */ + +/** + * @defgroup TSC_Out + */ +#define TSC_OUT_PIN (0x00000000U) /*!< TSC output to TSC_OUT pin */ +#define TSC_OUT_TIM4_ETR (0x1UL << TSC_CTRL_TM4_ETR_SHIFT) /*!< TSC output to TIM4 ETR */ +#define TSC_OUT_TIM2_ETR (0x2UL << TSC_CTRL_TM4_ETR_SHIFT) /*!< TSC output to TIM2 ETR and TIM2 CH1*/ +/** + * @ + */ + +/** + * @defgroup TSC_Flag + */ +#define TSC_FLAG_HW (0x1UL << TSC_CTRL_HW_DET_ST_SHIFT) /*!< Flag of hardware detect mode */ + +#define TSC_FLAG_GREAT_DET (0x1UL << TSC_STS_GREAT_DET_SHIFT) /*!< Flag of great detect type */ +#define TSC_FLAG_LESS_DET (0x1UL << TSC_STS_LESS_DET_SHIFT) /*!< Flag of less detect type */ +#define TSC_FLAG_PERIOD_DET (TSC_FLAG_GREAT_DET|TSC_FLAG_LESS_DET) /*!< Flag of period detect type */ +/** + * @ + */ + +/** + * @defgroup TSC_SW_Detect + */ +#define TSC_SW_MODE_DISABLE (0x00000000U) /*!< Disable software detect mode */ +#define TSC_SW_MODE_ENABLE (0x1UL << TSC_ANA_CTRL_SW_TSC_EN_SHIFT) /*!< Enable software detect mode */ +/** + * @ + */ + +/** + * @defgroup TSC_PadOption + */ +#define TSC_PAD_INTERNAL_RES (0x00000000U) /*!< Use internal resistor */ +#define TSC_PAD_EXTERNAL_RES (0x1UL << TSC_ANA_SEL_PAD_OPT_SHIFT) /*!< Use external resistor */ + +#define TSC_INNER_RESIST TSC_PAD_INTERNAL_RES + +/** + * @ + */ + +/** + * @defgroup TSC_PadSpeed + */ +#define TSC_PAD_SPEED_0 (0x00000000U) /*!< Low speed,about 100K */ +#define TSC_PAD_SPEED_1 (0x1UL << TSC_ANA_SEL_SP_OPT_SHIFT) /*!< Middle spped */ +#define TSC_PAD_SPEED_2 (0x2UL << TSC_ANA_SEL_SP_OPT_SHIFT) /*!< Middle spped */ +#define TSC_PAD_SPEED_3 (0x3UL << TSC_ANA_SEL_SP_OPT_SHIFT) /*!< Middle spped */ + +#define TSC_CMP_MASK (0x03UL) // comparator offset bit mask +#define TSC_CMP_OFFSET TSC_ANA_SEL_SP_OPT_SHIFT // offset of comparator speed configuration +#define TSC_CMP_SPEED_0 TSC_PAD_SPEED_0 // 100KHZ~200KHZ +#define TSC_CMP_SPEED_1 TSC_PAD_SPEED_1 // 300KHZ~700KHZ +#define TSC_CMP_SPEED_2 TSC_PAD_SPEED_2 // 300KHZ~700KHZ +#define TSC_CMP_SPEED_3 TSC_PAD_SPEED_3 // 300KHZ~700KHZ + +/** + * @ + */ + +/** + * @defgroup TSC_Touch_Lib + */ +#define TSC_RESIST_1M TSC_RESR_CHN_RESIST_1M +#define TSC_RESIST_875K TSC_RESR_CHN_RESIST_875K +#define TSC_RESIST_750K TSC_RESR_CHN_RESIST_750K +#define TSC_RESIST_625K TSC_RESR_CHN_RESIST_625K +#define TSC_RESIST_500K TSC_RESR_CHN_RESIST_500K +#define TSC_RESIST_375K TSC_RESR_CHN_RESIST_375K +#define TSC_RESIST_250K TSC_RESR_CHN_RESIST_250K +#define TSC_RESIST_125K TSC_RESR_CHN_RESIST_125K + +#define TSC_HW_CHN_MASK (0x00FFFFFF) +#define TSC_CHN_ADDR_WIDTH (4) + +#define TSC_HW_BASE_BITS_OFFSET (0) +#define TSC_HW_DELTA_BITS_OFFSET (16) + +/** + * @ + */ + +/** + * @defgroup TSC_Constant + */ +#define TSC_CHN_SEL_ALL (TSC_CHNEN_CHN_SEL_MASK) +#define MAX_TSC_HW_CHN (24) /*Maximum number of tsc pin*/ +#define TSC_DET_MAX_CHN_COUNT MAX_TSC_HW_CHN +#define MAX_TSC_THRESHOLD_BASE (2047) /*Maximum detect base value of threshold*/ +#define MAX_TSC_THRESHOLD_DELTA (255) /*Maximum detect delta value of threshold*/ +#define TSC_TIMEOUT (0x01000000) /*TSC normal timeout */ +/** + * @ + */ + +/* TSC Exported macros -----------------------------------------------------------*/ +/** @defgroup TSC_Exported_Macros + * @{ + */ + +/** @brief Enable the TSC HW detect mode + * @param None + * @retval None + */ +#define __TSC_HW_ENABLE() SET_BIT(TSC->CTRL, TSC_HW_DET_MODE_ENABLE) + +/** @brief Disable the TSC HW detect mode + * @param None + * @retval None + */ +#define __TSC_HW_DISABLE() CLEAR_BIT(TSC->CTRL, TSC_HW_DET_MODE_ENABLE) + +/** @brief Config TSC detect period for HW detect mode + * @param __PERIOD__ specifies the TSC detect period during HW detect mode + * @arg TSC_DET_PERIOD_8: Detect period = 8/TSC_CLK + * @arg TSC_DET_PERIOD_16: Detect Period = 1/TSC_CLK + * @arg TSC_DET_PERIOD_24: Detect Period = 2/TSC_CLK + * @arg TSC_DET_PERIOD_32: Detect Period = 3/TSC_CLK + * @arg TSC_DET_PERIOD_40: Detect Period = 4/TSC_CLK + * @arg TSC_DET_PERIOD_48: Detect Period = 5/TSC_CLK + * @arg TSC_DET_PERIOD_56: Detect Period = 6/TSC_CLK + * @arg TSC_DET_PERIOD_64: Detect Period = 7/TSC_CLK + * @arg TSC_DET_PERIOD_72: Detect Period = 7/TSC_CLK + * @arg TSC_DET_PERIOD_80: Detect Period = 7/TSC_CLK + * @arg TSC_DET_PERIOD_88: Detect Period = 7/TSC_CLK + * @arg TSC_DET_PERIOD_96: Detect Period = 7/TSC_CLK + * @arg TSC_DET_PERIOD_104:Detect Period = 7/TSC_CLK + * @retval None + */ +#define __TSC_PERIOD_CONFIG(__PERIOD__) MODIFY_REG(TSC->CTRL, TSC_CTRL_DET_PERIOD_MASK,__PERIOD__) + +/** @brief Config TSC detect filter for HW detect mode + * @param __FILTER__ specifies the least usefull continuous samples during HW detect mode + * @arg TSC_DET_FILTER_1: Detect filter = 1 pulse + * @arg TSC_DET_FILTER_2: Detect filter = 2 pulse + * @arg TSC_DET_FILTER_3: Detect filter = 3 pulse + * @arg TSC_DET_FILTER_4: Detect filter = 4 pulse + * @retval None + */ +#define __TSC_FILTER_CONFIG(__FILTER__) MODIFY_REG(TSC->CTRL, TSC_CTRL_DET_FILTER_MASK,__FILTER__) + +/** @brief Config TSC detect type for HW detect mode,less great or both + * @param __TYPE__ specifies the detect type of a sample during HW detect mode + * @arg TSC_DET_TYPE_NONE: Detect disable + * @arg TSC_DET_TYPE_LESS: Pulse number must be greater than the threshold(basee-delta) during a sample time + * @arg TSC_DET_TYPE_GREAT: Pulse number must be less than the threshold(basee+delta) during a sample time + * @arg TSC_DET_TYPE_PERIOD:Pulse number must be greater than (basee-delta) + and also be less than (basee+delta) during a sample time + * @retval None + */ +#define __TSC_LESS_GREAT_CONFIG(__TYPE__) MODIFY_REG(TSC->CTRL, \ + (TSC_CTRL_LESS_DET_SEL_MASK|TSC_CTRL_GREAT_DET_SEL_MASK), \ + __TYPE__) + +/** @brief Enable TSC interrupt + * @param None + * @retval None + */ +#define __TSC_INT_ENABLE() SET_BIT(TSC->CTRL, TSC_IT_DET_ENABLE) + +/** @brief Disable TSC interrupt + * @param None + * @retval None + */ +#define __TSC_INT_DISABLE() CLEAR_BIT(TSC->CTRL, TSC_IT_DET_ENABLE) + +/** @brief Config the TSC output + * @param __OUT__ specifies where the TSC output should go + * @arg TSC_OUT_PIN: TSC output to the TSC_OUT pin + * @arg TSC_OUT_TIM4_ETR: TSC output to TIM4 as ETR + * @arg TSC_OUT_TIM2_ETR: TSC output to TIM2 as ETR + * @retval None + */ +#define __TSC_OUT_CONFIG(__OUT__) MODIFY_REG( TSC->CTRL, \ + (TSC_CTRL_TM4_ETR_MASK|TSC_CTRL_TM2_ETR_CH1_MASK),\ + __OUT__) + +/** @brief Config the TSC channel + * @param __CHN__ specifies the pin of channels used for detect + * This parameter:bit[0:23] used,bit[24:31] must be 0 + * bitx: TSC channel x + * @retval None + */ +#define __TSC_CHN_CONFIG(__CHN__) WRITE_REG(TSC->CHNEN, __CHN__) + +/** @brief Enable the TSC SW detect mode + * @param None + * @retval None + */ +#define __TSC_SW_ENABLE() SET_BIT(TSC->ANA_CTRL, TSC_ANA_CTRL_SW_TSC_EN) + +/** @brief Disable the TSC SW detect mode + * @param None + * @retval None + */ +#define __TSC_SW_DISABLE() CLEAR_BIT(TSC->ANA_CTRL, TSC_ANA_CTRL_SW_TSC_EN) + +/** @brief Config the detect channel number during SW detect mode + * @param __NUM__ specifies channel number,must be less than MAX_TSC_HW_CHN + * @retval None + */ +#define __TSC_SW_CHN_NUM_CONFIG(__NUM__) MODIFY_REG(TSC->ANA_CTRL, TSC_ANA_CTRL_SW_PAD_MUX_MASK,__NUM__) + +/** @brief Config the pad charge type + * @param __OPT__ specifies which resistor is used for charge + * @arg TSC_PAD_INTERNAL_RES: Internal resistor is used + * @arg TSC_PAD_EXTERNAL_RES: External resistor is used + * @retval None + */ +#define __TSC_PAD_OPT_CONFIG(__OPT__) MODIFY_REG(TSC->ANA_SEL, TSC_ANA_SEL_PAD_OPT_MASK,__OPT__) + +/** @brief Config TSC speed + * @param __SPEED__ specifies the TSC speed range + * @arg TSC_PAD_SPEED_0: Low speed + * @arg TSC_PAD_SPEED_1: Middle speed + * @arg TSC_PAD_SPEED_2: Middle speed + * @arg TSC_PAD_SPEED_3: High speed + * @retval None + */ +#define __TSC_PAD_SPEED_CONFIG(__SPEED__) MODIFY_REG(TSC->ANA_SEL, TSC_ANA_SEL_SP_OPT_MASK,__SPEED__) + + +/** @brief Check if the HW detect mode is enable + * @param None + * @retval Current state of HW detect mode + */ +#define __TSC_GET_HW_MODE() (((TSC->CTRL) & TSC_FLAG_HW) == (TSC_FLAG_HW)) + +/** @brief Check the detect type during HW detect mode + * @param __FLAG__ specifies the flag of detect type + * @arg TSC_FLAG_LESS_DET: Flag of less detect type + * @arg TSC_FLAG_GREAT_DET: Flag of great detect type + * @arg TSC_FLAG_PERIOD_DET: Flag of priod detect type + * @retval Current state of flag + */ +#define __TSC_GET_HW_DET_TYPE(__FLAG__) (((TSC->STS) & (__FLAG__))==(__FLAG__)) + +/** @brief Get the number of channel which is detected now + * @param None + * @retval Current channel number + */ +#define __TSC_GET_CHN_NUMBER() (((TSC->STS) & TSC_STS_CHN_NUM_MASK) >> TSC_STS_CHN_NUM_SHIFT ) + +/** @brief Get the count value of pulse + * @param None + * @retval Pulse count of current channel + */ +#define __TSC_GET_CHN_CNT() (((TSC->STS) & TSC_STS_CNT_VAL_MASK ) >> TSC_STS_CNT_VAL_SHIFT ) + +/** @brief Get the base value of one channel + * @param __NUM__ specifies channel number,must be less than MAX_TSC_HW_CHN + * @retval base value of the channel + */ +#define __TSC_GET_CHN_BASE(__NUM__) ((*((&(TSC->THRHD0))+(__NUM__)) & TSC_THRHD_BASE_MASK ) >> TSC_THRHD_BASE_SHIFT) + +/** @brief Get the delta value of one channel + * @param __NUM__ specifies channel number,must be less than MAX_TSC_HW_CHN + * @retval delta value of the channel + */ +#define __TSC_GET_CHN_DELTA(__NUM__) ((*((&(TSC->THRHD0))+(__NUM__)) & TSC_THRHD_DELTA_MASK ) >> TSC_THRHD_DELTA_SHIFT ) + +/** @brief Get the internal resist value of one channel + * @param __NUM__ specifies channel number,must be less than MAX_TSC_HW_CHN + * @retval resist value of the channel + */ +#define __TSC_GET_CHN_RESIST(__NUM__) (((*((&(TSC->RESR0))+((__NUM__)>>3))) >>(((__NUM__) & 0x7UL)*4)) & TSC_RESR_CHN_RESIST_MASK) + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup TSC_Private_Macros + * @{ + */ +#define IS_TSC_DET_PERIOD(_PERIOD_) \ + (((_PERIOD_)==TSC_DET_PERIOD_8) ||((_PERIOD_)==TSC_DET_PERIOD_16)||((_PERIOD_)==TSC_DET_PERIOD_24) \ + ||((_PERIOD_)==TSC_DET_PERIOD_32)||((_PERIOD_)==TSC_DET_PERIOD_40)||((_PERIOD_)==TSC_DET_PERIOD_48) \ + ||((_PERIOD_)==TSC_DET_PERIOD_56)||((_PERIOD_)==TSC_DET_PERIOD_64)||((_PERIOD_)==TSC_DET_PERIOD_72) \ + ||((_PERIOD_)==TSC_DET_PERIOD_80)||((_PERIOD_)==TSC_DET_PERIOD_88)||((_PERIOD_)==TSC_DET_PERIOD_96) \ + ||((_PERIOD_)==TSC_DET_PERIOD_104) ) + +#define IS_TSC_FILTER(_FILTER_) \ + ( ((_FILTER_)==TSC_DET_FILTER_1) ||((_FILTER_)==TSC_DET_FILTER_2)\ + ||((_FILTER_)==TSC_DET_FILTER_3) ||((_FILTER_)==TSC_DET_FILTER_4) ) + +#define IS_TSC_DET_MODE(_MODE_) \ + ( ((_MODE_)==TSC_HW_DETECT_MODE) ||((_MODE_)==TSC_SW_DETECT_MODE) ) + +#define IS_TSC_DET_TYPE(_TYPE_) \ + ( ((_TYPE_)==TSC_DET_TYPE_GREAT) ||((_TYPE_)==TSC_DET_TYPE_LESS) \ + ||((_TYPE_)==TSC_DET_TYPE_PERIOD)|| ((_TYPE_)==TSC_DET_TYPE_NONE) ) + +#define IS_TSC_INT(_INT_) (((_INT_)==TSC_IT_DET_ENABLE)||((_INT_)==TSC_IT_DET_DISABLE)) + +#define IS_TSC_OUT(_ETR_) (((_ETR_)==TSC_OUT_PIN)||((_ETR_)==TSC_OUT_TIM2_ETR)||((_ETR_)==TSC_OUT_TIM4_ETR)) + +#define IS_TSC_CHN(_CHN_) (0==((_CHN_)&(~TSC_CHNEN_CHN_SEL_MASK))) + +#define IS_TSC_CHN_NUMBER(_NUM_) ((uint32_t)(_NUM_)BaudRate))) + - FractionalDivider = ((IntegerDivider - ((u32) IntegerDivider)) * 16) + 0.5 */ + + uint16_t WordLength; /*!< Specifies the number of data bits transmitted or received in a frame. + This parameter can be a value of @ref USART_Word_Length */ + + uint16_t StopBits; /*!< Specifies the number of stop bits transmitted. + This parameter can be a value of @ref USART_Stop_Bits */ + + uint16_t Parity; /*!< Specifies the parity mode. + This parameter can be a value of @ref Parity + @note When parity is enabled, the computed parity is inserted + at the MSB position of the transmitted data (9th bit when + the word length is set to 9 data bits; 8th bit when the + word length is set to 8 data bits). */ + + uint16_t Mode; /*!< Specifies wether the Receive or Transmit mode is enabled or disabled. + This parameter can be a value of @ref Mode */ + + uint16_t HardwareFlowControl; /*!< Specifies wether the hardware flow control mode is enabled + or disabled. + This parameter can be a value of @ref USART_Hardware_Flow_Control */ +} USART_InitType; + +/** + * @brief USART Clock Init Structure definition + */ + +typedef struct +{ + uint16_t Clock; /*!< Specifies whether the USART clock is enabled or disabled. + This parameter can be a value of @ref Clock */ + + uint16_t Polarity; /*!< Specifies the steady state value of the serial clock. + This parameter can be a value of @ref USART_Clock_Polarity */ + + uint16_t Phase; /*!< Specifies the clock transition on which the bit capture is made. + This parameter can be a value of @ref USART_Clock_Phase */ + + uint16_t LastBit; /*!< Specifies whether the clock pulse corresponding to the last transmitted + data bit (MSB) has to be output on the SCLK pin in synchronous mode. + This parameter can be a value of @ref USART_Last_Bit */ +} USART_ClockInitType; + +/** + * @} + */ + +/** @addtogroup USART_Exported_Constants + * @{ + */ + +#define IS_USART_ALL_PERIPH(PERIPH) \ + (((PERIPH) == USART1) || ((PERIPH) == USART2) || ((PERIPH) == USART3) || ((PERIPH) == UART4) \ + || ((PERIPH) == UART5) || ((PERIPH) == UART6) || ((PERIPH) == UART7)) + +#define IS_USART_123_PERIPH(PERIPH) (((PERIPH) == USART1) || ((PERIPH) == USART2) || ((PERIPH) == USART3)) + +#define IS_USART_1234_PERIPH(PERIPH) \ + (((PERIPH) == USART1) || ((PERIPH) == USART2) || ((PERIPH) == USART3) || ((PERIPH) == UART4)) +/** @addtogroup USART_Word_Length + * @{ + */ + +#define USART_WL_8B ((uint16_t)0x0000) +#define USART_WL_9B ((uint16_t)0x1000) + +#define IS_USART_WORD_LENGTH(LENGTH) (((LENGTH) == USART_WL_8B) || ((LENGTH) == USART_WL_9B)) +/** + * @} + */ + +/** @addtogroup USART_Stop_Bits + * @{ + */ + +#define USART_STPB_1 ((uint16_t)0x0000) +#define USART_STPB_0_5 ((uint16_t)0x1000) +#define USART_STPB_2 ((uint16_t)0x2000) +#define USART_STPB_1_5 ((uint16_t)0x3000) +#define IS_USART_STOPBITS(STOPBITS) \ + (((STOPBITS) == USART_STPB_1) || ((STOPBITS) == USART_STPB_0_5) || ((STOPBITS) == USART_STPB_2) \ + || ((STOPBITS) == USART_STPB_1_5)) +/** + * @} + */ + +/** @addtogroup Parity + * @{ + */ + +#define USART_PE_NO ((uint16_t)0x0000) +#define USART_PE_EVEN ((uint16_t)0x0400) +#define USART_PE_ODD ((uint16_t)0x0600) +#define IS_USART_PARITY(PARITY) (((PARITY) == USART_PE_NO) || ((PARITY) == USART_PE_EVEN) || ((PARITY) == USART_PE_ODD)) +/** + * @} + */ + +/** @addtogroup Mode + * @{ + */ + +#define USART_MODE_RX ((uint16_t)0x0004) +#define USART_MODE_TX ((uint16_t)0x0008) +#define IS_USART_MODE(MODE) ((((MODE) & (uint16_t)0xFFF3) == 0x00) && ((MODE) != (uint16_t)0x00)) +/** + * @} + */ + +/** @addtogroup USART_Hardware_Flow_Control + * @{ + */ +#define USART_HFCTRL_NONE ((uint16_t)0x0000) +#define USART_HFCTRL_RTS ((uint16_t)0x0100) +#define USART_HFCTRL_CTS ((uint16_t)0x0200) +#define USART_HFCTRL_RTS_CTS ((uint16_t)0x0300) +#define IS_USART_HARDWARE_FLOW_CONTROL(CONTROL) \ + (((CONTROL) == USART_HFCTRL_NONE) || ((CONTROL) == USART_HFCTRL_RTS) || ((CONTROL) == USART_HFCTRL_CTS) \ + || ((CONTROL) == USART_HFCTRL_RTS_CTS)) +/** + * @} + */ + +/** @addtogroup Clock + * @{ + */ +#define USART_CLK_DISABLE ((uint16_t)0x0000) +#define USART_CLK_ENABLE ((uint16_t)0x0800) +#define IS_USART_CLOCK(CLOCK) (((CLOCK) == USART_CLK_DISABLE) || ((CLOCK) == USART_CLK_ENABLE)) +/** + * @} + */ + +/** @addtogroup USART_Clock_Polarity + * @{ + */ + +#define USART_CLKPOL_LOW ((uint16_t)0x0000) +#define USART_CLKPOL_HIGH ((uint16_t)0x0400) +#define IS_USART_CPOL(CPOL) (((CPOL) == USART_CLKPOL_LOW) || ((CPOL) == USART_CLKPOL_HIGH)) + +/** + * @} + */ + +/** @addtogroup USART_Clock_Phase + * @{ + */ + +#define USART_CLKPHA_1EDGE ((uint16_t)0x0000) +#define USART_CLKPHA_2EDGE ((uint16_t)0x0200) +#define IS_USART_CPHA(CPHA) (((CPHA) == USART_CLKPHA_1EDGE) || ((CPHA) == USART_CLKPHA_2EDGE)) + +/** + * @} + */ + +/** @addtogroup USART_Last_Bit + * @{ + */ + +#define USART_CLKLB_DISABLE ((uint16_t)0x0000) +#define USART_CLKLB_ENABLE ((uint16_t)0x0100) +#define IS_USART_LASTBIT(LASTBIT) (((LASTBIT) == USART_CLKLB_DISABLE) || ((LASTBIT) == USART_CLKLB_ENABLE)) +/** + * @} + */ + +/** @addtogroup USART_Interrupt_definition + * @{ + */ + +#define USART_INT_PEF ((uint16_t)0x0028) +#define USART_INT_TXDE ((uint16_t)0x0727) +#define USART_INT_TXC ((uint16_t)0x0626) +#define USART_INT_RXDNE ((uint16_t)0x0525) +#define USART_INT_IDLEF ((uint16_t)0x0424) +#define USART_INT_LINBD ((uint16_t)0x0846) +#define USART_INT_CTSF ((uint16_t)0x096A) +#define USART_INT_ERRF ((uint16_t)0x0060) +#define USART_INT_OREF ((uint16_t)0x0360) +#define USART_INT_NEF ((uint16_t)0x0260) +#define USART_INT_FEF ((uint16_t)0x0160) +#define IS_USART_CFG_INT(IT) \ + (((IT) == USART_INT_PEF) || ((IT) == USART_INT_TXDE) || ((IT) == USART_INT_TXC) || ((IT) == USART_INT_RXDNE) \ + || ((IT) == USART_INT_IDLEF) || ((IT) == USART_INT_LINBD) || ((IT) == USART_INT_CTSF) \ + || ((IT) == USART_INT_ERRF)) +#define IS_USART_GET_INT(IT) \ + (((IT) == USART_INT_PEF) || ((IT) == USART_INT_TXDE) || ((IT) == USART_INT_TXC) || ((IT) == USART_INT_RXDNE) \ + || ((IT) == USART_INT_IDLEF) || ((IT) == USART_INT_LINBD) || ((IT) == USART_INT_CTSF) || ((IT) == USART_INT_OREF) \ + || ((IT) == USART_INT_NEF) || ((IT) == USART_INT_FEF)) +#define IS_USART_CLR_INT(IT) \ + (((IT) == USART_INT_TXC) || ((IT) == USART_INT_RXDNE) || ((IT) == USART_INT_LINBD) || ((IT) == USART_INT_CTSF)) +/** + * @} + */ + +/** @addtogroup USART_DMA_Requests + * @{ + */ + +#define USART_DMAREQ_TX ((uint16_t)0x0080) +#define USART_DMAREQ_RX ((uint16_t)0x0040) +#define IS_USART_DMAREQ(DMAREQ) ((((DMAREQ) & (uint16_t)0xFF3F) == 0x00) && ((DMAREQ) != (uint16_t)0x00)) + +/** + * @} + */ + +/** @addtogroup USART_WakeUp_methods + * @{ + */ + +#define USART_WUM_IDLELINE ((uint16_t)0x0000) +#define USART_WUM_ADDRMASK ((uint16_t)0x0800) +#define IS_USART_WAKEUP(WAKEUP) (((WAKEUP) == USART_WUM_IDLELINE) || ((WAKEUP) == USART_WUM_ADDRMASK)) +/** + * @} + */ + +/** @addtogroup USART_LIN_Break_Detection_Length + * @{ + */ + +#define USART_LINBDL_10B ((uint16_t)0x0000) +#define USART_LINBDL_11B ((uint16_t)0x0020) +#define IS_USART_LIN_BREAK_DETECT_LENGTH(LENGTH) (((LENGTH) == USART_LINBDL_10B) || ((LENGTH) == USART_LINBDL_11B)) +/** + * @} + */ + +/** @addtogroup USART_IrDA_Low_Power + * @{ + */ + +#define USART_IRDAMODE_LOWPPWER ((uint16_t)0x0004) +#define USART_IRDAMODE_NORMAL ((uint16_t)0x0000) +#define IS_USART_IRDA_MODE(MODE) (((MODE) == USART_IRDAMODE_LOWPPWER) || ((MODE) == USART_IRDAMODE_NORMAL)) +/** + * @} + */ + +/** @addtogroup USART_Flags + * @{ + */ + +#define USART_FLAG_CTSF ((uint16_t)0x0200) +#define USART_FLAG_LINBD ((uint16_t)0x0100) +#define USART_FLAG_TXDE ((uint16_t)0x0080) +#define USART_FLAG_TXC ((uint16_t)0x0040) +#define USART_FLAG_RXDNE ((uint16_t)0x0020) +#define USART_FLAG_IDLEF ((uint16_t)0x0010) +#define USART_FLAG_OREF ((uint16_t)0x0008) +#define USART_FLAG_NEF ((uint16_t)0x0004) +#define USART_FLAG_FEF ((uint16_t)0x0002) +#define USART_FLAG_PEF ((uint16_t)0x0001) +#define IS_USART_FLAG(FLAG) \ + (((FLAG) == USART_FLAG_PEF) || ((FLAG) == USART_FLAG_TXDE) || ((FLAG) == USART_FLAG_TXC) \ + || ((FLAG) == USART_FLAG_RXDNE) || ((FLAG) == USART_FLAG_IDLEF) || ((FLAG) == USART_FLAG_LINBD) \ + || ((FLAG) == USART_FLAG_CTSF) || ((FLAG) == USART_FLAG_OREF) || ((FLAG) == USART_FLAG_NEF) \ + || ((FLAG) == USART_FLAG_FEF)) + +#define IS_USART_CLEAR_FLAG(FLAG) ((((FLAG) & (uint16_t)0xFC9F) == 0x00) && ((FLAG) != (uint16_t)0x00)) +#define IS_USART_PERIPH_FLAG(PERIPH, USART_FLAG) \ + ((((*(uint32_t*)&(PERIPH)) != UART4_BASE) && ((*(uint32_t*)&(PERIPH)) != UART5_BASE)) \ + || ((USART_FLAG) != USART_FLAG_CTSF)) +#define IS_USART_BAUDRATE(BAUDRATE) (((BAUDRATE) > 0) && ((BAUDRATE) < 0x0044AA21)) +#define IS_USART_ADDRESS(ADDRESS) ((ADDRESS) <= 0xF) +#define IS_USART_DATA(DATA) ((DATA) <= 0x1FF) + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup USART_Exported_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup USART_Exported_Functions + * @{ + */ + +void USART_DeInit(USART_Module* USARTx); +void USART_Init(USART_Module* USARTx, USART_InitType* USART_InitStruct); +void USART_StructInit(USART_InitType* USART_InitStruct); +void USART_ClockInit(USART_Module* USARTx, USART_ClockInitType* USART_ClockInitStruct); +void USART_ClockStructInit(USART_ClockInitType* USART_ClockInitStruct); +void USART_Enable(USART_Module* USARTx, FunctionalState Cmd); +void USART_ConfigInt(USART_Module* USARTx, uint16_t USART_INT, FunctionalState Cmd); +void USART_EnableDMA(USART_Module* USARTx, uint16_t USART_DMAReq, FunctionalState Cmd); +void USART_SetAddr(USART_Module* USARTx, uint8_t USART_Addr); +void USART_ConfigWakeUpMode(USART_Module* USARTx, uint16_t USART_WakeUpMode); +void USART_EnableRcvWakeUp(USART_Module* USARTx, FunctionalState Cmd); +void USART_ConfigLINBreakDetectLength(USART_Module* USARTx, uint16_t USART_LINBreakDetectLength); +void USART_EnableLIN(USART_Module* USARTx, FunctionalState Cmd); +void USART_SendData(USART_Module* USARTx, uint16_t Data); +uint16_t USART_ReceiveData(USART_Module* USARTx); +void USART_SendBreak(USART_Module* USARTx); +void USART_SetGuardTime(USART_Module* USARTx, uint8_t USART_GuardTime); +void USART_SetPrescaler(USART_Module* USARTx, uint8_t USART_Prescaler); +void USART_EnableSmartCard(USART_Module* USARTx, FunctionalState Cmd); +void USART_SetSmartCardNACK(USART_Module* USARTx, FunctionalState Cmd); +void USART_EnableHalfDuplex(USART_Module* USARTx, FunctionalState Cmd); +void USART_ConfigIrDAMode(USART_Module* USARTx, uint16_t USART_IrDAMode); +void USART_EnableIrDA(USART_Module* USARTx, FunctionalState Cmd); +FlagStatus USART_GetFlagStatus(USART_Module* USARTx, uint16_t USART_FLAG); +void USART_ClrFlag(USART_Module* USARTx, uint16_t USART_FLAG); +INTStatus USART_GetIntStatus(USART_Module* USARTx, uint16_t USART_INT); +void USART_ClrIntPendingBit(USART_Module* USARTx, uint16_t USART_INT); + +#ifdef __cplusplus +} +#endif + +#endif /* __N32G45X_USART_H__ */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/inc/n32g45x_wwdg.h b/inc/n32g45x_wwdg.h new file mode 100644 index 0000000..6f7d32b --- /dev/null +++ b/inc/n32g45x_wwdg.h @@ -0,0 +1,122 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_wwdg.h + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32G45X_WWDG_H__ +#define __N32G45X_WWDG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "n32g45x.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup WWDG + * @{ + */ + +/** @addtogroup WWDG_Exported_Types + * @{ + */ + +/** + * @} + */ + +/** @addtogroup WWDG_Exported_Constants + * @{ + */ + +/** @addtogroup WWDG_Prescaler + * @{ + */ + +#define WWDG_PRESCALER_DIV1 ((uint32_t)0x00000000) +#define WWDG_PRESCALER_DIV2 ((uint32_t)0x00000080) +#define WWDG_PRESCALER_DIV4 ((uint32_t)0x00000100) +#define WWDG_PRESCALER_DIV8 ((uint32_t)0x00000180) +#define IS_WWDG_PRESCALER_DIV(PRESCALER) \ + (((PRESCALER) == WWDG_PRESCALER_DIV1) || ((PRESCALER) == WWDG_PRESCALER_DIV2) \ + || ((PRESCALER) == WWDG_PRESCALER_DIV4) || ((PRESCALER) == WWDG_PRESCALER_DIV8)) +#define IS_WWDG_WVALUE(VALUE) ((VALUE) <= 0x7F) +#define IS_WWDG_CNT(COUNTER) (((COUNTER) >= 0x40) && ((COUNTER) <= 0x7F)) + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup WWDG_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @addtogroup WWDG_Exported_Functions + * @{ + */ + +void WWDG_DeInit(void); +void WWDG_SetPrescalerDiv(uint32_t WWDG_Prescaler); +void WWDG_SetWValue(uint8_t WindowValue); +void WWDG_EnableInt(void); +void WWDG_SetCnt(uint8_t Counter); +void WWDG_Enable(uint8_t Counter); +FlagStatus WWDG_GetEWINTF(void); +void WWDG_ClrEWINTF(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __N32G45X__WWDG_H */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/inc/n32xx_tsc_alg_api.h b/inc/n32xx_tsc_alg_api.h new file mode 100644 index 0000000..a0bc723 --- /dev/null +++ b/inc/n32xx_tsc_alg_api.h @@ -0,0 +1,302 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @brief ´¥¿ØË㷨ͷÎļþ. + * ´ó¸ÅÁ÷³Ì:(ÅäÖÃTIMER->¶¨Ò廨µ÷API->³õʼ»¯->Æô¶¯) + * @file n32xx_tsc_alg_api.h + * @author Nations + * @version v1.0.1 + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#ifndef __N32XX_TSC_ALG_API__ +#define __N32XX_TSC_ALG_API__ + +#ifdef __cplusplus +extern "C" { +#endif // defined __cplusplus + +#define TSC_ALG_VERSION_NUMBER "Ver1.0.4" //Ëã·¨¿â°æ±¾ºÅ + +#define TSC_ALG_HANDLER_STOP2_DATA_SIZE (144) //ÓÃÓÚÔÚSTOP2ģʽϱ£´æ´¥¿Ø»½Ðѹ¦ÄÜÏà¹ØµÄTSCÊý¾Ý¡£ +#define TSC_ALG_HANDLER_PERIOD_PER_CHN (400) //´¥¿ØËã·¨µ¥Í¨µÀµÄ´¦ÀíÖÜÆÚÒò×Ó¡£ +#define TSC_ALG_WAKEUP_TIMES (1000) //ÓйØTSC»½Ðѹ¦ÄܵÄʱ¼äÅäÖ㬲»ÒªËæÒâÐÞ¸Ä +#define TSC_ALG_DEBUG_BUF_SIZE (260) //¶¨Òåµ÷ÊÔģʽϵÄBUF´óС +#define TSC_ALG_REF_SIZE_PER_CHN (430) //´¥¿ØÃ¿Í¨µÀµÄ²Î¿¼´óС£¬Êµ¼Ê´óСÒÔtsc_alg_need_sramsize()¼ÆËãΪ׼ + +/** + * @brief ¶¨Òå´¥¿ØÀàÐÍ + */ +typedef enum tsc_alg_type_e +{ + TSC_ALG_BUTTON_TYPE = 0, ///< tsc application of simple button + TSC_ALG_TYPE_MAX ///< +} tsc_alg_type; + +/** + * @brief °´¼üʼþ + */ +typedef enum tsc_press_key_event_e +{ + TSC_PRESS_KEY_NORMAL = 0, //Õý³£¶Ì°´Ê¼þ + TSC_PRESS_KEY_MAX ///< +} tsc_press_key_event; + +/** + * @brief ´íÎóÀàÐͶ¨Òå + */ +typedef enum tsc_ret_code_e +{ + TSC_SUCCESS = 0, ///< ³É¹¦ + TSC_NOT_INIT_ERR, ///< Ä£¿éδ³õʼ»¯´íÎó + TSC_NOT_REG_CHN_ERR, ///< Ä£¿é×¢²áÎÞЧµÄ´¥¿ØÍ¨µÀ´íÎó + TSC_NOT_ACCORD_LIB_ERR, ///< Ëã·¨¿â°æ±¾´íÎó + TSC_POINTER_NULL_ERR, ///< Ö¸ÕëΪ¿Õ´íÎó + TSC_PARAM_ZERO_ERR, ///< ²ÎÊý´íÎó + TSC_REPEAT_REG_ERR, ///< ÖØ¸´×¢²á´íÎó + TSC_CHN_NUM_ERR, ///< Óë³õʼ»¯µÄͨµÀ×ÜÊý²»Ò»Ö´íÎó + TSC_REG_CHANNEL_ENOUGH_ERR, ///< ×¢²áµÄͨµÀºÅ´íÎó»ò³¬³öϵͳ×ÜͨµÀÊý + TSC_REG_TIMX_ERR, ///< ×¢²áµÄTimer×ÊÔ´´íÎó + TSC_REG_DMA_ERR, ///< ×¢²áµÄDMA×ÊÔ´´íÎó + TSC_SOURCE_NOT_ENOUGH_ERR, ///< ×ÊÔ´²»×ã´íÎó + TSC_NOT_SUPPORT_ERR, ///< δʵÏÖ»ò²Ù×÷²»Ö§³Ö´íÎó + TSC_LEVEL_CFG_ERR, ///< ͨµÀµÄÁéÃ÷¶ÈÅäÖôíÎó + TSC_AUTO_CALIB_TIMER_ERR, ///< ×Ô¶¯Ð£×¼Ê±¼äСÓÚ2±¶Í¨µÀ°´¼ü±£³Öʱ¼ä. + TSC_DISTURB_ERR, ///< ¸ÉÈÅ´íÎó. + TSC_CHN_RAM_NOT_ENOUGH_ERR, ///< ÌṩµÄTSCͨµÀRAMΪNULL»ò¿Õ¼ä²»×ã´íÎó + TSC_STOP2_NULL_OR_INVALID_ERR, ///< ÌṩµÄStop2DataÊý¾Ý¿Õ¼äΪNULL»ò²»ÔÚ16K retentionÇøÓòÄÚ¡£ + TSC_DEBUG_BUF_ENOUGH_ERR ///< ÌṩµÄµ÷ÊÔ»º´æ¿Õ¼ä²»×ã´íÎó +} tsc_ret_code; + +/** + * @brief ´¥¿Ø°´¼ü³ÖÐøµÈ¼¶ + * ³ÖÐøµÈ¼¶Ô½Ð¡:·´Ó¦ËÙ¶ÈÔ½¿ì£¬¿¹Ë²¼äµÄ¸ÉÈÅÒ²Ô½Èõ£» + * ³ÖÐøµÈ¼¶Ô½´ó:·´Ó¦ËÙ¶ÈÏà¶ÔÈõ£¬¿¹Ë²¼ä¸ÉÈÅÄÜÁ¦Ô½Ç¿ + */ +typedef enum tsc_hld_lev_e +{ + TSC_HOLD_LEV1 = 1, // HOLDµÈ¼¶1(5ms) + TSC_HOLD_LEV2 = 2, // HOLDµÈ¼¶2(7ms) + TSC_HOLD_LEV3 = 3, // HOLDµÈ¼¶3(11ms) + TSC_HOLD_LEV4 = 4, // HOLDµÈ¼¶4(17ms) + TSC_HOLD_LEV5 = 5, // HOLDµÈ¼¶5(25ms) + TSC_HOLD_LEV6 = 6, // HOLDµÈ¼¶6(35ms) + TSC_HOLD_LEV7 = 7, // HOLDµÈ¼¶7(47ms) + TSC_HOLD_LEV8 = 8, // HOLDµÈ¼¶8(61ms) + TSC_HOLD_LEV9 = 9, // HOLDµÈ¼¶9(77ms) + TSC_HOLD_LEV10 = 10, // HOLDµÈ¼¶10(95ms) + TSC_HOLD_LEV11 = 11, // HOLDµÈ¼¶11(115ms) + TSC_HOLD_LEV12 = 12, // HOLDµÈ¼¶12(137ms) + TSC_HOLD_LEV13 = 13, // HOLDµÈ¼¶13(161ms) + TSC_HOLD_LEV14 = 14, // HOLDµÈ¼¶14(187ms) + TSC_HOLD_LEV15 = 15, // HOLDµÈ¼¶15(215ms) + TSC_HOLD_LEV16 = 16, // HOLDµÈ¼¶16(245ms) + TSC_HOLD_LEV17 = 17, // HOLDµÈ¼¶17(277ms) + TSC_HOLD_LEV18 = 18, // HOLDµÈ¼¶18(311ms) + TSC_HOLD_LEV19 = 19, // HOLDµÈ¼¶19(347ms) + TSC_HOLD_LEV20 = 20, // HOLDµÈ¼¶20(385ms) + TSC_HOLD_MAX ///< ÎÞЧ +} tsc_hld_lev; + +/** + * @brief Ôڵ͹¦ºÄģʽÏ£¬Ëæ»·¾³±ä»¯¶ø¸üл½ÐÑÃÅÏÞ¡£ + * Òò´ËÉèÖÃÒ»¸ö±ä»¯Á¿Òò×Ó¡£ + * СÓڴ˱仯Á¿Òò×ÓµÄdeltaÔòÈÏΪÊÇÓÐЧ±ä»¯£¬Ôòͨ¹ý´Ë½Ó¿Ú¸üÐÂTSC»½ÐÑÃÅÏÞ£» + * ´óÓڴ˱仯Á¿Òò×ÓµÄdeltaÔòÈÏΪÊÇÎÞЧ±ä»¯£¬Ôò´Ë½Ó¿ÚºöÂÔÖ®£¬²»¸üл½ÐÑÃÅÏÞ¡£ + * ±ä»¯Á¿Òò×ÓÔ½´ó£¬Ôò±íʾ±ä»¯Á¿Ô½´ó¡£Ò»°ãÉèÖÃΪLEV15¡£ + */ +typedef enum tsc_delta_limit_lev_e +{ + TSC_DELTA_LIMIT_LEV1 = 1, // + TSC_DELTA_LIMIT_LEV2 = 2, // + TSC_DELTA_LIMIT_LEV3 = 3, // + TSC_DELTA_LIMIT_LEV4 = 4, // + TSC_DELTA_LIMIT_LEV5 = 5, // + TSC_DELTA_LIMIT_LEV6 = 6, // + TSC_DELTA_LIMIT_LEV7 = 7, // + TSC_DELTA_LIMIT_LEV8 = 8, // + TSC_DELTA_LIMIT_LEV9 = 9, // + TSC_DELTA_LIMIT_LEV10 = 10, // + TSC_DELTA_LIMIT_LEV11 = 11, // + TSC_DELTA_LIMIT_LEV12 = 12, // + TSC_DELTA_LIMIT_LEV13 = 13, // + TSC_DELTA_LIMIT_LEV14 = 14, // + TSC_DELTA_LIMIT_LEV15 = 15, // + TSC_DELTA_LIMIT_LEV16 = 16, // + TSC_DELTA_LIMIT_LEV17 = 17, // + TSC_DELTA_LIMIT_LEV18 = 18, // + TSC_DELTA_LIMIT_LEV19 = 19, // + TSC_DELTA_LIMIT_LEV20 = 20, // + TSC_DELTA_LIMIT_MAX ///< ÎÞЧ +} tsc_delta_limit_lev; + +/** + * @brief ¿¹¸ÉÈŵȼ¶ + * ¿¹¸ÉÈŵȼ¶,µÈ¼¶Ô½¸ß¿¹¸ÉÈÅԽǿ£¬µ«Ò²¶Ô°å¼¶»·¾³ÒªÇóÔ½ÑÏ¿Á. + */ +typedef enum tsc_resist_disturb_lev_e +{ + TSC_RESIST_DIS_LEV0 = 0, //ĬÈϵȼ¶£¬¿¹Íⲿ¸ÉÈÅÒ»°ã¡£Ö§³ÖPCBA&ÑÇ¿ËÁ¦´¥Ãþ¡£ + TSC_RESIST_DIS_LEV1 = 1, //ÔöÇ¿µÈ¼¶£¬¿¹Íⲿ¸ÉÈÅÔöÇ¿¡£ÑÇ¿ËÁ¦Çé¿öÏÂÌåÑé¸üºÃ¡£ + TSC_RESIST_DIS_LEV2 = 2, //Ôݱ£Áô¡£ + TSC_RESIST_DIS_MAX ///< ÎÞЧ +} tsc_resist_disturb_lev; + +/** + * @brief TSC´¥¿ØÍ¨µÀ³õʼÃÅÏÞÖµÅäÖà + */ +typedef struct TSC_AlgInitThreValue_t +{ + uint16_t hold_level; /* °´¼ü´¥·¢³ÖÐøµÈ¼¶ */ + uint16_t rate_of_change; /* ¸ÃͨµÀ°´¼ü±ä»¯ÂÊ(ÈçÎÞѹÏÂΪ70,ѹÏÂΪ77£¬Ôò±ä»¯ÂÊΪ(77-70)/70 = 0.1¼´%10(×¢Òâ:Êʵ±½µµÍΪ8%)¡£Ä¬ÈÏΪ5,Ôò±ä»¯ÂÊ%5 */ + uint32_t chn; /* ͨµÀ */ +} TSC_AlgInitThreValue; + +/** + * @brief TSC³õʼ»¯ÅäÖòÎÊý + */ +typedef struct TSC_AlgInitTypeDef_t +{ + TIM_Module* TIMx; /* ´¥¿ØË㷨ʹÓõÄTIMER×ÊÔ´(½öÖ§³ÖTIMER2) */ + DMA_ChannelType* DMAyChx; /* ´¥¿ØË㷨ʹÓõÄDMA×ÊÔ´(½öÖ§³ÖDMA1_CH5) */ + uint32_t DMARemapEnable; /* ÊÇ·ñʹÄÜDMA È«¾ÖREMAP¹¦ÄÜ(ÈçDMA1ÖÐÆäËûͨµÀÓÐʹÄÜREMAP¹¦ÄÜ£¬Ôò´Ë´¦ÐèÅäÖÃΪ1) */ + TSC_AlgInitThreValue* pTScChannelList; /* ÓÉ´¥¿ØÍ¨µÀ×é³ÉÁбíµÄÊý×顣ĿǰÔÝÖ§³Ö1¸öÁÐ(¿Éͨ¹ýλ»òÔËËã,½«¶à¸öTSCͨµÀ×é³ÉÒ»¸öÁбí)¡£ */ + uint32_t AutoCalibrateTimer; /* ÅäÖÃÓи²¸ÇÎïÇé¿öϵÄ×Ô¶¯Ð£×¼Ê±¼ä(ÎÞ¸²¸ÇÎï»ò¸ÉÈÅʱ²»»áУ׼),Ò»°ãÉèÖÃ1000ms¼´¿É,×î´ó65535¡£µ¥Î»ms¡£´ËÖµ±ØÐë´óÓÚ°´¼ü±£³Öʱ¼äµÄ2±¶ÒÔÉÏ£¬·ñÔò³õʼ»¯´íÎó */ + uint32_t ResistDisturbLev; /* ¿¹¸ÉÈŵȼ¶(tsc_resist_disturb_lev),µÈ¼¶Ô½¸ß¿¹¸ÉÈÅԽǿ£¬µ«Ò²¶Ô°å¼¶×°Åä»·¾³ÒªÇóÔ½¸ß. */ + uint8_t* pTscSramAddr; /* Ó¦ÓóÌÐòÌṩ¸øTSCÇý¶¯¿âµÄ´¥¿ØÍ¨µÀRAM¿Õ¼äµØÖ·*/ + uint32_t TscSramSize; /* Ó¦ÓóÌÐòÌṩ¸øTSCÇý¶¯¿âµÄ´¥¿ØÍ¨µÀRAM¿Õ¼ä´óС.µ¥Î»(bytes) */ + uint16_t* LogBuf; /* ÓÃÓÚµ÷ÊÔģʽϵÄbuf»º´æ,·Çµ÷ÊÔģʽÏÂÔòΪ0 */ + uint16_t LogBufSize; /* ÿͨµÀ´óСΪu16 * 256.µ¥Î»(bytes) */ + uint8_t* Stop2Data; /* ÓÃÓÚÔÚSTOP2ģʽϱ£´æ´¥¿Ø»½Ðѹ¦ÄÜÏà¹ØµÄTSCÊý¾ÝBUF¡£ */ + uint16_t Stop2DataSize; /* ÓÃÓÚÔÚSTOP2ģʽϱ£´æ´¥¿Ø»½Ðѹ¦ÄÜÏà¹ØµÄTSCÊý¾ÝBUF´óС¡£µ¥Î»(bytes) */ +} TSC_AlgInitTypeDef; + +/** + * @brief ´¥¿ØË㷨ʵʱ·ÖÎö´¦Àíº¯Êý(±ØÐë·ÅÔÚTIMERÖжϺ¯ÊýÖÐ) + * @TIMER¶¨Ê±ÖÜÆÚ²Î¿¼ÖÜÆÚÒò×Ó£¬¶¨Ê±Æ÷ÖÜÆÚ²Î¿¼DEMO·¶Àý. + * @param void + * @return void + */ +void tsc_alg_analyze_handler(void); + +/** + * @brief µÍ¹¦ºÄУ׼ + * @param uint32_t delta_limit_level ±ä»¯Á¿ÏÞÖµµÈ¼¶tsc_delta_limit_lev + * @uint32_t hse_or_hsi 0:HSI, 1:HSE; + * @return + * - `TSC_SUCCESS£º ±íʾ²Ù×÷³É¹¦ + * - ÆäËüÖµ±íʾ³ö´í + * - ×¢Ò⣺ÓÃÓÚÔÚSTOP2µÍ¹¦ºÄģʽÏ£¬¶¨Ê±Ð£×¼¡£ + */ +int32_t tsc_alg_set_powerdown_calibrate(tsc_delta_limit_lev delta_limit_level, uint32_t hse_or_hsi); + +/** + * @brief µÍ¹¦ºÄģʽÏÂ,¼ì²âÊÇ·ñ±»¸ÉÈÅ»½ÐÑ + * @param void + * @return 0:Õý³£»½ÐÑ£»1:¸ÉÈÅ»½ÐÑ + */ +int32_t tsc_alg_wakeup_disturb_check(uint32_t* wakeup_src); + +/** + * @brief »ñÈ¡Ëã·¨°æ±¾ + * @param void + * @return void + */ +char* tsc_alg_get_version(void); + +/** + * @brief ´¥¿ØË㷨ϵͳµÎ´ð,ĬÈÏ1ms + * @param void + * @return void + */ +void tsc_alg_tick_count(void); + +/** + * @brief »ñÈ¡TSC´¥¿ØËã·¨ÐèÒªµÄSRAM´óС + * uint32_t chn_totals; // ʹÓõÄTSC´¥¿ØÍ¨µÀÊý + * @return + * - 0: ±íʾʧ°Ü + * - ·Ç0: ±íʾ³É¹¦ + */ +uint32_t tsc_alg_need_sramsize(uint32_t chn_totals); + +/** + * @brief ´¥¿ØËã·¨³õʼ»¯ + * @param tsc_init_parameter *ptsc_init_parameter ´¥¿ØËã·¨³õʼ»¯½á¹¹Ì嵨ַ. + * @param void + * @return + * - `TSC_SUCCESS£º ±íʾ²Ù×÷³É¹¦ + * - ÆäËüÖµ±íʾ³ö´í + */ +int32_t tsc_alg_init(TSC_AlgInitTypeDef* TSC_AlgInitStruct); + +/** + * @brief Æô¶¯´¥¿Ø¿ªÊ¼¹¤×÷ + * @param void + * @return + * - `TSC_SUCCESS£º ±íʾ²Ù×÷³É¹¦ + * - ÆäËüÖµ±íʾ³ö´í + */ +int32_t tsc_alg_start(void); + +/** + * @brief ÉèÖÃTSC½øÈëµÍ¹¦ºÄ(ÓÃÓڵ͹¦ºÄ»½ÐÑģʽ) + * @param uint32_t TScChannelList ±£Áô²ÎÊý¡£ÉèÖÃΪ0±íʾʹÄÜÒÑ×¢²áµÄËùÓÐͨµÀ + * @return + * - `TSC_SUCCESS£º ±íʾ²Ù×÷³É¹¦ + * - ÆäËüÖµ±íʾ³ö´í + * - ×¢Ò⣺STOP2µÍ¹¦ºÄģʽʹÓã¬Õý³£Ä£Ê½Ï²»¹Ø×¢¡£ + */ +int32_t tsc_alg_set_powerdown(uint32_t TscChannelList); + +//////////////////////////////////////////////////////////// + +/*****************ÉϲãÓ¦ÓÃÌṩµÄ°´¼ü»Øµ÷´¦Àíº¯Êý********* + * @brief ×¢²á°´Å¥ÐÍ¡¢»¬ÌõÐÍ¡¢×ªÂÖÐÍ´¥¿ØµÄ»Øµ÷º¯Êý + * @param tsc_touch_type type ²úÉúµÄ´¥¿ØÀàÐÍ(ÔÝÖ»Ö§³Ö°´¼üÐÍ) + * @param uint32_t event 0:Õý³£´¥Ãþʼþ£» + * @param uint32_t chn ±íʾ´¥ÃþͨµÀºÅ£» + * @param uint32_t value ´¥Ãþ״̬£º1ѹÏ£»0ËÉ¿ª£» + * @return + * - `TSC_SUCCESS£º ±íʾ²Ù×÷³É¹¦ + * - ÆäËüÖµ±íʾ³ö´í + * ×¢Òâ:´Ë»Øµ÷º¯Êý½«ÔÚÖжÏÖе÷Óã¬Òò´Ë¾¡Á¿¼õÉٻص÷º¯ÊýµÄ´¦Àíʱ¼ä¡£ + ********************************************************/ +int32_t tsc_alg_isr_callback(tsc_alg_type type, uint32_t event, uint32_t chn, uint32_t value); + +/** + * @brief ´¥¿ØÊý¾ÝÊä³öµ½PCµÄ½Ó¿Ú£¬ÒÔ±ãÓÚPC¶Ë¹¤¾ß¹Û²ì£¬É趨ºÏÀíµÄ´¥¿ØãÐÖµ + * @param uint32_t chn ´¥¿ØÍ¨µÀ + * @return uint8_t data ¸Ã´¥¿ØÍ¨µÀÊý¾Ý + */ +void tsc_alg_debug_output(uint32_t chn, uint8_t data); + +#ifdef __cplusplus +} +#endif // defined __cplusplus + +#endif //__N32XX_TSC_ALG_API__ diff --git a/inc/n32xx_tsc_alg_api.lib b/inc/n32xx_tsc_alg_api.lib new file mode 100644 index 0000000000000000000000000000000000000000..c388665630a76889413239c8cc2081bc99cb3fdf GIT binary patch literal 3211910 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

-Tg-v$Q0wsR7o)a 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

`$R^0Wdde=QL={nyH=`>%_&u5ze&%Yl0H6?KW7 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

@&+fWPP8hs*3rJO0TJ z+O(?HV%;_|#N@5jx^3cK#($G-;=U{kW7X7Hu!{RLZS=~ixxnUuOdGxWuuVLeX`?d` zwuy(CO%L0|Fay@>cJl<*FxiyG`SD+rV0~ z+chS0gC2(F6pPjiPNwEmlUM6a#^#$Qua=w4&9_Wmtu`5)(>dSM`oM{`# z1*fxfmTe$coDR>~wt-x7Iz8udgPz9cJQJ5oj^^jvwt-l3G(hLa20fl=FR*ACPBcK@ zGkFnBG(Z=cyv%<(Ko^<3On*8+7b`w*fG)9Ud$lw`mzun}S{k6sOx|2A4bbH#Z?2XG z=t|D_G(cCGxVc_8Kv&xa)`HytU1J+qD|Q2Pt!-c}*$vS3+@Oa6y1}CLf|CKd(d5;7 zlL7jH$*bii19X$gtJNk0bPMNu8lWGVxLR*IK)2cka>3~U-DVre6{iDqyKNwsoDR^P z+@Plcy354nlA{5-+cpqOjt1zyU{LR#GRe3r4>JhQ5chMsv7sa5V-D!0odcY1Z*I?g z?Fdf~4{;nWI=frVd+YQv>S2qPnQ^0&rrQyd7m0B^O}As5Z_a%M^#q3trKUE0L$$W9 zna;yb8n79-n>wc~+=|=HoYNLAD;U@5CeB9|F6$R)tTE8&496SHh2lC9{=|T-g-QNl;p{qw*w6WCC)lZnbUTf&;Crw^2HgxrP$HU`S z_0^Wvmd@t(Vt7s~dfaYOLiNd^COfKt?F)C1Gu}u;kDpIbsF4F4gm}+ss)ls}5XRGq zH#MwRk1*bCdP~DvXoT@xVw#4-^LojPe8|!enXcjR=pKVbh6fs2djzJs3__K|7 z4cbt~Pn!7#ZAjw>%>siqwDEIhA*YSYZWM-=xJaRfGGQRSuVF1rm@kVptaS;)Wr>Eh zEMc-N)v!{9LPiajX;_IuAtSt8!%7nh8Q~QgR+3Q22(J=w>p${tae|N}s}-swajQeW zYcwn+ajQdkt%ju}ZgmK+)3B7ptq$S!8WxiHkP+UXVIheR8R3l@7Lxdo5&l5KLJ}V` z!dqgvPwuAjp+c1;*iUX#*{WeFiGy)d*`{GBiGy)d*{)$JiGy)d*`Z+}iDPL~*{NY6 zi4PeQw@br95+5?cyEQB%@gXC;m&3W6%0A7SqCnw+=luq4sRES;^Z|pmWP#EH`k+Bu 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⋘VgTFVz_}Iqk|47y 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%0Dqnw_U?-RQsGw=^Dm{Z}PjnDRBN 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

@TfhlI~7Aoc)8fl7IyM>Awqlx5^q$y|P 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∓_+e<(;jIDf)04 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¥nGRa(2rGb?hG{hnvE1Ta@G+r2Um4B)?S1E>Tr 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

qr=It2Pnd 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

ZFc%mrzNoH5CfOGo6e@JIU!a)J4d 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 cJEECfnK>!Cn(&f3<-?yTwrAIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup; +} + +/** + * @brief Initializes the NVIC peripheral according to the specified + * parameters in the NVIC_InitStruct. + * @param NVIC_InitStruct pointer to a NVIC_InitType structure that contains + * the configuration information for the specified NVIC peripheral. + */ +void NVIC_Init(NVIC_InitType* NVIC_InitStruct) +{ + uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F; + + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd)); + assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority)); + assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority)); + + if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE) + { + /* Compute the Corresponding IRQ Priority --------------------------------*/ + tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700)) >> 0x08; + tmppre = (0x4 - tmppriority); + tmpsub = tmpsub >> tmppriority; + + tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre; + tmppriority |= NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub; + tmppriority = tmppriority << 0x04; + + NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority; + + /* Enable the Selected IRQ Channels --------------------------------------*/ + NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] = (uint32_t)0x01 + << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F); + } + else + { + /* Disable the Selected IRQ Channels -------------------------------------*/ + NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] = (uint32_t)0x01 + << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F); + } +} + +/** + * @brief Sets the vector table location and Offset. + * @param NVIC_VectTab specifies if the vector table is in RAM or FLASH memory. + * This parameter can be one of the following values: + * @arg NVIC_VectTab_RAM + * @arg NVIC_VectTab_FLASH + * @param Offset Vector Table base offset field. This value must be a multiple + * of 0x200. + */ +void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset) +{ + /* Check the parameters */ + assert_param(IS_NVIC_VECTTAB(NVIC_VectTab)); + assert_param(IS_NVIC_OFFSET(Offset)); + + SCB->VTOR = NVIC_VectTab | (Offset & (uint32_t)0x1FFFFF80); +} + +/** + * @brief Selects the condition for the system to enter low power mode. + * @param LowPowerMode Specifies the new mode for the system to enter low power mode. + * This parameter can be one of the following values: + * @arg NVIC_LP_SEVONPEND + * @arg NVIC_LP_SLEEPDEEP + * @arg NVIC_LP_SLEEPONEXIT + * @param Cmd new state of LP condition. This parameter can be: ENABLE or DISABLE. + */ +void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_NVIC_LP(LowPowerMode)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + SCB->SCR |= LowPowerMode; + } + else + { + SCB->SCR &= (uint32_t)(~(uint32_t)LowPowerMode); + } +} + +/** + * @brief Configures the SysTick clock source. + * @param SysTick_CLKSource specifies the SysTick clock source. + * This parameter can be one of the following values: + * @arg SysTick_CLKSource_HCLK_Div8 AHB clock divided by 8 selected as SysTick clock source. + * @arg SysTick_CLKSource_HCLK AHB clock selected as SysTick clock source. + */ +void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource) +{ + /* Check the parameters */ + assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource)); + if (SysTick_CLKSource == SysTick_CLKSource_HCLK) + { + SysTick->CTRL |= SysTick_CLKSource_HCLK; + } + else + { + //SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8; + } +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/src/n32g45x_adc.c b/src/n32g45x_adc.c new file mode 100644 index 0000000..5a07a85 --- /dev/null +++ b/src/n32g45x_adc.c @@ -0,0 +1,1468 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_adc.c + * @author Nations + * @version v1.0.3 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_adc.h" +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup ADC + * @brief ADC driver modules + * @{ + */ + +/** @addtogroup ADC_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup ADC_Private_Defines + * @{ + */ + +/* ADC DISC_NUM mask */ +#define CR1_DISCNUM_Reset ((uint32_t)0xFFFF1FFF) + +/* ADC DISC_EN mask */ +#define CTRL1_DISC_EN_SET ((uint32_t)0x00000800) +#define CTRL1_DISC_EN_RESET ((uint32_t)0xFFFFF7FF) + +/* ADC INJ_AUTO mask */ +#define CR1_JAUTO_Set ((uint32_t)0x00000400) +#define CR1_JAUTO_Reset ((uint32_t)0xFFFFFBFF) + +/* ADC INJ_DISC_EN mask */ +#define CTRL1_INJ_DISC_EN_SET ((uint32_t)0x00001000) +#define CTRL1_INJ_DISC_EN_RESET ((uint32_t)0xFFFFEFFF) + +/* ADC AWDG_CH mask */ +#define CTRL1_AWDG_CH_RESET ((uint32_t)0xFFFFFFE0) + +/* ADC Analog watchdog enable mode mask */ +#define CTRL1_AWDG_MODE_RESET ((uint32_t)0xFF3FFDFF) + +/* CTRL1 register Mask */ +#define CTRL1_CLR_MASK ((uint32_t)0xFFF0FEFF) + +/* ADC AD_ON mask */ +#define CTRL2_AD_ON_SET ((uint32_t)0x00000001) +#define CTRL2_AD_ON_RESET ((uint32_t)0xFFFFFFFE) + +/* ADC DMA mask */ +#define CTRL2_DMA_SET ((uint32_t)0x00000100) +#define CTRL2_DMA_RESET ((uint32_t)0xFFFFFEFF) + +/* ADC CAL mask */ +#define CTRL2_CAL_SET ((uint32_t)0x00000004) + +/* ADC SOFT_START mask */ +#define CTRL2_SOFT_START_SET ((uint32_t)0x00400000) + +/* ADC EXT_TRIG mask */ +#define CTRL2_EXT_TRIG_SET ((uint32_t)0x00100000) +#define CTRL2_EXT_TRIG_RESET ((uint32_t)0xFFEFFFFF) + +/* ADC Software start mask */ +#define CTRL2_EXT_TRIG_SWSTART_SET ((uint32_t)0x00500000) +#define CTRL2_EXT_TRIG_SWSTART_RESET ((uint32_t)0xFFAFFFFF) + +/* ADC INJ_EXT_SEL mask */ +#define CTRL2_INJ_EXT_SEL_RESET ((uint32_t)0xFFFF8FFF) + +/* ADC INJ_EXT_TRIG mask */ +#define CTRL2_INJ_EXT_TRIG_SET ((uint32_t)0x00008000) +#define CTRL2_INJ_EXT_TRIG_RESET ((uint32_t)0xFFFF7FFF) + +/* ADC INJ_SWSTART mask */ +#define CTRL2_INJ_SWSTART_SET ((uint32_t)0x00200000) + +/* ADC injected software start mask */ +#define CTRL2_INJ_EXT_TRIG_JSWSTART_SET ((uint32_t)0x00208000) +#define CTRL2_INJ_EXT_TRIG_JSWSTART_RESET ((uint32_t)0xFFDF7FFF) + +/* ADC TSPD mask */ +#define CTRL2_TSVREFE_SET ((uint32_t)0x00800000) +#define CTRL2_TSVREFE_RESET ((uint32_t)0xFF7FFFFF) + +/* CTRL2 register Mask */ +#define CTRL2_CLR_MASK ((uint32_t)0xFFF1F7FD) + +/* ADC SQx mask */ +#define SQR4_SEQ_SET ((uint32_t)0x0000001F) +#define SQR3_SEQ_SET ((uint32_t)0x0000001F) +#define SQR2_SEQ_SET ((uint32_t)0x0000001F) +#define SQR1_SEQ_SET ((uint32_t)0x0000001F) + +/* RSEQ1 register Mask */ +#define RSEQ1_CLR_MASK ((uint32_t)0xFF0FFFFF) + +/* ADC JSQx mask */ +#define JSEQ_JSQ_SET ((uint32_t)0x0000001F) + +/* ADC INJ_LEN mask */ +#define JSEQ_INJ_LEN_SET ((uint32_t)0x00300000) +#define JSEQ_INJ_LEN_RESET ((uint32_t)0xFFCFFFFF) + +/* ADC SAMPTx mask */ +#define SAMPT1_SMP_SET ((uint32_t)0x00000007) +#define SAMPT2_SMP_SET ((uint32_t)0x00000007) + +/* ADC JDATx registers offset */ +#define JDAT_OFFSET ((uint8_t)0x28) + +/* ADC1 DAT register base address */ +#define DAT_ADDR ((uint32_t)0x4001244C) + +/** + * @} + */ + +/** @addtogroup ADC_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup ADC_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup ADC_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup ADC_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the ADCx peripheral registers to their default reset values. + * @param ADCx where x can be 1, 2 ,3 or 4 to select the ADC peripheral. + */ +void ADC_DeInit(ADC_Module* ADCx) +{ + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + + if (ADCx == ADC1) + { + /* Enable ADC1 reset state */ + RCC_EnableAHBPeriphReset(RCC_AHB_PERIPH_ADC1, ENABLE); + /* Release ADC1 from reset state */ + RCC_EnableAHBPeriphReset(RCC_AHB_PERIPH_ADC1, DISABLE); + } + else if (ADCx == ADC2) + { + /* Enable ADC2 reset state */ + RCC_EnableAHBPeriphReset(RCC_AHB_PERIPH_ADC2, ENABLE); + /* Release ADC2 from reset state */ + RCC_EnableAHBPeriphReset(RCC_AHB_PERIPH_ADC2, DISABLE); + } + else if (ADCx == ADC3) + { + /* Enable ADC2 reset state */ + RCC_EnableAHBPeriphReset(RCC_AHB_PERIPH_ADC3, ENABLE); + /* Release ADC2 from reset state */ + RCC_EnableAHBPeriphReset(RCC_AHB_PERIPH_ADC3, DISABLE); + } + else + { + if (ADCx == ADC4) + { + /* Enable ADC3 reset state */ + RCC_EnableAHBPeriphReset(RCC_AHB_PERIPH_ADC4, ENABLE); + /* Release ADC3 from reset state */ + RCC_EnableAHBPeriphReset(RCC_AHB_PERIPH_ADC4, DISABLE); + } + } +} + +/** + * @brief Initializes the ADCx peripheral according to the specified parameters + * in the ADC_InitStruct. + * @param ADCx where x can be 1, 2 ,3 or 4 to select the ADC peripheral. + * @param ADC_InitStruct pointer to an ADC_InitType structure that contains + * the configuration information for the specified ADC peripheral. + */ +void ADC_Init(ADC_Module* ADCx, ADC_InitType* ADC_InitStruct) +{ + uint32_t tmpreg1 = 0; + uint8_t tmpreg2 = 0; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcWorkMode(ADC_InitStruct->WorkMode)); + assert_param(IS_FUNCTIONAL_STATE(ADC_InitStruct->MultiChEn)); + assert_param(IS_FUNCTIONAL_STATE(ADC_InitStruct->ContinueConvEn)); + assert_param(IsAdcExtTrig(ADC_InitStruct->ExtTrigSelect)); + assert_param(IsAdcDatAlign(ADC_InitStruct->DatAlign)); + assert_param(IsAdcSeqLenValid(ADC_InitStruct->ChsNumber)); + + /*---------------------------- ADCx CTRL1 Configuration -----------------*/ + /* Get the ADCx CTRL1 value */ + tmpreg1 = ADCx->CTRL1; + /* Clear DUALMOD and SCAN bits */ + tmpreg1 &= CTRL1_CLR_MASK; + /* Configure ADCx: Dual mode and scan conversion mode */ + /* Set DUALMOD bits according to WorkMode value */ + /* Set SCAN bit according to MultiChEn value */ + tmpreg1 |= (uint32_t)(ADC_InitStruct->WorkMode | ((uint32_t)ADC_InitStruct->MultiChEn << 8)); + /* Write to ADCx CTRL1 */ + ADCx->CTRL1 = tmpreg1; + + /*---------------------------- ADCx CTRL2 Configuration -----------------*/ + /* Get the ADCx CTRL2 value */ + tmpreg1 = ADCx->CTRL2; + /* Clear CONT, ALIGN and EXTSEL bits */ + tmpreg1 &= CTRL2_CLR_MASK; + /* Configure ADCx: external trigger event and continuous conversion mode */ + /* Set ALIGN bit according to DatAlign value */ + /* Set EXTSEL bits according to ExtTrigSelect value */ + /* Set CONT bit according to ContinueConvEn value */ + tmpreg1 |= (uint32_t)(ADC_InitStruct->DatAlign | ADC_InitStruct->ExtTrigSelect + | ((uint32_t)ADC_InitStruct->ContinueConvEn << 1)); + /* Write to ADCx CTRL2 */ + ADCx->CTRL2 = tmpreg1; + + /*---------------------------- ADCx RSEQ1 Configuration -----------------*/ + /* Get the ADCx RSEQ1 value */ + tmpreg1 = ADCx->RSEQ1; + /* Clear L bits */ + tmpreg1 &= RSEQ1_CLR_MASK; + /* Configure ADCx: regular channel sequence length */ + /* Set L bits according to ChsNumber value */ + tmpreg2 |= (uint8_t)(ADC_InitStruct->ChsNumber - (uint8_t)1); + tmpreg1 |= (uint32_t)tmpreg2 << 20; + /* Write to ADCx RSEQ1 */ + ADCx->RSEQ1 = tmpreg1; +} + +/** + * @brief Fills each ADC_InitStruct member with its default value. + * @param ADC_InitStruct pointer to an ADC_InitType structure which will be initialized. + */ +void ADC_InitStruct(ADC_InitType* ADC_InitStruct) +{ + /* Reset ADC init structure parameters values */ + /* Initialize the WorkMode member */ + ADC_InitStruct->WorkMode = ADC_WORKMODE_INDEPENDENT; + /* initialize the MultiChEn member */ + ADC_InitStruct->MultiChEn = DISABLE; + /* Initialize the ContinueConvEn member */ + ADC_InitStruct->ContinueConvEn = DISABLE; + /* Initialize the ExtTrigSelect member */ + ADC_InitStruct->ExtTrigSelect = ADC_EXT_TRIGCONV_T1_CC1; + /* Initialize the DatAlign member */ + ADC_InitStruct->DatAlign = ADC_DAT_ALIGN_R; + /* Initialize the ChsNumber member */ + ADC_InitStruct->ChsNumber = 1; +} + +/** + * @brief Enables or disables the specified ADC peripheral. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param Cmd new state of the ADCx peripheral. + * This parameter can be: ENABLE or DISABLE. + */ +void ADC_Enable(ADC_Module* ADCx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Set the AD_ON bit to wake up the ADC from power down mode */ + ADCx->CTRL2 |= CTRL2_AD_ON_SET; + } + else + { + /* Disable the selected ADC peripheral */ + ADCx->CTRL2 &= CTRL2_AD_ON_RESET; + } +} + +/** + * @brief Enables or disables the specified ADC DMA request. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param Cmd new state of the selected ADC DMA transfer. + * This parameter can be: ENABLE or DISABLE. + */ +void ADC_EnableDMA(ADC_Module* ADCx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsAdcDmaModule(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected ADC DMA request */ + ADCx->CTRL2 |= CTRL2_DMA_SET; + } + else + { + /* Disable the selected ADC DMA request */ + ADCx->CTRL2 &= CTRL2_DMA_RESET; + } +} + +/** + * @brief Enables or disables the specified ADC interrupts. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param ADC_IT specifies the ADC interrupt sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg ADC_INT_ENDC End of conversion interrupt mask + * @arg ADC_INT_AWD Analog watchdog interrupt mask + * @arg ADC_INT_JENDC End of injected conversion interrupt mask + * @param Cmd new state of the specified ADC interrupts. + * This parameter can be: ENABLE or DISABLE. + */ +void ADC_ConfigInt(ADC_Module* ADCx, uint16_t ADC_IT, FunctionalState Cmd) +{ + uint8_t itmask = 0; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + assert_param(IsAdcInt(ADC_IT)); + /* Get the ADC IT index */ + itmask = (uint8_t)ADC_IT; + if (Cmd != DISABLE) + { + /* Enable the selected ADC interrupts */ + ADCx->CTRL1 |= itmask; + } + else + { + /* Disable the selected ADC interrupts */ + ADCx->CTRL1 &= (~(uint32_t)itmask); + } +} + +/** + * @brief Starts the selected ADC calibration process. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + */ +void ADC_StartCalibration(ADC_Module* ADCx) +{ + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + /* Enable the selected ADC calibration process */ + if(ADCx->CALFACT==0) + ADCx->CTRL2 |= CTRL2_CAL_SET; +} + +/** + * @brief Gets the selected ADC calibration status. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @return The new state of ADC calibration (SET or RESET). + */ +FlagStatus ADC_GetCalibrationStatus(ADC_Module* ADCx) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + /* Check the status of CAL bit */ + if ((ADCx->CTRL2 & CTRL2_CAL_SET) != (uint32_t)RESET) + { + /* CAL bit is set: calibration on going */ + bitstatus = SET; + } + else + { + /* CAL bit is reset: end of calibration */ + bitstatus = RESET; + } + if(ADCx->CALFACT!=0) + bitstatus = RESET; + /* Return the CAL bit status */ + return bitstatus; +} + +/** + * @brief Enables or disables the selected ADC software start conversion . + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param Cmd new state of the selected ADC software start conversion. + * This parameter can be: ENABLE or DISABLE. + */ +void ADC_EnableSoftwareStartConv(ADC_Module* ADCx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected ADC conversion on external event and start the selected + ADC conversion */ + ADCx->CTRL2 |= CTRL2_EXT_TRIG_SWSTART_SET; + } + else + { + /* Disable the selected ADC conversion on external event and stop the selected + ADC conversion */ + ADCx->CTRL2 &= CTRL2_EXT_TRIG_SWSTART_RESET; + } +} + +/** + * @brief Gets the selected ADC Software start conversion Status. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @return The new state of ADC software start conversion (SET or RESET). + */ +FlagStatus ADC_GetSoftwareStartConvStatus(ADC_Module* ADCx) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + /* Check the status of SOFT_START bit */ + if ((ADCx->CTRL2 & CTRL2_SOFT_START_SET) != (uint32_t)RESET) + { + /* SOFT_START bit is set */ + bitstatus = SET; + } + else + { + /* SOFT_START bit is reset */ + bitstatus = RESET; + } + /* Return the SOFT_START bit status */ + return bitstatus; +} + +/** + * @brief Configures the discontinuous mode for the selected ADC regular + * group channel. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param Number specifies the discontinuous mode regular channel + * count value. This number must be between 1 and 8. + */ +void ADC_ConfigDiscModeChannelCount(ADC_Module* ADCx, uint8_t Number) +{ + uint32_t tmpreg1 = 0; + uint32_t tmpreg2 = 0; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcSeqDiscNumberValid(Number)); + /* Get the old register value */ + tmpreg1 = ADCx->CTRL1; + /* Clear the old discontinuous mode channel count */ + tmpreg1 &= CR1_DISCNUM_Reset; + /* Set the discontinuous mode channel count */ + tmpreg2 = Number - 1; + tmpreg1 |= tmpreg2 << 13; + /* Store the new register value */ + ADCx->CTRL1 = tmpreg1; +} + +/** + * @brief Enables or disables the discontinuous mode on regular group + * channel for the specified ADC + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param Cmd new state of the selected ADC discontinuous mode + * on regular group channel. + * This parameter can be: ENABLE or DISABLE. + */ +void ADC_EnableDiscMode(ADC_Module* ADCx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected ADC regular discontinuous mode */ + ADCx->CTRL1 |= CTRL1_DISC_EN_SET; + } + else + { + /* Disable the selected ADC regular discontinuous mode */ + ADCx->CTRL1 &= CTRL1_DISC_EN_RESET; + } +} + +/** + * @brief Configures for the selected ADC regular channel its corresponding + * rank in the sequencer and its sample time. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param ADC_Channel the ADC channel to configure. + * This parameter can be one of the following values: + * @arg ADC_CH_0 ADC Channel0 selected + * @arg ADC_CH_1 ADC Channel1 selected + * @arg ADC_CH_2 ADC Channel2 selected + * @arg ADC_CH_3 ADC Channel3 selected + * @arg ADC_CH_4 ADC Channel4 selected + * @arg ADC_CH_5 ADC Channel5 selected + * @arg ADC_CH_6 ADC Channel6 selected + * @arg ADC_CH_7 ADC Channel7 selected + * @arg ADC_CH_8 ADC Channel8 selected + * @arg ADC_CH_9 ADC Channel9 selected + * @arg ADC_CH_10 ADC Channel10 selected + * @arg ADC_CH_11 ADC Channel11 selected + * @arg ADC_CH_12 ADC Channel12 selected + * @arg ADC_CH_13 ADC Channel13 selected + * @arg ADC_CH_14 ADC Channel14 selected + * @arg ADC_CH_15 ADC Channel15 selected + * @arg ADC_CH_16 ADC Channel16 selected + * @arg ADC_CH_17 ADC Channel17 selected + * @arg ADC_CH_18 ADC Channel18 selected + * @param Rank The rank in the regular group sequencer. This parameter must be between 1 to 16. + * @param ADC_SampleTime The sample time value to be set for the selected channel. + * This parameter can be one of the following values: + * @arg ADC_SAMP_TIME_1CYCLES5 Sample time equal to 1.5 cycles + * @arg ADC_SAMP_TIME_7CYCLES5 Sample time equal to 7.5 cycles + * @arg ADC_SAMP_TIME_13CYCLES5 Sample time equal to 13.5 cycles + * @arg ADC_SAMP_TIME_28CYCLES5 Sample time equal to 28.5 cycles + * @arg ADC_SAMP_TIME_41CYCLES5 Sample time equal to 41.5 cycles + * @arg ADC_SAMP_TIME_55CYCLES5 Sample time equal to 55.5 cycles + * @arg ADC_SAMP_TIME_71CYCLES5 Sample time equal to 71.5 cycles + * @arg ADC_SAMP_TIME_239CYCLES5 Sample time equal to 239.5 cycles + */ +void ADC_ConfigRegularChannel(ADC_Module* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime) +{ + uint32_t tmpreg1 = 0, tmpreg2 = 0; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcChannel(ADC_Channel)); + assert_param(IsAdcReqRankValid(Rank)); + assert_param(IsAdcSampleTime(ADC_SampleTime)); + + if (ADC_Channel == ADC_CH_18) + { + tmpreg1 = ADCx->SAMPT3; + tmpreg1 &= (~0x00000007); + tmpreg1 |= ADC_SampleTime; + ADCx->SAMPT3 = tmpreg1; + } + else if (ADC_Channel > ADC_CH_9) /* if ADC_CH_10 ... ADC_CH_17 is selected */ + { + /* Get the old register value */ + tmpreg1 = ADCx->SAMPT1; + /* Calculate the mask to clear */ + tmpreg2 = SAMPT1_SMP_SET << (3 * (ADC_Channel - 10)); + /* Clear the old channel sample time */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_SampleTime << (3 * (ADC_Channel - 10)); + /* Set the new channel sample time */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->SAMPT1 = tmpreg1; + } + else /* ADC_Channel include in ADC_Channel_[0..9] */ + { + /* Get the old register value */ + tmpreg1 = ADCx->SAMPT2; + /* Calculate the mask to clear */ + tmpreg2 = SAMPT2_SMP_SET << (3 * ADC_Channel); + /* Clear the old channel sample time */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_SampleTime << (3 * ADC_Channel); + /* Set the new channel sample time */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->SAMPT2 = tmpreg1; + } + /* For Rank 1 to 6 */ + if (Rank < 7) + { + /* Get the old register value */ + tmpreg1 = ADCx->RSEQ3; + /* Calculate the mask to clear */ + tmpreg2 = SQR3_SEQ_SET << (5 * (Rank - 1)); + /* Clear the old SQx bits for the selected rank */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 1)); + /* Set the SQx bits for the selected rank */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->RSEQ3 = tmpreg1; + } + /* For Rank 7 to 12 */ + else if (Rank < 13) + { + /* Get the old register value */ + tmpreg1 = ADCx->RSEQ2; + /* Calculate the mask to clear */ + tmpreg2 = SQR2_SEQ_SET << (5 * (Rank - 7)); + /* Clear the old SQx bits for the selected rank */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 7)); + /* Set the SQx bits for the selected rank */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->RSEQ2 = tmpreg1; + } + /* For Rank 13 to 16 */ + else + { + /* Get the old register value */ + tmpreg1 = ADCx->RSEQ1; + /* Calculate the mask to clear */ + tmpreg2 = SQR1_SEQ_SET << (5 * (Rank - 13)); + /* Clear the old SQx bits for the selected rank */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 13)); + /* Set the SQx bits for the selected rank */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->RSEQ1 = tmpreg1; + } +} + +/** + * @brief Enables or disables the ADCx conversion through external trigger. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param Cmd new state of the selected ADC external trigger start of conversion. + * This parameter can be: ENABLE or DISABLE. + */ +void ADC_EnableExternalTrigConv(ADC_Module* ADCx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected ADC conversion on external event */ + ADCx->CTRL2 |= CTRL2_EXT_TRIG_SET; + } + else + { + /* Disable the selected ADC conversion on external event */ + ADCx->CTRL2 &= CTRL2_EXT_TRIG_RESET; + } +} + +/** + * @brief Returns the last ADCx conversion result data for regular channel. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @return The Data conversion value. + */ +uint16_t ADC_GetDat(ADC_Module* ADCx) +{ + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + /* Return the selected ADC conversion value */ + return (uint16_t)ADCx->DAT; +} + +/** + * @brief Returns the last ADC1 and ADC2 OR last ADC3 and ADC4 conversion result data in dual mode. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @return The Data conversion value. + */ +uint32_t ADC_GetDualModeConversionDat(ADC_Module* ADCx) +{ + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + /* Return the dual mode conversion value */ + if(ADCx==ADC1 || ADCx==ADC2) + return (uint32_t)ADC1->DAT; + else + return (uint32_t)ADC3->DAT; +} + +/** + * @brief Enables or disables the selected ADC automatic injected group + * conversion after regular one. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param Cmd new state of the selected ADC auto injected conversion + * This parameter can be: ENABLE or DISABLE. + */ +void ADC_EnableAutoInjectedConv(ADC_Module* ADCx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected ADC automatic injected group conversion */ + ADCx->CTRL1 |= CR1_JAUTO_Set; + } + else + { + /* Disable the selected ADC automatic injected group conversion */ + ADCx->CTRL1 &= CR1_JAUTO_Reset; + } +} + +/** + * @brief Enables or disables the discontinuous mode for injected group + * channel for the specified ADC + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param Cmd new state of the selected ADC discontinuous mode + * on injected group channel. + * This parameter can be: ENABLE or DISABLE. + */ +void ADC_EnableInjectedDiscMode(ADC_Module* ADCx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected ADC injected discontinuous mode */ + ADCx->CTRL1 |= CTRL1_INJ_DISC_EN_SET; + } + else + { + /* Disable the selected ADC injected discontinuous mode */ + ADCx->CTRL1 &= CTRL1_INJ_DISC_EN_RESET; + } +} + +/** + * @brief Configures the ADCx external trigger for injected channels conversion. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param ADC_ExternalTrigInjecConv specifies the ADC trigger to start injected conversion. + * This parameter can be one of the following values: + * @arg ADC_EXT_TRIG_INJ_CONV_T1_TRGO Timer1 TRGO event selected (for ADC1, ADC2 and ADC3) + * @arg ADC_EXT_TRIG_INJ_CONV_T1_CC4 Timer1 capture compare4 selected (for ADC1, ADC2 and ADC3) + * @arg ADC_EXT_TRIG_INJ_CONV_T2_TRGO Timer2 TRGO event selected (for ADC1 and ADC2) + * @arg ADC_EXT_TRIG_INJ_CONV_T2_CC1 Timer2 capture compare1 selected (for ADC1 and ADC2) + * @arg ADC_EXT_TRIG_INJ_CONV_T3_CC4 Timer3 capture compare4 selected (for ADC1 and ADC2) + * @arg ADC_EXT_TRIG_INJ_CONV_T4_TRGO Timer4 TRGO event selected (for ADC1 and ADC2) + * @arg ADC_EXT_TRIG_INJ_CONV_EXT_INT15_TIM8_CC4 External interrupt line 15 or Timer8 + * capture compare4 event selected (for ADC1 and ADC2) + * @arg ADC_EXT_TRIG_INJ_CONV_T4_CC3 Timer4 capture compare3 selected (for ADC3 only) + * @arg ADC_EXT_TRIG_INJ_CONV_T8_CC2 Timer8 capture compare2 selected (for ADC3 only) + * @arg ADC_EXT_TRIG_INJ_CONV_T8_CC4 Timer8 capture compare4 selected (for ADC3 only) + * @arg ADC_EXT_TRIG_INJ_CONV_T5_TRGO Timer5 TRGO event selected (for ADC3 only) + * @arg ADC_EXT_TRIG_INJ_CONV_T5_CC4 Timer5 capture compare4 selected (for ADC3 only) + * @arg ADC_EXT_TRIG_INJ_CONV_NONE Injected conversion started by software and not + * by external trigger (for ADC1, ADC2 and ADC3) + */ +void ADC_ConfigExternalTrigInjectedConv(ADC_Module* ADCx, uint32_t ADC_ExternalTrigInjecConv) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcExtInjTrig(ADC_ExternalTrigInjecConv)); + /* Get the old register value */ + tmpregister = ADCx->CTRL2; + /* Clear the old external event selection for injected group */ + tmpregister &= CTRL2_INJ_EXT_SEL_RESET; + /* Set the external event selection for injected group */ + tmpregister |= ADC_ExternalTrigInjecConv; + /* Store the new register value */ + ADCx->CTRL2 = tmpregister; +} + +/** + * @brief Enables or disables the ADCx injected channels conversion through + * external trigger + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param Cmd new state of the selected ADC external trigger start of + * injected conversion. + * This parameter can be: ENABLE or DISABLE. + */ +void ADC_EnableExternalTrigInjectedConv(ADC_Module* ADCx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected ADC external event selection for injected group */ + ADCx->CTRL2 |= CTRL2_INJ_EXT_TRIG_SET; + } + else + { + /* Disable the selected ADC external event selection for injected group */ + ADCx->CTRL2 &= CTRL2_INJ_EXT_TRIG_RESET; + } +} + +/** + * @brief Enables or disables the selected ADC start of the injected + * channels conversion. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param Cmd new state of the selected ADC software start injected conversion. + * This parameter can be: ENABLE or DISABLE. + */ +void ADC_EnableSoftwareStartInjectedConv(ADC_Module* ADCx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected ADC conversion for injected group on external event and start the selected + ADC injected conversion */ + ADCx->CTRL2 |= CTRL2_INJ_EXT_TRIG_JSWSTART_SET; + } + else + { + /* Disable the selected ADC conversion on external event for injected group and stop the selected + ADC injected conversion */ + ADCx->CTRL2 &= CTRL2_INJ_EXT_TRIG_JSWSTART_RESET; + } +} + +/** + * @brief Gets the selected ADC Software start injected conversion Status. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @return The new state of ADC software start injected conversion (SET or RESET). + */ +FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_Module* ADCx) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + /* Check the status of INJ_SWSTART bit */ + if ((ADCx->CTRL2 & CTRL2_INJ_SWSTART_SET) != (uint32_t)RESET) + { + /* INJ_SWSTART bit is set */ + bitstatus = SET; + } + else + { + /* INJ_SWSTART bit is reset */ + bitstatus = RESET; + } + /* Return the INJ_SWSTART bit status */ + return bitstatus; +} + +/** + * @brief Configures for the selected ADC injected channel its corresponding + * rank in the sequencer and its sample time. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param ADC_Channel the ADC channel to configure. + * This parameter can be one of the following values: + * @arg ADC_CH_0 ADC Channel0 selected + * @arg ADC_CH_1 ADC Channel1 selected + * @arg ADC_CH_2 ADC Channel2 selected + * @arg ADC_CH_3 ADC Channel3 selected + * @arg ADC_CH_4 ADC Channel4 selected + * @arg ADC_CH_5 ADC Channel5 selected + * @arg ADC_CH_6 ADC Channel6 selected + * @arg ADC_CH_7 ADC Channel7 selected + * @arg ADC_CH_8 ADC Channel8 selected + * @arg ADC_CH_9 ADC Channel9 selected + * @arg ADC_CH_10 ADC Channel10 selected + * @arg ADC_CH_11 ADC Channel11 selected + * @arg ADC_CH_12 ADC Channel12 selected + * @arg ADC_CH_13 ADC Channel13 selected + * @arg ADC_CH_14 ADC Channel14 selected + * @arg ADC_CH_15 ADC Channel15 selected + * @arg ADC_CH_16 ADC Channel16 selected + * @arg ADC_CH_17 ADC Channel17 selected + * @arg ADC_CH_18 ADC Channel18 selected + * @param Rank The rank in the injected group sequencer. This parameter must be between 1 and 4. + * @param ADC_SampleTime The sample time value to be set for the selected channel. + * This parameter can be one of the following values: + * @arg ADC_SAMP_TIME_1CYCLES5 Sample time equal to 1.5 cycles + * @arg ADC_SAMP_TIME_7CYCLES5 Sample time equal to 7.5 cycles + * @arg ADC_SAMP_TIME_13CYCLES5 Sample time equal to 13.5 cycles + * @arg ADC_SAMP_TIME_28CYCLES5 Sample time equal to 28.5 cycles + * @arg ADC_SAMP_TIME_41CYCLES5 Sample time equal to 41.5 cycles + * @arg ADC_SAMP_TIME_55CYCLES5 Sample time equal to 55.5 cycles + * @arg ADC_SAMP_TIME_71CYCLES5 Sample time equal to 71.5 cycles + * @arg ADC_SAMP_TIME_239CYCLES5 Sample time equal to 239.5 cycles + */ +void ADC_ConfigInjectedChannel(ADC_Module* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime) +{ + uint32_t tmpreg1 = 0, tmpreg2 = 0, tmpreg3 = 0; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcChannel(ADC_Channel)); + assert_param(IsAdcInjRankValid(Rank)); + assert_param(IsAdcSampleTime(ADC_SampleTime)); + + if (ADC_Channel == ADC_CH_18) + { + tmpreg1 = ADCx->SAMPT3; + tmpreg1 &= (~0x00000007); + tmpreg1 |= ADC_SampleTime; + ADCx->SAMPT3 = tmpreg1; + } + else if (ADC_Channel > ADC_CH_9) /* if ADC_CH_10 ... ADC_CH_17 is selected */ + { + /* Get the old register value */ + tmpreg1 = ADCx->SAMPT1; + /* Calculate the mask to clear */ + tmpreg2 = SAMPT1_SMP_SET << (3 * (ADC_Channel - 10)); + /* Clear the old channel sample time */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_SampleTime << (3 * (ADC_Channel - 10)); + /* Set the new channel sample time */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->SAMPT1 = tmpreg1; + } + else /* ADC_Channel include in ADC_Channel_[0..9] */ + { + /* Get the old register value */ + tmpreg1 = ADCx->SAMPT2; + /* Calculate the mask to clear */ + tmpreg2 = SAMPT2_SMP_SET << (3 * ADC_Channel); + /* Clear the old channel sample time */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set */ + tmpreg2 = (uint32_t)ADC_SampleTime << (3 * ADC_Channel); + /* Set the new channel sample time */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->SAMPT2 = tmpreg1; + } + /* Rank configuration */ + /* Get the old register value */ + tmpreg1 = ADCx->JSEQ; + /* Get INJ_LEN value: Number = INJ_LEN+1 */ + tmpreg3 = (tmpreg1 & JSEQ_INJ_LEN_SET) >> 20; + /* Calculate the mask to clear: ((Rank-1)+(4-INJ_LEN-1)) */ + tmpreg2 = JSEQ_JSQ_SET << (5 * (uint8_t)((Rank + 3) - (tmpreg3 + 1))); + /* Clear the old JSQx bits for the selected rank */ + tmpreg1 &= ~tmpreg2; + /* Calculate the mask to set: ((Rank-1)+(4-INJ_LEN-1)) */ + tmpreg2 = (uint32_t)ADC_Channel << (5 * (uint8_t)((Rank + 3) - (tmpreg3 + 1))); + /* Set the JSQx bits for the selected rank */ + tmpreg1 |= tmpreg2; + /* Store the new register value */ + ADCx->JSEQ = tmpreg1; +} + +/** + * @brief Configures the sequencer length for injected channels + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param Length The sequencer length. + * This parameter must be a number between 1 to 4. + */ +void ADC_ConfigInjectedSequencerLength(ADC_Module* ADCx, uint8_t Length) +{ + uint32_t tmpreg1 = 0; + uint32_t tmpreg2 = 0; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcInjLenValid(Length)); + + /* Get the old register value */ + tmpreg1 = ADCx->JSEQ; + /* Clear the old injected sequnence lenght INJ_LEN bits */ + tmpreg1 &= JSEQ_INJ_LEN_RESET; + /* Set the injected sequnence lenght INJ_LEN bits */ + tmpreg2 = Length - 1; + tmpreg1 |= tmpreg2 << 20; + /* Store the new register value */ + ADCx->JSEQ = tmpreg1; +} + +/** + * @brief Set the injected channels conversion value offset + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param ADC_InjectedChannel the ADC injected channel to set its offset. + * This parameter can be one of the following values: + * @arg ADC_INJ_CH_1 Injected Channel1 selected + * @arg ADC_INJ_CH_2 Injected Channel2 selected + * @arg ADC_INJ_CH_3 Injected Channel3 selected + * @arg ADC_INJ_CH_4 Injected Channel4 selected + * @param Offset the offset value for the selected ADC injected channel + * This parameter must be a 12bit value. + */ +void ADC_SetInjectedOffsetDat(ADC_Module* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcInjCh(ADC_InjectedChannel)); + assert_param(IsAdcOffsetValid(Offset)); + + tmp = (uint32_t)ADCx; + tmp += ADC_InjectedChannel; + + /* Set the selected injected channel data offset */ + *(__IO uint32_t*)tmp = (uint32_t)Offset; +} + +/** + * @brief Returns the ADC injected channel conversion result + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param ADC_InjectedChannel the converted ADC injected channel. + * This parameter can be one of the following values: + * @arg ADC_INJ_CH_1 Injected Channel1 selected + * @arg ADC_INJ_CH_2 Injected Channel2 selected + * @arg ADC_INJ_CH_3 Injected Channel3 selected + * @arg ADC_INJ_CH_4 Injected Channel4 selected + * @return The Data conversion value. + */ +uint16_t ADC_GetInjectedConversionDat(ADC_Module* ADCx, uint8_t ADC_InjectedChannel) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcInjCh(ADC_InjectedChannel)); + + tmp = (uint32_t)ADCx; + tmp += ADC_InjectedChannel + JDAT_OFFSET; + + /* Returns the selected injected channel conversion data value */ + return (uint16_t)(*(__IO uint32_t*)tmp); +} + +/** + * @brief Enables or disables the analog watchdog on single/all regular + * or injected channels + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param ADC_AnalogWatchdog the ADC analog watchdog configuration. + * This parameter can be one of the following values: + * @arg ADC_ANALOG_WTDG_SINGLEREG_ENABLE Analog watchdog on a single regular channel + * @arg ADC_ANALOG_WTDG_SINGLEINJEC_ENABLE Analog watchdog on a single injected channel + * @arg ADC_ANALOG_WTDG_SINGLEREG_OR_INJEC_ENABLE Analog watchdog on a single regular or injected channel + * @arg ADC_ANALOG_WTDG_ALLREG_ENABLE Analog watchdog on all regular channel + * @arg ADC_ANALOG_WTDG_ALLINJEC_ENABLE Analog watchdog on all injected channel + * @arg ADC_ANALOG_WTDG_ALLREG_ALLINJEC_ENABLE Analog watchdog on all regular and injected channels + * @arg ADC_ANALOG_WTDG_NONE No channel guarded by the analog watchdog + */ +void ADC_ConfigAnalogWatchdogWorkChannelType(ADC_Module* ADCx, uint32_t ADC_AnalogWatchdog) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcAnalogWatchdog(ADC_AnalogWatchdog)); + /* Get the old register value */ + tmpregister = ADCx->CTRL1; + /* Clear AWDEN, AWDENJ and AWDSGL bits */ + tmpregister &= CTRL1_AWDG_MODE_RESET; + /* Set the analog watchdog enable mode */ + tmpregister |= ADC_AnalogWatchdog; + /* Store the new register value */ + ADCx->CTRL1 = tmpregister; +} + +/** + * @brief Configures the high and low thresholds of the analog watchdog. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param HighThreshold the ADC analog watchdog High threshold value. + * This parameter must be a 12bit value. + * @param LowThreshold the ADC analog watchdog Low threshold value. + * This parameter must be a 12bit value. + */ +void ADC_ConfigAnalogWatchdogThresholds(ADC_Module* ADCx, uint16_t HighThreshold, uint16_t LowThreshold) +{ + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcValid(HighThreshold)); + assert_param(IsAdcValid(LowThreshold)); + /* Set the ADCx high threshold */ + ADCx->WDGHIGH = HighThreshold; + /* Set the ADCx low threshold */ + ADCx->WDGLOW = LowThreshold; +} + +/** + * @brief Configures the analog watchdog guarded single channel + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param ADC_Channel the ADC channel to configure for the analog watchdog. + * This parameter can be one of the following values: + * @arg ADC_CH_0 ADC Channel0 selected + * @arg ADC_CH_1 ADC Channel1 selected + * @arg ADC_CH_2 ADC Channel2 selected + * @arg ADC_CH_3 ADC Channel3 selected + * @arg ADC_CH_4 ADC Channel4 selected + * @arg ADC_CH_5 ADC Channel5 selected + * @arg ADC_CH_6 ADC Channel6 selected + * @arg ADC_CH_7 ADC Channel7 selected + * @arg ADC_CH_8 ADC Channel8 selected + * @arg ADC_CH_9 ADC Channel9 selected + * @arg ADC_CH_10 ADC Channel10 selected + * @arg ADC_CH_11 ADC Channel11 selected + * @arg ADC_CH_12 ADC Channel12 selected + * @arg ADC_CH_13 ADC Channel13 selected + * @arg ADC_CH_14 ADC Channel14 selected + * @arg ADC_CH_15 ADC Channel15 selected + * @arg ADC_CH_16 ADC Channel16 selected + * @arg ADC_CH_17 ADC Channel17 selected + * @arg ADC_CH_18 ADC Channel18 selected + */ +void ADC_ConfigAnalogWatchdogSingleChannel(ADC_Module* ADCx, uint8_t ADC_Channel) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcChannel(ADC_Channel)); + /* Get the old register value */ + tmpregister = ADCx->CTRL1; + /* Clear the Analog watchdog channel select bits */ + tmpregister &= CTRL1_AWDG_CH_RESET; + /* Set the Analog watchdog channel */ + tmpregister |= ADC_Channel; + /* Store the new register value */ + ADCx->CTRL1 = tmpregister; +} + +/** + * @brief Enables or disables the temperature sensor and Vrefint channel. + * @param Cmd new state of the temperature sensor. + * This parameter can be: ENABLE or DISABLE. + */ +void ADC_EnableTempSensorVrefint(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the temperature sensor and Vrefint channel*/ + ADC1->CTRL2 |= CTRL2_TSVREFE_SET; + _EnVref1p2() + } + else + { + /* Disable the temperature sensor and Vrefint channel*/ + ADC1->CTRL2 &= CTRL2_TSVREFE_RESET; + _DisVref1p2() + } +} + +/** + * @brief Checks whether the specified ADC flag is set or not. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param ADC_FLAG specifies the flag to check. + * This parameter can be one of the following values: + * @arg ADC_FLAG_AWDG Analog watchdog flag + * @arg ADC_FLAG_ENDC End of conversion flag + * @arg ADC_FLAG_JENDC End of injected group conversion flag + * @arg ADC_FLAG_JSTR Start of injected group conversion flag + * @arg ADC_FLAG_STR Start of regular group conversion flag + * @return The new state of ADC_FLAG (SET or RESET). + */ +FlagStatus ADC_GetFlagStatus(ADC_Module* ADCx, uint8_t ADC_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcGetFlag(ADC_FLAG)); + /* Check the status of the specified ADC flag */ + if ((ADCx->STS & ADC_FLAG) != (uint8_t)RESET) + { + /* ADC_FLAG is set */ + bitstatus = SET; + } + else + { + /* ADC_FLAG is reset */ + bitstatus = RESET; + } + /* Return the ADC_FLAG status */ + return bitstatus; +} + +/** + * @brief Clears the ADCx's pending flags. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param ADC_FLAG specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg ADC_FLAG_AWDG Analog watchdog flag + * @arg ADC_FLAG_ENDC End of conversion flag + * @arg ADC_FLAG_JENDC End of injected group conversion flag + * @arg ADC_FLAG_JSTR Start of injected group conversion flag + * @arg ADC_FLAG_STR Start of regular group conversion flag + */ +void ADC_ClearFlag(ADC_Module* ADCx, uint8_t ADC_FLAG) +{ + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcClrFlag(ADC_FLAG)); + /* Clear the selected ADC flags */ + ADCx->STS &= ~(uint32_t)ADC_FLAG; +} + +/** + * @brief Checks whether the specified ADC interrupt has occurred or not. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param ADC_IT specifies the ADC interrupt source to check. + * This parameter can be one of the following values: + * @arg ADC_INT_ENDC End of conversion interrupt mask + * @arg ADC_INT_AWD Analog watchdog interrupt mask + * @arg ADC_INT_JENDC End of injected conversion interrupt mask + * @return The new state of ADC_IT (SET or RESET). + */ +INTStatus ADC_GetIntStatus(ADC_Module* ADCx, uint16_t ADC_IT) +{ + INTStatus bitstatus = RESET; + uint32_t itmask = 0, enablestatus = 0; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcGetInt(ADC_IT)); + /* Get the ADC IT index */ + itmask = ADC_IT >> 8; + /* Get the ADC_IT enable bit status */ + enablestatus = (ADCx->CTRL1 & (uint8_t)ADC_IT); + /* Check the status of the specified ADC interrupt */ + if (((ADCx->STS & itmask) != (uint32_t)RESET) && enablestatus) + { + /* ADC_IT is set */ + bitstatus = SET; + } + else + { + /* ADC_IT is reset */ + bitstatus = RESET; + } + /* Return the ADC_IT status */ + return bitstatus; +} + +/** + * @brief Clears the ADCx's interrupt pending bits. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param ADC_IT specifies the ADC interrupt pending bit to clear. + * This parameter can be any combination of the following values: + * @arg ADC_INT_ENDC End of conversion interrupt mask + * @arg ADC_INT_AWD Analog watchdog interrupt mask + * @arg ADC_INT_JENDC End of injected conversion interrupt mask + */ +void ADC_ClearIntPendingBit(ADC_Module* ADCx, uint16_t ADC_IT) +{ + uint8_t itmask = 0; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcInt(ADC_IT)); + /* Get the ADC IT index */ + itmask = (uint8_t)(ADC_IT >> 8); + /* Clear the selected ADC interrupt pending bits */ + ADCx->STS &= ~(uint32_t)itmask; +} + +/** + * @brief Initializes the ADCx peripheral according to the specified parameters + * in the ADC_InitStructEx. + * @param ADCx where x can be 1, 2 ,3 or 4 to select the ADC peripheral. + * @param ADC_InitStructEx pointer to an ADC_InitTypeEx structure that contains + * the configuration information for the specified ADC peripheral. + */ +void ADC_InitEx(ADC_Module* ADCx, ADC_InitTypeEx* ADC_InitStructEx) +{ + uint32_t tmpregister = 0; + /*ADC_SAMPT3 samp time sele ,as sam 103 or 303 style*/ + if (ADC_InitStructEx->SampSecondStyle) + ADCx->SAMPT3 |= ADC_SAMPT3_SAMPSEL_MSK; + else + ADCx->SAMPT3 &= (~ADC_SAMPT3_SAMPSEL_MSK); + + /*intial ADC_CTRL3 once initiall config*/ + tmpregister = ADCx->CTRL3; + if (ADC_InitStructEx->VbatMinitEn) + { + tmpregister |= ADC_CTRL3_VABTMEN_MSK; + _EnVref1p2() + } + else + { + tmpregister &= (~ADC_CTRL3_VABTMEN_MSK); + _DisVref1p2() + } + + if (ADC_InitStructEx->DeepPowerModEn) + tmpregister |= ADC_CTRL3_DPWMOD_MSK; + else + tmpregister &= (~ADC_CTRL3_DPWMOD_MSK); + + if (ADC_InitStructEx->JendcIntEn) + tmpregister |= ADC_CTRL3_JENDCAIEN_MSK; + else + tmpregister &= (~ADC_CTRL3_JENDCAIEN_MSK); + + if (ADC_InitStructEx->EndcIntEn) + tmpregister |= ADC_CTRL3_ENDCAIEN_MSK; + else + tmpregister &= (~ADC_CTRL3_ENDCAIEN_MSK); + + if (ADC_InitStructEx->CalAtuoLoadEn) + tmpregister |= ADC_CTRL3_CALALD_MSK; + else + tmpregister &= (~ADC_CTRL3_CALALD_MSK); + + if (ADC_InitStructEx->DifModCal) + tmpregister |= ADC_CTRL3_CALDIF_MSK; + else + tmpregister &= (~ADC_CTRL3_CALDIF_MSK); + + tmpregister &= (~ADC_CTRL3_RES_MSK); + tmpregister |= ADC_InitStructEx->ResBit; + + tmpregister &= (~ADC_CTRL3_CKMOD_MSK); + if(ADC_InitStructEx->ClkMode==ADC_CTRL3_CKMOD_PLL) + tmpregister |= ADC_CTRL3_CKMOD_MSK; + + ADCx->CTRL3 = tmpregister; +} +/** + * @brief Configure differential channels enable. + * @param ADCx where x can be 1, 2 ,3 or 4 to select the ADC peripheral. + * @param DifChs differential channels,see @ADC_dif_sel_ch_definition. eg: ADC_DIFSEL_CHS_3|ADC_DIFSEL_CHS_4 + */ +void ADC_SetDifChs(ADC_Module* ADCx,uint32_t DifChs) +{ + ADCx->DIFSEL = DifChs; +} +/** + * @brief Checks whether the specified ADC flag is set or not. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param ADC_FLAG_NEW specifies the flag to check. + * This parameter can be one of the following values: + * @arg ADC_FLAG_RDY ADC ready flag + * @arg ADC_FLAG_PD_RDY ADC powerdown ready flag + * @return The new state of ADC_FLAG_NEW (SET or RESET). + */ +FlagStatus ADC_GetFlagStatusNew(ADC_Module* ADCx, uint8_t ADC_FLAG_NEW) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IsAdcModule(ADCx)); + assert_param(IsAdcGetFlag(ADC_FLAG_NEW)); + /* Check the status of the specified ADC flag */ + if ((ADCx->CTRL3 & ADC_FLAG_NEW) != (uint8_t)RESET) + { + /* ADC_FLAG_NEW is set */ + bitstatus = SET; + } + else + { + /* ADC_FLAG_NEW is reset */ + bitstatus = RESET; + } + /* Return the ADC_FLAG_NEW status */ + return bitstatus; +} +/** + * @brief Set Adc calibration bypass or enable. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param en enable bypass calibration. + * This parameter can be one of the following values: + * @arg true bypass calibration + * @arg false not bypass calibration + */ +void ADC_SetBypassCalibration(ADC_Module* ADCx, FunctionalState en) +{ + uint32_t tmpregister = 0; + + tmpregister = ADCx->CTRL3; + if (en) + tmpregister |= ADC_CTRL3_BPCAL_MSK; + else + tmpregister &= (~ADC_CTRL3_BPCAL_MSK); + ADCx->CTRL3 = tmpregister; +} +/** + * @brief Set Adc trans bits width. + * @param ADCx where x can be 1, 2, 3 or 4 to select the ADC peripheral. + * @param ResultBitNum specifies num with adc trans width. + * This parameter can be one of the following values: + * @arg ADC_RST_BIT_12 12 bit trans + * @arg ADC_RST_BIT_10 10 bit trans + * @arg ADC_RST_BIT_8 8 bit trans + * @arg ADC_RESULT_BIT_6 6 bit trans + */ +void ADC_SetConvResultBitNum(ADC_Module* ADCx, uint32_t ResultBitNum) +{ + uint32_t tmpregister = 0; + + tmpregister = ADCx->CTRL3; + tmpregister &= 0xFFFFFFFC; + tmpregister |= ResultBitNum; + ADCx->CTRL3 = tmpregister; + return; +} + +/** + * @brief Configures the ADCHCLK prescaler. + * @param RCC_ADCHCLKPrescaler specifies the ADCHCLK prescaler. + * This parameter can be on of the following values: + * @arg RCC_ADCHCLK_DIV1 ADCHCLKPRE[3:0] = 0000, HCLK Clock Divided By 1 + * @arg RCC_ADCHCLK_DIV2 ADCHCLKPRE[3:0] = 0001, HCLK Clock Divided By 2 + * @arg RCC_ADCHCLK_DIV4 ADCHCLKPRE[3:0] = 0010, HCLK Clock Divided By 4 + * @arg RCC_ADCHCLK_DIV6 ADCHCLKPRE[3:0] = 0011, HCLK Clock Divided By 6 + * @arg RCC_ADCHCLK_DIV8 ADCHCLKPRE[3:0] = 0100, HCLK Clock Divided By 8 + * @arg RCC_ADCHCLK_DIV10 ADCHCLKPRE[3:0] = 0101, HCLK Clock Divided By 10 + * @arg RCC_ADCHCLK_DIV12 ADCHCLKPRE[3:0] = 0110, HCLK Clock Divided By 12 + * @arg RCC_ADCHCLK_DIV16 ADCHCLKPRE[3:0] = 0111, HCLK Clock Divided By 16 + * @arg RCC_ADCHCLK_DIV32 ADCHCLKPRE[3:0] = 1000, HCLK Clock Divided By 32 + * @arg RCC_ADCHCLK_DIV32 ADCHCLKPRE[3:0] = others, HCLK Clock Divided By 32 + + * @arg RCC_ADCPLLCLK_DISABLE ADCPLLCLKPRES[4:0] = 0xxxx, ADC Pll Clock Disable + * @arg RCC_ADCPLLCLK_DIV1 ADCPLLCLKPRES[4:0] = 10000, Pll Clock Divided By 1 + * @arg RCC_ADCPLLCLK_DIV2 ADCPLLCLKPRES[4:0] = 10001, Pll Clock Divided By 2 + * @arg RCC_ADCPLLCLK_DIV4 ADCPLLCLKPRES[4:0] = 10010, Pll Clock Divided By 4 + * @arg RCC_ADCPLLCLK_DIV6 ADCPLLCLKPRES[4:0] = 10011, Pll Clock Divided By 6 + * @arg RCC_ADCPLLCLK_DIV8 ADCPLLCLKPRES[4:0] = 10100, Pll Clock Divided By 8 + * @arg RCC_ADCPLLCLK_DIV10 ADCPLLCLKPRES[4:0] = 10101, Pll Clock Divided By 10 + * @arg RCC_ADCPLLCLK_DIV12 ADCPLLCLKPRES[4:0] = 10110, Pll Clock Divided By 12 + * @arg RCC_ADCPLLCLK_DIV16 ADCPLLCLKPRES[4:0] = 10111, Pll Clock Divided By 16 + * @arg RCC_ADCPLLCLK_DIV32 ADCPLLCLKPRES[4:0] = 11000, Pll Clock Divided By 32 + * @arg RCC_ADCPLLCLK_DIV64 ADCPLLCLKPRES[4:0] = 11001, Pll Clock Divided By 64 + * @arg RCC_ADCPLLCLK_DIV128 ADCPLLCLKPRES[4:0] = 11010, Pll Clock Divided By 128 + * @arg RCC_ADCPLLCLK_DIV256 ADCPLLCLKPRES[4:0] = 11011, Pll Clock Divided By 256 + * @arg RCC_ADCPLLCLK_DIV256 ADCPLLCLKPRES[4:0] = others, Pll Clock Divided By 256 + */ +void ADC_ConfigClk(ADC_CTRL3_CKMOD ADC_ClkMode, uint32_t RCC_ADCHCLKPrescaler) +{ + if(ADC_ClkMode==ADC_CTRL3_CKMOD_AHB) + { + RCC_ConfigAdcPllClk(RCC_ADCPLLCLK_DIV1, DISABLE); + RCC_ConfigAdcHclk(RCC_ADCHCLKPrescaler); + } + else + { + RCC_ConfigAdcPllClk(RCC_ADCHCLKPrescaler, ENABLE); + RCC_ConfigAdcHclk(RCC_ADCHCLK_DIV1); + } +} +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/src/n32g45x_bkp.c b/src/n32g45x_bkp.c new file mode 100644 index 0000000..5c8a983 --- /dev/null +++ b/src/n32g45x_bkp.c @@ -0,0 +1,252 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_bkp.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_bkp.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup BKP + * @brief BKP driver modules + * @{ + */ + +/** @addtogroup BKP_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup BKP_Private_Defines + * @{ + */ + +/* ------------ BKP registers bit address in the alias region --------------- */ +#define BKP_OFFSET (BKP_BASE - PERIPH_BASE) + +/* --- CTRL Register ----*/ + +/* Alias word address of TP_ALEV bit */ +#define CTRL_OFFSET (BKP_OFFSET + 0x30) +#define TP_ALEV_BIT 0x01 +#define CTRL_TP_ALEV_BB (PERIPH_BB_BASE + (CTRL_OFFSET * 32) + (TP_ALEV_BIT * 4)) + +/* Alias word address of TP_EN bit */ +#define TP_EN_BIT 0x00 +#define CTRL_TP_EN_BB (PERIPH_BB_BASE + (CTRL_OFFSET * 32) + (TP_EN_BIT * 4)) + +/* --- CTRLSTS Register ---*/ + +/* Alias word address of TPINT_EN bit */ +#define CTRLSTS_OFFSET (BKP_OFFSET + 0x34) +#define TPINT_EN_BIT 0x02 +#define CTRLSTS_TPINT_EN_BB (PERIPH_BB_BASE + (CTRLSTS_OFFSET * 32) + (TPINT_EN_BIT * 4)) + +/* Alias word address of TINTF bit */ +#define TINTF_BIT 0x09 +#define CTRLSTS_TINTF_BB (PERIPH_BB_BASE + (CTRLSTS_OFFSET * 32) + (TINTF_BIT * 4)) + +/* Alias word address of TEF bit */ +#define TEF_BIT 0x08 +#define CTRLSTS_TEF_BB (PERIPH_BB_BASE + (CTRLSTS_OFFSET * 32) + (TEF_BIT * 4)) + + +/** + * @} + */ + +/** @addtogroup BKP_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup BKP_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup BKP_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup BKP_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the BKP peripheral registers to their default reset values. + */ +void BKP_DeInit(void) +{ + RCC_EnableBackupReset(ENABLE); + RCC_EnableBackupReset(DISABLE); +} + +/** + * @brief Configures the Tamper Pin active level. + * @param BKP_TamperPinLevel specifies the Tamper Pin active level. + * This parameter can be one of the following values: + * @arg BKP_TP_HIGH Tamper pin active on high level + * @arg BKP_TP_LOW Tamper pin active on low level + */ +void BKP_ConfigTPLevel(uint16_t BKP_TamperPinLevel) +{ + /* Check the parameters */ + assert_param(IS_BKP_TP_LEVEL(BKP_TamperPinLevel)); + *(__IO uint32_t*)CTRL_TP_ALEV_BB = BKP_TamperPinLevel; +} + +/** + * @brief Enables or disables the Tamper Pin activation. + * @param Cmd new state of the Tamper Pin activation. + * This parameter can be: ENABLE or DISABLE. + */ +void BKP_TPEnable(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + *(__IO uint32_t*)CTRL_TP_EN_BB = (uint32_t)Cmd; +} + +/** + * @brief Enables or disables the Tamper Pin Interrupt. + * @param Cmd new state of the Tamper Pin Interrupt. + * This parameter can be: ENABLE or DISABLE. + */ +void BKP_TPIntEnable(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + *(__IO uint32_t*)CTRLSTS_TPINT_EN_BB = (uint32_t)Cmd; +} + + +/** + * @brief Writes user data to the specified Data Backup Register. + * @param BKP_DAT specifies the Data Backup Register. + * This parameter can be BKP_DATx where x:[1, 42] + * @param Data data to write + */ +void BKP_WriteBkpData(uint16_t BKP_DAT, uint16_t Data) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_BKP_DAT(BKP_DAT)); + + tmp = (uint32_t)BKP_BASE; + tmp += BKP_DAT; + + *(__IO uint32_t*)tmp = Data; +} + +/** + * @brief Reads data from the specified Data Backup Register. + * @param BKP_DAT specifies the Data Backup Register. + * This parameter can be BKP_DATx where x:[1, 42] + * @return The content of the specified Data Backup Register + */ +uint16_t BKP_ReadBkpData(uint16_t BKP_DAT) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_BKP_DAT(BKP_DAT)); + + tmp = (uint32_t)BKP_BASE; + tmp += BKP_DAT; + + return (*(__IO uint16_t*)tmp); +} + +/** + * @brief Checks whether the Tamper Pin Event flag is set or not. + * @return The new state of the Tamper Pin Event flag (SET or RESET). + */ +FlagStatus BKP_GetTEFlag(void) +{ + return (FlagStatus)(*(__IO uint32_t*)CTRLSTS_TEF_BB); +} + +/** + * @brief Clears Tamper Pin Event pending flag. + */ +void BKP_ClrTEFlag(void) +{ + /* Set CTE bit to clear Tamper Pin Event flag */ + BKP->CTRLSTS |= BKP_CTRLSTS_CLRTE; +} + +/** + * @brief Checks whether the Tamper Pin Interrupt has occurred or not. + * @return The new state of the Tamper Pin Interrupt (SET or RESET). + */ +INTStatus BKP_GetTINTFlag(void) +{ + return (INTStatus)(*(__IO uint32_t*)CTRLSTS_TINTF_BB); +} + +/** + * @brief Clears Tamper Pin Interrupt pending bit. + */ +void BKP_ClrTINTFlag(void) +{ + /* Set CTI bit to clear Tamper Pin Interrupt pending bit */ + BKP->CTRLSTS |= BKP_CTRLSTS_CLRTINT; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/src/n32g45x_can.c b/src/n32g45x_can.c new file mode 100644 index 0000000..715f693 --- /dev/null +++ b/src/n32g45x_can.c @@ -0,0 +1,1478 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_can.c + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_can.h" +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup CAN + * @brief CAN driver modules + * @{ + */ + +/** @addtogroup CAN_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup CAN_Private_Defines + * @{ + */ + +/* CAN Master Control Register bits */ +#define MCTRL_DBGF ((uint32_t)0x00010000) /* Debug freeze */ +#define MCTRL_MRST ((uint32_t)0x00010000) /* software master reset */ + +/* CAN Mailbox Transmit Request */ +#define TMIDxR_TXRQ ((uint32_t)0x00000001) /* Transmit mailbox request */ + +/* CAN Filter Master Register bits */ +#define FMC_FINITM ((uint32_t)0x00000001) /* Filter init mode */ + +/* Time out for INAK bit */ +#define INIAK_TIMEOUT ((uint32_t)0x0000FFFF) +/* Time out for SLAK bit */ +#define SLPAK_TIMEOUT ((uint32_t)0x0000FFFF) + +/* Flags in TSTS register */ +#define CAN_FLAGS_TSTS ((uint32_t)0x08000000) +/* Flags in RFF1 register */ +#define CAN_FLAGS_RFF1 ((uint32_t)0x04000000) +/* Flags in RFF0 register */ +#define CAN_FLAGS_RFF0 ((uint32_t)0x02000000) +/* Flags in MSTS register */ +#define CAN_FLAGS_MSTS ((uint32_t)0x01000000) +/* Flags in ESTS register */ +#define CAN_FLAGS_ESTS ((uint32_t)0x00F00000) + +/* Mailboxes definition */ +#define CAN_TXMAILBOX_0 ((uint8_t)0x00) +#define CAN_TXMAILBOX_1 ((uint8_t)0x01) +#define CAN_TXMAILBOX_2 ((uint8_t)0x02) + +#define CAN_MODE_MASK ((uint32_t)0x00000003) +/** + * @} + */ + +/** @addtogroup CAN_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup CAN_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup CAN_Private_FunctionPrototypes + * @{ + */ + +static INTStatus CheckINTStatus(uint32_t CAN_Reg, uint32_t Int_Bit); + +/** + * @} + */ + +/** @addtogroup CAN_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the CAN peripheral registers to their default reset values. + * @param CANx where x can be 1 or 2 to select the CAN peripheral. + */ +void CAN_DeInit(CAN_Module* CANx) +{ + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + + if (CANx == CAN1) + { + /* Enable CAN1 reset state */ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_CAN1, ENABLE); + /* Release CAN1 from reset state */ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_CAN1, DISABLE); + } + else + { + /* Enable CAN2 reset state */ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_CAN2, ENABLE); + /* Release CAN2 from reset state */ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_CAN2, DISABLE); + } +} + +/** + * @brief Initializes the CAN peripheral according to the specified + * parameters in the CAN_InitParam. + * @param CANx where x can be 1 or 2 to to select the CAN + * peripheral. + * @param CAN_InitParam pointer to a CAN_InitType structure that + * contains the configuration information for the + * CAN peripheral. + * @return Constant indicates initialization succeed which will be + * CAN_InitSTS_Failed or CAN_InitSTS_Success. + */ +uint8_t CAN_Init(CAN_Module* CANx, CAN_InitType* CAN_InitParam) +{ + uint8_t InitStatus = CAN_InitSTS_Failed; + uint32_t wait_ack = 0x00000000; + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_FUNCTIONAL_STATE(CAN_InitParam->TTCM)); + assert_param(IS_FUNCTIONAL_STATE(CAN_InitParam->ABOM)); + assert_param(IS_FUNCTIONAL_STATE(CAN_InitParam->AWKUM)); + assert_param(IS_FUNCTIONAL_STATE(CAN_InitParam->NART)); + assert_param(IS_FUNCTIONAL_STATE(CAN_InitParam->RFLM)); + assert_param(IS_FUNCTIONAL_STATE(CAN_InitParam->TXFP)); + assert_param(IS_CAN_MODE(CAN_InitParam->OperatingMode)); + assert_param(IS_CAN_RSJW(CAN_InitParam->RSJW)); + assert_param(IS_CAN_TBS1(CAN_InitParam->TBS1)); + assert_param(IS_CAN_TBS2(CAN_InitParam->TBS2)); + assert_param(IS_CAN_BAUDRATEPRESCALER(CAN_InitParam->BaudRatePrescaler)); + + /* Exit from sleep mode */ + CANx->MCTRL &= (~(uint32_t)CAN_MCTRL_SLPRQ); + + /* Request initialisation */ + CANx->MCTRL |= CAN_MCTRL_INIRQ; + + /* Wait the acknowledge */ + while (((CANx->MSTS & CAN_MSTS_INIAK) != CAN_MSTS_INIAK) && (wait_ack != INIAK_TIMEOUT)) + { + wait_ack++; + } + + /* Check acknowledge */ + if ((CANx->MSTS & CAN_MSTS_INIAK) != CAN_MSTS_INIAK) + { + InitStatus = CAN_InitSTS_Failed; + } + else + { + /* Set the time triggered communication mode */ + if (CAN_InitParam->TTCM == ENABLE) + { + CANx->MCTRL |= CAN_MCTRL_TTCM; + } + else + { + CANx->MCTRL &= ~(uint32_t)CAN_MCTRL_TTCM; + } + + /* Set the automatic bus-off management */ + if (CAN_InitParam->ABOM == ENABLE) + { + CANx->MCTRL |= CAN_MCTRL_ABOM; + } + else + { + CANx->MCTRL &= ~(uint32_t)CAN_MCTRL_ABOM; + } + + /* Set the automatic wake-up mode */ + if (CAN_InitParam->AWKUM == ENABLE) + { + CANx->MCTRL |= CAN_MCTRL_AWKUM; + } + else + { + CANx->MCTRL &= ~(uint32_t)CAN_MCTRL_AWKUM; + } + + /* Set the no automatic retransmission */ + if (CAN_InitParam->NART == ENABLE) + { + CANx->MCTRL |= CAN_MCTRL_NART; + } + else + { + CANx->MCTRL &= ~(uint32_t)CAN_MCTRL_NART; + } + + /* Set the receive DATFIFO locked mode */ + if (CAN_InitParam->RFLM == ENABLE) + { + CANx->MCTRL |= CAN_MCTRL_RFLM; + } + else + { + CANx->MCTRL &= ~(uint32_t)CAN_MCTRL_RFLM; + } + + /* Set the transmit DATFIFO priority */ + if (CAN_InitParam->TXFP == ENABLE) + { + CANx->MCTRL |= CAN_MCTRL_TXFP; + } + else + { + CANx->MCTRL &= ~(uint32_t)CAN_MCTRL_TXFP; + } + + /* Set the bit timing register */ + CANx->BTIM = (uint32_t)((uint32_t)CAN_InitParam->OperatingMode << 30) | ((uint32_t)CAN_InitParam->RSJW << 24) + | ((uint32_t)CAN_InitParam->TBS1 << 16) | ((uint32_t)CAN_InitParam->TBS2 << 20) + | ((uint32_t)CAN_InitParam->BaudRatePrescaler - 1); + + /* Request leave initialisation */ + CANx->MCTRL &= ~(uint32_t)CAN_MCTRL_INIRQ; + + /* Wait the acknowledge */ + wait_ack = 0; + + while (((CANx->MSTS & CAN_MSTS_INIAK) == CAN_MSTS_INIAK) && (wait_ack != INIAK_TIMEOUT)) + { + wait_ack++; + } + + /* ...and check acknowledged */ + if ((CANx->MSTS & CAN_MSTS_INIAK) == CAN_MSTS_INIAK) + { + InitStatus = CAN_InitSTS_Failed; + } + else + { + InitStatus = CAN_InitSTS_Success; + } + } + + /* At this step, return the status of initialization */ + return InitStatus; +} + +/** + * @brief Initializes the CAN1 peripheral according to the specified + * parameters in the CAN_InitFilterStruct. + * @param CAN_InitFilterStruct pointer to a CAN_FilterInitType + * structure that contains the configuration + * information. + */ +void CAN1_InitFilter(CAN_FilterInitType* CAN_InitFilterStruct) +{ + uint32_t filter_number_bit_pos = 0; + /* Check the parameters */ + assert_param(IS_CAN_FILTER_NUM(CAN_InitFilterStruct->Filter_Num)); + assert_param(IS_CAN_FILTER_MODE(CAN_InitFilterStruct->Filter_Mode)); + assert_param(IS_CAN_FILTER_SCALE(CAN_InitFilterStruct->Filter_Scale)); + assert_param(IS_CAN_FILTER_FIFO(CAN_InitFilterStruct->Filter_FIFOAssignment)); + assert_param(IS_FUNCTIONAL_STATE(CAN_InitFilterStruct->Filter_Act)); + + filter_number_bit_pos = ((uint32_t)1) << CAN_InitFilterStruct->Filter_Num; + + /* Initialisation mode for the filter */ + CAN1->FMC |= FMC_FINITM; + + /* Filter Deactivation */ + CAN1->FA1 &= ~(uint32_t)filter_number_bit_pos; + + /* Filter Scale */ + if (CAN_InitFilterStruct->Filter_Scale == CAN_Filter_16bitScale) + { + /* 16-bit scale for the filter */ + CAN1->FS1 &= ~(uint32_t)filter_number_bit_pos; + + /* First 16-bit identifier and First 16-bit mask */ + /* Or First 16-bit identifier and Second 16-bit identifier */ + CAN1->sFilterRegister[CAN_InitFilterStruct->Filter_Num].FR1 = + ((0x0000FFFF & (uint32_t)CAN_InitFilterStruct->FilterMask_LowId) << 16) + | (0x0000FFFF & (uint32_t)CAN_InitFilterStruct->Filter_LowId); + + /* Second 16-bit identifier and Second 16-bit mask */ + /* Or Third 16-bit identifier and Fourth 16-bit identifier */ + CAN1->sFilterRegister[CAN_InitFilterStruct->Filter_Num].FR2 = + ((0x0000FFFF & (uint32_t)CAN_InitFilterStruct->FilterMask_HighId) << 16) + | (0x0000FFFF & (uint32_t)CAN_InitFilterStruct->Filter_HighId); + } + + if (CAN_InitFilterStruct->Filter_Scale == CAN_Filter_32bitScale) + { + /* 32-bit scale for the filter */ + CAN1->FS1 |= filter_number_bit_pos; + /* 32-bit identifier or First 32-bit identifier */ + CAN1->sFilterRegister[CAN_InitFilterStruct->Filter_Num].FR1 = + ((0x0000FFFF & (uint32_t)CAN_InitFilterStruct->Filter_HighId) << 16) + | (0x0000FFFF & (uint32_t)CAN_InitFilterStruct->Filter_LowId); + /* 32-bit mask or Second 32-bit identifier */ + CAN1->sFilterRegister[CAN_InitFilterStruct->Filter_Num].FR2 = + ((0x0000FFFF & (uint32_t)CAN_InitFilterStruct->FilterMask_HighId) << 16) + | (0x0000FFFF & (uint32_t)CAN_InitFilterStruct->FilterMask_LowId); + } + + /* Filter Mode */ + if (CAN_InitFilterStruct->Filter_Mode == CAN_Filter_IdMaskMode) + { + /*Id/Mask mode for the filter*/ + CAN1->FM1 &= ~(uint32_t)filter_number_bit_pos; + } + else /* CAN_InitFilterStruct->Filter_Mode == CAN_Filter_IdListMode */ + { + /*Identifier list mode for the filter*/ + CAN1->FM1 |= (uint32_t)filter_number_bit_pos; + } + + /* Filter DATFIFO assignment */ + if (CAN_InitFilterStruct->Filter_FIFOAssignment == CAN_Filter_FIFO0) + { + /* DATFIFO 0 assignation for the filter */ + CAN1->FFA1 &= ~(uint32_t)filter_number_bit_pos; + } + + if (CAN_InitFilterStruct->Filter_FIFOAssignment == CAN_Filter_FIFO1) + { + /* DATFIFO 1 assignation for the filter */ + CAN1->FFA1 |= (uint32_t)filter_number_bit_pos; + } + + /* Filter activation */ + if (CAN_InitFilterStruct->Filter_Act == ENABLE) + { + CAN1->FA1 |= filter_number_bit_pos; + } + + /* Leave the initialisation mode for the filter */ + CAN1->FMC &= ~FMC_FINITM; +} + +/** + * @brief Initializes the CAN2 peripheral according to the specified + * parameters in the CAN_InitFilterStruct. + * @param CAN_InitFilterStruct pointer to a CAN_FilterInitType + * structure that contains the configuration + * information. + */ +void CAN2_InitFilter(CAN_FilterInitType* CAN_InitFilterStruct) +{ + uint32_t filter_number_bit_pos = 0; + /* Check the parameters */ + assert_param(IS_CAN_FILTER_NUM(CAN_InitFilterStruct->Filter_Num)); + assert_param(IS_CAN_FILTER_MODE(CAN_InitFilterStruct->Filter_Mode)); + assert_param(IS_CAN_FILTER_SCALE(CAN_InitFilterStruct->Filter_Scale)); + assert_param(IS_CAN_FILTER_FIFO(CAN_InitFilterStruct->Filter_FIFOAssignment)); + assert_param(IS_FUNCTIONAL_STATE(CAN_InitFilterStruct->Filter_Act)); + + filter_number_bit_pos = ((uint32_t)1) << CAN_InitFilterStruct->Filter_Num; + + /* Initialisation mode for the filter */ + CAN2->FMC |= FMC_FINITM; + + /* Filter Deactivation */ + CAN2->FA1 &= ~(uint32_t)filter_number_bit_pos; + + /* Filter Scale */ + if (CAN_InitFilterStruct->Filter_Scale == CAN_Filter_16bitScale) + { + /* 16-bit scale for the filter */ + CAN2->FS1 &= ~(uint32_t)filter_number_bit_pos; + + /* First 16-bit identifier and First 16-bit mask */ + /* Or First 16-bit identifier and Second 16-bit identifier */ + CAN2->sFilterRegister[CAN_InitFilterStruct->Filter_Num].FR1 = + ((0x0000FFFF & (uint32_t)CAN_InitFilterStruct->FilterMask_LowId) << 16) + | (0x0000FFFF & (uint32_t)CAN_InitFilterStruct->Filter_LowId); + + /* Second 16-bit identifier and Second 16-bit mask */ + /* Or Third 16-bit identifier and Fourth 16-bit identifier */ + CAN2->sFilterRegister[CAN_InitFilterStruct->Filter_Num].FR2 = + ((0x0000FFFF & (uint32_t)CAN_InitFilterStruct->FilterMask_HighId) << 16) + | (0x0000FFFF & (uint32_t)CAN_InitFilterStruct->Filter_HighId); + } + + if (CAN_InitFilterStruct->Filter_Scale == CAN_Filter_32bitScale) + { + /* 32-bit scale for the filter */ + CAN2->FS1 |= filter_number_bit_pos; + /* 32-bit identifier or First 32-bit identifier */ + CAN2->sFilterRegister[CAN_InitFilterStruct->Filter_Num].FR1 = + ((0x0000FFFF & (uint32_t)CAN_InitFilterStruct->Filter_HighId) << 16) + | (0x0000FFFF & (uint32_t)CAN_InitFilterStruct->Filter_LowId); + /* 32-bit mask or Second 32-bit identifier */ + CAN2->sFilterRegister[CAN_InitFilterStruct->Filter_Num].FR2 = + ((0x0000FFFF & (uint32_t)CAN_InitFilterStruct->FilterMask_HighId) << 16) + | (0x0000FFFF & (uint32_t)CAN_InitFilterStruct->FilterMask_LowId); + } + + /* Filter Mode */ + if (CAN_InitFilterStruct->Filter_Mode == CAN_Filter_IdMaskMode) + { + /*Id/Mask mode for the filter*/ + CAN2->FM1 &= ~(uint32_t)filter_number_bit_pos; + } + else /* CAN_InitFilterStruct->Filter_Mode == CAN_Filter_IdListMode */ + { + /*Identifier list mode for the filter*/ + CAN2->FM1 |= (uint32_t)filter_number_bit_pos; + } + + /* Filter DATFIFO assignment */ + if (CAN_InitFilterStruct->Filter_FIFOAssignment == CAN_Filter_FIFO0) + { + /* DATFIFO 0 assignation for the filter */ + CAN2->FFA1 &= ~(uint32_t)filter_number_bit_pos; + } + + if (CAN_InitFilterStruct->Filter_FIFOAssignment == CAN_Filter_FIFO1) + { + /* DATFIFO 1 assignation for the filter */ + CAN2->FFA1 |= (uint32_t)filter_number_bit_pos; + } + + /* Filter activation */ + if (CAN_InitFilterStruct->Filter_Act == ENABLE) + { + CAN2->FA1 |= filter_number_bit_pos; + } + + /* Leave the initialisation mode for the filter */ + CAN2->FMC &= ~FMC_FINITM; +} + +/** + * @brief Fills each CAN_InitParam member with its default value. + * @param CAN_InitParam pointer to a CAN_InitType structure which + * will be initialized. + */ +void CAN_InitStruct(CAN_InitType* CAN_InitParam) +{ + /* Reset CAN init structure parameters values */ + + /* Initialize the time triggered communication mode */ + CAN_InitParam->TTCM = DISABLE; + + /* Initialize the automatic bus-off management */ + CAN_InitParam->ABOM = DISABLE; + + /* Initialize the automatic wake-up mode */ + CAN_InitParam->AWKUM = DISABLE; + + /* Initialize the no automatic retransmission */ + CAN_InitParam->NART = DISABLE; + + /* Initialize the receive DATFIFO locked mode */ + CAN_InitParam->RFLM = DISABLE; + + /* Initialize the transmit DATFIFO priority */ + CAN_InitParam->TXFP = DISABLE; + + /* Initialize the OperatingMode member */ + CAN_InitParam->OperatingMode = CAN_Normal_Mode; + + /* Initialize the RSJW member */ + CAN_InitParam->RSJW = CAN_RSJW_1tq; + + /* Initialize the TBS1 member */ + CAN_InitParam->TBS1 = CAN_TBS1_4tq; + + /* Initialize the TBS2 member */ + CAN_InitParam->TBS2 = CAN_TBS2_3tq; + + /* Initialize the BaudRatePrescaler member */ + CAN_InitParam->BaudRatePrescaler = 1; +} + +/** + * @brief Enables or disables the DBG Freeze for CAN. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @param Cmd new state of the CAN peripheral. This parameter can + * be: ENABLE or DISABLE. + */ +void CAN_DebugFreeze(CAN_Module* CANx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable Debug Freeze */ + CANx->MCTRL |= MCTRL_DBGF; + } + else + { + /* Disable Debug Freeze */ + CANx->MCTRL &= ~MCTRL_DBGF; + } +} + +/** + * @brief Enables or disabes the CAN Time TriggerOperation communication mode. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @param Cmd Mode new state , can be one of @ref FunctionalState. + * @note when enabled, Time stamp (TIME[15:0]) value is sent in the last + * two data bytes of the 8-byte message: TIME[7:0] in data byte 6 + * and TIME[15:8] in data byte 7 + * @note DLC must be programmed as 8 in order Time Stamp (2 bytes) to be + * sent over the CAN bus. + */ +void CAN_EnTTComMode(CAN_Module* CANx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the TTCM mode */ + CANx->MCTRL |= CAN_MCTRL_TTCM; + + /* Set TGT bits */ + CANx->sTxMailBox[0].TMDT |= ((uint32_t)CAN_TMDT0_TGT); + CANx->sTxMailBox[1].TMDT |= ((uint32_t)CAN_TMDT1_TGT); + CANx->sTxMailBox[2].TMDT |= ((uint32_t)CAN_TMDT2_TGT); + } + else + { + /* Disable the TTCM mode */ + CANx->MCTRL &= (uint32_t)(~(uint32_t)CAN_MCTRL_TTCM); + + /* Reset TGT bits */ + CANx->sTxMailBox[0].TMDT &= ((uint32_t)~CAN_TMDT0_TGT); + CANx->sTxMailBox[1].TMDT &= ((uint32_t)~CAN_TMDT1_TGT); + CANx->sTxMailBox[2].TMDT &= ((uint32_t)~CAN_TMDT2_TGT); + } +} +/** + * @brief Initiates the transmission of a message. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @param TxMessage pointer to a structure which contains CAN Id, CAN + * DLC and CAN data. + * @return The number of the mailbox that is used for transmission + * or CAN_TxSTS_NoMailBox if there is no empty mailbox. + */ +uint8_t CAN_TransmitMessage(CAN_Module* CANx, CanTxMessage* TxMessage) +{ + uint8_t transmit_mailbox = 0; + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_ID(TxMessage->IDE)); + assert_param(IS_CAN_RTRQ(TxMessage->RTR)); + assert_param(IS_CAN_DLC(TxMessage->DLC)); + + /* Select one empty transmit mailbox */ + if ((CANx->TSTS & CAN_TSTS_TMEM0) == CAN_TSTS_TMEM0) + { + transmit_mailbox = 0; + } + else if ((CANx->TSTS & CAN_TSTS_TMEM1) == CAN_TSTS_TMEM1) + { + transmit_mailbox = 1; + } + else if ((CANx->TSTS & CAN_TSTS_TMEM2) == CAN_TSTS_TMEM2) + { + transmit_mailbox = 2; + } + else + { + transmit_mailbox = CAN_TxSTS_NoMailBox; + } + + if (transmit_mailbox != CAN_TxSTS_NoMailBox) + { + /* Set up the Id */ + CANx->sTxMailBox[transmit_mailbox].TMI &= TMIDxR_TXRQ; + if (TxMessage->IDE == CAN_Standard_Id) + { + assert_param(IS_CAN_STDID(TxMessage->StdId)); + CANx->sTxMailBox[transmit_mailbox].TMI |= ((TxMessage->StdId << 21) | TxMessage->RTR); + } + else + { + assert_param(IS_CAN_EXTID(TxMessage->ExtId)); + CANx->sTxMailBox[transmit_mailbox].TMI |= ((TxMessage->ExtId << 3) | TxMessage->IDE | TxMessage->RTR); + } + + /* Set up the DLC */ + TxMessage->DLC &= (uint8_t)0x0000000F; + CANx->sTxMailBox[transmit_mailbox].TMDT &= (uint32_t)0xFFFFFFF0; + CANx->sTxMailBox[transmit_mailbox].TMDT |= TxMessage->DLC; + + /* Set up the data field */ + CANx->sTxMailBox[transmit_mailbox].TMDL = + (((uint32_t)TxMessage->Data[3] << 24) | ((uint32_t)TxMessage->Data[2] << 16) + | ((uint32_t)TxMessage->Data[1] << 8) | ((uint32_t)TxMessage->Data[0])); + CANx->sTxMailBox[transmit_mailbox].TMDH = + (((uint32_t)TxMessage->Data[7] << 24) | ((uint32_t)TxMessage->Data[6] << 16) + | ((uint32_t)TxMessage->Data[5] << 8) | ((uint32_t)TxMessage->Data[4])); + /* Request transmission */ + CANx->sTxMailBox[transmit_mailbox].TMI |= TMIDxR_TXRQ; + } + return transmit_mailbox; +} + +/** + * @brief Checks the transmission of a message. + * @param CANx where x can be 1 or 2 to to select the + * CAN peripheral. + * @param TransmitMailbox the number of the mailbox that is used for + * transmission. + * @return CAN_TxSTS_Ok if the CAN driver transmits the message, CAN_TxSTS_Failed + * in an other case. + */ +uint8_t CAN_TransmitSTS(CAN_Module* CANx, uint8_t TransmitMailbox) +{ + uint32_t state = 0; + + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_TRANSMITMAILBOX(TransmitMailbox)); + + switch (TransmitMailbox) + { + case (CAN_TXMAILBOX_0): + state = CANx->TSTS & (CAN_TSTS_RQCPM0 | CAN_TSTS_TXOKM0 | CAN_TSTS_TMEM0); + break; + case (CAN_TXMAILBOX_1): + state = CANx->TSTS & (CAN_TSTS_RQCPM1 | CAN_TSTS_TXOKM1 | CAN_TSTS_TMEM1); + break; + case (CAN_TXMAILBOX_2): + state = CANx->TSTS & (CAN_TSTS_RQCPM2 | CAN_TSTS_TXOKM2 | CAN_TSTS_TMEM2); + break; + default: + state = CAN_TxSTS_Failed; + break; + } + switch (state) + { + /* transmit pending */ + case (0x0): + state = CAN_TxSTS_Pending; + break; + /* transmit failed */ + case (CAN_TSTS_RQCPM0 | CAN_TSTS_TMEM0): + state = CAN_TxSTS_Failed; + break; + case (CAN_TSTS_RQCPM1 | CAN_TSTS_TMEM1): + state = CAN_TxSTS_Failed; + break; + case (CAN_TSTS_RQCPM2 | CAN_TSTS_TMEM2): + state = CAN_TxSTS_Failed; + break; + /* transmit succeeded */ + case (CAN_TSTS_RQCPM0 | CAN_TSTS_TXOKM0 | CAN_TSTS_TMEM0): + state = CAN_TxSTS_Ok; + break; + case (CAN_TSTS_RQCPM1 | CAN_TSTS_TXOKM1 | CAN_TSTS_TMEM1): + state = CAN_TxSTS_Ok; + break; + case (CAN_TSTS_RQCPM2 | CAN_TSTS_TXOKM2 | CAN_TSTS_TMEM2): + state = CAN_TxSTS_Ok; + break; + default: + state = CAN_TxSTS_Failed; + break; + } + return (uint8_t)state; +} + +/** + * @brief Cancels a transmit request. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @param Mailbox Mailbox number. + */ +void CAN_CancelTransmitMessage(CAN_Module* CANx, uint8_t Mailbox) +{ + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_TRANSMITMAILBOX(Mailbox)); + /* abort transmission */ + switch (Mailbox) + { + case (CAN_TXMAILBOX_0): + CANx->TSTS |= CAN_TSTS_ABRQM0; + break; + case (CAN_TXMAILBOX_1): + CANx->TSTS |= CAN_TSTS_ABRQM1; + break; + case (CAN_TXMAILBOX_2): + CANx->TSTS |= CAN_TSTS_ABRQM2; + break; + default: + break; + } +} + +/** + * @brief Receives a message. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @param FIFONum Receive DATFIFO number, CAN_FIFO0 or CAN_FIFO1. + * @param RxMessage pointer to a structure receive message which contains + * CAN Id, CAN DLC, CAN datas and FMI number. + */ +void CAN_ReceiveMessage(CAN_Module* CANx, uint8_t FIFONum, CanRxMessage* RxMessage) +{ + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_FIFO(FIFONum)); + /* Get the Id */ + RxMessage->IDE = (uint8_t)0x04 & CANx->sFIFOMailBox[FIFONum].RMI; + if (RxMessage->IDE == CAN_Standard_Id) + { + RxMessage->StdId = (uint32_t)0x000007FF & (CANx->sFIFOMailBox[FIFONum].RMI >> 21); + } + else + { + RxMessage->ExtId = (uint32_t)0x1FFFFFFF & (CANx->sFIFOMailBox[FIFONum].RMI >> 3); + } + + RxMessage->RTR = (uint8_t)0x02 & CANx->sFIFOMailBox[FIFONum].RMI; + /* Get the DLC */ + RxMessage->DLC = (uint8_t)0x0F & CANx->sFIFOMailBox[FIFONum].RMDT; + /* Get the FMI */ + RxMessage->FMI = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONum].RMDT >> 8); + /* Get the data field */ + RxMessage->Data[0] = (uint8_t)0xFF & CANx->sFIFOMailBox[FIFONum].RMDL; + RxMessage->Data[1] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONum].RMDL >> 8); + RxMessage->Data[2] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONum].RMDL >> 16); + RxMessage->Data[3] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONum].RMDL >> 24); + RxMessage->Data[4] = (uint8_t)0xFF & CANx->sFIFOMailBox[FIFONum].RMDH; + RxMessage->Data[5] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONum].RMDH >> 8); + RxMessage->Data[6] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONum].RMDH >> 16); + RxMessage->Data[7] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONum].RMDH >> 24); + /* Release the DATFIFO */ + /* Release FIFO0 */ + if (FIFONum == CAN_FIFO0) + { + CANx->RFF0 |= CAN_RFF0_RFFOM0; + } + /* Release FIFO1 */ + else /* FIFONum == CAN_FIFO1 */ + { + CANx->RFF1 |= CAN_RFF1_RFFOM1; + } +} + +/** + * @brief Releases the specified DATFIFO. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @param FIFONum DATFIFO to release, CAN_FIFO0 or CAN_FIFO1. + */ +void CAN_ReleaseFIFO(CAN_Module* CANx, uint8_t FIFONum) +{ + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_FIFO(FIFONum)); + /* Release FIFO0 */ + if (FIFONum == CAN_FIFO0) + { + CANx->RFF0 |= CAN_RFF0_RFFOM0; + } + /* Release FIFO1 */ + else /* FIFONum == CAN_FIFO1 */ + { + CANx->RFF1 |= CAN_RFF1_RFFOM1; + } +} + +/** + * @brief Returns the number of pending messages. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @param FIFONum Receive DATFIFO number, CAN_FIFO0 or CAN_FIFO1. + * @return NbMessage : which is the number of pending message. + */ +uint8_t CAN_PendingMessage(CAN_Module* CANx, uint8_t FIFONum) +{ + uint8_t message_pending = 0; + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_FIFO(FIFONum)); + if (FIFONum == CAN_FIFO0) + { + message_pending = (uint8_t)(CANx->RFF0 & (uint32_t)0x03); + } + else if (FIFONum == CAN_FIFO1) + { + message_pending = (uint8_t)(CANx->RFF1 & (uint32_t)0x03); + } + else + { + message_pending = 0; + } + return message_pending; +} + +/** + * @brief Select the CAN Operation mode. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @param CAN_OperatingMode CAN Operating Mode. This parameter can be one + * of @ref CAN_operating_mode enumeration. + * @return status of the requested mode which can be + * - CAN_ModeSTS_Failed CAN failed entering the specific mode + * - CAN_ModeSTS_Success CAN Succeed entering the specific mode + + */ +uint8_t CAN_OperatingModeReq(CAN_Module* CANx, uint8_t CAN_OperatingMode) +{ + uint8_t status = CAN_ModeSTS_Failed; + + /* Timeout for INAK or also for SLAK bits*/ + uint32_t timeout = INIAK_TIMEOUT; + + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_OPERATING_MODE(CAN_OperatingMode)); + + if (CAN_OperatingMode == CAN_Operating_InitMode) + { + /* Request initialisation */ + CANx->MCTRL = (uint32_t)((CANx->MCTRL & (uint32_t)(~(uint32_t)CAN_MCTRL_SLPRQ)) | CAN_MCTRL_INIRQ); + + /* Wait the acknowledge */ + while (((CANx->MSTS & CAN_MODE_MASK) != CAN_MSTS_INIAK) && (timeout != 0)) + { + timeout--; + } + if ((CANx->MSTS & CAN_MODE_MASK) != CAN_MSTS_INIAK) + { + status = CAN_ModeSTS_Failed; + } + else + { + status = CAN_ModeSTS_Success; + } + } + else if (CAN_OperatingMode == CAN_Operating_NormalMode) + { + /* Request leave initialisation and sleep mode and enter Normal mode */ + CANx->MCTRL &= (uint32_t)(~(CAN_MCTRL_SLPRQ | CAN_MCTRL_INIRQ)); + + /* Wait the acknowledge */ + while (((CANx->MSTS & CAN_MODE_MASK) != 0) && (timeout != 0)) + { + timeout--; + } + if ((CANx->MSTS & CAN_MODE_MASK) != 0) + { + status = CAN_ModeSTS_Failed; + } + else + { + status = CAN_ModeSTS_Success; + } + } + else if (CAN_OperatingMode == CAN_Operating_SleepMode) + { + /* Request Sleep mode */ + CANx->MCTRL = (uint32_t)((CANx->MCTRL & (uint32_t)(~(uint32_t)CAN_MCTRL_INIRQ)) | CAN_MCTRL_SLPRQ); + + /* Wait the acknowledge */ + while (((CANx->MSTS & CAN_MODE_MASK) != CAN_MSTS_SLPAK) && (timeout != 0)) + { + timeout--; + } + if ((CANx->MSTS & CAN_MODE_MASK) != CAN_MSTS_SLPAK) + { + status = CAN_ModeSTS_Failed; + } + else + { + status = CAN_ModeSTS_Success; + } + } + else + { + status = CAN_ModeSTS_Failed; + } + + return (uint8_t)status; +} + +/** + * @brief Enters the low power mode. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @return status: CAN_SLEEP_Ok if sleep entered, CAN_SLEEP_Failed in an + * other case. + */ +uint8_t CAN_EnterSleep(CAN_Module* CANx) +{ + uint8_t sleepstatus = CAN_SLEEP_Failed; + + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + + /* Request Sleep mode */ + CANx->MCTRL = (((CANx->MCTRL) & (uint32_t)(~(uint32_t)CAN_MCTRL_INIRQ)) | CAN_MCTRL_SLPRQ); + + /* Sleep mode status */ + if ((CANx->MSTS & (CAN_MSTS_SLPAK | CAN_MSTS_INIAK)) == CAN_MSTS_SLPAK) + { + /* Sleep mode not entered */ + sleepstatus = CAN_SLEEP_Ok; + } + /* return sleep mode status */ + return (uint8_t)sleepstatus; +} + +/** + * @brief Wakes the CAN up. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @return status: CAN_WKU_Ok if sleep mode left, CAN_WKU_Failed in an + * other case. + */ +uint8_t CAN_WakeUp(CAN_Module* CANx) +{ + uint32_t wait_slak = SLPAK_TIMEOUT; + uint8_t wakeupstatus = CAN_WKU_Failed; + + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + + /* Wake up request */ + CANx->MCTRL &= ~(uint32_t)CAN_MCTRL_SLPRQ; + + /* Sleep mode status */ + while (((CANx->MSTS & CAN_MSTS_SLPAK) == CAN_MSTS_SLPAK) && (wait_slak != 0x00)) + { + wait_slak--; + } + if ((CANx->MSTS & CAN_MSTS_SLPAK) != CAN_MSTS_SLPAK) + { + /* wake up done : Sleep mode exited */ + wakeupstatus = CAN_WKU_Ok; + } + /* return wakeup status */ + return (uint8_t)wakeupstatus; +} + +/** + * @brief Returns the CANx's last error code (LEC). + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @return CAN_ErrorCode: specifies the Error code : + * - CAN_ERRORCODE_NoErr No Error + * - CAN_ERRORCODE_StuffErr Stuff Error + * - CAN_ERRORCODE_FormErr Form Error + * - CAN_ERRORCODE_ACKErr Acknowledgment Error + * - CAN_ERRORCODE_BitRecessiveErr Bit Recessive Error + * - CAN_ERRORCODE_BitDominantErr Bit Dominant Error + * - CAN_ERRORCODE_CRCErr CRC Error + * - CAN_ERRORCODE_SoftwareSetErr Software Set Error + */ + +uint8_t CAN_GetLastErrCode(CAN_Module* CANx) +{ + uint8_t errorcode = 0; + + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + + /* Get the error code*/ + errorcode = (((uint8_t)CANx->ESTS) & (uint8_t)CAN_ESTS_LEC); + + /* Return the error code*/ + return errorcode; +} +/** + * @brief Returns the CANx Receive Error Counter (REC). + * @note In case of an error during reception, this counter is incremented + * by 1 or by 8 depending on the error condition as defined by the CAN + * standard. After every successful reception, the counter is + * decremented by 1 or reset to 120 if its value was higher than 128. + * When the counter value exceeds 127, the CAN controller enters the + * error passive state. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @return CAN Receive Error Counter. + */ +uint8_t CAN_GetReceiveErrCounter(CAN_Module* CANx) +{ + uint8_t counter = 0; + + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + + /* Get the Receive Error Counter*/ + counter = (uint8_t)((CANx->ESTS & CAN_ESTS_RXEC) >> 24); + + /* Return the Receive Error Counter*/ + return counter; +} + +/** + * @brief Returns the LSB of the 9-bit CANx Transmit Error Counter(TEC). + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @return LSB of the 9-bit CAN Transmit Error Counter. + */ +uint8_t CAN_GetLSBTransmitErrCounter(CAN_Module* CANx) +{ + uint8_t counter = 0; + + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + + /* Get the LSB of the 9-bit CANx Transmit Error Counter(TEC) */ + counter = (uint8_t)((CANx->ESTS & CAN_ESTS_TXEC) >> 16); + + /* Return the LSB of the 9-bit CANx Transmit Error Counter(TEC) */ + return counter; +} + +/** + * @brief Enables or disables the specified CANx interrupts. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @param CAN_INT specifies the CAN interrupt sources to be enabled or disabled. + * This parameter can be: + * - CAN_INT_TME, + * - CAN_INT_FMP0, + * - CAN_INT_FF0, + * - CAN_INT_FOV0, + * - CAN_INT_FMP1, + * - CAN_INT_FF1, + * - CAN_INT_FOV1, + * - CAN_INT_EWG, + * - CAN_INT_EPV, + * - CAN_INT_LEC, + * - CAN_INT_ERR, + * - CAN_INT_WKU or + * - CAN_INT_SLK. + * @param Cmd new state of the CAN interrupts. + * This parameter can be: ENABLE or DISABLE. + */ +void CAN_INTConfig(CAN_Module* CANx, uint32_t CAN_INT, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_INT(CAN_INT)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the selected CANx interrupt */ + CANx->INTE |= CAN_INT; + } + else + { + /* Disable the selected CANx interrupt */ + CANx->INTE &= ~CAN_INT; + } +} +/** + * @brief Checks whether the specified CAN flag is set or not. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @param CAN_FLAG specifies the flag to check. + * This parameter can be one of the following flags: + * - CAN_FLAG_EWGFL + * - CAN_FLAG_EPVFL + * - CAN_FLAG_BOFFL + * - CAN_FLAG_RQCPM0 + * - CAN_FLAG_RQCPM1 + * - CAN_FLAG_RQCPM2 + * - CAN_FLAG_FFMP1 + * - CAN_FLAG_FFULL1 + * - CAN_FLAG_FFOVR1 + * - CAN_FLAG_FFMP0 + * - CAN_FLAG_FFULL0 + * - CAN_FLAG_FFOVR0 + * - CAN_FLAG_WKU + * - CAN_FLAG_SLAK + * - CAN_FLAG_LEC + * @return The new state of CAN_FLAG (SET or RESET). + */ +FlagStatus CAN_GetFlagSTS(CAN_Module* CANx, uint32_t CAN_FLAG) +{ + FlagStatus bitstatus = RESET; + + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_GET_FLAG(CAN_FLAG)); + + if ((CAN_FLAG & CAN_FLAGS_ESTS) != (uint32_t)RESET) + { + /* Check the status of the specified CAN flag */ + if ((CANx->ESTS & (CAN_FLAG & 0x000FFFFF)) != (uint32_t)RESET) + { + /* CAN_FLAG is set */ + bitstatus = SET; + } + else + { + /* CAN_FLAG is reset */ + bitstatus = RESET; + } + } + else if ((CAN_FLAG & CAN_FLAGS_MSTS) != (uint32_t)RESET) + { + /* Check the status of the specified CAN flag */ + if ((CANx->MSTS & (CAN_FLAG & 0x000FFFFF)) != (uint32_t)RESET) + { + /* CAN_FLAG is set */ + bitstatus = SET; + } + else + { + /* CAN_FLAG is reset */ + bitstatus = RESET; + } + } + else if ((CAN_FLAG & CAN_FLAGS_TSTS) != (uint32_t)RESET) + { + /* Check the status of the specified CAN flag */ + if ((CANx->TSTS & (CAN_FLAG & 0x000FFFFF)) != (uint32_t)RESET) + { + /* CAN_FLAG is set */ + bitstatus = SET; + } + else + { + /* CAN_FLAG is reset */ + bitstatus = RESET; + } + } + else if ((CAN_FLAG & CAN_FLAGS_RFF0) != (uint32_t)RESET) + { + /* Check the status of the specified CAN flag */ + if ((CANx->RFF0 & (CAN_FLAG & 0x000FFFFF)) != (uint32_t)RESET) + { + /* CAN_FLAG is set */ + bitstatus = SET; + } + else + { + /* CAN_FLAG is reset */ + bitstatus = RESET; + } + } + else /* If(CAN_FLAG & CAN_FLAGS_RFF1 != (uint32_t)RESET) */ + { + /* Check the status of the specified CAN flag */ + if ((uint32_t)(CANx->RFF1 & (CAN_FLAG & 0x000FFFFF)) != (uint32_t)RESET) + { + /* CAN_FLAG is set */ + bitstatus = SET; + } + else + { + /* CAN_FLAG is reset */ + bitstatus = RESET; + } + } + /* Return the CAN_FLAG status */ + return bitstatus; +} + +/** + * @brief Clears the CAN's pending flags. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @param CAN_FLAG specifies the flag to clear. + * This parameter can be one of the following flags: + * - CAN_FLAG_RQCPM0 + * - CAN_FLAG_RQCPM1 + * - CAN_FLAG_RQCPM2 + * - CAN_FLAG_FFULL1 + * - CAN_FLAG_FFOVR1 + * - CAN_FLAG_FFULL0 + * - CAN_FLAG_FFOVR0 + * - CAN_FLAG_WKU + * - CAN_FLAG_SLAK + * - CAN_FLAG_LEC + */ +void CAN_ClearFlag(CAN_Module* CANx, uint32_t CAN_FLAG) +{ + uint32_t flagtmp = 0; + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_CLEAR_FLAG(CAN_FLAG)); + + if (CAN_FLAG == CAN_FLAG_LEC) /* ESTS register */ + { + /* Clear the selected CAN flags */ + CANx->ESTS = (uint32_t)RESET; + } + else /* MSTS or TSTS or RFF0 or RFF1 */ + { + flagtmp = CAN_FLAG & 0x000FFFFF; + + if ((CAN_FLAG & CAN_FLAGS_RFF0) != (uint32_t)RESET) + { + /* Receive Flags */ + CANx->RFF0 = (uint32_t)(flagtmp); + } + else if ((CAN_FLAG & CAN_FLAGS_RFF1) != (uint32_t)RESET) + { + /* Receive Flags */ + CANx->RFF1 = (uint32_t)(flagtmp); + } + else if ((CAN_FLAG & CAN_FLAGS_TSTS) != (uint32_t)RESET) + { + /* Transmit Flags */ + CANx->TSTS = (uint32_t)(flagtmp); + } + else /* If((CAN_FLAG & CAN_FLAGS_MSTS)!=(uint32_t)RESET) */ + { + /* Operating mode Flags */ + CANx->MSTS = (uint32_t)(flagtmp); + } + } +} + +/** + * @brief Checks whether the specified CANx interrupt has occurred or not. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @param CAN_INT specifies the CAN interrupt source to check. + * This parameter can be one of the following flags: + * - CAN_INT_TME + * - CAN_INT_FMP0 + * - CAN_INT_FF0 + * - CAN_INT_FOV0 + * - CAN_INT_FMP1 + * - CAN_INT_FF1 + * - CAN_INT_FOV1 + * - CAN_INT_WKU + * - CAN_INT_SLK + * - CAN_INT_EWG + * - CAN_INT_EPV + * - CAN_INT_BOF + * - CAN_INT_LEC + * - CAN_INT_ERR + * @return The current state of CAN_INT (SET or RESET). + */ +INTStatus CAN_GetIntStatus(CAN_Module* CANx, uint32_t CAN_INT) +{ + INTStatus itstatus = RESET; + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_INT(CAN_INT)); + + /* check the enable interrupt bit */ + if ((CANx->INTE & CAN_INT) != RESET) + { + /* in case the Interrupt is enabled, .... */ + switch (CAN_INT) + { + case CAN_INT_TME: + /* Check CAN_TSTS_RQCPx bits */ + itstatus = CheckINTStatus(CANx->TSTS, CAN_TSTS_RQCPM0 | CAN_TSTS_RQCPM1 | CAN_TSTS_RQCPM2); + break; + case CAN_INT_FMP0: + /* Check CAN_RFF0_FFMP0 bit */ + itstatus = CheckINTStatus(CANx->RFF0, CAN_RFF0_FFMP0); + break; + case CAN_INT_FF0: + /* Check CAN_RFF0_FFULL0 bit */ + itstatus = CheckINTStatus(CANx->RFF0, CAN_RFF0_FFULL0); + break; + case CAN_INT_FOV0: + /* Check CAN_RFF0_FFOVR0 bit */ + itstatus = CheckINTStatus(CANx->RFF0, CAN_RFF0_FFOVR0); + break; + case CAN_INT_FMP1: + /* Check CAN_RFF1_FFMP1 bit */ + itstatus = CheckINTStatus(CANx->RFF1, CAN_RFF1_FFMP1); + break; + case CAN_INT_FF1: + /* Check CAN_RFF1_FFULL1 bit */ + itstatus = CheckINTStatus(CANx->RFF1, CAN_RFF1_FFULL1); + break; + case CAN_INT_FOV1: + /* Check CAN_RFF1_FFOVR1 bit */ + itstatus = CheckINTStatus(CANx->RFF1, CAN_RFF1_FFOVR1); + break; + case CAN_INT_WKU: + /* Check CAN_MSTS_WKUINT bit */ + itstatus = CheckINTStatus(CANx->MSTS, CAN_MSTS_WKUINT); + break; + case CAN_INT_SLK: + /* Check CAN_MSTS_SLAKINT bit */ + itstatus = CheckINTStatus(CANx->MSTS, CAN_MSTS_SLAKINT); + break; + case CAN_INT_EWG: + /* Check CAN_ESTS_EWGFL bit */ + itstatus = CheckINTStatus(CANx->ESTS, CAN_ESTS_EWGFL); + break; + case CAN_INT_EPV: + /* Check CAN_ESTS_EPVFL bit */ + itstatus = CheckINTStatus(CANx->ESTS, CAN_ESTS_EPVFL); + break; + case CAN_INT_BOF: + /* Check CAN_ESTS_BOFFL bit */ + itstatus = CheckINTStatus(CANx->ESTS, CAN_ESTS_BOFFL); + break; + case CAN_INT_LEC: + /* Check CAN_ESTS_LEC bit */ + itstatus = CheckINTStatus(CANx->ESTS, CAN_ESTS_LEC); + break; + case CAN_INT_ERR: + /* Check CAN_MSTS_ERRINT bit */ + itstatus = CheckINTStatus(CANx->MSTS, CAN_MSTS_ERRINT); + break; + default: + /* in case of error, return RESET */ + itstatus = RESET; + break; + } + } + else + { + /* in case the Interrupt is not enabled, return RESET */ + itstatus = RESET; + } + + /* Return the CAN_INT status */ + return itstatus; +} + +/** + * @brief Clears the CANx's interrupt pending bits. + * @param CANx where x can be 1 or 2 to to select the CAN peripheral. + * @param CAN_INT specifies the interrupt pending bit to clear. + * - CAN_INT_TME + * - CAN_INT_FF0 + * - CAN_INT_FOV0 + * - CAN_INT_FF1 + * - CAN_INT_FOV1 + * - CAN_INT_WKU + * - CAN_INT_SLK + * - CAN_INT_EWG + * - CAN_INT_EPV + * - CAN_INT_BOF + * - CAN_INT_LEC + * - CAN_INT_ERR + */ +void CAN_ClearINTPendingBit(CAN_Module* CANx, uint32_t CAN_INT) +{ + /* Check the parameters */ + assert_param(IS_CAN_ALL_PERIPH(CANx)); + assert_param(IS_CAN_CLEAR_INT(CAN_INT)); + + switch (CAN_INT) + { + case CAN_INT_TME: + /* Clear CAN_TSTS_RQCPx (rc_w1)*/ + CANx->TSTS = CAN_TSTS_RQCPM0 | CAN_TSTS_RQCPM1 | CAN_TSTS_RQCPM2; + break; + case CAN_INT_FF0: + /* Clear CAN_RFF0_FFULL0 (rc_w1)*/ + CANx->RFF0 = CAN_RFF0_FFULL0; + break; + case CAN_INT_FOV0: + /* Clear CAN_RFF0_FFOVR0 (rc_w1)*/ + CANx->RFF0 = CAN_RFF0_FFOVR0; + break; + case CAN_INT_FF1: + /* Clear CAN_RFF1_FFULL1 (rc_w1)*/ + CANx->RFF1 = CAN_RFF1_FFULL1; + break; + case CAN_INT_FOV1: + /* Clear CAN_RFF1_FFOVR1 (rc_w1)*/ + CANx->RFF1 = CAN_RFF1_FFOVR1; + break; + case CAN_INT_WKU: + /* Clear CAN_MSTS_WKUINT (rc_w1)*/ + CANx->MSTS = CAN_MSTS_WKUINT; + break; + case CAN_INT_SLK: + /* Clear CAN_MSTS_SLAKINT (rc_w1)*/ + CANx->MSTS = CAN_MSTS_SLAKINT; + break; + case CAN_INT_EWG: + /* Clear CAN_MSTS_ERRINT (rc_w1) */ + CANx->MSTS = CAN_MSTS_ERRINT; + /* Note : the corresponding Flag is cleared by hardware depending + of the CAN Bus status*/ + break; + case CAN_INT_EPV: + /* Clear CAN_MSTS_ERRINT (rc_w1) */ + CANx->MSTS = CAN_MSTS_ERRINT; + /* Note : the corresponding Flag is cleared by hardware depending + of the CAN Bus status*/ + break; + case CAN_INT_BOF: + /* Clear CAN_MSTS_ERRINT (rc_w1) */ + CANx->MSTS = CAN_MSTS_ERRINT; + /* Note : the corresponding Flag is cleared by hardware depending + of the CAN Bus status*/ + break; + case CAN_INT_LEC: + /* Clear LEC bits */ + CANx->ESTS = RESET; + /* Clear CAN_MSTS_ERRINT (rc_w1) */ + CANx->MSTS = CAN_MSTS_ERRINT; + break; + case CAN_INT_ERR: + /*Clear LEC bits */ + CANx->ESTS = RESET; + /* Clear CAN_MSTS_ERRINT (rc_w1) */ + CANx->MSTS = CAN_MSTS_ERRINT; + /* Note : BOFF, EPVF and EWGF Flags are cleared by hardware depending + of the CAN Bus status*/ + break; + default: + break; + } +} + +/** + * @brief Checks whether the CAN interrupt has occurred or not. + * @param CAN_Reg specifies the CAN interrupt register to check. + * @param Int_Bit specifies the interrupt source bit to check. + * @return The new state of the CAN Interrupt (SET or RESET). + */ +static INTStatus CheckINTStatus(uint32_t CAN_Reg, uint32_t Int_Bit) +{ + INTStatus pendingbitstatus = RESET; + + if ((CAN_Reg & Int_Bit) != (uint32_t)RESET) + { + /* CAN_INT is set */ + pendingbitstatus = SET; + } + else + { + /* CAN_INT is reset */ + pendingbitstatus = RESET; + } + return pendingbitstatus; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/src/n32g45x_comp.c b/src/n32g45x_comp.c new file mode 100644 index 0000000..f8e0c53 --- /dev/null +++ b/src/n32g45x_comp.c @@ -0,0 +1,297 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_comp.c + * @author Nations + * @version v1.0.2 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_comp.h" +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup COMP + * @brief COMP driver modules + * @{ + */ + +/** @addtogroup COMP_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup COMP_Private_Defines + * @{ + */ + +/** + * @} + */ + +/** @addtogroup COMP_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup COMP_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup COMP_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup COMP_Private_Functions + * @{ + */ +#define SetBitMsk(reg, bit, msk) ((reg) = ((reg) & ~(msk) | (bit))) +#define ClrBit(reg, bit) ((reg) &= ~(bit)) +#define SetBit(reg, bit) ((reg) |= (bit)) +#define GetBit(reg, bit) ((reg) & (bit)) +/** + * @brief Deinitializes the COMP peripheral registers to their default reset values. + */ +void COMP_DeInit(void) +{ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_COMP, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_COMP, DISABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_COMP_FILT, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_COMP_FILT, DISABLE); +} +void COMP_StructInit(COMP_InitType* COMP_InitStruct) +{ + COMP_InitStruct->InpDacConnect = false; // only COMP1 have this bit + + COMP_InitStruct->Blking = COMP_CTRL_BLKING_NO; /*see @ref COMP_CTRL_BLKING */ + + COMP_InitStruct->Hyst = COMP_CTRL_HYST_NO; // see @COMPx_CTRL_HYST_MASK + + COMP_InitStruct->PolRev = false; // out polarity reverse + + COMP_InitStruct->OutSel = COMPX_CTRL_OUTSEL_NC; + COMP_InitStruct->InpSel = COMPX_CTRL_INPSEL_RES; + COMP_InitStruct->InmSel = COMPX_CTRL_INMSEL_RES; + COMP_InitStruct->FilterEn=false; + COMP_InitStruct->ClkPsc=0; + COMP_InitStruct->SampWindow=0; + COMP_InitStruct->Thresh=0; + COMP_InitStruct->En = false; +} +void COMP_Init(COMPX COMPx, COMP_InitType* COMP_InitStruct) +{ + COMP_SingleType* pCS = &COMP->Cmp[COMPx]; + __IO uint32_t tmp; + + // filter + tmp = pCS->FILC; + SetBitMsk(tmp, COMP_InitStruct->SampWindow << 6, COMP_FILC_SAMPW_MASK); + SetBitMsk(tmp, COMP_InitStruct->Thresh << 1, COMP_FILC_THRESH_MASK); + SetBitMsk(tmp, COMP_InitStruct->FilterEn << 0, COMP_FILC_FILEN_MASK); + pCS->FILC = tmp; + // filter psc + pCS->FILP = COMP_InitStruct->ClkPsc; + + // ctrl + tmp = pCS->CTRL; + if (COMPx == COMP1) + { + if (COMP_InitStruct->InpDacConnect) + SetBit(tmp, COMP1_CTRL_INPDAC_MASK); + else + ClrBit(tmp, COMP1_CTRL_INPDAC_MASK); + } + SetBitMsk(tmp, COMP_InitStruct->Blking, COMP_CTRL_BLKING_MASK); + SetBitMsk(tmp, COMP_InitStruct->Hyst, COMPx_CTRL_HYST_MASK); + if (COMP_InitStruct->PolRev) + SetBit(tmp, COMP_POL_MASK); + else + ClrBit(tmp, COMP_POL_MASK); + SetBitMsk(tmp, COMP_InitStruct->OutSel, COMP_CTRL_OUTSEL_MASK); + SetBitMsk(tmp, COMP_InitStruct->InpSel, COMP_CTRL_INPSEL_MASK); + SetBitMsk(tmp, COMP_InitStruct->InmSel, COMP_CTRL_INMSEL_MASK); + if (COMP_InitStruct->En) + SetBit(tmp, COMP_CTRL_EN_MASK); + else + ClrBit(tmp, COMP_CTRL_EN_MASK); + pCS->CTRL = tmp; +} +void COMP_Enable(COMPX COMPx, FunctionalState en) +{ + if (en) + SetBit(COMP->Cmp[COMPx].CTRL, COMP_CTRL_EN_MASK); + else + ClrBit(COMP->Cmp[COMPx].CTRL, COMP_CTRL_EN_MASK); +} + +void COMP_SetInpSel(COMPX COMPx, COMP_CTRL_INPSEL VpSel) +{ + __IO uint32_t tmp = COMP->Cmp[COMPx].CTRL; + SetBitMsk(tmp, VpSel, COMP_CTRL_INPSEL_MASK); + COMP->Cmp[COMPx].CTRL = tmp; +} +void COMP_SetInmSel(COMPX COMPx, COMP_CTRL_INMSEL VmSel) +{ + __IO uint32_t tmp = COMP->Cmp[COMPx].CTRL; + SetBitMsk(tmp, VmSel, COMP_CTRL_INMSEL_MASK); + COMP->Cmp[COMPx].CTRL = tmp; +} +void COMP_SetOutTrig(COMPX COMPx, COMP_CTRL_OUTTRIG OutTrig) +{ + __IO uint32_t tmp = COMP->Cmp[COMPx].CTRL; + SetBitMsk(tmp, OutTrig, COMP_CTRL_OUTSEL_MASK); + COMP->Cmp[COMPx].CTRL = tmp; +} +// Lock see @COMP_LOCK +void COMP_SetLock(uint32_t Lock) +{ + COMP->LOCK = Lock; +} +// IntEn see @COMP_INTEN_CMPIEN +void COMP_SetIntEn(uint32_t IntEn) +{ + COMP->INTEN = IntEn; +} +// return see @COMP_INTSTS_CMPIS +uint32_t COMP_GetIntSts(void) +{ + return COMP->INTSTS; +} +// parma range see @COMP_VREFSCL +// Vv2Trim,Vv1Trim max 63 +void COMP_SetRefScl(uint8_t Vv2Trim, bool Vv2En, uint8_t Vv1Trim, bool Vv1En) +{ + __IO uint32_t tmp = 0; + + SetBitMsk(tmp, Vv2Trim << 8, COMP_VREFSCL_VV2TRM_MSK); + SetBitMsk(tmp, Vv2En << 7, COMP_VREFSCL_VV2EN_MSK); + SetBitMsk(tmp, Vv1Trim << 1, COMP_VREFSCL_VV1TRM_MSK); + SetBitMsk(tmp, Vv1En << 0, COMP_VREFSCL_VV1EN_MSK); + + COMP->VREFSCL = tmp; +} +// SET when comp out 1 +// RESET when comp out 0 +FlagStatus COMP_GetOutStatus(COMPX COMPx) +{ + return (COMP->Cmp[COMPx].CTRL & COMP_CTRL_OUT_MASK) ? SET : RESET; +} +// get one comp interrupt flags +FlagStatus COMP_GetIntStsOneComp(COMPX COMPx) +{ + return (COMP_GetIntSts() & (0x01 << COMPx)) ? SET : RESET; +} + +/** + * @brief Set the COMP filter clock Prescaler value. + * @param COMPx where x can be 1 to 7 to select the COMP peripheral. + * @param FilPreVal Prescaler Value,Div clock = FilPreVal+1. + * @return void + */ +void COMP_SetFilterPrescaler(COMPX COMPx , uint16_t FilPreVal) +{ + COMP->Cmp[COMPx].FILP=FilPreVal; +} + +/** + * @brief Set the COMP filter control value. + * @param COMPx where x can be 1 to 7 to select the COMP peripheral. + * @param FilEn 1 for enable ,0 or disable + * @param TheresNum num under this value is noise + * @param SampPW total sample number in a window + * @return void + */ +void COMP_SetFilterControl(COMPX COMPx , uint8_t FilEn, uint8_t TheresNum , uint8_t SampPW) +{ + COMP->Cmp[COMPx].FILC=(FilEn&COMP_FILC_FILEN_MASK)+((TheresNum<<1)&COMP_FILC_THRESH_MASK)+((SampPW<<6)&COMP_FILC_SAMPW_MASK); +} + +/** + * @brief Set the COMP Hyst value. + * @param COMPx where x can be 1 to 7 to select the COMP peripheral. + * @param HYST specifies the HYST level. + * This parameter can be one of the following values: +* @arg COMP_CTRL_HYST_NO Hyst disable +* @arg COMP_CTRL_HYST_LOW Hyst level 5.1mV +* @arg COMP_CTRL_HYST_MID Hyst level 15mV +* @arg COMP_CTRL_HYST_HIGH Hyst level 25mV + * @return void + */ +void COMP_SetHyst(COMPX COMPx , COMP_CTRL_HYST HYST) +{ + uint32_t tmp=COMP->Cmp[COMPx].CTRL; + tmp&=~COMP_CTRL_HYST_HIGH; + tmp|=HYST; + COMP->Cmp[COMPx].CTRL=tmp; +} + +/** + * @brief Set the COMP Blanking source . + * @param COMPx where x can be 1 to 7 to select the COMP peripheral. + * @param BLK specifies the blanking source . + * This parameter can be one of the following values: +* @arg COMP_CTRL_BLKING_NO Blanking disable +* @arg COMP_CTRL_BLKING_TIM1_OC5 Blanking source TIM1_OC5 +* @arg COMP_CTRL_BLKING_TIM8_OC5 Blanking source TIM8_OC5 + * @return void + */ +void COMP_SetBlanking(COMPX COMPx , COMP_CTRL_BLKING BLK) +{ + uint32_t tmp=COMP->Cmp[COMPx].CTRL; + tmp&=~(7<<14); + tmp|=BLK; + COMP->Cmp[COMPx].CTRL=tmp; +} + + +/** + * @} + */ +/** + * @} + */ +/** + * @} + */ diff --git a/src/n32g45x_crc.c b/src/n32g45x_crc.c new file mode 100644 index 0000000..e4a9200 --- /dev/null +++ b/src/n32g45x_crc.c @@ -0,0 +1,228 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_crc.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_crc.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup CRC + * @brief CRC driver modules + * @{ + */ + +/** @addtogroup CRC_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup CRC_Private_Defines + * @{ + */ + +/** + * @} + */ + +/** @addtogroup CRC_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup CRC_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup CRC_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup CRC_Private_Functions + * @{ + */ + +/** + * @brief Resets the CRC Data register (DAT). + */ +void CRC32_ResetCrc(void) +{ + /* Reset CRC generator */ + CRC->CRC32CTRL = CRC32_CTRL_RESET; +} + +/** + * @brief Computes the 32-bit CRC of a given data word(32-bit). + * @param Data data word(32-bit) to compute its CRC + * @return 32-bit CRC + */ +uint32_t CRC32_CalcCrc(uint32_t Data) +{ + CRC->CRC32DAT = Data; + + return (CRC->CRC32DAT); +} + +/** + * @brief Computes the 32-bit CRC of a given buffer of data word(32-bit). + * @param pBuffer pointer to the buffer containing the data to be computed + * @param BufferLength length of the buffer to be computed + * @return 32-bit CRC + */ +uint32_t CRC32_CalcBufCrc(uint32_t pBuffer[], uint32_t BufferLength) +{ + uint32_t index = 0; + + for (index = 0; index < BufferLength; index++) + { + CRC->CRC32DAT = pBuffer[index]; + } + return (CRC->CRC32DAT); +} + +/** + * @brief Returns the current CRC value. + * @return 32-bit CRC + */ +uint32_t CRC32_GetCrc(void) +{ + return (CRC->CRC32DAT); +} + +/** + * @brief Stores a 8-bit data in the Independent Data(ID) register. + * @param IDValue 8-bit value to be stored in the ID register + */ +void CRC32_SetIDat(uint8_t IDValue) +{ + CRC->CRC32IDAT = IDValue; +} + +/** + * @brief Returns the 8-bit data stored in the Independent Data(ID) register + * @return 8-bit value of the ID register + */ +uint8_t CRC32_GetIDat(void) +{ + return (CRC->CRC32IDAT); +} + +// CRC16 add +void __CRC16_SetLittleEndianFmt(void) +{ + CRC->CRC16CTRL = CRC16_CTRL_LITTLE | CRC->CRC16CTRL; +} +void __CRC16_SetBigEndianFmt(void) +{ + CRC->CRC16CTRL = CRC16_CTRL_BIG & CRC->CRC16CTRL; +} +void __CRC16_SetCleanEnable(void) +{ + CRC->CRC16CTRL = CRC16_CTRL_RESET | CRC->CRC16CTRL; +} +void __CRC16_SetCleanDisable(void) +{ + CRC->CRC16CTRL = CRC16_CTRL_NO_RESET & CRC->CRC16CTRL; +} + +uint16_t __CRC16_CalcCrc(uint8_t Data) +{ + CRC->CRC16DAT = Data; + return (CRC->CRC16D); +} + +void __CRC16_SetCrc(uint8_t Data) +{ + CRC->CRC16DAT = Data; +} + +uint16_t __CRC16_GetCrc(void) +{ + return (CRC->CRC16D); +} + +void __CRC16_SetLRC(uint8_t Data) +{ + CRC->LRC = Data; +} + +uint8_t __CRC16_GetLRC(void) +{ + return (CRC->LRC); +} + +uint16_t CRC16_CalcBufCrc(uint8_t pBuffer[], uint32_t BufferLength) +{ + uint32_t index = 0; + + CRC->CRC16D = 0x00; + // CRC16_SetCleanEnable(); + for (index = 0; index < BufferLength; index++) + { + CRC->CRC16DAT = pBuffer[index]; + } + return (CRC->CRC16D); +} + +uint16_t CRC16_CalcCRC(uint8_t Data) +{ + CRC->CRC16DAT = Data; + + return (CRC->CRC16D); +} +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/src/n32g45x_dac.c b/src/n32g45x_dac.c new file mode 100644 index 0000000..ce1b063 --- /dev/null +++ b/src/n32g45x_dac.c @@ -0,0 +1,425 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_dac.c + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_dac.h" +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup DAC + * @brief DAC driver modules + * @{ + */ + +/** @addtogroup DAC_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DAC_Private_Defines + * @{ + */ + +/* CTRL register Mask */ +#define CTRL_CLEAR_MASK ((uint32_t)0x00000FFE) + +/* DAC Dual Channels SWTRIG masks */ +#define DUAL_SWTRIG_SET ((uint32_t)0x00000003) +#define DUAL_SWTRIG_RESET ((uint32_t)0xFFFFFFFC) + +/* DCH registers offsets */ +#define DR12CH1_OFFSET ((uint32_t)0x00000008) +#define DR12CH2_OFFSET ((uint32_t)0x00000014) +#define DR12DCH_OFFSET ((uint32_t)0x00000020) + +/* DATO register offset */ +#define DATO1_OFFSET ((uint32_t)0x0000002C) +/** + * @} + */ + +/** @addtogroup DAC_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DAC_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DAC_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DAC_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the DAC peripheral registers to their default reset values. + */ +void DAC_DeInit(void) +{ + /* Enable DAC reset state */ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_DAC, ENABLE); + /* Release DAC from reset state */ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_DAC, DISABLE); +} + +/** + * @brief Initializes the DAC peripheral according to the specified + * parameters in the DAC_InitStruct. + * @param DAC_Channel the selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_CHANNEL_1 DAC Channel1 selected + * @arg DAC_CHANNEL_2 DAC Channel2 selected + * @param DAC_InitStruct pointer to a DAC_InitType structure that + * contains the configuration information for the specified DAC channel. + */ +void DAC_Init(uint32_t DAC_Channel, DAC_InitType* DAC_InitStruct) +{ + uint32_t tmpreg1 = 0, tmpreg2 = 0; + /* Check the DAC parameters */ + assert_param(IS_DAC_TRIGGER(DAC_InitStruct->Trigger)); + assert_param(IS_DAC_GENERATE_WAVE(DAC_InitStruct->WaveGen)); + assert_param(IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(DAC_InitStruct->LfsrUnMaskTriAmp)); + assert_param(IS_DAC_OUTPUT_BUFFER_STATE(DAC_InitStruct->BufferOutput)); + /*---------------------------- DAC CTRL Configuration --------------------------*/ + /* Get the DAC CTRL value */ + tmpreg1 = DAC->CTRL; + /* Clear BOFFx, TENx, TSELx, WAVEx and MAMPx bits */ + tmpreg1 &= ~(CTRL_CLEAR_MASK << DAC_Channel); + /* Configure for the selected DAC channel: buffer output, trigger, wave generation, + mask/amplitude for wave generation */ + /* Set TSELx and TENx bits according to Trigger value */ + /* Set WAVEx bits according to WaveGen value */ + /* Set MAMPx bits according to LfsrUnMaskTriAmp value */ + /* Set BOFFx bit according to BufferOutput value */ + tmpreg2 = (DAC_InitStruct->Trigger | DAC_InitStruct->WaveGen | DAC_InitStruct->LfsrUnMaskTriAmp + | DAC_InitStruct->BufferOutput); + /* Calculate CTRL register value depending on DAC_Channel */ + tmpreg1 |= tmpreg2 << DAC_Channel; + /* Write to DAC CTRL */ + DAC->CTRL = tmpreg1; +} + +/** + * @brief Fills each DAC_InitStruct member with its default value. + * @param DAC_InitStruct pointer to a DAC_InitType structure which will + * be initialized. + */ +void DAC_ClearStruct(DAC_InitType* DAC_InitStruct) +{ + /*--------------- Reset DAC init structure parameters values -----------------*/ + /* Initialize the Trigger member */ + DAC_InitStruct->Trigger = DAC_TRG_NONE; + /* Initialize the WaveGen member */ + DAC_InitStruct->WaveGen = DAC_WAVEGEN_NONE; + /* Initialize the LfsrUnMaskTriAmp member */ + DAC_InitStruct->LfsrUnMaskTriAmp = DAC_UNMASK_LFSRBIT0; + /* Initialize the BufferOutput member */ + DAC_InitStruct->BufferOutput = DAC_BUFFOUTPUT_ENABLE; +} + +/** + * @brief Enables or disables the specified DAC channel. + * @param DAC_Channel the selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_CHANNEL_1 DAC Channel1 selected + * @arg DAC_CHANNEL_2 DAC Channel2 selected + * @param Cmd new state of the DAC channel. + * This parameter can be: ENABLE or DISABLE. + */ +void DAC_Enable(uint32_t DAC_Channel, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected DAC channel */ + DAC->CTRL |= (DAC_CTRL_CH1EN << DAC_Channel); + } + else + { + /* Disable the selected DAC channel */ + DAC->CTRL &= ~(DAC_CTRL_CH1EN << DAC_Channel); + } +} + +/** + * @brief Enables or disables the specified DAC channel DMA request. + * @param DAC_Channel the selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_CHANNEL_1 DAC Channel1 selected + * @arg DAC_CHANNEL_2 DAC Channel2 selected + * @param Cmd new state of the selected DAC channel DMA request. + * This parameter can be: ENABLE or DISABLE. + */ +void DAC_DmaEnable(uint32_t DAC_Channel, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected DAC channel DMA request */ + DAC->CTRL |= (DAC_CTRL_DMA1EN << DAC_Channel); + } + else + { + /* Disable the selected DAC channel DMA request */ + DAC->CTRL &= ~(DAC_CTRL_DMA1EN << DAC_Channel); + } +} + +/** + * @brief Enables or disables the selected DAC channel software trigger. + * @param DAC_Channel the selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_CHANNEL_1 DAC Channel1 selected + * @arg DAC_CHANNEL_2 DAC Channel2 selected + * @param Cmd new state of the selected DAC channel software trigger. + * This parameter can be: ENABLE or DISABLE. + */ +void DAC_SoftTrgEnable(uint32_t DAC_Channel, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable software trigger for the selected DAC channel */ + DAC->SOTTR |= (uint32_t)DAC_SOTTR_TR1EN << (DAC_Channel >> 4); + } + else + { + /* Disable software trigger for the selected DAC channel */ + DAC->SOTTR &= ~((uint32_t)DAC_SOTTR_TR1EN << (DAC_Channel >> 4)); + } +} + +/** + * @brief Enables or disables simultaneously the two DAC channels software + * triggers. + * @param Cmd new state of the DAC channels software triggers. + * This parameter can be: ENABLE or DISABLE. + */ +void DAC_DualSoftwareTrgEnable(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable software trigger for both DAC channels */ + DAC->SOTTR |= DUAL_SWTRIG_SET; + } + else + { + /* Disable software trigger for both DAC channels */ + DAC->SOTTR &= DUAL_SWTRIG_RESET; + } +} + +/** + * @brief Enables or disables the selected DAC channel wave generation. + * @param DAC_Channel the selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_CHANNEL_1 DAC Channel1 selected + * @arg DAC_CHANNEL_2 DAC Channel2 selected + * @param DAC_Wave Specifies the wave type to enable or disable. + * This parameter can be one of the following values: + * @arg DAC_WAVE_NOISE noise wave generation + * @arg DAC_WAVE_TRIANGLE triangle wave generation + * @param Cmd new state of the selected DAC channel wave generation. + * This parameter can be: ENABLE or DISABLE. + */ +void DAC_WaveGenerationEnable(uint32_t DAC_Channel, uint32_t DAC_Wave, FunctionalState Cmd) +{ + /* Check the parameters */ + __IO uint32_t tmp = 0; + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + assert_param(IS_DAC_WAVE(DAC_Wave)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + tmp=DAC->CTRL; + tmp&=~(3<<(DAC_Channel+6)); + if (Cmd != DISABLE) + { + /* Enable the selected wave generation for the selected DAC channel */ + tmp |= DAC_Wave << DAC_Channel; + } + else + { + /* Disable the selected wave generation for the selected DAC channel */ + tmp &=~(3<<(DAC_Channel+6)); + } + DAC->CTRL = tmp; +} + +/** + * @brief Set the specified data holding register value for DAC channel1. + * @param DAC_Align Specifies the data alignment for DAC channel1. + * This parameter can be one of the following values: + * @arg DAC_ALIGN_R_8BIT 8bit right data alignment selected + * @arg DAC_ALIGN_L_12BIT 12bit left data alignment selected + * @arg DAC_ALIGN_R_12BIT 12bit right data alignment selected + * @param Data Data to be loaded in the selected data holding register. + */ +void DAC_SetCh1Data(uint32_t DAC_Align, uint16_t Data) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_DAC_ALIGN(DAC_Align)); + assert_param(IS_DAC_DATA(Data)); + + tmp = (uint32_t)DAC_BASE; + tmp += DR12CH1_OFFSET + DAC_Align; + + /* Set the DAC channel1 selected data holding register */ + *(__IO uint32_t*)tmp = Data; +} + +/** + * @brief Set the specified data holding register value for DAC channel2. + * @param DAC_Align Specifies the data alignment for DAC channel2. + * This parameter can be one of the following values: + * @arg DAC_ALIGN_R_8BIT 8bit right data alignment selected + * @arg DAC_ALIGN_L_12BIT 12bit left data alignment selected + * @arg DAC_ALIGN_R_12BIT 12bit right data alignment selected + * @param Data Data to be loaded in the selected data holding register. + */ +void DAC_SetCh2Data(uint32_t DAC_Align, uint16_t Data) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_DAC_ALIGN(DAC_Align)); + assert_param(IS_DAC_DATA(Data)); + + tmp = (uint32_t)DAC_BASE; + tmp += DR12CH2_OFFSET + DAC_Align; + + /* Set the DAC channel2 selected data holding register */ + *(__IO uint32_t*)tmp = Data; +} + +/** + * @brief Set the specified data holding register value for dual channel + * DAC. + * @param DAC_Align Specifies the data alignment for dual channel DAC. + * This parameter can be one of the following values: + * @arg DAC_ALIGN_R_8BIT 8bit right data alignment selected + * @arg DAC_ALIGN_L_12BIT 12bit left data alignment selected + * @arg DAC_ALIGN_R_12BIT 12bit right data alignment selected + * @param Data2 Data for DAC Channel2 to be loaded in the selected data + * holding register. + * @param Data1 Data for DAC Channel1 to be loaded in the selected data + * holding register. + */ +void DAC_SetDualChData(uint32_t DAC_Align, uint16_t Data2, uint16_t Data1) +{ + uint32_t data = 0, tmp = 0; + + /* Check the parameters */ + assert_param(IS_DAC_ALIGN(DAC_Align)); + assert_param(IS_DAC_DATA(Data1)); + assert_param(IS_DAC_DATA(Data2)); + + /* Calculate and set dual DAC data holding register value */ + if (DAC_Align == DAC_ALIGN_R_8BIT) + { + data = ((uint32_t)Data2 << 8) | Data1; + } + else + { + data = ((uint32_t)Data2 << 16) | Data1; + } + + tmp = (uint32_t)DAC_BASE; + tmp += DR12DCH_OFFSET + DAC_Align; + + /* Set the dual DAC selected data holding register */ + *(__IO uint32_t*)tmp = data; +} + +/** + * @brief Returns the last data output value of the selected DAC channel. + * @param DAC_Channel the selected DAC channel. + * This parameter can be one of the following values: + * @arg DAC_CHANNEL_1 DAC Channel1 selected + * @arg DAC_CHANNEL_2 DAC Channel2 selected + * @return The selected DAC channel data output value. + */ +uint16_t DAC_GetOutputDataVal(uint32_t DAC_Channel) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_DAC_CHANNEL(DAC_Channel)); + + tmp = (uint32_t)DAC_BASE; + tmp += DATO1_OFFSET + ((uint32_t)DAC_Channel >> 2); + + /* Returns the DAC channel data output register value */ + return (uint16_t)(*(__IO uint32_t*)tmp); +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/src/n32g45x_dbg.c b/src/n32g45x_dbg.c new file mode 100644 index 0000000..7432951 --- /dev/null +++ b/src/n32g45x_dbg.c @@ -0,0 +1,263 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_dbg.c + * @author Nations + * @version v1.0.2 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_dbg.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup DBG + * @brief DBG driver modules + * @{ + */ + +/** @addtogroup DBGMCU_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DBGMCU_Private_Defines + * @{ + */ + +#define IDCODE_DEVID_MASK ((uint32_t)0x00000FFF) +/** + * @} + */ + +/** @addtogroup DBGMCU_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DBGMCU_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DBGMCU_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DBGMCU_Private_Functions + * @{ + */ + +/** + * @brief Returns the UCID. + * @return UCID + */ + +void GetUCID(uint8_t *UCIDbuf) +{ + uint8_t num = 0; + uint32_t* ucid_addr = (uint32_t*)0; + uint32_t temp = 0; + + if (0xFFFFFFFF == *(uint32_t*)(0x1FFFF260)) + { + ucid_addr = (uint32_t*)UCID_BASE; + } + else + { + ucid_addr = (uint32_t*)(0x1FFFF260); + } + + for (num = 0; num < UCID_LENGTH;) + { + temp = *(__IO uint32_t*)(ucid_addr++); + UCIDbuf[num++] = (temp & 0xFF); + UCIDbuf[num++] = (temp & 0xFF00) >> 8; + UCIDbuf[num++] = (temp & 0xFF0000) >> 16; + UCIDbuf[num++] = (temp & 0xFF000000) >> 24; + } +} + +/** + * @brief Returns the UID. + * @return UID + */ + +void GetUID(uint8_t *UIDbuf) +{ + uint8_t num = 0; + uint32_t* uid_addr = (uint32_t*)0; + uint32_t temp = 0; + + if (0xFFFFFFFF == *(uint32_t*)(0x1FFFF270)) + { + uid_addr = (uint32_t*)UID_BASE; + } + else + { + uid_addr = (uint32_t*)(0x1FFFF270); + } + + for (num = 0; num < UID_LENGTH;) + { + temp = *(__IO uint32_t*)(uid_addr++); + UIDbuf[num++] = (temp & 0xFF); + UIDbuf[num++] = (temp & 0xFF00) >> 8; + UIDbuf[num++] = (temp & 0xFF0000) >> 16; + UIDbuf[num++] = (temp & 0xFF000000) >> 24; + } +} + +/** + * @brief Returns the DBGMCU_ID. + * @return DBGMCU_ID + */ + +void GetDBGMCU_ID(uint8_t *DBGMCU_IDbuf) +{ + uint8_t num = 0; + uint32_t* dbgid_addr = (uint32_t*)0; + uint32_t temp = 0; + + dbgid_addr = (uint32_t*)DBGMCU_ID_BASE; + for (num = 0; num < DBGMCU_ID_LENGTH;) + { + temp = *(__IO uint32_t*)(dbgid_addr++); + DBGMCU_IDbuf[num++] = (temp & 0xFF); + DBGMCU_IDbuf[num++] = (temp & 0xFF00) >> 8; + DBGMCU_IDbuf[num++] = (temp & 0xFF0000) >> 16; + DBGMCU_IDbuf[num++] = (temp & 0xFF000000) >> 24; + } +} + +/** + * @brief Returns the device revision number. + * @return Device revision identifier + */ +uint32_t DBG_GetRevNum(void) +{ + return (DBG->ID & 0x00FF); +} + +/** + * @brief Returns the device identifier. + * @return Device identifier + */ +uint32_t DBG_GetDevNum(void) +{ + uint32_t id = DBG->ID; + return ((id & 0x00F00000) >> 20) | ((id & 0xFF00) >> 4); +} + +/** + * @brief Configures the specified peripheral and low power mode behavior + * when the MCU under Debug mode. + * @param DBG_Periph specifies the peripheral and low power mode. + * This parameter can be any combination of the following values: + * @arg DBG_SLEEP Keep debugger connection during SLEEP mode + * @arg DBG_STOP Keep debugger connection during STOP mode + * @arg DBG_STDBY Keep debugger connection during STANDBY mode + * @arg DBG_IWDG_STOP Debug IWDG stopped when Core is halted + * @arg DBG_WWDG_STOP Debug WWDG stopped when Core is halted + * @arg DBG_TIM1_STOP TIM1 counter stopped when Core is halted + * @arg DBG_TIM2_STOP TIM2 counter stopped when Core is halted + * @arg DBG_TIM3_STOP TIM3 counter stopped when Core is halted + * @arg DBG_TIM4_STOP TIM4 counter stopped when Core is halted + * @arg DBG_CAN1_STOP Debug CAN2 stopped when Core is halted + * @arg DBG_I2C1SMBUS_TIMEOUT I2C1 SMBUS timeout mode stopped when Core is halted + * @arg DBG_I2C2SMBUS_TIMEOUT I2C2 SMBUS timeout mode stopped when Core is halted + * @arg DBG_TIM8_STOP TIM8 counter stopped when Core is halted + * @arg DBG_TIM5_STOP TIM5 counter stopped when Core is halted + * @arg DBG_TIM6_STOP TIM6 counter stopped when Core is halted + * @arg DBG_TIM7_STOP TIM7 counter stopped when Core is halted + * @arg DBG_CAN2_STOP Debug CAN2 stopped when Core is halted + * @param Cmd new state of the specified peripheral in Debug mode. + * This parameter can be: ENABLE or DISABLE. + */ +void DBG_ConfigPeriph(uint32_t DBG_Periph, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_DBGMCU_PERIPH(DBG_Periph)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + DBG->CTRL |= DBG_Periph; + } + else + { + DBG->CTRL &= ~DBG_Periph; + } +} + +/** + * @brief Get FLASH size of this chip. + * + * @return FLASH size in bytes. + */ +uint32_t DBG_GetFlashSize(void) +{ + return (DBG->ID & 0x000F0000); +} + +/** + * @brief Get SRAM size of this chip. + * + * @return SRAM size in bytes. + */ +uint32_t DBG_GetSramSize(void) +{ + return (((DBG->ID & 0xF0000000) >> 28) + 1) << 14; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/src/n32g45x_dma.c b/src/n32g45x_dma.c new file mode 100644 index 0000000..a4bf607 --- /dev/null +++ b/src/n32g45x_dma.c @@ -0,0 +1,888 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_dma.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_dma.h" +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup DMA + * @brief DMA driver modules + * @{ + */ + +/** @addtogroup DMA_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + +/** @addtogroup DMA_Private_Defines + * @{ + */ + +/* DMA1 Channelx interrupt pending bit masks */ +#define DMA1_CH1_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF1 | DMA_INTSTS_TXCF1 | DMA_INTSTS_HTXF1 | DMA_INTSTS_ERRF1)) +#define DMA1_CH2_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF2 | DMA_INTSTS_TXCF2 | DMA_INTSTS_HTXF2 | DMA_INTSTS_ERRF2)) +#define DMA1_CH3_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF3 | DMA_INTSTS_TXCF3 | DMA_INTSTS_HTXF3 | DMA_INTSTS_ERRF3)) +#define DMA1_CH4_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF4 | DMA_INTSTS_TXCF4 | DMA_INTSTS_HTXF4 | DMA_INTSTS_ERRF4)) +#define DMA1_CH5_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF5 | DMA_INTSTS_TXCF5 | DMA_INTSTS_HTXF5 | DMA_INTSTS_ERRF5)) +#define DMA1_CH6_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF6 | DMA_INTSTS_TXCF6 | DMA_INTSTS_HTXF6 | DMA_INTSTS_ERRF6)) +#define DMA1_CH7_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF7 | DMA_INTSTS_TXCF7 | DMA_INTSTS_HTXF7 | DMA_INTSTS_ERRF7)) +#define DMA1_CH8_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF8 | DMA_INTSTS_TXCF8 | DMA_INTSTS_HTXF8 | DMA_INTSTS_ERRF8)) + +/* DMA2 Channelx interrupt pending bit masks */ +#define DMA2_CH1_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF1 | DMA_INTSTS_TXCF1 | DMA_INTSTS_HTXF1 | DMA_INTSTS_ERRF1)) +#define DMA2_CH2_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF2 | DMA_INTSTS_TXCF2 | DMA_INTSTS_HTXF2 | DMA_INTSTS_ERRF2)) +#define DMA2_CH3_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF3 | DMA_INTSTS_TXCF3 | DMA_INTSTS_HTXF3 | DMA_INTSTS_ERRF3)) +#define DMA2_CH4_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF4 | DMA_INTSTS_TXCF4 | DMA_INTSTS_HTXF4 | DMA_INTSTS_ERRF4)) +#define DMA2_CH5_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF5 | DMA_INTSTS_TXCF5 | DMA_INTSTS_HTXF5 | DMA_INTSTS_ERRF5)) +#define DMA2_CH6_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF6 | DMA_INTSTS_TXCF6 | DMA_INTSTS_HTXF6 | DMA_INTSTS_ERRF6)) +#define DMA2_CH7_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF7 | DMA_INTSTS_TXCF7 | DMA_INTSTS_HTXF7 | DMA_INTSTS_ERRF7)) +#define DMA2_CH8_INT_MASK ((uint32_t)(DMA_INTSTS_GLBF8 | DMA_INTSTS_TXCF8 | DMA_INTSTS_HTXF8 | DMA_INTSTS_ERRF8)) + +/* DMA CHCFGx registers Masks, MEM2MEM, PL, MSIZE, PSIZE, MINC, PINC, CIRC and DIR bits */ +#define CCR_CLEAR_Mask ((uint32_t)0xFFFF800F) + +/** + * @} + */ + +/** @addtogroup DMA_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DMA_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DMA_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DMA_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the DMAy Channelx registers to their default reset + * values. + * @param DMAyChx where y can be 1 or 2 to select the DMA and + * x can be 1 to 8 for DMA1 and 1 to 8 for DMA2 to select the DMA Channel. + */ +void DMA_DeInit(DMA_ChannelType* DMAyChx) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAyChx)); + + /* Disable the selected DMAy Channelx */ + DMAyChx->CHCFG &= (uint16_t)(~DMA_CHCFG1_CHEN); + + /* Reset DMAy Channelx control register */ + DMAyChx->CHCFG = 0; + + /* Reset DMAy Channelx remaining bytes register */ + DMAyChx->TXNUM = 0; + + /* Reset DMAy Channelx peripheral address register */ + DMAyChx->PADDR = 0; + + /* Reset DMAy Channelx memory address register */ + DMAyChx->MADDR = 0; + + if (DMAyChx == DMA1_CH1) + { + /* Reset interrupt pending bits for DMA1 Channel1 */ + DMA1->INTCLR |= DMA1_CH1_INT_MASK; + } + else if (DMAyChx == DMA1_CH2) + { + /* Reset interrupt pending bits for DMA1 Channel2 */ + DMA1->INTCLR |= DMA1_CH2_INT_MASK; + } + else if (DMAyChx == DMA1_CH3) + { + /* Reset interrupt pending bits for DMA1 Channel3 */ + DMA1->INTCLR |= DMA1_CH3_INT_MASK; + } + else if (DMAyChx == DMA1_CH4) + { + /* Reset interrupt pending bits for DMA1 Channel4 */ + DMA1->INTCLR |= DMA1_CH4_INT_MASK; + } + else if (DMAyChx == DMA1_CH5) + { + /* Reset interrupt pending bits for DMA1 Channel5 */ + DMA1->INTCLR |= DMA1_CH5_INT_MASK; + } + else if (DMAyChx == DMA1_CH6) + { + /* Reset interrupt pending bits for DMA1 Channel6 */ + DMA1->INTCLR |= DMA1_CH6_INT_MASK; + } + else if (DMAyChx == DMA1_CH7) + { + /* Reset interrupt pending bits for DMA1 Channel7 */ + DMA1->INTCLR |= DMA1_CH7_INT_MASK; + } + else if (DMAyChx == DMA1_CH8) + { + /* Reset interrupt pending bits for DMA1 Channel8 */ + DMA1->INTCLR |= DMA1_CH8_INT_MASK; + } + else if (DMAyChx == DMA2_CH1) + { + /* Reset interrupt pending bits for DMA2 Channel1 */ + DMA2->INTCLR |= DMA2_CH1_INT_MASK; + } + else if (DMAyChx == DMA2_CH2) + { + /* Reset interrupt pending bits for DMA2 Channel2 */ + DMA2->INTCLR |= DMA2_CH2_INT_MASK; + } + else if (DMAyChx == DMA2_CH3) + { + /* Reset interrupt pending bits for DMA2 Channel3 */ + DMA2->INTCLR |= DMA2_CH3_INT_MASK; + } + else if (DMAyChx == DMA2_CH4) + { + /* Reset interrupt pending bits for DMA2 Channel4 */ + DMA2->INTCLR |= DMA2_CH4_INT_MASK; + } + else if (DMAyChx == DMA2_CH5) + { + /* Reset interrupt pending bits for DMA2 Channel5 */ + DMA2->INTCLR |= DMA2_CH5_INT_MASK; + } + else if (DMAyChx == DMA2_CH6) + { + /* Reset interrupt pending bits for DMA2 Channel6 */ + DMA2->INTCLR |= DMA2_CH6_INT_MASK; + } + else if (DMAyChx == DMA2_CH7) + { + /* Reset interrupt pending bits for DMA2 Channel7 */ + DMA2->INTCLR |= DMA2_CH7_INT_MASK; + } + else + { + if (DMAyChx == DMA2_CH8) + { + /* Reset interrupt pending bits for DMA2 Channel8 */ + DMA2->INTCLR |= DMA2_CH8_INT_MASK; + } + } +} + +/** + * @brief Initializes the DMAy Channelx according to the specified + * parameters in the DMA_InitParam. + * @param DMAyChx where y can be 1 or 2 to select the DMA and + * x can be 1 to 8 for DMA1 and 1 to 8 for DMA2 to select the DMA Channel. + * @param DMA_InitParam pointer to a DMA_InitType structure that + * contains the configuration information for the specified DMA Channel. + */ +void DMA_Init(DMA_ChannelType* DMAyChx, DMA_InitType* DMA_InitParam) +{ + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAyChx)); + assert_param(IS_DMA_DIR(DMA_InitParam->Direction)); + assert_param(IS_DMA_BUF_SIZE(DMA_InitParam->BufSize)); + assert_param(IS_DMA_PERIPH_INC_STATE(DMA_InitParam->PeriphInc)); + assert_param(IS_DMA_MEM_INC_STATE(DMA_InitParam->DMA_MemoryInc)); + assert_param(IS_DMA_PERIPH_DATA_SIZE(DMA_InitParam->PeriphDataSize)); + assert_param(IS_DMA_MEMORY_DATA_SIZE(DMA_InitParam->MemDataSize)); + assert_param(IS_DMA_MODE(DMA_InitParam->CircularMode)); + assert_param(IS_DMA_PRIORITY(DMA_InitParam->Priority)); + assert_param(IS_DMA_M2M_STATE(DMA_InitParam->Mem2Mem)); + + /*--------------------------- DMAy Channelx CHCFG Configuration -----------------*/ + /* Get the DMAyChx CHCFG value */ + tmpregister = DMAyChx->CHCFG; + /* Clear MEM2MEM, PL, MSIZE, PSIZE, MINC, PINC, CIRC and DIR bits */ + tmpregister &= CCR_CLEAR_Mask; + /* Configure DMAy Channelx: data transfer, data size, priority level and mode */ + /* Set DIR bit according to Direction value */ + /* Set CIRC bit according to CircularMode value */ + /* Set PINC bit according to PeriphInc value */ + /* Set MINC bit according to DMA_MemoryInc value */ + /* Set PSIZE bits according to PeriphDataSize value */ + /* Set MSIZE bits according to MemDataSize value */ + /* Set PL bits according to Priority value */ + /* Set the MEM2MEM bit according to Mem2Mem value */ + tmpregister |= DMA_InitParam->Direction | DMA_InitParam->CircularMode | DMA_InitParam->PeriphInc + | DMA_InitParam->DMA_MemoryInc | DMA_InitParam->PeriphDataSize | DMA_InitParam->MemDataSize + | DMA_InitParam->Priority | DMA_InitParam->Mem2Mem; + + /* Write to DMAy Channelx CHCFG */ + DMAyChx->CHCFG = tmpregister; + + /*--------------------------- DMAy Channelx TXNUM Configuration ---------------*/ + /* Write to DMAy Channelx TXNUM */ + DMAyChx->TXNUM = DMA_InitParam->BufSize; + + /*--------------------------- DMAy Channelx PADDR Configuration ----------------*/ + /* Write to DMAy Channelx PADDR */ + DMAyChx->PADDR = DMA_InitParam->PeriphAddr; + + /*--------------------------- DMAy Channelx MADDR Configuration ----------------*/ + /* Write to DMAy Channelx MADDR */ + DMAyChx->MADDR = DMA_InitParam->MemAddr; +} + +/** + * @brief Fills each DMA_InitParam member with its default value. + * @param DMA_InitParam pointer to a DMA_InitType structure which will + * be initialized. + */ +void DMA_StructInit(DMA_InitType* DMA_InitParam) +{ + /*-------------- Reset DMA init structure parameters values ------------------*/ + /* Initialize the PeriphAddr member */ + DMA_InitParam->PeriphAddr = 0; + /* Initialize the MemAddr member */ + DMA_InitParam->MemAddr = 0; + /* Initialize the Direction member */ + DMA_InitParam->Direction = DMA_DIR_PERIPH_SRC; + /* Initialize the BufSize member */ + DMA_InitParam->BufSize = 0; + /* Initialize the PeriphInc member */ + DMA_InitParam->PeriphInc = DMA_PERIPH_INC_DISABLE; + /* Initialize the DMA_MemoryInc member */ + DMA_InitParam->DMA_MemoryInc = DMA_MEM_INC_DISABLE; + /* Initialize the PeriphDataSize member */ + DMA_InitParam->PeriphDataSize = DMA_PERIPH_DATA_SIZE_BYTE; + /* Initialize the MemDataSize member */ + DMA_InitParam->MemDataSize = DMA_MemoryDataSize_Byte; + /* Initialize the CircularMode member */ + DMA_InitParam->CircularMode = DMA_MODE_NORMAL; + /* Initialize the Priority member */ + DMA_InitParam->Priority = DMA_PRIORITY_LOW; + /* Initialize the Mem2Mem member */ + DMA_InitParam->Mem2Mem = DMA_M2M_DISABLE; +} + +/** + * @brief Enables or disables the specified DMAy Channelx. + * @param DMAyChx where y can be 1 or 2 to select the DMA and + * x can be 1 to 8 for DMA1 and 1 to 8 for DMA2 to select the DMA Channel. + * @param Cmd new state of the DMAy Channelx. + * This parameter can be: ENABLE or DISABLE. + */ +void DMA_EnableChannel(DMA_ChannelType* DMAyChx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAyChx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the selected DMAy Channelx */ + DMAyChx->CHCFG |= DMA_CHCFG1_CHEN; + } + else + { + /* Disable the selected DMAy Channelx */ + DMAyChx->CHCFG &= (uint16_t)(~DMA_CHCFG1_CHEN); + } +} + +/** + * @brief Enables or disables the specified DMAy Channelx interrupts. + * @param DMAyChx where y can be 1 or 2 to select the DMA and + * x can be 1 to 8 for DMA1 and 1 to 8 for DMA2 to select the DMA Channel. + * @param DMAInt specifies the DMA interrupts sources to be enabled + * or disabled. + * This parameter can be any combination of the following values: + * @arg DMA_INT_TXC Transfer complete interrupt mask + * @arg DMA_INT_HTX Half transfer interrupt mask + * @arg DMA_INT_ERR Transfer error interrupt mask + * @param Cmd new state of the specified DMA interrupts. + * This parameter can be: ENABLE or DISABLE. + */ +void DMA_ConfigInt(DMA_ChannelType* DMAyChx, uint32_t DMAInt, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAyChx)); + assert_param(IS_DMA_CONFIG_INT(DMAInt)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected DMA interrupts */ + DMAyChx->CHCFG |= DMAInt; + } + else + { + /* Disable the selected DMA interrupts */ + DMAyChx->CHCFG &= ~DMAInt; + } +} + +/** + * @brief Sets the number of data units in the current DMAy Channelx transfer. + * @param DMAyChx where y can be 1 or 2 to select the DMA and + * x can be 1 to 8 for DMA1 and 1 to 8 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 DMAyChx is disabled. + */ +void DMA_SetCurrDataCounter(DMA_ChannelType* DMAyChx, uint16_t DataNumber) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAyChx)); + + /*--------------------------- DMAy Channelx TXNUM Configuration ---------------*/ + /* Write to DMAy Channelx TXNUM */ + DMAyChx->TXNUM = DataNumber; +} + +/** + * @brief Returns the number of remaining data units in the current + * DMAy Channelx transfer. + * @param DMAyChx where y can be 1 or 2 to select the DMA and + * x can be 1 to 8 for DMA1 and 1 to 8 for DMA2 to select the DMA Channel. + * @return The number of remaining data units in the current DMAy Channelx + * transfer. + */ +uint16_t DMA_GetCurrDataCounter(DMA_ChannelType* DMAyChx) +{ + /* Check the parameters */ + assert_param(IS_DMA_ALL_PERIPH(DMAyChx)); + /* Return the number of remaining data units for DMAy Channelx */ + return ((uint16_t)(DMAyChx->TXNUM)); +} + +/** + * @brief Checks whether the specified DMAy Channelx flag is set or not. + * @param DMAyFlag 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 DMA1_FLAG_GL8 DMA1 Channel7 global flag. + * @arg DMA1_FLAG_TC8 DMA1 Channel7 transfer complete flag. + * @arg DMA1_FLAG_HT8 DMA1 Channel7 half transfer flag. + * @arg DMA1_FLAG_TE8 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. + * @arg DMA2_FLAG_GL6 DMA1 Channel6 global flag. + * @arg DMA2_FLAG_TC6 DMA1 Channel6 transfer complete flag. + * @arg DMA2_FLAG_HT6 DMA1 Channel6 half transfer flag. + * @arg DMA2_FLAG_TE6 DMA1 Channel6 transfer error flag. + * @arg DMA2_FLAG_GL7 DMA1 Channel7 global flag. + * @arg DMA2_FLAG_TC7 DMA1 Channel7 transfer complete flag. + * @arg DMA2_FLAG_HT7 DMA1 Channel7 half transfer flag. + * @arg DMA2_FLAG_TE7 DMA1 Channel7 transfer error flag. + * @arg DMA2_FLAG_GL8 DMA1 Channel7 global flag. + * @arg DMA2_FLAG_TC8 DMA1 Channel7 transfer complete flag. + * @arg DMA2_FLAG_HT8 DMA1 Channel7 half transfer flag. + * @arg DMA2_FLAG_TE8 DMA1 Channel7 transfer error flag. + * @param DMAy DMA1 or DMA2. + * This parameter can be one of the following values: + * @arg DMA1 . + * @arg DMA2 . + * @return The new state of DMAyFlag (SET or RESET). + */ +FlagStatus DMA_GetFlagStatus(uint32_t DMAyFlag, DMA_Module* DMAy) +{ + FlagStatus bitstatus = RESET; + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_DMA_GET_FLAG(DMAyFlag)); + + /* Calculate the used DMAy */ + /* Get DMAy INTSTS register value */ + tmpregister = DMAy->INTSTS; + + /* Check the status of the specified DMAy flag */ + if ((tmpregister & DMAyFlag) != (uint32_t)RESET) + { + /* DMAyFlag is set */ + bitstatus = SET; + } + else + { + /* DMAyFlag is reset */ + bitstatus = RESET; + } + + /* Return the DMAyFlag status */ + return bitstatus; +} + +/** + * @brief Clears the DMAy Channelx's pending flags. + * @param DMAyFlag 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 DMA1_FLAG_GL8 DMA1 Channel8 global flag. + * @arg DMA1_FLAG_TC8 DMA1 Channel8 transfer complete flag. + * @arg DMA1_FLAG_HT8 DMA1 Channel8 half transfer flag. + * @arg DMA1_FLAG_TE8 DMA1 Channel8 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. + * @arg DMA2_FLAG_GL6 DMA2 Channel6 global flag. + * @arg DMA2_FLAG_TC6 DMA2 Channel6 transfer complete flag. + * @arg DMA2_FLAG_HT6 DMA2 Channel6 half transfer flag. + * @arg DMA2_FLAG_TE6 DMA2 Channel6 transfer error flag. + * @arg DMA2_FLAG_GL7 DMA2 Channel7 global flag. + * @arg DMA2_FLAG_TC7 DMA2 Channel7 transfer complete flag. + * @arg DMA2_FLAG_HT7 DMA2 Channel7 half transfer flag. + * @arg DMA2_FLAG_TE7 DMA2 Channel7 transfer error flag. + * @arg DMA2_FLAG_GL8 DMA2 Channel8 global flag. + * @arg DMA2_FLAG_TC8 DMA2 Channel8 transfer complete flag. + * @arg DMA2_FLAG_HT8 DMA2 Channel8 half transfer flag. + * @arg DMA2_FLAG_TE8 DMA2 Channel8 transfer error flag. + * @param DMAy DMA1 or DMA2. + * This parameter can be one of the following values: + * @arg DMA1 . + * @arg DMA2 . + */ +void DMA_ClearFlag(uint32_t DMAyFlag, DMA_Module* DMAy) +{ + /* Check the parameters */ + assert_param(IS_DMA_CLEAR_FLAG(DMAyFlag)); + + /* Calculate the used DMAy */ + /* Clear the selected DMAy flags */ + DMAy->INTCLR = DMAyFlag; +} + +/** + * @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_INT_GLB1 DMA1 Channel1 global interrupt. + * @arg DMA1_INT_TXC1 DMA1 Channel1 transfer complete interrupt. + * @arg DMA1_INT_HTX1 DMA1 Channel1 half transfer interrupt. + * @arg DMA1_INT_ERR1 DMA1 Channel1 transfer error interrupt. + * @arg DMA1_INT_GLB2 DMA1 Channel2 global interrupt. + * @arg DMA1_INT_TXC2 DMA1 Channel2 transfer complete interrupt. + * @arg DMA1_INT_HTX2 DMA1 Channel2 half transfer interrupt. + * @arg DMA1_INT_ERR2 DMA1 Channel2 transfer error interrupt. + * @arg DMA1_INT_GLB3 DMA1 Channel3 global interrupt. + * @arg DMA1_INT_TXC3 DMA1 Channel3 transfer complete interrupt. + * @arg DMA1_INT_HTX3 DMA1 Channel3 half transfer interrupt. + * @arg DMA1_INT_ERR3 DMA1 Channel3 transfer error interrupt. + * @arg DMA1_INT_GLB4 DMA1 Channel4 global interrupt. + * @arg DMA1_INT_TXC4 DMA1 Channel4 transfer complete interrupt. + * @arg DMA1_INT_HTX4 DMA1 Channel4 half transfer interrupt. + * @arg DMA1_INT_ERR4 DMA1 Channel4 transfer error interrupt. + * @arg DMA1_INT_GLB5 DMA1 Channel5 global interrupt. + * @arg DMA1_INT_TXC5 DMA1 Channel5 transfer complete interrupt. + * @arg DMA1_INT_HTX5 DMA1 Channel5 half transfer interrupt. + * @arg DMA1_INT_ERR5 DMA1 Channel5 transfer error interrupt. + * @arg DMA1_INT_GLB6 DMA1 Channel6 global interrupt. + * @arg DMA1_INT_TXC6 DMA1 Channel6 transfer complete interrupt. + * @arg DMA1_INT_HTX6 DMA1 Channel6 half transfer interrupt. + * @arg DMA1_INT_ERR6 DMA1 Channel6 transfer error interrupt. + * @arg DMA1_INT_GLB7 DMA1 Channel7 global interrupt. + * @arg DMA1_INT_TXC7 DMA1 Channel7 transfer complete interrupt. + * @arg DMA1_INT_HTX7 DMA1 Channel7 half transfer interrupt. + * @arg DMA1_INT_ERR7 DMA1 Channel7 transfer error interrupt. + * @arg DMA1_INT_GLB8 DMA1 Channel8 global interrupt. + * @arg DMA1_INT_TXC8 DMA1 Channel8 transfer complete interrupt. + * @arg DMA1_INT_HTX8 DMA1 Channel8 half transfer interrupt. + * @arg DMA1_INT_ERR8 DMA1 Channel8 transfer error interrupt. + * @arg DMA2_INT_GLB1 DMA2 Channel1 global interrupt. + * @arg DMA2_INT_TXC1 DMA2 Channel1 transfer complete interrupt. + * @arg DMA2_INT_HTX1 DMA2 Channel1 half transfer interrupt. + * @arg DMA2_INT_ERR1 DMA2 Channel1 transfer error interrupt. + * @arg DMA2_INT_GLB2 DMA2 Channel2 global interrupt. + * @arg DMA2_INT_TXC2 DMA2 Channel2 transfer complete interrupt. + * @arg DMA2_INT_HTX2 DMA2 Channel2 half transfer interrupt. + * @arg DMA2_INT_ERR2 DMA2 Channel2 transfer error interrupt. + * @arg DMA2_INT_GLB3 DMA2 Channel3 global interrupt. + * @arg DMA2_INT_TXC3 DMA2 Channel3 transfer complete interrupt. + * @arg DMA2_INT_HTX3 DMA2 Channel3 half transfer interrupt. + * @arg DMA2_INT_ERR3 DMA2 Channel3 transfer error interrupt. + * @arg DMA2_INT_GLB4 DMA2 Channel4 global interrupt. + * @arg DMA2_INT_TXC4 DMA2 Channel4 transfer complete interrupt. + * @arg DMA2_INT_HTX4 DMA2 Channel4 half transfer interrupt. + * @arg DMA2_INT_ERR4 DMA2 Channel4 transfer error interrupt. + * @arg DMA2_INT_GLB5 DMA2 Channel5 global interrupt. + * @arg DMA2_INT_TXC5 DMA2 Channel5 transfer complete interrupt. + * @arg DMA2_INT_HTX5 DMA2 Channel5 half transfer interrupt. + * @arg DMA2_INT_ERR5 DMA2 Channel5 transfer error interrupt. + * @arg DMA2_INT_GLB6 DMA2 Channel6 global interrupt. + * @arg DMA2_INT_TXC6 DMA2 Channel6 transfer complete interrupt. + * @arg DMA2_INT_HTX6 DMA2 Channel6 half transfer interrupt. + * @arg DMA2_INT_ERR6 DMA2 Channel6 transfer error interrupt. + * @arg DMA2_INT_GLB7 DMA2 Channel7 global interrupt. + * @arg DMA2_INT_TXC7 DMA2 Channel7 transfer complete interrupt. + * @arg DMA2_INT_HTX7 DMA2 Channel7 half transfer interrupt. + * @arg DMA2_INT_ERR7 DMA2 Channel7 transfer error interrupt. + * @arg DMA2_INT_GLB8 DMA2 Channel8 global interrupt. + * @arg DMA2_INT_TXC8 DMA2 Channel8 transfer complete interrupt. + * @arg DMA2_INT_HTX8 DMA2 Channel8 half transfer interrupt. + * @arg DMA2_INT_ERR8 DMA2 Channel8 transfer error interrupt. + * @param DMAy DMA1 or DMA2. + * This parameter can be one of the following values: + * @arg DMA1 . + * @arg DMA2 . + * @return The new state of DMAy_IT (SET or RESET). + */ +INTStatus DMA_GetIntStatus(uint32_t DMAy_IT, DMA_Module* DMAy) +{ + INTStatus bitstatus = RESET; + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_DMA_GET_IT(DMAy_IT)); + + /* Calculate the used DMA */ + /* Get DMAy INTSTS register value */ + tmpregister = DMAy->INTSTS; + + /* Check the status of the specified DMAy interrupt */ + if ((tmpregister & DMAy_IT) != (uint32_t)RESET) + { + /* DMAy_IT is set */ + bitstatus = SET; + } + else + { + /* DMAy_IT is reset */ + bitstatus = RESET; + } + /* Return the DMAInt 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_INT_GLB1 DMA1 Channel1 global interrupt. + * @arg DMA1_INT_TXC1 DMA1 Channel1 transfer complete interrupt. + * @arg DMA1_INT_HTX1 DMA1 Channel1 half transfer interrupt. + * @arg DMA1_INT_ERR1 DMA1 Channel1 transfer error interrupt. + * @arg DMA1_INT_GLB2 DMA1 Channel2 global interrupt. + * @arg DMA1_INT_TXC2 DMA1 Channel2 transfer complete interrupt. + * @arg DMA1_INT_HTX2 DMA1 Channel2 half transfer interrupt. + * @arg DMA1_INT_ERR2 DMA1 Channel2 transfer error interrupt. + * @arg DMA1_INT_GLB3 DMA1 Channel3 global interrupt. + * @arg DMA1_INT_TXC3 DMA1 Channel3 transfer complete interrupt. + * @arg DMA1_INT_HTX3 DMA1 Channel3 half transfer interrupt. + * @arg DMA1_INT_ERR3 DMA1 Channel3 transfer error interrupt. + * @arg DMA1_INT_GLB4 DMA1 Channel4 global interrupt. + * @arg DMA1_INT_TXC4 DMA1 Channel4 transfer complete interrupt. + * @arg DMA1_INT_HTX4 DMA1 Channel4 half transfer interrupt. + * @arg DMA1_INT_ERR4 DMA1 Channel4 transfer error interrupt. + * @arg DMA1_INT_GLB5 DMA1 Channel5 global interrupt. + * @arg DMA1_INT_TXC5 DMA1 Channel5 transfer complete interrupt. + * @arg DMA1_INT_HTX5 DMA1 Channel5 half transfer interrupt. + * @arg DMA1_INT_ERR5 DMA1 Channel5 transfer error interrupt. + * @arg DMA1_INT_GLB6 DMA1 Channel6 global interrupt. + * @arg DMA1_INT_TXC6 DMA1 Channel6 transfer complete interrupt. + * @arg DMA1_INT_HTX6 DMA1 Channel6 half transfer interrupt. + * @arg DMA1_INT_ERR6 DMA1 Channel6 transfer error interrupt. + * @arg DMA1_INT_GLB7 DMA1 Channel7 global interrupt. + * @arg DMA1_INT_TXC7 DMA1 Channel7 transfer complete interrupt. + * @arg DMA1_INT_HTX7 DMA1 Channel7 half transfer interrupt. + * @arg DMA1_INT_ERR7 DMA1 Channel7 transfer error interrupt. + * @arg DMA1_INT_GLB8 DMA1 Channel8 global interrupt. + * @arg DMA1_INT_TXC8 DMA1 Channel8 transfer complete interrupt. + * @arg DMA1_INT_HTX8 DMA1 Channel8 half transfer interrupt. + * @arg DMA1_INT_ERR8 DMA1 Channel8 transfer error interrupt. + * @arg DMA2_INT_GLB1 DMA2 Channel1 global interrupt. + * @arg DMA2_INT_TXC1 DMA2 Channel1 transfer complete interrupt. + * @arg DMA2_INT_HTX1 DMA2 Channel1 half transfer interrupt. + * @arg DMA2_INT_ERR1 DMA2 Channel1 transfer error interrupt. + * @arg DMA2_INT_GLB2 DMA2 Channel2 global interrupt. + * @arg DMA2_INT_TXC2 DMA2 Channel2 transfer complete interrupt. + * @arg DMA2_INT_HTX2 DMA2 Channel2 half transfer interrupt. + * @arg DMA2_INT_ERR2 DMA2 Channel2 transfer error interrupt. + * @arg DMA2_INT_GLB3 DMA2 Channel3 global interrupt. + * @arg DMA2_INT_TXC3 DMA2 Channel3 transfer complete interrupt. + * @arg DMA2_INT_HTX3 DMA2 Channel3 half transfer interrupt. + * @arg DMA2_INT_ERR3 DMA2 Channel3 transfer error interrupt. + * @arg DMA2_INT_GLB4 DMA2 Channel4 global interrupt. + * @arg DMA2_INT_TXC4 DMA2 Channel4 transfer complete interrupt. + * @arg DMA2_INT_HTX4 DMA2 Channel4 half transfer interrupt. + * @arg DMA2_INT_ERR4 DMA2 Channel4 transfer error interrupt. + * @arg DMA2_INT_GLB5 DMA2 Channel5 global interrupt. + * @arg DMA2_INT_TXC5 DMA2 Channel5 transfer complete interrupt. + * @arg DMA2_INT_HTX5 DMA2 Channel5 half transfer interrupt. + * @arg DMA2_INT_ERR5 DMA2 Channel5 transfer error interrupt. + * @arg DMA2_INT_GLB6 DMA2 Channel6 global interrupt. + * @arg DMA2_INT_TXC6 DMA2 Channel6 transfer complete interrupt. + * @arg DMA2_INT_HTX6 DMA2 Channel6 half transfer interrupt. + * @arg DMA2_INT_ERR6 DMA2 Channel6 transfer error interrupt. + * @arg DMA2_INT_GLB7 DMA2 Channel7 global interrupt. + * @arg DMA2_INT_TXC7 DMA2 Channel7 transfer complete interrupt. + * @arg DMA2_INT_HTX7 DMA2 Channel7 half transfer interrupt. + * @arg DMA2_INT_ERR7 DMA2 Channel7 transfer error interrupt. + * @arg DMA2_INT_GLB8 DMA2 Channel8 global interrupt. + * @arg DMA2_INT_TXC8 DMA2 Channel8 transfer complete interrupt. + * @arg DMA2_INT_HTX8 DMA2 Channel8 half transfer interrupt. + * @arg DMA2_INT_ERR8 DMA2 Channel8 transfer error interrupt. + * @param DMAy DMA1 or DMA2. + * This parameter can be one of the following values: + * @arg DMA1 . + * @arg DMA2 . + */ +void DMA_ClrIntPendingBit(uint32_t DMAy_IT, DMA_Module* DMAy) +{ + /* Check the parameters */ + assert_param(IS_DMA_CLR_INT(DMAy_IT)); + + /* Calculate the used DMAy */ + /* Clear the selected DMAy interrupt pending bits */ + DMAy->INTCLR = DMAy_IT; +} + +/** + * @brief Set the DMAy Channelx's remap request. + * @param DMAy_REMAP specifies the DMAy request. + * This parameter can be set by the following values: + * @arg DMA1_REMAP_ADC1 DMA1 Request For ADC1. + * @arg DMA1_REMAP_UART5_TX DMA1 Request For UART5_TX. + * @arg DMA1_REMAP_I2C3_TX DMA1 Request For I2C3_TX. + * @arg DMA1_REMAP_TIM2_CH3 DMA1 Request For TIM2_CH3. + * @arg DMA1_REMAP_TIM4_CH1 DMA1 Request For TIM4_CH1. + * @arg DMA1_REMAP_USART3_TX DMA1 Request For USART3_TX. + * @arg DMA1_REMAP_I2C3_RX DMA1 Request For I2C3_RX. + * @arg DMA1_REMAP_TIM1_CH1 DMA1 Request For TIM1_CH1. + * @arg DMA1_REMAP_TIM2_UP DMA1 Request For TIM2_UP. + * @arg DMA1_REMAP_TIM3_CH3 DMA1 Request For TIM3_CH3. + * @arg DMA1_REMAP_SPI1_RX DMA1 Request For SPI1_RX. + * @arg DMA1_REMAP_USART3_RX DMA1 Request For USART3_RX. + * @arg DMA1_REMAP_TIM1_CH2 DMA1 Request For TIM1_CH2. + * @arg DMA1_REMAP_TIM3_CH4 DMA1 Request For TIM3_CH4. + * @arg DMA1_REMAP_TIM3_UP DMA1 Request For TIM3_UP. + * @arg DMA1_REMAP_SPI1_TX DMA1 Request For SPI1_TX. + * @arg DMA1_REMAP_USART1_TX DMA1 Request For USART1_TX. + * @arg DMA1_REMAP_TIM1_CH4 DMA1 Request For TIM1_CH4. + * @arg DMA1_REMAP_TIM1_TRIG DMA1 Request For TIM1_TRIG. + * @arg DMA1_REMAP_TIM1_COM DMA1 Request For TIM1_COM. + * @arg DMA1_REMAP_TIM4_CH2 DMA1 Request For TIM4_CH2. + * @arg DMA1_REMAP_SPI_I2S2_RX DMA1 Request For SPI_I2S2_RX. + * @arg DMA1_REMAP_I2C2_TX DMA1 Request For I2C2_TX. + * @arg DMA1_REMAP_USART1_RX DMA1 Request For USART1_RX. + * @arg DMA1_REMAP_TIM1_UP DMA1 Request For TIM1_UP. + * @arg DMA1_REMAP_SPI_I2S2_TX DMA1 Request For SPI_I2S2_TX. + * @arg DMA1_REMAP_TIM4_CH3 DMA1 Request For TIM4_CH3. + * @arg DMA1_REMAP_I2C2_RX DMA1 Request For I2C2_RX. + * @arg DMA1_REMAP_TIM2_CH1 DMA1 Request For TIM2_CH1. + * @arg DMA1_REMAP_USART2_RX DMA1 Request For USART2_RX. + * @arg DMA1_REMAP_TIM1_CH3 DMA1 Request For TIM1_CH3. + * @arg DMA1_REMAP_TIM3_CH1 DMA1 Request For TIM3_CH1. + * @arg DMA1_REMAP_TIM3_TRIG DMA1 Request For TIM3_TRIG. + * @arg DMA1_REMAP_I2C1_TX DMA1 Request For I2C1_TX. + * @arg DMA1_REMAP_USART2_TX DMA1 Request For USART2_TX. + * @arg DMA1_REMAP_TIM2_CH2 DMA1 Request For TIM2_CH2. + * @arg DMA1_REMAP_TIM2_CH4 DMA1 Request For TIM2_CH4. + * @arg DMA1_REMAP_TIM4_UP DMA1 Request For TIM4_UP. + * @arg DMA1_REMAP_I2C1_RX DMA1 Request For I2C1_RX. + * @arg DMA1_REMAP_ADC2 DMA1 Request For ADC2. + * @arg DMA1_REMAP_UART5_RX DMA1 Request For UART5_RX. + * @arg DMA2_REMAP_TIM5_CH4 DMA2 Request For TIM5_CH4. + * @arg DMA2_REMAP_TIM5_TRIG DMA2 Request For TIM5_TRIG. + * @arg DMA2_REMAP_TIM8_CH3 DMA2 Request For TIM8_CH3. + * @arg DMA2_REMAP_TIM8_UP DMA2 Request For TIM8_UP. + * @arg DMA2_REMAP_SPI_I2S3_RX DMA2 Request For SPI_I2S3_RX. + * @arg DMA2_REMAP_UART6_RX DMA2 Request For UART6_RX. + * @arg DMA2_REMAP_TIM8_CH4 DMA2 Request For TIM8_CH4. + * @arg DMA2_REMAP_TIM8_TRIG DMA2 Request For TIM8_TRIG. + * @arg DMA2_REMAP_TIM8_COM DMA2 Request For TIM8_COM. + * @arg DMA2_REMAP_TIM5_CH3 DMA2 Request For TIM5_CH3. + * @arg DMA2_REMAP_TIM5_UP DMA2 Request For TIM5_UP. + * @arg DMA2_REMAP_SPI_I2S3_TX DMA2 Request For SPI_I2S3_TX. + * @arg DMA2_REMAP_UART6_TX DMA2 Request For UART6_TX. + * @arg DMA2_REMAP_TIM8_CH1 DMA2 Request For TIM8_CH1. + * @arg DMA2_REMAP_UART4_RX DMA2 Request For UART4_RX. + * @arg DMA2_REMAP_TIM6_UP DMA2 Request For TIM6_UP. + * @arg DMA2_REMAP_DAC1 DMA2 Request For DAC1. + * @arg DMA2_REMAP_TIM5_CH2 DMA2 Request For TIM5_CH2. + * @arg DMA2_REMAP_SDIO DMA2 Request For SDIO. + * @arg DMA2_REMAP_TIM7_UP DMA2 Request For TIM7_UP. + * @arg DMA2_REMAP_DAC2 DMA2 Request For DAC2. + * @arg DMA2_REMAP_ADC3 DMA2 Request For ADC3. + * @arg DMA2_REMAP_TIM8_CH2 DMA2 Request For TIM8_CH2. + * @arg DMA2_REMAP_TIM5_CH1 DMA2 Request For TIM5_CH1. + * @arg DMA2_REMAP_UART4_TX DMA2 Request For UART4_TX. + * @arg DMA2_REMAP_QSPI_RX DMA2 Request For QSPI_RX. + * @arg DMA2_REMAP_I2C4_TX DMA2 Request For I2C4_TX. + * @arg DMA2_REMAP_UART7_RX DMA2 Request For UART7_RX. + * @arg DMA2_REMAP_QSPI_TX DMA2 Request For QSPI_TX. + * @arg DMA2_REMAP_I2C4_RX DMA2 Request For I2C4_RX. + * @arg DMA2_REMAP_UART7_TX DMA2 Request For UART7_TX. + * @arg DMA2_REMAP_ADC4 DMA2 Request For ADC4. + * @arg DMA2_REMAP_DVP DMA2 Request For DVP. + * @param DMAy DMA1 or DMA2. + * This parameter can be one of the following values: + * @arg DMA1 . + * @arg DMA2 . + * @param DMAyChx where y can be 1 or 2 to select the DMA and + * x can be 1 to 8 for DMA1 and 1 to 8 for DMA2 to select the DMA Channel. + * @param Cmd new state of the DMAy Channelx. + * This parameter can be: ENABLE or DISABLE. + */ +void DMA_RequestRemap(uint32_t DMAy_REMAP, DMA_Module* DMAy, DMA_ChannelType* DMAyChx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_DMA_REMAP(DMAy_REMAP)); + + if (Cmd != DISABLE) + { + /* Calculate the used DMAy */ + /* Set the selected DMAy remap request */ + DMAyChx->CHSEL = DMAy_REMAP; + DMAy->CHMAPEN = 1; + } + else + { + DMAy->CHMAPEN = 0; + } +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/src/n32g45x_dvp.c b/src/n32g45x_dvp.c new file mode 100644 index 0000000..3672816 --- /dev/null +++ b/src/n32g45x_dvp.c @@ -0,0 +1,166 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_dvp.c + * @author Nations + * @version v1.0.2 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_dvp.h" +#include "n32g45x_rcc.h" + +/** + * @brief Deinitializes the DVP peripheral registers to their default reset values. + * @param None + * @retval None + */ +void DVP_ResetReg(void) +{ + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_DVP, ENABLE); + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_DVP, DISABLE); +} + +/** + * @brief Initializes the DVP peripheral according to the specified + * parameters in the DVP_InitStruct . + * @param DVP_InitStruct pointer to a DVP_InitType structure + * that contains the configuration information for the specified DVP + * peripheral. + * @retval None + */ +void DVP_Init( DVP_InitType* DVP_InitStruct) +{ + uint32_t tmpregister = 0x00; + + /* Check the parameters */ + assert_param(IS_DVP_LINE_CAPTURE(DVP_InitStruct->LineCapture)); + assert_param(IS_DVP_BYTE_CAPTURE(DVP_InitStruct->ByteCapture)); + assert_param(IS_DVP_DATA_INVERT(DVP_InitStruct->DataInvert)); + assert_param(IS_DVP_PIXEL_POLARITY(DVP_InitStruct->PixelClkPolarity)); + assert_param(IS_DVP_VSYNC_POLARITY(DVP_InitStruct->VsyncPolarity)); + assert_param(IS_DVP_HSYNC_POLARITY(DVP_InitStruct->HsyncPolarity)); + assert_param(IS_DVP_CAPTURE_MODE(DVP_InitStruct->CaptureMode)); + assert_param(IS_DVP_FIFOWATERMARK(DVP_InitStruct->FifoWatermark)); + + /*---------------------------- DVP CTRL Configuration -----------------------*/ + tmpregister = 0; + tmpregister |= DVP_InitStruct->LineCapture | DVP_InitStruct->ByteCapture + | DVP_InitStruct->DataInvert | DVP_InitStruct->PixelClkPolarity + | DVP_InitStruct->VsyncPolarity | DVP_InitStruct->HsyncPolarity + | DVP_InitStruct->CaptureMode | DVP_InitStruct->FifoWatermark; + DVP->CTRL = tmpregister; + + /*---------------------------- DVP WST Configuration -----------------------*/ + if (DVP_InitStruct->RowStart) + DVP_InitStruct->RowStart--; + + if (DVP_InitStruct->ColumnStart) + DVP_InitStruct->ColumnStart--; + + DVP->WST = ( (((uint32_t)(DVP_InitStruct->RowStart)) << DVP_WST_VST_SHIFT) \ + | (((uint32_t)(DVP_InitStruct->ColumnStart))<< DVP_WST_HST_SHIFT) ); + + /*---------------------------- DVP WSIZE Configuration -----------------------*/ + DVP->WSIZE = ( (((uint32_t)(DVP_InitStruct->ImageHeight-1)) << DVP_WSIZE_VLINE_SHIFT) \ + | (((uint32_t)(DVP_InitStruct->ImageWidth-1)) << DVP_WSIZE_HCNT_SHIFT) ); +} + +/** + * @brief Fills DVP_InitStruct member with its default value. + * @param DVP_InitStruct pointer to a DVP_InitType structure + * which will be initialized. + * @retval None + */ +void DVP_DafaultInitParam(DVP_InitType* DVP_InitStruct) +{ + /* DVP_InitStruct members default value */ + DVP_InitStruct->FifoWatermark = DVP_WATER_MARK_1; + DVP_InitStruct->LineCapture = DVP_LINE_CAPTURE_ALL; + DVP_InitStruct->ByteCapture = DVP_BYTE_CAPTURE_ALL; + DVP_InitStruct->DataInvert = DVP_DATA_NOTINVERT; + DVP_InitStruct->PixelClkPolarity = DVP_PIXEL_POLARITY_FALLING; + DVP_InitStruct->VsyncPolarity = DVP_VSYNC_POLARITY_LOW; + DVP_InitStruct->HsyncPolarity = DVP_HSYNC_POLARITY_HIGH; + DVP_InitStruct->CaptureMode = DVP_CAPTURE_MODE_SINGLE; + DVP_InitStruct->RowStart = 0; + DVP_InitStruct->ColumnStart = 0; + DVP_InitStruct->ImageHeight = 240; + DVP_InitStruct->ImageWidth = 320; +} + +/** + * @brief Enables or disables the DVP DMA interface. + * @param Cmd New state of the DMA Request. + * This parameter can be: ENABLE or DISABLE. + * @retval None + */ +void DVP_ConfigDma( FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* When DMA is enable, the FWM in CTRL1 should be set 1*/ + __DVP_SetFifoWatermark(DVP_WATER_MARK_1); + + __DVP_EnableDMA(); + } + else + { + __DVP_DisableDMA(); + } +} + +/** + * @brief Get the data length in FIFO. + * @param None. + * @retval Current date length in FIFO + */ +uint32_t DVP_GetFifoCount(void) +{ + if (__FIFOIsNotEmpty()) + return ((DVP->STS & DVP_STS_FCNT_MASK)>>DVP_STS_FCNT_SHIFT); + else + return 0; +} + +/** + * @brief Software Reset FIFO + * @param None. + * @retval None. + */ +void DVP_ResetFifo(void) +{ + __DVP_StopCapture(); + + DVP->CTRL |= DVP_FIFO_SOFT_RESET; + + while(DVP->CTRL & DVP_FIFO_SOFT_RESET); +} diff --git a/src/n32g45x_eth.c b/src/n32g45x_eth.c new file mode 100644 index 0000000..ec645ee --- /dev/null +++ b/src/n32g45x_eth.c @@ -0,0 +1,3100 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_eth.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_eth.h" +#include "n32g45x_gpio.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup ETH + * @brief ETH driver modules + * @{ + */ + +/** + * @brief Initialize GPIO pins for MII/RMII interface. + * + * @param ETH_Interface specifies the interface, can be the following values: + * @arg ETH_INTERFACE_RMII Reduced media-independent interface + * @arg ETH_INTERFACE_MII Media-independent interface + * @param remap remap mode, can be 0~3 + */ +void ETH_ConfigGpio(uint8_t ETH_Interface, uint8_t remap) +{ + GPIO_InitType GPIO_InitStructure; + uint32_t ETH_PA_O; + uint32_t ETH_PA_I; + uint32_t ETH_PB_O; + uint32_t ETH_PB_I; + uint32_t ETH_PC_O; + uint32_t ETH_PC_I; + uint32_t ETH_PD_O; + uint32_t ETH_PD_I; + if (ETH_Interface == ETH_INTERFACE_MII) + { + switch (remap) + { + case 0: + ETH_PA_O = GPIO_PIN_2; + ETH_PA_I = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3 | GPIO_PIN_7; + ETH_PB_O = GPIO_PIN_8 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13; + ETH_PB_I = GPIO_PIN_10 | GPIO_PIN_0 | GPIO_PIN_1; + ETH_PC_O = GPIO_PIN_1 | GPIO_PIN_2; + ETH_PC_I = GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5; + ETH_PD_O = 0; + ETH_PD_I = 0; + break; + case 1: + ETH_PA_O = GPIO_PIN_2; + ETH_PA_I = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3; + ETH_PB_O = GPIO_PIN_8 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13; + ETH_PB_I = GPIO_PIN_10; + ETH_PC_O = GPIO_PIN_1 | GPIO_PIN_2; + ETH_PC_I = GPIO_PIN_3; + ETH_PD_O = 0; + ETH_PD_I = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12; + GPIO_ConfigPinRemap(GPIO_RMP1_ETH, ENABLE); + break; + case 2: + ETH_PA_O = GPIO_PIN_2; + ETH_PA_I = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3 | GPIO_PIN_7; + ETH_PB_O = GPIO_PIN_7 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13; + ETH_PB_I = GPIO_PIN_10 | GPIO_PIN_0 | GPIO_PIN_1; + ETH_PC_O = GPIO_PIN_1 | GPIO_PIN_2; + ETH_PC_I = GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5; + ETH_PD_O = 0; + ETH_PD_I = 0; + GPIO_ConfigPinRemap(GPIO_RMP2_ETH, ENABLE); + break; + case 3: + ETH_PA_O = GPIO_PIN_2; + ETH_PA_I = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3; + ETH_PB_O = GPIO_PIN_7 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13; + ETH_PB_I = GPIO_PIN_10 | GPIO_PIN_0 | GPIO_PIN_1; + ETH_PC_O = GPIO_PIN_1 | GPIO_PIN_2; + ETH_PC_I = GPIO_PIN_3; + ETH_PD_O = 0; + ETH_PD_I = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10; + GPIO_ConfigPinRemap(GPIO_RMP3_ETH, ENABLE); + break; + default: + while (1) + ; + } + } + else /* RMII */ + { + switch (remap) + { + case 0: + case 2: + ETH_PA_O = GPIO_PIN_2; + ETH_PA_I = GPIO_PIN_1 | GPIO_PIN_7; + ETH_PB_O = GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13; + ETH_PB_I = 0; + ETH_PC_O = GPIO_PIN_1; + ETH_PC_I = GPIO_PIN_4 | GPIO_PIN_5; + ETH_PD_O = 0; + ETH_PD_I = 0; + break; + case 1: + case 3: + ETH_PA_O = GPIO_PIN_2; + ETH_PA_I = GPIO_PIN_1; + ETH_PB_O = GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13; + ETH_PB_I = 0; + ETH_PC_O = GPIO_PIN_1; + ETH_PC_I = 0; + ETH_PD_O = 0; + ETH_PD_I = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10; + GPIO_ConfigPinRemap(GPIO_RMP1_ETH, ENABLE); + break; + default: + while (1) + ; + } + } + if (ETH_PA_O) + { + /* Configure Ethernet PA and PA8 (MCO) as alternate function push-pull */ + GPIO_InitStructure.Pin = ETH_PA_O; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure); + } + if (ETH_PB_O) + { + /* Configure Ethernet PB and PB5 (PPS) as alternate function push-pull */ + GPIO_InitStructure.Pin = ETH_PB_O; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure); + } + if (ETH_PC_O) + { + /* Configure Ethernet PC as alternate function push-pull */ + GPIO_InitStructure.Pin = ETH_PC_O; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitPeripheral(GPIOC, &GPIO_InitStructure); + } + if (ETH_PD_O) + { + /* Configure Ethernet PD as alternate function push-pull */ + GPIO_InitStructure.Pin = ETH_PD_O; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitPeripheral(GPIOD, &GPIO_InitStructure); + } + + if (ETH_PA_I) + { + /* Configure Ethernet PA as input */ + GPIO_InitStructure.Pin = ETH_PA_I; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure); + } + if (ETH_PB_I) + { + /* Configure Ethernet PB as input */ + GPIO_InitStructure.Pin = ETH_PB_I; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure); + } + if (ETH_PC_I) + { + /* Configure Ethernet PC as input */ + GPIO_InitStructure.Pin = ETH_PC_I; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitPeripheral(GPIOC, &GPIO_InitStructure); + } + if (ETH_PD_I) + { + /* Configure Ethernet PD as input */ + GPIO_InitStructure.Pin = ETH_PD_I; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitPeripheral(GPIOD, &GPIO_InitStructure); + } +} + +/** @addtogroup ETH_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + +/** @addtogroup ETH_Private_Defines + * @{ + */ +/* Global pointers on Tx and Rx descriptor used to track transmit and receive descriptors */ +__IO ETH_DMADescType* DMATxDescToSet; +__IO ETH_DMADescType* DMARxDescToGet; +__IO ETH_DMADescType* DMAPTPTxDescToSet; +__IO ETH_DMADescType* DMAPTPRxDescToGet; + +/* ETHERNET MAC address offsets */ +#define ETH_MAC_ADDR_HBASE (ETH_MAC_BASE + 0x40) /* ETHERNET MAC address high offset */ +#define ETH_MAC_ADDR_LBASE (ETH_MAC_BASE + 0x44) /* ETHERNET MAC address low offset */ + +/* ETHERNET MACMIIADDR register Mask */ +#define MACMIIAR_CR_MASK ((uint32_t)0xFFFFFFE3) + +/* ETHERNET MACCFG register Mask */ +#define MACCR_CLR_MASK ((uint32_t)0xFF20810F) + +/* ETHERNET MACFLWCTRL register Mask */ +#define MACFCR_CLR_MASK ((uint32_t)0x0000FF41) + +/* ETHERNET DMAOPMOD register Mask */ +#define DMAOMR_CLR_MASK ((uint32_t)0xF8DE3F23) + +/* ETHERNET Remote Wake-up frame register length */ +#define ETH_WAKEUP_REG_LEN 8 + +/* ETHERNET Missed frames counter Shift */ +#define ETH_DMA_RX_OVERFLOW_MISSEDFRAMES_COUNTER_SHIFT 17 + +/* ETHERNET DMA Tx descriptors Collision Count Shift */ +#define ETH_DMA_TX_DESC_COLLISION_COUNTER_SHIFT 3 + +/* ETHERNET DMA Tx descriptors Buffer2 Size Shift */ +#define ETH_DMA_TX_DESC_BUF2_SIZE_SHIFT 11 + +/* ETHERNET DMA Rx descriptors Frame Length Shift */ +#define ETH_DMA_RX_DESC_FRAME_LEN_SHIFT 16 + +/* ETHERNET DMA Rx descriptors Buffer2 Size Shift */ +#define ETH_DMA_RX_DESC_BUF2_SIZE_SHIFT 11 + +/** + * @} + */ + +/** @addtogroup ETH_Private_Macros + * @{ + */ +/** + * @} + */ + +/** @addtogroup ETH_Private_Variables + * @{ + */ +/** + * @} + */ + +/** @addtogroup ETH_Private_FunctionPrototypes + * @{ + */ +/** + * @} + */ + +/** @addtogroup ETH_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the ETHERNET peripheral registers to their default reset values. + */ +void ETH_DeInit(void) +{ + RCC_EnableAHBPeriphReset(RCC_AHB_PERIPH_ETHMAC, ENABLE); + RCC_EnableAHBPeriphReset(RCC_AHB_PERIPH_ETHMAC, DISABLE); +} +/** + * @brief Initializes the ETHERNET peripheral according to the specified + * parameters in the ETH_InitStruct . + * @param ETH_InitStruct pointer to a ETH_InitType structure that contains + * the configuration information for the specified ETHERNET peripheral. + * @param callable a function pointer of @ref ETH_InitPHY + * @return ETH_ERROR: Ethernet initialization failed + * ETH_SUCCESS: Ethernet successfully initialized + */ +uint32_t ETH_Init(ETH_InitType* ETH_InitStruct, ETH_InitPHY callable) +{ + uint32_t tmpregister = 0; + RCC_ClocksType rcc_clocks; + uint32_t hclk = 60000000; + /* Check the parameters */ + /* MAC --------------------------*/ + assert_param(IS_ETH_AUTONEG(ETH_InitStruct->AutoNegotiation)); + assert_param(IS_ETH_WATCHDOG(ETH_InitStruct->Watchdog)); + assert_param(IS_ETH_JABBER(ETH_InitStruct->Jabber)); + assert_param(IS_ETH_INTER_FRAME_GAP(ETH_InitStruct->InterFrameGap)); + assert_param(IS_ETH_CARRIER_SENSE(ETH_InitStruct->CarrierSense)); + assert_param(IS_ETH_SPEED_MODE(ETH_InitStruct->SpeedMode)); + assert_param(IS_ETH_RX_OWN(ETH_InitStruct->RxOwn)); + assert_param(IS_ETH_LOOPBACK_MODE(ETH_InitStruct->LoopbackMode)); + assert_param(IS_ETH_DUPLEX_MODE(ETH_InitStruct->DuplexMode)); + assert_param(IS_ETH_CHECKSUM_OFFLOAD(ETH_InitStruct->ChecksumOffload)); + assert_param(IS_ETH_RETRY_TRANSMISSION(ETH_InitStruct->RetryTransmission)); + assert_param(IS_ETH_AUTO_PAD_CRC_STRIP(ETH_InitStruct->AutomaticPadCRCStrip)); + assert_param(IS_ETH_BACKOFF_LIMIT(ETH_InitStruct->BackoffLimit)); + assert_param(IS_ETH_DEFERRAL_CHECK(ETH_InitStruct->DeferralCheck)); + assert_param(IS_ETH_RX_ALL(ETH_InitStruct->RxAll)); + assert_param(IS_ETH_SRC_ADDR_FILTER(ETH_InitStruct->SrcAddrFilter)); + assert_param(IS_ETH_PASS_CTRL_FRAMES(ETH_InitStruct->PassCtrlFrames)); + assert_param(IS_ETH_BROADCAST_FRAMES_RECEPTION(ETH_InitStruct->BroadcastFramesReception)); + assert_param(IS_ETH_DEST_ADDR_FILTER(ETH_InitStruct->DestAddrFilter)); + assert_param(IS_ETH_PROMISCUOUS_MODE(ETH_InitStruct->PromiscuousMode)); + assert_param(IS_ETH_MULTICAST_FRAMES_FILTER(ETH_InitStruct->MulticastFramesFilter)); + assert_param(IS_ETH_UNICAST_FRAMES_FILTER(ETH_InitStruct->UnicastFramesFilter)); + assert_param(IS_ETH_PAUSE_TIME(ETH_InitStruct->PauseTime)); + assert_param(IS_ETH_ZERO_QUANTA_PAUSE(ETH_InitStruct->ZeroQuantaPause)); + assert_param(IS_ETH_PAUSE_LOW_THRESHOLD(ETH_InitStruct->PauseLowThreshold)); + assert_param(IS_ETH_UNICAST_PAUSE_FRAME_DETECT(ETH_InitStruct->UnicastPauseFrameDetect)); + assert_param(IS_ETH_RX_FLOW_CTRL(ETH_InitStruct->RxFlowCtrl)); + assert_param(IS_ETH_TX_FLOW_CTRL(ETH_InitStruct->TxFlowCtrl)); + assert_param(IS_ETH_VLAN_TAG_COMPARISON(ETH_InitStruct->VLANTagComparison)); + assert_param(IS_ETH_VLAN_TAG_IDENTIFIER(ETH_InitStruct->VLANTagIdentifier)); + /* DMA --------------------------*/ + assert_param(IS_ETH_DROP_TCPIP_CHECKSUM_FRAME(ETH_InitStruct->DropTCPIPChecksumErrorFrame)); + assert_param(IS_ETH_RX_STORE_FORWARD(ETH_InitStruct->RxStoreForward)); + assert_param(IS_ETH_FLUSH_RX_FRAME(ETH_InitStruct->FlushRxFrame)); + assert_param(IS_ETH_TX_STORE_FORWARD(ETH_InitStruct->TxStoreForward)); + assert_param(IS_ETH_TX_THRESHOLD_CTRL(ETH_InitStruct->TxThresholdCtrl)); + assert_param(IS_ETH_FORWARD_ERROR_FRAMES(ETH_InitStruct->ForwardErrorFrames)); + assert_param(IS_ETH_FORWARD_UNDERSIZED_GOOD_FRAMES(ETH_InitStruct->ForwardUndersizedGoodFrames)); + assert_param(IS_ETH_RX_THRESHOLD_CTRL(ETH_InitStruct->RxThresholdCtrl)); + assert_param(IS_ETH_SECOND_FRAME_OPERATE(ETH_InitStruct->SecondFrameOperate)); + assert_param(IS_ETH_ADDR_ALIGNED_BEATS(ETH_InitStruct->AddrAlignedBeats)); + assert_param(IS_ETH_FIXED_BURST(ETH_InitStruct->FixedBurst)); + assert_param(IS_ETH_RX_DMA_BURST_LEN(ETH_InitStruct->RxDMABurstLen)); + assert_param(IS_ETH_TX_DMA_BURST_LEN(ETH_InitStruct->TxDMABurstLen)); + assert_param(IS_ETH_DMA_DESC_SKIP_LEN(ETH_InitStruct->DescSkipLen)); + assert_param(IS_ETH_DMA_ARBITRATION_ROUND_ROBIN_RXTX(ETH_InitStruct->DMAArbitration)); + /*-------------------------------- MAC Config ------------------------------*/ + /*---------------------- ETHERNET MACMIIADDR Configuration -------------------*/ + /* Get the ETHERNET MACMIIADDR value */ + tmpregister = ETH->MACMIIADDR; + /* Clear CTRLSTS Clock Range CTRL[2:0] bits */ + tmpregister &= MACMIIAR_CR_MASK; + /* Get hclk frequency value */ + RCC_GetClocksFreqValue(&rcc_clocks); + hclk = rcc_clocks.HclkFreq; + /* Set CTRL bits depending on hclk value */ + if (/*(hclk >= 20000000) && */ (hclk < 35000000)) + { + /* CTRLSTS Clock Range between 20-35 MHz */ + tmpregister |= (uint32_t)ETH_MACMIIADDR_CR_DIV16; + } + else if ((hclk >= 35000000) && (hclk < 60000000)) + { + /* CTRLSTS Clock Range between 35-60 MHz */ + tmpregister |= (uint32_t)ETH_MACMIIADDR_CR_DIV26; + } + else if ((hclk >= 60000000) && (hclk <= 72000000)) + { + /* CTRLSTS Clock Range between 60-72 MHz */ + tmpregister |= (uint32_t)ETH_MACMIIADDR_CR_DIV42; + } + /* Write to ETHERNET MAC MIIAR: Configure the ETHERNET CTRLSTS Clock Range */ + ETH->MACMIIADDR = (uint32_t)tmpregister; + /*-------------------- PHY initialization and configuration ----------------*/ + if (ETH_ERROR == callable(ETH_InitStruct)) + { + return ETH_ERROR; + } + + /*------------------------ ETHERNET MACCFG Configuration --------------------*/ + /* Get the ETHERNET MACCFG value */ + tmpregister = ETH->MACCFG; + /* Clear WD, PCE, PS, TE and RE bits */ + tmpregister &= MACCR_CLR_MASK; + /* Set the WD bit according to Watchdog value */ + /* Set the JD: bit according to Jabber value */ + /* Set the IFG bit according to InterFrameGap value */ + /* Set the DCRS bit according to CarrierSense value */ + /* Set the FES bit according to SpeedMode value */ + /* Set the DO bit according to RxOwn value */ + /* Set the LM bit according to LoopbackMode value */ + /* Set the DM bit according to DuplexMode value */ + /* Set the IPC bit according to ChecksumOffload value */ + /* Set the DAT bit according to RetryTransmission value */ + /* Set the ACS bit according to AutomaticPadCRCStrip value */ + /* Set the BL bit according to BackoffLimit value */ + /* Set the DC bit according to DeferralCheck value */ + tmpregister |= (uint32_t)( + ETH_InitStruct->Watchdog | ETH_InitStruct->Jabber | ETH_InitStruct->InterFrameGap | ETH_InitStruct->CarrierSense + | ETH_InitStruct->SpeedMode | ETH_InitStruct->RxOwn | ETH_InitStruct->LoopbackMode | ETH_InitStruct->DuplexMode + | ETH_InitStruct->ChecksumOffload | ETH_InitStruct->RetryTransmission | ETH_InitStruct->AutomaticPadCRCStrip + | ETH_InitStruct->BackoffLimit | ETH_InitStruct->DeferralCheck); + /* Write to ETHERNET MACCFG */ + ETH->MACCFG = (uint32_t)tmpregister; + + /*----------------------- ETHERNET MACFFLT Configuration --------------------*/ + /* Set the RA bit according to RxAll value */ + /* Set the SAF and SAIF bits according to SrcAddrFilter value */ + /* Set the PCF bit according to PassCtrlFrames value */ + /* Set the DBF bit according to BroadcastFramesReception value */ + /* Set the DAIF bit according to DestAddrFilter value */ + /* Set the PEND bit according to PromiscuousMode value */ + /* Set the PM, HMC and HPF bits according to MulticastFramesFilter value */ + /* Set the HUC and HPF bits according to UnicastFramesFilter value */ + /* Write to ETHERNET MACFFLT */ + ETH->MACFFLT = (uint32_t)(ETH_InitStruct->RxAll | ETH_InitStruct->SrcAddrFilter | ETH_InitStruct->PassCtrlFrames + | ETH_InitStruct->BroadcastFramesReception | ETH_InitStruct->DestAddrFilter + | ETH_InitStruct->PromiscuousMode | ETH_InitStruct->MulticastFramesFilter + | ETH_InitStruct->UnicastFramesFilter); + /*--------------- ETHERNET MACHASHHI and MACHASHLO Configuration ---------------*/ + /* Write to ETHERNET MACHASHHI */ + ETH->MACHASHHI = (uint32_t)ETH_InitStruct->HashTableHigh; + /* Write to ETHERNET MACHASHLO */ + ETH->MACHASHLO = (uint32_t)ETH_InitStruct->HashTableLow; + /*----------------------- ETHERNET MACFLWCTRL Configuration --------------------*/ + /* Get the ETHERNET MACFLWCTRL value */ + tmpregister = ETH->MACFLWCTRL; + /* Clear xx bits */ + tmpregister &= MACFCR_CLR_MASK; + + /* Set the PT bit according to PauseTime value */ + /* Set the DZPQ bit according to ZeroQuantaPause value */ + /* Set the PLT bit according to PauseLowThreshold value */ + /* Set the UP bit according to UnicastPauseFrameDetect value */ + /* Set the RFE bit according to RxFlowCtrl value */ + /* Set the TFE bit according to TxFlowCtrl value */ + tmpregister |= (uint32_t)((ETH_InitStruct->PauseTime << 16) | ETH_InitStruct->ZeroQuantaPause + | ETH_InitStruct->PauseLowThreshold | ETH_InitStruct->UnicastPauseFrameDetect + | ETH_InitStruct->RxFlowCtrl | ETH_InitStruct->TxFlowCtrl); + /* Write to ETHERNET MACFLWCTRL */ + ETH->MACFLWCTRL = (uint32_t)tmpregister; + /*----------------------- ETHERNET MACVLANTAG Configuration -----------------*/ + /* Set the ETV bit according to VLANTagComparison value */ + /* Set the VL bit according to VLANTagIdentifier value */ + ETH->MACVLANTAG = (uint32_t)(ETH_InitStruct->VLANTagComparison | ETH_InitStruct->VLANTagIdentifier); + + /*-------------------------------- DMA Config ------------------------------*/ + /*----------------------- ETHERNET DMAOPMOD Configuration --------------------*/ + /* Get the ETHERNET DMAOPMOD value */ + tmpregister = ETH->DMAOPMOD; + /* Clear xx bits */ + tmpregister &= DMAOMR_CLR_MASK; + + /* Set the DT bit according to DropTCPIPChecksumErrorFrame value */ + /* Set the RSYF bit according to RxStoreForward value */ + /* Set the DFF bit according to FlushRxFrame value */ + /* Set the TSF bit according to TxStoreForward value */ + /* Set the TTC bit according to TxThresholdCtrl value */ + /* Set the FEF bit according to ForwardErrorFrames value */ + /* Set the FUF bit according to ForwardUndersizedGoodFrames value */ + /* Set the RTC bit according to RxThresholdCtrl value */ + /* Set the OSF bit according to SecondFrameOperate value */ + tmpregister |= + (uint32_t)(ETH_InitStruct->DropTCPIPChecksumErrorFrame | ETH_InitStruct->RxStoreForward + | ETH_InitStruct->FlushRxFrame | ETH_InitStruct->TxStoreForward | ETH_InitStruct->TxThresholdCtrl + | ETH_InitStruct->ForwardErrorFrames | ETH_InitStruct->ForwardUndersizedGoodFrames + | ETH_InitStruct->RxThresholdCtrl | ETH_InitStruct->SecondFrameOperate); + /* Write to ETHERNET DMAOPMOD */ + ETH->DMAOPMOD = (uint32_t)tmpregister; + + /*----------------------- ETHERNET DMABUSMOD Configuration --------------------*/ + /* Set the AAL bit according to AddrAlignedBeats value */ + /* Set the FB bit according to FixedBurst value */ + /* Set the RPBL and 4*PBL bits according to RxDMABurstLen value */ + /* Set the PBL and 4*PBL bits according to TxDMABurstLen value */ + /* Set the DSL bit according to ETH_DesciptorSkipLength value */ + /* Set the PEND and DA bits according to DMAArbitration value */ + ETH->DMABUSMOD = + (uint32_t)(ETH_InitStruct->AddrAlignedBeats | ETH_InitStruct->FixedBurst | ETH_InitStruct->RxDMABurstLen + | /* !! if 4xPBL is selected for Tx or Rx it is applied for the other */ + ETH_InitStruct->TxDMABurstLen | (ETH_InitStruct->DescSkipLen << 2) | ETH_InitStruct->DMAArbitration + | ETH_DMABUSMOD_USP); /* Enable use of separate PBL for Rx and Tx */ + + /* Disable all MMC interrupt */ + ETH->MMCRXINTMSK = 0xffffffffUL; + ETH->MMCTXINTMSK = 0xffffffffUL; + ETH->MMCRXCOINTMSK = 0xffffffffUL; + + /* Return Ethernet configuration success */ + return ETH_SUCCESS; +} + +/** + * @brief Fills each ETH_InitStruct member with its default value. + * @param ETH_InitStruct pointer to a ETH_InitType structure which will be initialized. + */ +void ETH_InitStruct(ETH_InitType* ETH_InitStruct) +{ + /* ETH_InitStruct members default value */ + /*------------------------ MAC -----------------------------------*/ + ETH_InitStruct->AutoNegotiation = ETH_AUTONEG_DISABLE; + ETH_InitStruct->Watchdog = ETH_WATCHDOG_ENABLE; + ETH_InitStruct->Jabber = ETH_JABBER_ENABLE; + ETH_InitStruct->InterFrameGap = ETH_INTER_FRAME_GAP_96BIT; + ETH_InitStruct->CarrierSense = ETH_CARRIER_SENSE_ENABLE; + ETH_InitStruct->SpeedMode = ETH_SPEED_MODE_10M; + ETH_InitStruct->RxOwn = ETH_RX_OWN_ENABLE; + ETH_InitStruct->LoopbackMode = ETH_LOOPBACK_MODE_DISABLE; + ETH_InitStruct->DuplexMode = ETH_DUPLEX_MODE_HALF; + ETH_InitStruct->ChecksumOffload = ETH_CHECKSUM_OFFLOAD_DISABLE; + ETH_InitStruct->RetryTransmission = ETH_RETRY_TRANSMISSION_ENABLE; + ETH_InitStruct->AutomaticPadCRCStrip = ETH_AUTO_PAD_CRC_STRIP_DISABLE; + ETH_InitStruct->BackoffLimit = ETH_BACKOFF_LIMIT_10; + ETH_InitStruct->DeferralCheck = ETH_DEFERRAL_CHECK_DISABLE; + ETH_InitStruct->RxAll = ETH_RX_ALL_DISABLE; + ETH_InitStruct->SrcAddrFilter = ETH_SRC_ADDR_FILTER_DISABLE; + ETH_InitStruct->PassCtrlFrames = ETH_PASS_CTRL_FRAMES_BLOCK_ALL; + ETH_InitStruct->BroadcastFramesReception = ETH_BROADCAST_FRAMES_RECEPTION_DISABLE; + ETH_InitStruct->DestAddrFilter = ETH_DEST_ADDR_FILTER_NORMAL; + ETH_InitStruct->PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE; + ETH_InitStruct->MulticastFramesFilter = ETH_MULTICAST_FRAMES_FILTER_PERFECT; + ETH_InitStruct->UnicastFramesFilter = ETH_UNICAST_FRAMES_FILTER_PERFECT; + ETH_InitStruct->HashTableHigh = 0x0; + ETH_InitStruct->HashTableLow = 0x0; + ETH_InitStruct->PauseTime = 0x0; + ETH_InitStruct->ZeroQuantaPause = ETH_ZERO_QUANTA_PAUSE_DISABLE; + ETH_InitStruct->PauseLowThreshold = ETH_PAUSE_LOW_THRESHOLD_MINUS4; + ETH_InitStruct->UnicastPauseFrameDetect = ETH_UNICAST_PAUSE_FRAME_DETECT_DISABLE; + ETH_InitStruct->RxFlowCtrl = ETH_RX_FLOW_CTRL_DISABLE; + ETH_InitStruct->TxFlowCtrl = ETH_TX_FLOW_CTRL_DISABLE; + ETH_InitStruct->VLANTagComparison = ETH_VLAN_TAG_COMPARISON_16BIT; + ETH_InitStruct->VLANTagIdentifier = 0x0; + /*------------------------ DMA -----------------------------------*/ + ETH_InitStruct->DropTCPIPChecksumErrorFrame = ETH_DROP_TCPIP_CHECKSUM_ERROR_FRAME_DISABLE; + ETH_InitStruct->RxStoreForward = ETH_RX_STORE_FORWARD_ENABLE; + ETH_InitStruct->FlushRxFrame = ETH_FLUSH_RX_FRAME_DISABLE; + ETH_InitStruct->TxStoreForward = ETH_TX_STORE_FORWARD_ENABLE; + ETH_InitStruct->TxThresholdCtrl = ETH_TX_THRESHOLD_CTRL_64BYTES; + ETH_InitStruct->ForwardErrorFrames = ETH_FORWARD_ERROR_FRAMES_DISABLE; + ETH_InitStruct->ForwardUndersizedGoodFrames = ETH_FORWARD_UNDERSIZED_GOOD_FRAMES_ENABLE; + ETH_InitStruct->RxThresholdCtrl = ETH_RX_THRESHOLD_CTRL_64BYTES; + ETH_InitStruct->SecondFrameOperate = ETH_SECOND_FRAME_OPERATE_DISABLE; + ETH_InitStruct->AddrAlignedBeats = ETH_ADDR_ALIGNED_BEATS_ENABLE; + ETH_InitStruct->FixedBurst = ETH_FIXED_BURST_DISABLE; + ETH_InitStruct->RxDMABurstLen = ETH_RX_DMA_BURST_LEN_1BEAT; + ETH_InitStruct->TxDMABurstLen = ETH_TX_DMA_BURST_LEN_1BEAT; + ETH_InitStruct->DescSkipLen = 0x0; + ETH_InitStruct->DMAArbitration = ETH_DMA_ARBITRATION_ROUND_ROBIN_RXTX_1_1; +} + +/** + * @brief Enables ENET MAC and DMA reception/transmission + */ +void ETH_EnableTxRx(void) +{ + /* Enable transmit state machine of the MAC for transmission on the MII */ + ETH_EnableMacTx(ENABLE); + /* Flush Transmit DATFIFO */ + ETH_FlushTxFifo(); + /* Enable receive state machine of the MAC for reception from the MII */ + ETH_EnableMacRx(ENABLE); + + /* Start DMA transmission */ + ETH_EnableDmaTx(ENABLE); + /* Start DMA reception */ + ETH_EnableDmaRx(ENABLE); +} + +/** + * @brief Transmits a packet, from application buffer, pointed by ppkt. + * @param ppkt pointer to the application's packet buffer to transmit. + * @param FrameLength Tx Packet size. + * @return ETH_ERROR: in case of Tx desc owned by DMA + * ETH_SUCCESS: for correct transmission + */ +uint32_t ETH_TxPacket(uint8_t* ppkt, uint16_t FrameLength) +{ + uint32_t send_len = 0; + + while (send_len < FrameLength) + { + uint32_t offset = 0; + + /* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset) */ + if ((DMATxDescToSet->Status & ETH_DMA_TX_DESC_OWN) != (uint32_t)RESET) + { + /* Return ERROR: OWN bit set */ + return ETH_ERROR; + } + + uint16_t block_len = FrameLength - send_len; + if (block_len > ETH_DMA_TX_DESC_TBS1) + { + block_len = ETH_DMA_TX_DESC_TBS1; + } + /* Copy the frame to be sent into memory pointed by the current ETHERNET DMA Tx descriptor */ + for (offset = 0; offset < block_len; offset++) + { + (*(__IO uint8_t*)((DMATxDescToSet->Buf1Addr) + offset)) = (*(ppkt + offset + send_len)); + } + + /* Setting the Frame Length: bits[10:0] */ + DMATxDescToSet->CtrlOrBufSize &= (~ETH_DMA_TX_DESC_TBS1); + DMATxDescToSet->CtrlOrBufSize |= block_len; + /* Setting the last segment and first segment bits (in this case a frame is transmitted in one descriptor) */ + if (send_len == 0) + { + DMATxDescToSet->CtrlOrBufSize |= ETH_DMA_TX_DESC_FS; + } + send_len += block_len; + if (send_len == FrameLength) + { + DMATxDescToSet->CtrlOrBufSize |= ETH_DMA_TX_DESC_LS; + } + + /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */ + DMATxDescToSet->Status |= ETH_DMA_TX_DESC_OWN; + /* When Tx Buffer unavailable flag is set: clear it and resume transmission */ + if ((ETH->DMASTS & ETH_DMASTS_TU) != (uint32_t)RESET) + { + /* Clear TBUS ETHERNET DMA flag */ + ETH->DMASTS = ETH_DMASTS_TU; + /* Resume DMA transmission*/ + ETH->DMATXPD = 0; + } + + /* Update the ETHERNET DMA global Tx descriptor with next Tx decriptor */ + /* Chained Mode */ + if ((DMATxDescToSet->CtrlOrBufSize & ETH_DMA_TX_DESC_TCH) != (uint32_t)RESET) + { + /* Selects the next DMA Tx descriptor list for next buffer to send */ + DMATxDescToSet = (ETH_DMADescType*)(DMATxDescToSet->Buf2OrNextDescAddr); + } + else /* Ring Mode */ + { + if ((DMATxDescToSet->CtrlOrBufSize & ETH_DMA_TX_DESC_TER) != (uint32_t)RESET) + { + /* Selects the first DMA Tx descriptor for next buffer to send: last Tx descriptor was used */ + DMATxDescToSet = (ETH_DMADescType*)(ETH->DMATXDLADDR); + } + else + { + /* Selects the next DMA Tx descriptor list for next buffer to send */ + DMATxDescToSet = + (ETH_DMADescType*)((uint32_t)DMATxDescToSet + 0x10 + ((ETH->DMABUSMOD & ETH_DMABUSMOD_DSL))); + } + } + } + /* Return SUCCESS */ + return ETH_SUCCESS; +} + +/** + * @brief Receives a packet and copies it to memory pointed by ppkt. + * @param ppkt pointer to the application packet receive buffer. + * @param checkErr whether check error + * @return ETH_ERROR: if there is error in reception + * framelength: received packet size if packet reception is correct + */ +uint32_t ETH_RxPacket(uint8_t* ppkt, uint8_t checkErr) +{ + uint32_t offset = 0, framelength = 0; + /* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset) */ + if ((DMARxDescToGet->Status & ETH_DMA_RX_DESC_OWN) != (uint32_t)RESET) + { + /* Return error: OWN bit set */ + return ETH_ERROR; + } + + if (((checkErr && ((DMARxDescToGet->Status & ETH_DMA_RX_DESC_ES) == (uint32_t)RESET)) || !checkErr) + && ((DMARxDescToGet->Status & ETH_DMA_RX_DESC_LS) != (uint32_t)RESET) + && ((DMARxDescToGet->Status & ETH_DMA_RX_DESC_FS) != (uint32_t)RESET)) + { + /* Get the Frame Length of the received packet */ + framelength = ((DMARxDescToGet->Status & ETH_DMA_RX_DESC_FL) >> ETH_DMA_RX_DESC_FRAME_LEN_SHIFT); + /* Copy the received frame into buffer from memory pointed by the current ETHERNET DMA Rx descriptor */ + for (offset = 0; offset < framelength; offset++) + { + (*(ppkt + offset)) = (*(__IO uint8_t*)((DMARxDescToGet->Buf1Addr) + offset)); + } + } + else + { + /* Return ERROR */ + framelength = ETH_ERROR; + } + /* Set Own bit of the Rx descriptor Status: gives the buffer back to ETHERNET DMA */ + DMARxDescToGet->Status = ETH_DMA_RX_DESC_OWN; + + /* When Rx Buffer unavailable flag is set: clear it and resume reception */ + if ((ETH->DMASTS & ETH_DMASTS_RU) != (uint32_t)RESET) + { + /* Clear RBUS ETHERNET DMA flag */ + ETH->DMASTS = ETH_DMASTS_RU; + /* Resume DMA reception */ + ETH->DMARXPD = 0; + } + + /* Update the ETHERNET DMA global Rx descriptor with next Rx decriptor */ + /* Chained Mode */ + if ((DMARxDescToGet->CtrlOrBufSize & ETH_DMA_RX_DESC_RCH) != (uint32_t)RESET) + { + /* Selects the next DMA Rx descriptor list for next buffer to read */ + DMARxDescToGet = (ETH_DMADescType*)(DMARxDescToGet->Buf2OrNextDescAddr); + } + else /* Ring Mode */ + { + if ((DMARxDescToGet->CtrlOrBufSize & ETH_DMA_RX_DESC_RER) != (uint32_t)RESET) + { + /* Selects the first DMA Rx descriptor for next buffer to read: last Rx descriptor was used */ + DMARxDescToGet = (ETH_DMADescType*)(ETH->DMARXDLADDR); + } + else + { + /* Selects the next DMA Rx descriptor list for next buffer to read */ + DMARxDescToGet = + (ETH_DMADescType*)((uint32_t)DMARxDescToGet + 0x10 + ((ETH->DMABUSMOD & ETH_DMABUSMOD_DSL))); + } + } + + /* Return Frame Length/ERROR */ + return (framelength); +} + +/** + * @brief Get the size of received the received packet. + * @return framelength: received packet size + */ +uint32_t ETH_GetRxPacketSize(void) +{ + uint32_t frameLength = 0; + if (((DMARxDescToGet->Status & ETH_DMA_RX_DESC_OWN) == (uint32_t)RESET) + && ((DMARxDescToGet->Status & ETH_DMA_RX_DESC_ES) == (uint32_t)RESET) + && ((DMARxDescToGet->Status & ETH_DMA_RX_DESC_LS) != (uint32_t)RESET) + && ((DMARxDescToGet->Status & ETH_DMA_RX_DESC_FS) != (uint32_t)RESET)) + { + /* Get the size of the packet: including 4 bytes of the CRC */ + frameLength = ETH_GetDmaRxDescFrameLen(DMARxDescToGet); + } + + /* Return Frame Length */ + return frameLength; +} + +/** + * @brief Drop a Received packet (too small packet, etc...) + */ +void ETH_DropRxPacket(void) +{ + /* Set Own bit of the Rx descriptor Status: gives the buffer back to ETHERNET DMA */ + DMARxDescToGet->Status = ETH_DMA_RX_DESC_OWN; + /* Chained Mode */ + if ((DMARxDescToGet->CtrlOrBufSize & ETH_DMA_RX_DESC_RCH) != (uint32_t)RESET) + { + /* Selects the next DMA Rx descriptor list for next buffer read */ + DMARxDescToGet = (ETH_DMADescType*)(DMARxDescToGet->Buf2OrNextDescAddr); + } + else /* Ring Mode */ + { + if ((DMARxDescToGet->CtrlOrBufSize & ETH_DMA_RX_DESC_RER) != (uint32_t)RESET) + { + /* Selects the next DMA Rx descriptor list for next buffer read: this will + be the first Rx descriptor in this case */ + DMARxDescToGet = (ETH_DMADescType*)(ETH->DMARXDLADDR); + } + else + { + /* Selects the next DMA Rx descriptor list for next buffer read */ + DMARxDescToGet = + (ETH_DMADescType*)((uint32_t)DMARxDescToGet + 0x10 + ((ETH->DMABUSMOD & ETH_DMABUSMOD_DSL))); + } + } +} + +/*--------------------------------- PHY ------------------------------------*/ +/** + * @brief Read a PHY register + * @param PHYAddress PHY device address, is the index of one of supported 32 PHY devices. + * This parameter can be one of the following values: 0,..,31 + * @param PHYReg PHY register address, is the index of one of the 32 PHY register. + * This parameter can be one of the following values: + * @arg PHY_BCR Tranceiver Basic Control Register + * @arg PHY_BSR Tranceiver Basic Status Register + * @arg PHY_SR Tranceiver Status Register + * @arg More PHY register could be read depending on the used PHY + * @return ETH_ERROR: in case of timeout + * MAC MIIDR register value: Data read from the selected PHY register (correct read ) + */ +uint16_t ETH_ReadPhyRegister(uint16_t PHYAddress, uint16_t PHYReg) +{ + uint32_t tmpregister = 0; + __IO uint32_t timeout = 0; + /* Check the parameters */ + assert_param(IS_ETH_PHY_ADDRESS(PHYAddress)); + assert_param(IS_ETH_PHY_REG(PHYReg)); + + /* Get the ETHERNET MACMIIADDR value */ + tmpregister = ETH->MACMIIADDR; + /* Keep only the CTRLSTS Clock Range CTRL[2:0] bits value */ + tmpregister &= ~MACMIIAR_CR_MASK; + /* Prepare the MII address register value */ + tmpregister |= (((uint32_t)PHYAddress << 11) & ETH_MACMIIADDR_PA); /* Set the PHY device address */ + tmpregister |= (((uint32_t)PHYReg << 6) & ETH_MACMIIADDR_MR); /* Set the PHY register address */ + tmpregister &= ~ETH_MACMIIADDR_MW; /* Set the read mode */ + tmpregister |= ETH_MACMIIADDR_MB; /* Set the MII Busy bit */ + /* Write the result value into the MII Address register */ + ETH->MACMIIADDR = tmpregister; + /* Check for the Busy flag */ + do + { + timeout++; + tmpregister = ETH->MACMIIADDR; + } while ((tmpregister & ETH_MACMIIADDR_MB) && (timeout < (uint32_t)PHY_READ_TO)); + /* Return ERROR in case of timeout */ + if (timeout == PHY_READ_TO) + { + return (uint16_t)ETH_ERROR; + } + + /* Return data register value */ + uint16_t ret = (uint16_t)(ETH->MACMIIDAT); + return ret; +} + +/** + * @brief Write to a PHY register + * @param PHYAddress PHY device address, is the index of one of supported 32 PHY devices. + * This parameter can be one of the following values: 0,..,31 + * @param PHYReg PHY register address, is the index of one of the 32 PHY register. + * This parameter can be one of the following values: + * @arg PHY_BCR Tranceiver Control Register + * @arg More PHY register could be written depending on the used PHY + * @param PHYValue the value to write + * @return ETH_ERROR: in case of timeout + * ETH_SUCCESS: for correct write + */ +uint32_t ETH_WritePhyRegister(uint16_t PHYAddress, uint16_t PHYReg, uint16_t PHYValue) +{ + uint32_t tmpregister = 0; + __IO uint32_t timeout = 0; + /* Check the parameters */ + assert_param(IS_ETH_PHY_ADDRESS(PHYAddress)); + assert_param(IS_ETH_PHY_REG(PHYReg)); + + /* Get the ETHERNET MACMIIADDR value */ + tmpregister = ETH->MACMIIADDR; + /* Keep only the CTRLSTS Clock Range CTRL[2:0] bits value */ + tmpregister &= ~MACMIIAR_CR_MASK; + /* Prepare the MII register address value */ + tmpregister |= (((uint32_t)PHYAddress << 11) & ETH_MACMIIADDR_PA); /* Set the PHY device address */ + tmpregister |= (((uint32_t)PHYReg << 6) & ETH_MACMIIADDR_MR); /* Set the PHY register address */ + tmpregister |= ETH_MACMIIADDR_MW; /* Set the write mode */ + tmpregister |= ETH_MACMIIADDR_MB; /* Set the MII Busy bit */ + /* Give the value to the MII data register */ + ETH->MACMIIDAT = PHYValue; + /* Write the result value into the MII Address register */ + ETH->MACMIIADDR = tmpregister; + /* Check for the Busy flag */ + do + { + timeout++; + tmpregister = ETH->MACMIIADDR; + } while ((tmpregister & ETH_MACMIIADDR_MB) && (timeout < (uint32_t)PHY_WRITE_TO)); + /* Return ERROR in case of timeout */ + if (timeout == PHY_WRITE_TO) + { + return ETH_ERROR; + } + + /* Return SUCCESS */ + return ETH_SUCCESS; +} + +/** + * @brief Enables or disables the PHY loopBack mode. + * @note: Don't be confused with ETH_MACLoopBackCmd function which enables internal + * loopback at MII level + * @param PHYAddress PHY device address, is the index of one of supported 32 PHY devices. + * This parameter can be one of the following values: + * @param Cmd new state of the PHY loopBack mode. + * This parameter can be: ENABLE or DISABLE. + * @return ETH_ERROR: in case of bad PHY configuration + * ETH_SUCCESS: for correct PHY configuration + */ +uint32_t ETH_EnablePhyLoopBack(uint16_t PHYAddress, FunctionalState Cmd) +{ + uint16_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_ETH_PHY_ADDRESS(PHYAddress)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + /* Get the PHY configuration to update it */ + tmpregister = ETH_ReadPhyRegister(PHYAddress, PHY_BCR); + + if (Cmd != DISABLE) + { + /* Enable the PHY loopback mode */ + tmpregister |= PHY_LOOPBACK; + } + else + { + /* Disable the PHY loopback mode: normal mode */ + tmpregister &= (uint16_t)(~(uint16_t)PHY_LOOPBACK); + } + /* Update the PHY control register with the new configuration */ + if (ETH_WritePhyRegister(PHYAddress, PHY_BCR, tmpregister) != (uint32_t)RESET) + { + return ETH_SUCCESS; + } + else + { + /* Return SUCCESS */ + return ETH_ERROR; + } +} + +/*--------------------------------- MAC ------------------------------------*/ +/** + * @brief Enables or disables the MAC transmission. + * @param Cmd new state of the MAC transmission. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableMacTx(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the MAC transmission */ + ETH->MACCFG |= ETH_MACCFG_TE; + } + else + { + /* Disable the MAC transmission */ + ETH->MACCFG &= ~ETH_MACCFG_TE; + } +} + +/** + * @brief Enables or disables the MAC reception. + * @param Cmd new state of the MAC reception. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableMacRx(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the MAC reception */ + ETH->MACCFG |= ETH_MACCFG_RE; + } + else + { + /* Disable the MAC reception */ + ETH->MACCFG &= ~ETH_MACCFG_RE; + } +} + +/** + * @brief Checks whether the ETHERNET flow control busy bit is set or not. + * @return The new state of flow control busy status bit (SET or RESET). + */ +FlagStatus ETH_GetFlowCtrlBusyStatus(void) +{ + FlagStatus bitstatus = RESET; + /* The Flow Control register should not be written to until this bit is cleared */ + if ((ETH->MACFLWCTRL & ETH_MACFLWCTRL_FCB_BPA) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Initiate a Pause Control Frame (Full-duplex only). + */ +void ETH_GeneratePauseCtrlFrame(void) +{ + /* When Set In full duplex MAC initiates pause control frame */ + ETH->MACFLWCTRL |= ETH_MACFLWCTRL_FCB_BPA; +} + +/** + * @brief Enables or disables the MAC BackPressure operation activation (Half-duplex only). + * @param Cmd new state of the MAC BackPressure operation activation. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableBackPressureActivation(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Activate the MAC BackPressure operation */ + /* In Half duplex: during backpressure, when the MAC receives a new frame, + the transmitter starts sending a JAM pattern resulting in a collision */ + ETH->MACFLWCTRL |= ETH_MACFLWCTRL_FCB_BPA; + } + else + { + /* Desactivate the MAC BackPressure operation */ + ETH->MACFLWCTRL &= ~ETH_MACFLWCTRL_FCB_BPA; + } +} + +/** + * @brief Checks whether the specified ETHERNET MAC flag is set or not. + * @param ETH_MAC_FLAG specifies the flag to check. + * This parameter can be one of the following values: + * @arg ETH_MAC_FLAG_TST Time stamp trigger flag + * @arg ETH_MAC_FLAG_MMCTX MMC transmit flag + * @arg ETH_MAC_FLAG_MMCRX MMC receive flag + * @arg ETH_MAC_FLAG_MMC MMC flag + * @arg ETH_MAC_FLAG_PMT PMT flag + * @return The new state of ETHERNET MAC flag (SET or RESET). + */ +FlagStatus ETH_GetMacFlagStatus(uint32_t ETH_MAC_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ETH_MAC_GET_FLAG(ETH_MAC_FLAG)); + if ((ETH->MACINTSTS & ETH_MAC_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Checks whether the specified ETHERNET MAC interrupt has occurred or not. + * @param ETH_MAC_IT specifies the interrupt source to check. + * This parameter can be one of the following values: + * @arg ETH_MAC_INT_TST Time stamp trigger interrupt + * @arg ETH_MAC_INT_MMCTX MMC transmit interrupt + * @arg ETH_MAC_INT_MMCRX MMC receive interrupt + * @arg ETH_MAC_INT_MMC MMC interrupt + * @arg ETH_MAC_INT_PMT PMT interrupt + * @return The new state of ETHERNET MAC interrupt (SET or RESET). + */ +INTStatus ETH_GetMacIntStatus(uint32_t ETH_MAC_IT) +{ + INTStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ETH_MAC_GET_INT(ETH_MAC_IT)); + if ((ETH->MACINTSTS & ETH_MAC_IT) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Enables or disables the specified ETHERNET MAC interrupts. + * @param ETH_MAC_IT specifies the ETHERNET MAC interrupt sources to be + * enabled or disabled. + * This parameter can be any combination of the following values: + * @arg ETH_MAC_INT_TST Time stamp trigger interrupt + * @arg ETH_MAC_INT_PMT PMT interrupt + * @param Cmd new state of the specified ETHERNET MAC interrupts. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableMacInt(uint32_t ETH_MAC_IT, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_ETH_MAC_INT(ETH_MAC_IT)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the selected ETHERNET MAC interrupts */ + ETH->MACINTMSK &= (~(uint32_t)ETH_MAC_IT); + } + else + { + /* Disable the selected ETHERNET MAC interrupts */ + ETH->MACINTMSK |= ETH_MAC_IT; + } +} + +/** + * @brief Configures the selected MAC address. + * @param MacAddr The MAC addres to configure. + * This parameter can be one of the following values: + * @arg ETH_MAC_ADDR0 MAC Address0 + * @arg ETH_MAC_ADDR1 MAC Address1 + * @arg ETH_MAC_ADDR2 MAC Address2 + * @arg ETH_MAC_ADDR3 MAC Address3 + * @param Addr Pointer on MAC address buffer data (6 bytes). + */ +void ETH_SetMacAddr(uint32_t MacAddr, uint8_t* Addr) +{ + uint32_t tmpregister; + /* Check the parameters */ + assert_param(IS_ETH_MAC_ADDR0123(MacAddr)); + + /* Calculate the selectecd MAC address high register */ + tmpregister = ((uint32_t)Addr[5] << 8) | (uint32_t)Addr[4]; + /* Load the selectecd MAC address high register */ + (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + MacAddr)) = tmpregister; + /* Calculate the selectecd MAC address low register */ + tmpregister = ((uint32_t)Addr[3] << 24) | ((uint32_t)Addr[2] << 16) | ((uint32_t)Addr[1] << 8) | Addr[0]; + + /* Load the selectecd MAC address low register */ + (*(__IO uint32_t*)(ETH_MAC_ADDR_LBASE + MacAddr)) = tmpregister; +} + +/** + * @brief Get the selected MAC address. + * @param MacAddr The MAC addres to return. + * This parameter can be one of the following values: + * @arg ETH_MAC_ADDR0 MAC Address0 + * @arg ETH_MAC_ADDR1 MAC Address1 + * @arg ETH_MAC_ADDR2 MAC Address2 + * @arg ETH_MAC_ADDR3 MAC Address3 + * @param Addr Pointer on MAC address buffer data (6 bytes). + */ +void ETH_GetMacAddr(uint32_t MacAddr, uint8_t* Addr) +{ + uint32_t tmpregister; + /* Check the parameters */ + assert_param(IS_ETH_MAC_ADDR0123(MacAddr)); + + /* Get the selectecd MAC address high register */ + tmpregister = (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + MacAddr)); + + /* Calculate the selectecd MAC address buffer */ + Addr[5] = ((tmpregister >> 8) & (uint8_t)0xFF); + Addr[4] = (tmpregister & (uint8_t)0xFF); + /* Load the selectecd MAC address low register */ + tmpregister = (*(__IO uint32_t*)(ETH_MAC_ADDR_LBASE + MacAddr)); + /* Calculate the selectecd MAC address buffer */ + Addr[3] = ((tmpregister >> 24) & (uint8_t)0xFF); + Addr[2] = ((tmpregister >> 16) & (uint8_t)0xFF); + Addr[1] = ((tmpregister >> 8) & (uint8_t)0xFF); + Addr[0] = (tmpregister & (uint8_t)0xFF); +} + +/** + * @brief Enables or disables the Address filter module uses the specified + * ETHERNET MAC address for perfect filtering + * @param MacAddr specifies the ETHERNET MAC address to be used for prfect filtering. + * This parameter can be one of the following values: + * @arg ETH_MAC_ADDR1 MAC Address1 + * @arg ETH_MAC_ADDR2 MAC Address2 + * @arg ETH_MAC_ADDR3 MAC Address3 + * @param Cmd new state of the specified ETHERNET MAC address use. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableMacAddrPerfectFilter(uint32_t MacAddr, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_ETH_MAC_ADDR123(MacAddr)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the selected ETHERNET MAC address for perfect filtering */ + (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + MacAddr)) |= ETH_MACADDR1HI_AE; + } + else + { + /* Disable the selected ETHERNET MAC address for perfect filtering */ + (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + MacAddr)) &= (~(uint32_t)ETH_MACADDR1HI_AE); + } +} + +/** + * @brief Set the filter type for the specified ETHERNET MAC address + * @param MacAddr specifies the ETHERNET MAC address + * This parameter can be one of the following values: + * @arg ETH_MAC_ADDR1 MAC Address1 + * @arg ETH_MAC_ADDR2 MAC Address2 + * @arg ETH_MAC_ADDR3 MAC Address3 + * @param Filter specifies the used frame received field for comparaison + * This parameter can be one of the following values: + * @arg ETH_MAC_ADDR_FILTER_SA MAC Address is used to compare with the + * SA fields of the received frame. + * @arg ETH_MAC_ADDR_FILTER_DA MAC Address is used to compare with the + * DA fields of the received frame. + */ +void ETH_ConfigMacAddrFilter(uint32_t MacAddr, uint32_t Filter) +{ + /* Check the parameters */ + assert_param(IS_ETH_MAC_ADDR123(MacAddr)); + assert_param(IS_ETH_MAC_ADDR_FILTER(Filter)); + + if (Filter != ETH_MAC_ADDR_FILTER_DA) + { + /* The selected ETHERNET MAC address is used to compare with the SA fields of the + received frame. */ + (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + MacAddr)) |= ETH_MACADDR1HI_SA; + } + else + { + /* The selected ETHERNET MAC address is used to compare with the DA fields of the + received frame. */ + (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + MacAddr)) &= (~(uint32_t)ETH_MACADDR1HI_SA); + } +} + +/** + * @brief Set the filter type for the specified ETHERNET MAC address + * @param MacAddr specifies the ETHERNET MAC address + * This parameter can be one of the following values: + * @arg ETH_MAC_ADDR1 MAC Address1 + * @arg ETH_MAC_ADDR2 MAC Address2 + * @arg ETH_MAC_ADDR3 MAC Address3 + * @param MaskByte specifies the used address bytes for comparaison + * This parameter can be any combination of the following values: + * @arg ETH_MAC_ADDR_MASK_BYTE6 Mask MAC Address high reg bits [15:8]. + * @arg ETH_MAC_ADDR_MASK_BYTE5 Mask MAC Address high reg bits [7:0]. + * @arg ETH_MAC_ADDR_MASK_BYTE4 Mask MAC Address low reg bits [31:24]. + * @arg ETH_MAC_ADDR_MASK_BYTE3 Mask MAC Address low reg bits [23:16]. + * @arg ETH_MAC_ADDR_MASK_BYTE2 Mask MAC Address low reg bits [15:8]. + * @arg ETH_MAC_ADDR_MASK_BYTE1 Mask MAC Address low reg bits [7:0]. + */ +void ETH_ConfigMacAddrMaskBytesFilter(uint32_t MacAddr, uint32_t MaskByte) +{ + /* Check the parameters */ + assert_param(IS_ETH_MAC_ADDR123(MacAddr)); + assert_param(IS_ETH_MAC_ADDR_MASK(MaskByte)); + + /* Clear MBC bits in the selected MAC address high register */ + (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + MacAddr)) &= (~(uint32_t)ETH_MACADDR1HI_MBC); + /* Set the selected Filetr mask bytes */ + (*(__IO uint32_t*)(ETH_MAC_ADDR_HBASE + MacAddr)) |= MaskByte; +} +/*------------------------ DMA Tx/Rx Desciptors -----------------------------*/ + +/** + * @brief Initializes the DMA Tx descriptors in chain mode. + * @param DMATxDescTab Pointer on the first Tx desc list + * @param TxBuff Pointer on the first TxBuffer list + * @param BuffSize Buffer size of each descriptor + * @param TxBuffCount Number of the used Tx desc in the list + */ +void ETH_ConfigDmaTxDescInChainMode(ETH_DMADescType* DMATxDescTab, + uint8_t* TxBuff, + uint32_t BuffSize, + uint32_t TxBuffCount) +{ + uint32_t i = 0; + ETH_DMADescType* DMATxDesc; + + /* Set the DMATxDescToSet pointer with the first one of the DMATxDescTab list */ + DMATxDescToSet = DMATxDescTab; + /* Fill each DMATxDesc descriptor with the right values */ + for (i = 0; i < TxBuffCount; i++) + { + /* Get the pointer on the ith member of the Tx Desc list */ + DMATxDesc = DMATxDescTab + i; + /* Set Second Address Chained bit */ + DMATxDesc->Status = 0; + DMATxDesc->CtrlOrBufSize = ETH_DMA_TX_DESC_TCH; + + /* Set Buffer1 address pointer */ + DMATxDesc->Buf1Addr = (uint32_t)(&TxBuff[i * BuffSize]); + + /* Initialize the next descriptor with the Next Desciptor Polling Enable */ + if (i < (TxBuffCount - 1)) + { + /* Set next descriptor address register with next descriptor base address */ + DMATxDesc->Buf2OrNextDescAddr = (uint32_t)(DMATxDescTab + i + 1); + } + else + { + /* For last descriptor, set next descriptor address register equal to the first descriptor base address */ + DMATxDesc->Buf2OrNextDescAddr = (uint32_t)DMATxDescTab; + } + } + + /* Set Transmit Desciptor List Address Register */ + ETH->DMATXDLADDR = (uint32_t)DMATxDescTab; +} + +/** + * @brief Initializes the DMA Tx descriptors in ring mode. + * @param DMATxDescTab Pointer on the first Tx desc list + * @param TxBuff1 Pointer on the first TxBuffer1 list + * @param TxBuff2 Pointer on the first TxBuffer2 list + * @param BuffSize Buffer size of each descriptor + * @param TxBuffCount Number of the used Tx desc in the list + * Note: see decriptor skip length defined in ETH_DMA_InitStruct + * for the number of Words to skip between two unchained descriptors. + */ +void ETH_ConfigDmaTxDescInRingMode(ETH_DMADescType* DMATxDescTab, + uint8_t* TxBuff1, + uint8_t* TxBuff2, + uint32_t BuffSize, + uint32_t TxBuffCount) +{ + uint32_t i = 0; + ETH_DMADescType* DMATxDesc; + uint32_t dsl = (ETH->DMABUSMOD & ETH_DMABUSMOD_DSL) >> 2; + + /* Set the DMATxDescToSet pointer with the first one of the DMATxDescTab list */ + DMATxDescToSet = DMATxDescTab; + /* Fill each DMATxDesc descriptor with the right values */ + for (i = 0; i < TxBuffCount; i++) + { + /* Get the pointer on the ith member of the Tx Desc list */ + // DMATxDesc = DMATxDescTab + i; + DMATxDesc = (ETH_DMADescType*)((uint32_t)DMATxDescTab + i * (16 + 4 * dsl)); + /* Set Buffer1 address pointer */ + DMATxDesc->Buf1Addr = (uint32_t)(&TxBuff1[i * BuffSize]); + + /* Set Buffer2 address pointer */ + DMATxDesc->Buf2OrNextDescAddr = (uint32_t)(&TxBuff2[i * BuffSize]); + + /* Set Transmit End of Ring bit for last descriptor: The DMA returns to the base + address of the list, creating a Desciptor Ring */ + if (i == (TxBuffCount - 1)) + { + /* Set Transmit End of Ring bit */ + DMATxDesc->CtrlOrBufSize = ETH_DMA_TX_DESC_TER; + } + } + + /* Set Transmit Desciptor List Address Register */ + ETH->DMATXDLADDR = (uint32_t)DMATxDescTab; +} + +/** + * @brief Checks whether the specified ETHERNET DMA Tx Desc flag is set or not. + * @param DMATxDesc pointer on a DMA Tx descriptor + * @param ETH_DMATxDescFlag specifies the flag to check. + * This parameter can be one of the following values: + * @arg ETH_DMA_TX_DESC_OWN OWN bit: descriptor is owned by DMA engine + * @arg ETH_DMA_TX_DESC_IC Interrupt on completetion + * @arg ETH_DMA_TX_DESC_LS Last Segment + * @arg ETH_DMA_TX_DESC_FS First Segment + * @arg ETH_DMA_TX_DESC_DC Disable CRC + * @arg ETH_DMA_TX_DESC_DP Disable Pad + * @arg ETH_DMA_TX_DESC_TTSE Transmit Time Stamp Enable + * @arg ETH_DMA_TX_DESC_TER Transmit End of Ring + * @arg ETH_DMA_TX_DESC_TCH Second Address Chained + * @arg ETH_DMA_TX_DESC_TTSS Tx Time Stamp Status + * @arg ETH_DMA_TX_DESC_IHE IP Header Error + * @arg ETH_DMA_TX_DESC_ES Error summary + * @arg ETH_DMA_TX_DESC_JT Jabber Timeout + * @arg ETH_DMA_TX_DESC_FF Frame Flushed: DMA/MTL flushed the frame due to SW flush + * @arg ETH_DMA_TX_DESC_PCE Payload Checksum Error + * @arg ETH_DMA_TX_DESC_LOC Loss of Carrier: carrier lost during tramsmission + * @arg ETH_DMA_TX_DESC_NC No Carrier: no carrier signal from the tranceiver + * @arg ETH_DMA_TX_DESC_LC Late Collision: transmission aborted due to collision + * @arg ETH_DMA_TX_DESC_EC Excessive Collision: transmission aborted after 16 collisions + * @arg ETH_DMA_TX_DESC_VF VLAN Frame + * @arg ETH_DMA_TX_DESC_CC Collision Count + * @arg ETH_DMA_TX_DESC_ED Excessive Deferral + * @arg ETH_DMA_TX_DESC_UF Underflow Error: late data arrival from the memory + * @arg ETH_DMA_TX_DESC_DB Deferred Bit + * @return The new state of ETH_DMATxDescFlag (SET or RESET). + */ +FlagStatus ETH_GetDmaTxDescFlagStatus(ETH_DMADescType* DMATxDesc, uint32_t ETH_DMATxDescFlag) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ETH_DMATXDESC_GET_FLAG(ETH_DMATxDescFlag)); + + if ((DMATxDesc->Status & ETH_DMATxDescFlag) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Returns the specified ETHERNET DMA Tx Desc collision count. + * @param DMATxDesc pointer on a DMA Tx descriptor + * @return The Transmit descriptor collision counter value. + */ +uint32_t ETH_GetDmaTxDescCollisionCount(ETH_DMADescType* DMATxDesc) +{ + /* Return the Receive descriptor frame length */ + return ((DMATxDesc->Status & ETH_DMA_TX_DESC_CC) >> ETH_DMA_TX_DESC_COLLISION_COUNTER_SHIFT); +} + +/** + * @brief Set the specified DMA Tx Desc Own bit. + * @param DMATxDesc Pointer on a Tx desc + */ +void ETH_SetDmaTxDescOwn(ETH_DMADescType* DMATxDesc) +{ + /* Set the DMA Tx Desc Own bit */ + DMATxDesc->Status |= ETH_DMA_TX_DESC_OWN; +} + +/** + * @brief Enables or disables the specified DMA Tx Desc Transmit interrupt. + * @param DMATxDesc Pointer on a Tx desc + * @param Cmd new state of the DMA Tx Desc transmit interrupt. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableDmaTxDescTransmitInt(ETH_DMADescType* DMATxDesc, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the DMA Tx Desc Transmit interrupt */ + DMATxDesc->CtrlOrBufSize |= ETH_DMA_TX_DESC_IC; + } + else + { + /* Disable the DMA Tx Desc Transmit interrupt */ + DMATxDesc->CtrlOrBufSize &= (~(uint32_t)ETH_DMA_TX_DESC_IC); + } +} + +/** + * @brief Set the specified DMA Tx Desc frame segment. + * @param DMATxDesc Pointer on a Tx desc + * @param DMATxDesc_FrameSegment specifies is the actual Tx desc contain last or first segment. + * This parameter can be one of the following values: + * @arg ETH_DMA_TX_DESC_LAST_SEGMENT actual Tx desc contain last segment + * @arg ETH_DMA_TX_DESC_FIRST_SEGMENT actual Tx desc contain first segment + */ +void ETH_ConfigDmaTxDescFrameSegment(ETH_DMADescType* DMATxDesc, uint32_t DMATxDesc_FrameSegment) +{ + /* Check the parameters */ + assert_param(IS_ETH_DMA_TX_DESC_SEGMENT(DMATxDesc_FrameSegment)); + + /* Selects the DMA Tx Desc Frame segment */ + DMATxDesc->CtrlOrBufSize |= DMATxDesc_FrameSegment; +} + +/** + * @brief Selects the specified ETHERNET DMA Tx Desc Checksum Insertion. + * @param DMATxDesc pointer on a DMA Tx descriptor + * @param DMATxDesc_Checksum specifies is the DMA Tx desc checksum insertion. + * This parameter can be one of the following values: + * @arg ETH_DMA_TX_DESC_CHECKSUM_BYPASS Checksum bypass + * @arg ETH_DMA_TX_DESC_CHECKSUM_IPV4_HEADER IPv4 header checksum + * @arg ETH_DMA_TX_DESC_CHECKSUM_TCPUDPICMP_SEGMENT TCP/UDP/ICMP checksum. Pseudo header checksum is assumed to be + * present + * @arg ETH_DMA_TX_DESC_CHECKSUM_TCPUDPICMP_FULL TCP/UDP/ICMP checksum fully in hardware including pseudo header + */ +void ETH_ConfigDmaTxDescChecksumInsertion(ETH_DMADescType* DMATxDesc, uint32_t DMATxDesc_Checksum) +{ + /* Check the parameters */ + assert_param(IS_ETH_DMA_TX_DESC_CHECKSUM(DMATxDesc_Checksum)); + + /* Set the selected DMA Tx desc checksum insertion control */ + DMATxDesc->CtrlOrBufSize |= DMATxDesc_Checksum; +} + +/** + * @brief Enables or disables the DMA Tx Desc CRC. + * @param DMATxDesc pointer on a DMA Tx descriptor + * @param Cmd new state of the specified DMA Tx Desc CRC. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableDmaTxDescCrc(ETH_DMADescType* DMATxDesc, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the selected DMA Tx Desc CRC */ + DMATxDesc->CtrlOrBufSize &= (~(uint32_t)ETH_DMA_TX_DESC_DC); + } + else + { + /* Disable the selected DMA Tx Desc CRC */ + DMATxDesc->CtrlOrBufSize |= ETH_DMA_TX_DESC_DC; + } +} + +/** + * @brief Enables or disables the DMA Tx Desc end of ring. + * @param DMATxDesc pointer on a DMA Tx descriptor + * @param Cmd new state of the specified DMA Tx Desc end of ring. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableDmaTxDescEndOfRing(ETH_DMADescType* DMATxDesc, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the selected DMA Tx Desc end of ring */ + DMATxDesc->CtrlOrBufSize |= ETH_DMA_TX_DESC_TER; + } + else + { + /* Disable the selected DMA Tx Desc end of ring */ + DMATxDesc->CtrlOrBufSize &= (~(uint32_t)ETH_DMA_TX_DESC_TER); + } +} + +/** + * @brief Enables or disables the DMA Tx Desc second address chained. + * @param DMATxDesc pointer on a DMA Tx descriptor + * @param Cmd new state of the specified DMA Tx Desc second address chained. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableDmaTxDescSecondAddrChained(ETH_DMADescType* DMATxDesc, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the selected DMA Tx Desc second address chained */ + DMATxDesc->CtrlOrBufSize |= ETH_DMA_TX_DESC_TCH; + } + else + { + /* Disable the selected DMA Tx Desc second address chained */ + DMATxDesc->CtrlOrBufSize &= (~(uint32_t)ETH_DMA_TX_DESC_TCH); + } +} + +/** + * @brief Enables or disables the DMA Tx Desc padding for frame shorter than 64 bytes. + * @param DMATxDesc pointer on a DMA Tx descriptor + * @param Cmd new state of the specified DMA Tx Desc padding for frame shorter than 64 bytes. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableDmaTxDescShortFramePadding(ETH_DMADescType* DMATxDesc, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the selected DMA Tx Desc padding for frame shorter than 64 bytes */ + DMATxDesc->CtrlOrBufSize &= (~(uint32_t)ETH_DMA_TX_DESC_DP); + } + else + { + /* Disable the selected DMA Tx Desc padding for frame shorter than 64 bytes*/ + DMATxDesc->CtrlOrBufSize |= ETH_DMA_TX_DESC_DP; + } +} + +/** + * @brief Enables or disables the DMA Tx Desc time stamp. + * @param DMATxDesc pointer on a DMA Tx descriptor + * @param Cmd new state of the specified DMA Tx Desc time stamp. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableDmaTxDescTimeStamp(ETH_DMADescType* DMATxDesc, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the selected DMA Tx Desc time stamp */ + DMATxDesc->CtrlOrBufSize |= ETH_DMA_TX_DESC_TTSE; + } + else + { + /* Disable the selected DMA Tx Desc time stamp */ + DMATxDesc->CtrlOrBufSize &= (~(uint32_t)ETH_DMA_TX_DESC_TTSE); + } +} + +/** + * @brief Configures the specified DMA Tx Desc buffer1 and buffer2 sizes. + * @param DMATxDesc Pointer on a Tx desc + * @param BufferSize1 specifies the Tx desc buffer1 size. + * @param BufferSize2 specifies the Tx desc buffer2 size (put "0" if not used). + */ +void ETH_ConfigDmaTxDescBufSize(ETH_DMADescType* DMATxDesc, uint32_t BufferSize1, uint32_t BufferSize2) +{ + /* Check the parameters */ + assert_param(IS_ETH_DMA_TX_DESC_BUFFER_SIZE(BufferSize1)); + assert_param(IS_ETH_DMA_TX_DESC_BUFFER_SIZE(BufferSize2)); + + /* Set the DMA Tx Desc buffer1 and buffer2 sizes values */ + DMATxDesc->CtrlOrBufSize |= (BufferSize1 | (BufferSize2 << ETH_DMA_TX_DESC_BUF2_SIZE_SHIFT)); +} + +/** + * @brief Initializes the DMA Rx descriptors in chain mode. + * @param DMARxDescTab Pointer on the first Rx desc list + * @param RxBuff Pointer on the first RxBuffer list + * @param BuffSize the buffer size of each RxBuffer + * @param RxBuffCount Number of the used Rx desc in the list + */ +void ETH_ConfigDmaRxDescInChainMode(ETH_DMADescType* DMARxDescTab, + uint8_t* RxBuff, + uint32_t BuffSize, + uint32_t RxBuffCount) +{ + uint32_t i = 0; + ETH_DMADescType* DMARxDesc; + + /* Set the DMARxDescToGet pointer with the first one of the DMARxDescTab list */ + DMARxDescToGet = DMARxDescTab; + /* Fill each DMARxDesc descriptor with the right values */ + for (i = 0; i < RxBuffCount; i++) + { + /* Get the pointer on the ith member of the Rx Desc list */ + DMARxDesc = DMARxDescTab + i; + /* Set Own bit of the Rx descriptor Status */ + DMARxDesc->Status = ETH_DMA_RX_DESC_OWN; + + /* Set Buffer1 size and Second Address Chained bit */ + DMARxDesc->CtrlOrBufSize = ETH_DMA_RX_DESC_RCH | (uint32_t)(BuffSize & 0x1FFFUL); + /* Set Buffer1 address pointer */ + DMARxDesc->Buf1Addr = (uint32_t)(&RxBuff[i * BuffSize]); + + /* Initialize the next descriptor with the Next Desciptor Polling Enable */ + if (i < (RxBuffCount - 1)) + { + /* Set next descriptor address register with next descriptor base address */ + DMARxDesc->Buf2OrNextDescAddr = (uint32_t)(DMARxDescTab + i + 1); + } + else + { + /* For last descriptor, set next descriptor address register equal to the first descriptor base address */ + DMARxDesc->Buf2OrNextDescAddr = (uint32_t)(DMARxDescTab); + } + } + + /* Set Receive Desciptor List Address Register */ + ETH->DMARXDLADDR = (uint32_t)DMARxDescTab; +} + +/** + * @brief Initializes the DMA Rx descriptors in ring mode. + * @param DMARxDescTab Pointer on the first Rx desc list + * @param RxBuff1 Pointer on the first RxBuffer1 list + * @param RxBuff2 Pointer on the first RxBuffer2 list + * @param BuffSize the buffer size of each RxBuffer + * @param RxBuffCount Number of the used Rx desc in the list + * Note: see decriptor skip length defined in ETH_DMA_InitStruct + * for the number of Words to skip between two unchained descriptors. + */ +void ETH_ConfigDmaRxDescInRingMode(ETH_DMADescType* DMARxDescTab, + uint8_t* RxBuff1, + uint8_t* RxBuff2, + uint32_t BuffSize, + uint32_t RxBuffCount) +{ + uint32_t i = 0; + ETH_DMADescType* DMARxDesc; + uint32_t dsl = (ETH->DMABUSMOD & ETH_DMABUSMOD_DSL) >> 2; + /* Set the DMARxDescToGet pointer with the first one of the DMARxDescTab list */ + DMARxDescToGet = DMARxDescTab; + /* Fill each DMARxDesc descriptor with the right values */ + for (i = 0; i < RxBuffCount; i++) + { + /* Get the pointer on the ith member of the Rx Desc list */ + // DMARxDesc = DMARxDescTab + i; + DMARxDesc = (ETH_DMADescType*)((uint32_t)DMARxDescTab + i * (16 + 4 * dsl)); + /* Set Own bit of the Rx descriptor Status */ + DMARxDesc->Status = ETH_DMA_RX_DESC_OWN; + /* Set Buffer1 size */ + DMARxDesc->CtrlOrBufSize = BuffSize; + /* Set Buffer1 address pointer */ + DMARxDesc->Buf1Addr = (uint32_t)(&RxBuff1[i * BuffSize]); + + /* Set Buffer2 address pointer */ + DMARxDesc->Buf2OrNextDescAddr = (uint32_t)(&RxBuff2[i * BuffSize]); + + /* Set Receive End of Ring bit for last descriptor: The DMA returns to the base + address of the list, creating a Desciptor Ring */ + if (i == (RxBuffCount - 1)) + { + /* Set Receive End of Ring bit */ + DMARxDesc->CtrlOrBufSize |= ETH_DMA_RX_DESC_RER; + } + } + + /* Set Receive Desciptor List Address Register */ + ETH->DMARXDLADDR = (uint32_t)DMARxDescTab; +} + +/** + * @brief Checks whether the specified ETHERNET Rx Desc flag is set or not. + * @param DMARxDesc pointer on a DMA Rx descriptor + * @param ETH_DMARxDescFlag specifies the flag to check. + * This parameter can be one of the following values: + * @arg ETH_DMA_RX_DESC_OWN OWN bit: descriptor is owned by DMA engine + * @arg ETH_DMA_RX_DESC_AFM DA Filter Fail for the rx frame + * @arg ETH_DMA_RX_DESC_ES Error summary + * @arg ETH_DMA_RX_DESC_DE Desciptor error: no more descriptors for receive frame + * @arg ETH_DMA_RX_DESC_SAF SA Filter Fail for the received frame + * @arg ETH_DMA_RX_DESC_LE Frame size not matching with length field + * @arg ETH_DMA_RX_DESC_OE Overflow Error: Frame was damaged due to buffer overflow + * @arg ETH_DMA_RX_DESC_VLAN VLAN Tag: received frame is a VLAN frame + * @arg ETH_DMA_RX_DESC_FS First descriptor of the frame + * @arg ETH_DMA_RX_DESC_LS Last descriptor of the frame + * @arg ETH_DMA_RX_DESC_IPV4HCE IPC Checksum Error/Giant Frame: Rx Ipv4 header checksum error + * @arg ETH_DMA_RX_DESC_LC Late collision occurred during reception + * @arg ETH_DMA_RX_DESC_FT Frame type - Ethernet, otherwise 802.3 + * @arg ETH_DMA_RX_DESC_RWT Receive Watchdog Timeout: watchdog timer expired during reception + * @arg ETH_DMA_RX_DESC_RE Receive error: error reported by MII interface + * @arg ETH_DMA_RX_DESC_DE Dribble bit error: frame contains non int multiple of 8 bits + * @arg ETH_DMA_RX_DESC_CE CRC error + * @arg ETH_DMA_RX_DESC_RMAPCE Rx MAC Address/Payload Checksum Error: Rx MAC address matched/ Rx Payload Checksum + * Error + * @return The new state of ETH_DMARxDescFlag (SET or RESET). + */ +FlagStatus ETH_GetDmaRxDescFlagStatus(ETH_DMADescType* DMARxDesc, uint32_t ETH_DMARxDescFlag) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ETH_DMA_RX_DESC_GET_FLAG(ETH_DMARxDescFlag)); + if ((DMARxDesc->Status & ETH_DMARxDescFlag) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Set the specified DMA Rx Desc Own bit. + * @param DMARxDesc Pointer on a Rx desc + */ +void ETH_SetDmaRxDescOwn(ETH_DMADescType* DMARxDesc) +{ + /* Set the DMA Rx Desc Own bit */ + DMARxDesc->Status |= ETH_DMA_RX_DESC_OWN; +} + +/** + * @brief Returns the specified DMA Rx Desc frame length. + * @param DMARxDesc pointer on a DMA Rx descriptor + * @return The Rx descriptor received frame length. + */ +uint32_t ETH_GetDmaRxDescFrameLen(__IO ETH_DMADescType* DMARxDesc) +{ + /* Return the Receive descriptor frame length */ + return ((DMARxDesc->Status & ETH_DMA_RX_DESC_FL) >> ETH_DMA_RX_DESC_FRAME_LEN_SHIFT); +} + +/** + * @brief Enables or disables the specified DMA Rx Desc receive interrupt. + * @param DMARxDesc Pointer on a Rx desc + * @param Cmd new state of the specified DMA Rx Desc interrupt. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableDmaRxDescReceiveInt(ETH_DMADescType* DMARxDesc, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the DMA Rx Desc receive interrupt */ + DMARxDesc->CtrlOrBufSize &= (~(uint32_t)ETH_DMA_RX_DESC_DIC); + } + else + { + /* Disable the DMA Rx Desc receive interrupt */ + DMARxDesc->CtrlOrBufSize |= ETH_DMA_RX_DESC_DIC; + } +} + +/** + * @brief Enables or disables the DMA Rx Desc end of ring. + * @param DMARxDesc pointer on a DMA Rx descriptor + * @param Cmd new state of the specified DMA Rx Desc end of ring. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableDmaRxDescEndOfRing(ETH_DMADescType* DMARxDesc, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the selected DMA Rx Desc end of ring */ + DMARxDesc->CtrlOrBufSize |= ETH_DMA_RX_DESC_RER; + } + else + { + /* Disable the selected DMA Rx Desc end of ring */ + DMARxDesc->CtrlOrBufSize &= (~(uint32_t)ETH_DMA_RX_DESC_RER); + } +} + +/** + * @brief Enables or disables the DMA Rx Desc second address chained. + * @param DMARxDesc pointer on a DMA Rx descriptor + * @param Cmd new state of the specified DMA Rx Desc second address chained. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableDmaRxDescSecondAddrChained(ETH_DMADescType* DMARxDesc, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the selected DMA Rx Desc second address chained */ + DMARxDesc->CtrlOrBufSize |= ETH_DMA_RX_DESC_RCH; + } + else + { + /* Disable the selected DMA Rx Desc second address chained */ + DMARxDesc->CtrlOrBufSize &= (~(uint32_t)ETH_DMA_RX_DESC_RCH); + } +} + +/** + * @brief Returns the specified ETHERNET DMA Rx Desc buffer size. + * @param DMARxDesc pointer on a DMA Rx descriptor + * @param DMARxDesc_Buffer specifies the DMA Rx Desc buffer. + * This parameter can be any one of the following values: + * @arg ETH_DMA_RX_DESC_BUFFER1 DMA Rx Desc Buffer1 + * @arg ETH_DMA_RX_DESC_BUFFER2 DMA Rx Desc Buffer2 + * @return The Receive descriptor frame length. + */ +uint32_t ETH_GetDmaRxDescBufSize(ETH_DMADescType* DMARxDesc, uint32_t DMARxDesc_Buffer) +{ + /* Check the parameters */ + assert_param(IS_ETH_DMA_RXDESC_BUFFER(DMARxDesc_Buffer)); + + if (DMARxDesc_Buffer != ETH_DMA_RX_DESC_BUFFER1) + { + /* Return the DMA Rx Desc buffer2 size */ + return ((DMARxDesc->CtrlOrBufSize & ETH_DMA_RX_DESC_RBS2) >> ETH_DMA_RX_DESC_BUF2_SIZE_SHIFT); + } + else + { + /* Return the DMA Rx Desc buffer1 size */ + return (DMARxDesc->CtrlOrBufSize & ETH_DMA_RX_DESC_RBS1); + } +} + +/*--------------------------------- DMA ------------------------------------*/ +/** + * @brief Resets all MAC subsystem internal registers and logic. + */ +void ETH_SoftwareReset(void) +{ + /* Set the SWR bit: resets all MAC subsystem internal registers and logic */ + /* After reset all the registers holds their respective reset values */ + ETH->DMABUSMOD |= ETH_DMABUSMOD_SWR; +} + +/** + * @brief Checks whether the ETHERNET software reset bit is set or not. + * @return The new state of DMA Bus Mode register STS bit (SET or RESET). + */ +FlagStatus ETH_GetSoftwareResetStatus(void) +{ + FlagStatus bitstatus = RESET; + if ((ETH->DMABUSMOD & ETH_DMABUSMOD_SWR) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Checks whether the specified ETHERNET DMA flag is set or not. + * @param ETH_DMA_FLAG specifies the flag to check. + * This parameter can be one of the following values: + * @arg ETH_DMA_FLAG_TST Time-stamp trigger flag + * @arg ETH_DMA_FLAG_PMT PMT flag + * @arg ETH_DMA_FLAG_MMC MMC flag + * @arg ETH_DMA_FLAG_DATA_TRANSFER_ERROR Error bits 0-data buffer, 1-desc. access + * @arg ETH_DMA_FLAG_READ_WRITE_ERROR Error bits 0-write trnsf, 1-read transfr + * @arg ETH_DMA_FLAG_ACCESS_ERROR Error bits 0-Rx DMA, 1-Tx DMA + * @arg ETH_DMA_FLAG_NIS Normal interrupt summary flag + * @arg ETH_DMA_FLAG_AIS Abnormal interrupt summary flag + * @arg ETH_DMA_FLAG_EARLY_RX Early receive flag + * @arg ETH_DMA_FLAG_FATAL_BUS_ERROR Fatal bus error flag + * @arg ETH_DMA_FLAG_EARLY_TX Early transmit flag + * @arg ETH_DMA_FLAG_RX_WDG_TIMEOUT Receive watchdog timeout flag + * @arg ETH_DMA_FLAG_RX_PROC_STOP Receive process stopped flag + * @arg ETH_DMA_FLAG_RX_BUF_UA Receive buffer unavailable flag + * @arg ETH_DMA_FLAG_RX Receive flag + * @arg ETH_DMA_FLAG_TX_UNDERFLOW Underflow flag + * @arg ETH_DMA_FLAG_RX_OVERFLOW Overflow flag + * @arg ETH_DMA_FLAG_TX_JABBER_TIMEOUT Transmit jabber timeout flag + * @arg ETH_DMA_FLAG_TX_BUF_UA Transmit buffer unavailable flag + * @arg ETH_DMA_FLAG_TX_PROC_STOP Transmit process stopped flag + * @arg ETH_DMA_FLAG_TX Transmit flag + * @return The new state of ETH_DMA_FLAG (SET or RESET). + */ +FlagStatus ETH_GetDmaFlagStatus(uint32_t ETH_DMA_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ETH_DMA_GET_INT(ETH_DMA_FLAG)); + if ((ETH->DMASTS & ETH_DMA_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the ETHERNET's DMA pending flag. + * @param ETH_DMA_FLAG specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg ETH_DMA_FLAG_NIS Normal interrupt summary flag + * @arg ETH_DMA_FLAG_AIS Abnormal interrupt summary flag + * @arg ETH_DMA_FLAG_EARLY_RX Early receive flag + * @arg ETH_DMA_FLAG_FATAL_BUS_ERROR Fatal bus error flag + * @arg ETH_DMA_FLAG_ETI Early transmit flag + * @arg ETH_DMA_FLAG_RX_WDG_TIMEOUT Receive watchdog timeout flag + * @arg ETH_DMA_FLAG_RX_PROC_STOP Receive process stopped flag + * @arg ETH_DMA_FLAG_RX_BUF_UA Receive buffer unavailable flag + * @arg ETH_DMA_FLAG_RX Receive flag + * @arg ETH_DMA_FLAG_TX_UNDERFLOW Transmit Underflow flag + * @arg ETH_DMA_FLAG_RX_OVERFLOW Receive Overflow flag + * @arg ETH_DMA_FLAG_TX_JABBER_TIMEOUT Transmit jabber timeout flag + * @arg ETH_DMA_FLAG_TX_BUF_UA Transmit buffer unavailable flag + * @arg ETH_DMA_FLAG_TX_PROC_STOP Transmit process stopped flag + * @arg ETH_DMA_FLAG_TX Transmit flag + */ +void ETH_ClrDmaFlag(uint32_t ETH_DMA_FLAG) +{ + /* Check the parameters */ + assert_param(IS_ETH_DMA_FLAG(ETH_DMA_FLAG)); + + /* Clear the selected ETHERNET DMA FLAG */ + ETH->DMASTS = (uint32_t)ETH_DMA_FLAG; +} + +/** + * @brief Checks whether the specified ETHERNET DMA interrupt has occured or not. + * @param ETH_DMA_IT specifies the interrupt source to check. + * This parameter can be one of the following values: + * @arg ETH_DMA_INT_TST Time-stamp trigger interrupt + * @arg ETH_DMA_INT_PMT PMT interrupt + * @arg ETH_DMA_INT_MMC MMC interrupt + * @arg ETH_DMA_INT_NIS Normal interrupt summary + * @arg ETH_DMA_INT_AIS Abnormal interrupt summary + * @arg ETH_DMA_INT_EARLY_RX Early receive interrupt + * @arg ETH_DMA_INT_FATAL_BUS_ERROR Fatal bus error interrupt + * @arg ETH_DMA_INT_EARLY_TX Early transmit interrupt + * @arg ETH_DMA_INT_RX_WDG_TIMEOUT Receive watchdog timeout interrupt + * @arg ETH_DMA_INT_RX_PROC_STOP Receive process stopped interrupt + * @arg ETH_DMA_INT_RX_BUF_UA Receive buffer unavailable interrupt + * @arg ETH_DMA_INT_RX Receive interrupt + * @arg ETH_DMA_INT_TX_UNDERFLOW Underflow interrupt + * @arg ETH_DMA_INT_RX_OVERFLOW Overflow interrupt + * @arg ETH_DMA_INT_TX_JABBER_TIMEOUT Transmit jabber timeout interrupt + * @arg ETH_DMA_INT_TX_BUF_UA Transmit buffer unavailable interrupt + * @arg ETH_DMA_INT_TX_PROC_STOP Transmit process stopped interrupt + * @arg ETH_DMA_INT_TX Transmit interrupt + * @return The new state of ETH_DMA_IT (SET or RESET). + */ +INTStatus ETH_GetDmaIntStatus(uint32_t ETH_DMA_IT) +{ + INTStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ETH_DMA_GET_INT(ETH_DMA_IT)); + if ((ETH->DMASTS & ETH_DMA_IT) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the ETHERNET's DMA IT pending bit. + * @param ETH_DMA_IT specifies the interrupt pending bit to clear. + * This parameter can be any combination of the following values: + * @arg ETH_DMA_INT_NIS Normal interrupt summary + * @arg ETH_DMA_INT_AIS Abnormal interrupt summary + * @arg ETH_DMA_INT_EARLY_RX Early receive interrupt + * @arg ETH_DMA_INT_FATAL_BUS_ERROR Fatal bus error interrupt + * @arg ETH_DMA_IT_ETI Early transmit interrupt + * @arg ETH_DMA_INT_RX_WDG_TIMEOUT Receive watchdog timeout interrupt + * @arg ETH_DMA_INT_RX_PROC_STOP Receive process stopped interrupt + * @arg ETH_DMA_INT_RX_BUF_UA Receive buffer unavailable interrupt + * @arg ETH_DMA_INT_RX Receive interrupt + * @arg ETH_DMA_INT_TX_UNDERFLOW Transmit Underflow interrupt + * @arg ETH_DMA_INT_RX_OVERFLOW Receive Overflow interrupt + * @arg ETH_DMA_INT_TX_JABBER_TIMEOUT Transmit jabber timeout interrupt + * @arg ETH_DMA_INT_TX_BUF_UA Transmit buffer unavailable interrupt + * @arg ETH_DMA_INT_TX_PROC_STOP Transmit process stopped interrupt + * @arg ETH_DMA_INT_TX Transmit interrupt + */ +void ETH_ClrDmaIntPendingBit(uint32_t ETH_DMA_IT) +{ + /* Check the parameters */ + assert_param(IS_ETH_DMA_INT(ETH_DMA_IT)); + + /* Clear the selected ETHERNET DMA IT */ + ETH->DMASTS = (uint32_t)ETH_DMA_IT; +} + +/** + * @brief Returns the ETHERNET DMA Transmit Process State. + * @return The new ETHERNET DMA Transmit Process State: + * This can be one of the following values: + * - ETH_DMA_TX_PROC_STOPPED : Stopped - Reset or Stop Tx Command issued + * - ETH_DMA_TX_PROC_FETCHING : Running - fetching the Tx descriptor + * - ETH_DMA_TX_PROC_WAITING : Running - waiting for status + * - ETH_DMA_TX_PROC_READING : unning - reading the data from host memory + * - ETH_DMA_TX_PROC_SUSPENDED : Suspended - Tx Desciptor unavailabe + * - ETH_DMA_TX_PROC_CLOSING : Running - closing Rx descriptor + */ +uint32_t ETH_GetTxProcState(void) +{ + return ((uint32_t)(ETH->DMASTS & ETH_DMASTS_TI)); +} + +/** + * @brief Returns the ETHERNET DMA Receive Process State. + * @return The new ETHERNET DMA Receive Process State: + * This can be one of the following values: + * - ETH_DMA_RX_PROC_STOPPED : Stopped - Reset or Stop Rx Command issued + * - ETH_DMA_RX_PROC_FETCHING : Running - fetching the Rx descriptor + * - ETH_DMA_RX_PROC_WAITING : Running - waiting for packet + * - ETH_DMA_RX_PROC_SUSPENDED : Suspended - Rx Desciptor unavailable + * - ETH_DMA_RX_PROC_CLOSING : Running - closing descriptor + * - ETH_DMA_RX_PROC_QUEUING : Running - queuing the recieve frame into host memory + */ +uint32_t ETH_GetRxProcState(void) +{ + return ((uint32_t)(ETH->DMASTS & ETH_DMASTS_RI)); +} + +/** + * @brief Clears the ETHERNET transmit DATFIFO. + */ +void ETH_FlushTxFifo(void) +{ + /* Set the Flush Transmit DATFIFO bit */ + ETH->DMAOPMOD |= ETH_DMAOPMOD_FTF; +} + +/** + * @brief Checks whether the ETHERNET transmit DATFIFO bit is cleared or not. + * @return The new state of ETHERNET flush transmit DATFIFO bit (SET or RESET). + */ +FlagStatus ETH_GetFlushTxFifoStatus(void) +{ + FlagStatus bitstatus = RESET; + if ((ETH->DMAOPMOD & ETH_DMAOPMOD_FTF) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Enables or disables the DMA transmission. + * @param Cmd new state of the DMA transmission. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableDmaTx(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the DMA transmission */ + ETH->DMAOPMOD |= ETH_DMAOPMOD_ST; + } + else + { + /* Disable the DMA transmission */ + ETH->DMAOPMOD &= ~ETH_DMAOPMOD_ST; + } +} + +/** + * @brief Enables or disables the DMA reception. + * @param Cmd new state of the DMA reception. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableDmaRx(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the DMA reception */ + ETH->DMAOPMOD |= ETH_DMAOPMOD_SR; + } + else + { + /* Disable the DMA reception */ + ETH->DMAOPMOD &= ~ETH_DMAOPMOD_SR; + } +} + +/** + * @brief Enables or disables the specified ETHERNET DMA interrupts. + * @param ETH_DMA_IT specifies the ETHERNET DMA interrupt sources to be + * enabled or disabled. + * This parameter can be any combination of the following values: + * @arg ETH_DMA_INT_NIS Normal interrupt summary + * @arg ETH_DMA_INT_AIS Abnormal interrupt summary + * @arg ETH_DMA_INT_EARLY_RX Early receive interrupt + * @arg ETH_DMA_INT_FATAL_BUS_ERROR Fatal bus error interrupt + * @arg ETH_DMA_INT_EARLY_TX Early transmit interrupt + * @arg ETH_DMA_INT_RX_WDG_TIMEOUT Receive watchdog timeout interrupt + * @arg ETH_DMA_INT_RX_PROC_STOP Receive process stopped interrupt + * @arg ETH_DMA_INT_RX_BUF_UA Receive buffer unavailable interrupt + * @arg ETH_DMA_INT_RX Receive interrupt + * @arg ETH_DMA_INT_TX_UNDERFLOW Underflow interrupt + * @arg ETH_DMA_INT_RX_OVERFLOW Overflow interrupt + * @arg ETH_DMA_INT_TX_JABBER_TIMEOUT Transmit jabber timeout interrupt + * @arg ETH_DMA_INT_TX_BUF_UA Transmit buffer unavailable interrupt + * @arg ETH_DMA_INT_TX_PROC_STOP Transmit process stopped interrupt + * @arg ETH_DMA_INT_TX Transmit interrupt + * @param Cmd new state of the specified ETHERNET DMA interrupts. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableDmaInt(uint32_t ETH_DMA_IT, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_ETH_DMA_INT(ETH_DMA_IT)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the selected ETHERNET DMA interrupts */ + ETH->DMAINTEN |= ETH_DMA_IT; + } + else + { + /* Disable the selected ETHERNET DMA interrupts */ + ETH->DMAINTEN &= (~(uint32_t)ETH_DMA_IT); + } +} + +/** + * @brief Checks whether the specified ETHERNET DMA overflow flag is set or not. + * @param ETH_DMA_Overflow specifies the DMA overflow flag to check. + * This parameter can be one of the following values: + * @arg ETH_DMA_OVERFLOW_RX_FIFO_COUNTER Overflow for DATFIFO Overflow Counter + * @arg ETH_DMA_OVERFLOW_MISSED_FRAME_COUNTER Overflow for Missed Frame Counter + * @return The new state of ETHERNET DMA overflow Flag (SET or RESET). + */ +FlagStatus ETH_GetDmaOverflowStatus(uint32_t ETH_DMA_Overflow) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ETH_DMA_GET_OVERFLOW(ETH_DMA_Overflow)); + + if ((ETH->DMAMFBOCNT & ETH_DMA_Overflow) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Get the ETHERNET DMA Rx Overflow Missed Frame Counter value. + * @return The value of Rx overflow Missed Frame Counter. + */ +uint32_t ETH_GetRxOverflowMissedFrameCounter(void) +{ + return ((uint32_t)((ETH->DMAMFBOCNT & ETH_DMAMFBOCNT_OVFFRMCNT) >> ETH_DMA_RX_OVERFLOW_MISSEDFRAMES_COUNTER_SHIFT)); +} + +/** + * @brief Get the ETHERNET DMA Buffer Unavailable Missed Frame Counter value. + * @return The value of Buffer unavailable Missed Frame Counter. + */ +uint32_t ETH_GetBufUnavailableMissedFrameCounter(void) +{ + return ((uint32_t)(ETH->DMAMFBOCNT) & ETH_DMAMFBOCNT_MISFRMCNT); +} + +/** + * @brief Get the ETHERNET DMA DMACHTXDESC register value. + * @return The value of the current Tx desc start address. + */ +uint32_t ETH_GetCurrentTxDescAddr(void) +{ + return ((uint32_t)(ETH->DMACHTXDESC)); +} + +/** + * @brief Get the ETHERNET DMA DMACHRXDESC register value. + * @return The value of the current Rx desc start address. + */ +uint32_t ETH_GetCurrentRxDescAddr(void) +{ + return ((uint32_t)(ETH->DMACHRXDESC)); +} + +/** + * @brief Get the ETHERNET DMA DMACHTXBADDR register value. + * @return The value of the current Tx buffer address. + */ +uint32_t ETH_GetCurrentTxBufAddr(void) +{ + return ((uint32_t)(ETH->DMACHTXBADDR)); +} + +/** + * @brief Get the ETHERNET DMA DMACHRXBADDR register value. + * @return The value of the current Rx buffer address. + */ +uint32_t ETH_GetCurrentRxBufAddr(void) +{ + return ((uint32_t)(ETH->DMACHRXBADDR)); +} + +/** + * @brief Resumes the DMA Transmission by writing to the DmaTxPollDemand register + * (the data written could be anything). This forces the DMA to resume transmission. + */ +void ETH_ResumeDmaTx(void) +{ + ETH->DMATXPD = 0; +} + +/** + * @brief Resumes the DMA Transmission by writing to the DmaRxPollDemand register + * (the data written could be anything). This forces the DMA to resume reception. + */ +void ETH_ResumeDmaRx(void) +{ + ETH->DMARXPD = 0; +} + +/*--------------------------------- PMT ------------------------------------*/ +/** + * @brief Reset Wakeup frame filter register pointer. + */ +void ETH_ResetWakeUpFrameFilter(void) +{ + /* Resets the Remote Wake-up Frame Filter register pointer to 0x0000 */ + ETH->MACPMTCTRLSTS |= ETH_MACPMTCTRLSTS_RWKUPFLTRST; +} + +/** + * @brief Populates the remote wakeup frame registers. + * @param Buffer Pointer on remote WakeUp Frame Filter Register buffer data (8 words). + */ +void ETH_SetWakeUpFrameFilter(uint32_t* Buffer) +{ + uint32_t i = 0; + + /* Fill Remote Wake-up Frame Filter register with Buffer data */ + for (i = 0; i < ETH_WAKEUP_REG_LEN; i++) + { + /* Write each time to the same register */ + ETH->MACRMTWUFRMFLT = Buffer[i]; + } +} + +/** + * @brief Enables or disables any unicast packet filtered by the MAC address + * recognition to be a wake-up frame. + * @param Cmd new state of the MAC Global Unicast Wake-Up. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableGlobalUnicastWakeUp(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the MAC Global Unicast Wake-Up */ + ETH->MACPMTCTRLSTS |= ETH_MACPMTCTRLSTS_GLBLUCAST; + } + else + { + /* Disable the MAC Global Unicast Wake-Up */ + ETH->MACPMTCTRLSTS &= ~ETH_MACPMTCTRLSTS_GLBLUCAST; + } +} + +/** + * @brief Checks whether the specified ETHERNET PMT flag is set or not. + * @param ETH_PMT_FLAG specifies the flag to check. + * This parameter can be one of the following values: + * @arg ETH_PMT_FLAG_RWKUPFILTRST Wake-Up Frame Filter Register Poniter Reset + * @arg ETH_PMT_FLAG_RWKPRCVD Wake-Up Frame Received + * @arg ETH_PMT_FLAG_MGKPRCVD Magic Packet Received + * @return The new state of ETHERNET PMT Flag (SET or RESET). + */ +FlagStatus ETH_GetPmtFlagStatus(uint32_t ETH_PMT_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ETH_PMT_GET_FLAG(ETH_PMT_FLAG)); + + if ((ETH->MACPMTCTRLSTS & ETH_PMT_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Enables or disables the MAC Wake-Up Frame Detection. + * @param Cmd new state of the MAC Wake-Up Frame Detection. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableWakeUpFrameDetection(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the MAC Wake-Up Frame Detection */ + ETH->MACPMTCTRLSTS |= ETH_MACPMTCTRLSTS_RWKPKTEN; + } + else + { + /* Disable the MAC Wake-Up Frame Detection */ + ETH->MACPMTCTRLSTS &= ~ETH_MACPMTCTRLSTS_RWKPKTEN; + } +} + +/** + * @brief Enables or disables the MAC Magic Packet Detection. + * @param Cmd new state of the MAC Magic Packet Detection. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableMagicPacketDetection(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the MAC Magic Packet Detection */ + ETH->MACPMTCTRLSTS |= ETH_MACPMTCTRLSTS_MGKPKTEN; + } + else + { + /* Disable the MAC Magic Packet Detection */ + ETH->MACPMTCTRLSTS &= ~ETH_MACPMTCTRLSTS_MGKPKTEN; + } +} + +/** + * @brief Enables or disables the MAC Power Down. + * @param Cmd new state of the MAC Power Down. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnablePowerDown(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the MAC Power Down */ + /* This puts the MAC in power down mode */ + ETH->MACPMTCTRLSTS |= ETH_MACPMTCTRLSTS_PWRDWN; + } + else + { + /* Disable the MAC Power Down */ + ETH->MACPMTCTRLSTS &= ~ETH_MACPMTCTRLSTS_PWRDWN; + } +} + +/*--------------------------------- MMC ------------------------------------*/ +/** + * @brief Enables or disables the MMC Counter Freeze. + * @param Cmd new state of the MMC Counter Freeze. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableMmcCounterFreeze(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the MMC Counter Freeze */ + ETH->MMCCTRL |= ETH_MMCCTRL_CNTFREEZ; + } + else + { + /* Disable the MMC Counter Freeze */ + ETH->MMCCTRL &= ~ETH_MMCCTRL_CNTFREEZ; + } +} + +/** + * @brief Enables or disables the MMC Reset On Read. + * @param Cmd new state of the MMC Reset On Read. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableMmcResetOnRead(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the MMC Counter reset on read */ + ETH->MMCCTRL |= ETH_MMCCTRL_RSTONRD; + } + else + { + /* Disable the MMC Counter reset on read */ + ETH->MMCCTRL &= ~ETH_MMCCTRL_RSTONRD; + } +} + +/** + * @brief Enables or disables the MMC Counter Stop Rollover. + * @param Cmd new state of the MMC Counter Stop Rollover. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableMmcCounterRollover(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Disable the MMC Counter Stop Rollover */ + ETH->MMCCTRL &= ~ETH_MMCCTRL_CNTSTOPRO; + } + else + { + /* Enable the MMC Counter Stop Rollover */ + ETH->MMCCTRL |= ETH_MMCCTRL_CNTSTOPRO; + } +} + +/** + * @brief Resets the MMC Counters. + */ +void ETH_ResetMmcCounters(void) +{ + /* Resets the MMC Counters */ + ETH->MMCCTRL |= ETH_MMCCTRL_CNTRST; +} + +/** + * @brief Enables or disables the specified ETHERNET MMC interrupts. + * @param ETH_MMC_IT specifies the ETHERNET MMC interrupt sources to be enabled or disabled. + * This parameter can be any combination of Tx interrupt or + * any combination of Rx interrupt (but not both)of the following values: + * @arg ETH_MMC_INT_TXGFRMIS When Tx good frame counter reaches half the maximum value + * @arg ETH_MMC_INT_TXMCOLGFIS When Tx good multi col counter reaches half the maximum value + * @arg ETH_MMC_INT_TXSCOLGFIS When Tx good single col counter reaches half the maximum value + * @arg ETH_MMC_INT_RXUCGFIS When Rx good unicast frames counter reaches half the maximum value + * @arg ETH_MMC_INT_RXALGNERFIS When Rx alignment error counter reaches half the maximum value + * @arg ETH_MMC_INT_RXCRCERFIS When Rx crc error counter reaches half the maximum value + * @param Cmd new state of the specified ETHERNET MMC interrupts. + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_EnableMmcInt(uint32_t ETH_MMC_IT, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_ETH_MMC_INT(ETH_MMC_IT)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if ((ETH_MMC_IT & (uint32_t)0x10000000) != (uint32_t)RESET) + { + /* Remove egister mak from IT */ + ETH_MMC_IT &= 0xEFFFFFFF; + + /* ETHERNET MMC Rx interrupts selected */ + if (Cmd != DISABLE) + { + /* Enable the selected ETHERNET MMC interrupts */ + ETH->MMCRXINTMSK &= (~(uint32_t)ETH_MMC_IT); + } + else + { + /* Disable the selected ETHERNET MMC interrupts */ + ETH->MMCRXINTMSK |= ETH_MMC_IT; + } + } + else + { + /* ETHERNET MMC Tx interrupts selected */ + if (Cmd != DISABLE) + { + /* Enable the selected ETHERNET MMC interrupts */ + ETH->MMCTXINTMSK &= (~(uint32_t)ETH_MMC_IT); + } + else + { + /* Disable the selected ETHERNET MMC interrupts */ + ETH->MMCTXINTMSK |= ETH_MMC_IT; + } + } +} + +/** + * @brief Checks whether the specified ETHERNET MMC IT is set or not. + * @param ETH_MMC_IT specifies the ETHERNET MMC interrupt. + * This parameter can be one of the following values: + * @arg ETH_MMC_IT_TxFCGC When Tx good frame counter reaches half the maximum value + * @arg ETH_MMC_IT_TxMCGC When Tx good multi col counter reaches half the maximum value + * @arg ETH_MMC_IT_TxSCGC When Tx good single col counter reaches half the maximum value + * @arg ETH_MMC_IT_RxUGFC When Rx good unicast frames counter reaches half the maximum value + * @arg ETH_MMC_IT_RxAEC When Rx alignment error counter reaches half the maximum value + * @arg ETH_MMC_IT_RxCEC When Rx crc error counter reaches half the maximum value + * @return The value of ETHERNET MMC IT (SET or RESET). + */ +INTStatus ETH_GetMmcIntStatus(uint32_t ETH_MMC_IT) +{ + INTStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ETH_MMC_GET_INT(ETH_MMC_IT)); + + if ((ETH_MMC_IT & (uint32_t)0x10000000) != (uint32_t)RESET) + { + /* ETHERNET MMC Rx interrupts selected */ + /* Check if the ETHERNET MMC Rx selected interrupt is enabled and occured */ + if ((((ETH->MMCRXINT & ETH_MMC_IT) != (uint32_t)RESET)) && ((ETH->MMCRXINTMSK & ETH_MMC_IT) != (uint32_t)RESET)) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + } + else + { + /* ETHERNET MMC Tx interrupts selected */ + /* Check if the ETHERNET MMC Tx selected interrupt is enabled and occured */ + if ((((ETH->MMCTXINT & ETH_MMC_IT) != (uint32_t)RESET)) && ((ETH->MMCRXINTMSK & ETH_MMC_IT) != (uint32_t)RESET)) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + } + + return bitstatus; +} + +/** + * @brief Get the specified ETHERNET MMC register value. + * @param ETH_MMCReg specifies the ETHERNET MMC register. + * This parameter can be one of the following values: + * @arg ETH_MMCCTRL MMC CTRL register + * @arg ETH_MMCRXINT MMC RIR register + * @arg ETH_MMCTXINT MMC TIR register + * @arg ETH_MMCRXINTMSK MMC RIMR register + * @arg ETH_MMCTXINTMSK MMC TIMR register + * @arg ETH_MMCTXGFASCCNT MMC TGFSCCR register + * @arg ETH_MMCTXGFAMSCCNT MMC TGFMSCCR register + * @arg ETH_MMCTXGFCNT MMC TGFCR register + * @arg ETH_MMCRXFCECNT MMC RFCECR register + * @arg ETH_MMCRXFAECNT MMC RFAECR register + * @arg ETH_MMCRXGUFCNT MMC RGUFCRregister + * @return The value of ETHERNET MMC Register value. + */ +uint32_t ETH_GetMmcRegisterValue(uint32_t ETH_MMCReg) +{ + /* Check the parameters */ + assert_param(IS_ETH_MMC_REGISTER(ETH_MMCReg)); + + /* Return the selected register value */ + return (*(__IO uint32_t*)(ETH_MAC_BASE + ETH_MMCReg)); +} +/*--------------------------------- PTP ------------------------------------*/ + +/** + * @brief Updated the PTP block for fine correction with the Time Stamp Addend register value. + */ +void ETH_UpdatePtpTimeStampAddend(void) +{ + /* Enable the PTP block update with the Time Stamp Addend register value */ + ETH->PTPTSCTRL |= ETH_PTPTSCTRL_TSADDREG; +} + +/** + * @brief Enable the PTP Time Stamp interrupt trigger + */ +void ETH_EnablePtpTimeStampIntTrigger(void) +{ + /* Enable the PTP target time interrupt */ + ETH->PTPTSCTRL |= ETH_PTPTSCTRL_TSTRIG; +} + +/** + * @brief Updated the PTP system time with the Time Stamp Update register value. + */ +void ETH_UpdatePtpTimeStamp(void) +{ + /* Enable the PTP system time update with the Time Stamp Update register value */ + ETH->PTPTSCTRL |= ETH_PTPTSCTRL_TSUPDT; +} + +/** + * @brief Initialize the PTP Time Stamp + */ +void ETH_InitPtpTimeStamp(void) +{ + /* Initialize the PTP Time Stamp */ + ETH->PTPTSCTRL |= ETH_PTPTSCTRL_TSINIT; +} + +/** + * @brief Selects the PTP Update method + * @param UpdateMethod the PTP Update method + * This parameter can be one of the following values: + * @arg ETH_PTP_FINE_UPDATE Fine Update method + * @arg ETH_PTP_COARSE_UPDATE Coarse Update method + */ +void ETH_ConfigPtpUpdateMethod(uint32_t UpdateMethod) +{ + /* Check the parameters */ + assert_param(IS_ETH_PTP_UPDATE(UpdateMethod)); + + if (UpdateMethod != ETH_PTP_COARSE_UPDATE) + { + /* Enable the PTP Fine Update method */ + ETH->PTPTSCTRL |= ETH_PTPTSCTRL_TSCFUPDT; + } + else + { + /* Disable the PTP Coarse Update method */ + ETH->PTPTSCTRL &= (~(uint32_t)ETH_PTPTSCTRL_TSCFUPDT); + } +} + +/** + * @brief Enables or disables the PTP time stamp for transmit and receive frames. + * @param Cmd new state of the PTP time stamp for transmit and receive frames + * This parameter can be: ENABLE or DISABLE. + */ +void ETH_StartPTPTimeStamp(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the PTP time stamp for transmit and receive frames */ + ETH->PTPTSCTRL |= ETH_PTPTSCTRL_TSENA; + } + else + { + /* Disable the PTP time stamp for transmit and receive frames */ + ETH->PTPTSCTRL &= (~(uint32_t)ETH_PTPTSCTRL_TSENA); + } +} + +/** + * @brief Checks whether the specified ETHERNET PTP flag is set or not. + * @param ETH_PTP_FLAG specifies the flag to check. + * This parameter can be one of the following values: + * @arg ETH_PTP_FLAG_TSADDREG Addend Register Update + * @arg ETH_PTP_FLAG_TSTRIG Time Stamp Interrupt Trigger Enable + * @arg ETH_PTP_FLAG_TSUPDT Time Stamp Update + * @arg ETH_PTP_FLAG_TSINIT Time Stamp Initialize + * @return The new state of ETHERNET PTP Flag (SET or RESET). + */ +FlagStatus ETH_GetPtpFlagStatus(uint32_t ETH_PTP_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_ETH_PTP_GET_FLAG(ETH_PTP_FLAG)); + + if ((ETH->PTPTSCTRL & ETH_PTP_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Sets the system time Sub-Second Increment value. + * @param SubSecondValue specifies the PTP Sub-Second Increment Register value. + */ +void ETH_SetPtpSubSecondInc(uint32_t SubSecondValue) +{ + /* Check the parameters */ + assert_param(IS_ETH_PTP_SUBSECOND_INCREMENT(SubSecondValue)); + /* Set the PTP Sub-Second Increment Register */ + ETH->PTPSSINC = SubSecondValue; +} + +/** + * @brief Sets the Time Stamp update sign and values. + * @param Sign specifies the PTP Time update value sign. + * This parameter can be one of the following values: + * @arg ETH_PTP_POSITIVE_TIME positive time value. + * @arg ETH_PTP_NEGATIVE_TIME negative time value. + * @param SecondValue specifies the PTP Time update second value. + * @param SubSecondValue specifies the PTP Time update sub-second value. + * This parameter is a 31 bit value, bit32 correspond to the sign. + */ +void ETH_SetPtpTimeStampUpdate(uint32_t Sign, uint32_t SecondValue, uint32_t SubSecondValue) +{ + /* Check the parameters */ + assert_param(IS_ETH_PTP_TIME_SIGN(Sign)); + assert_param(IS_ETH_PTP_TIME_STAMP_UPDATE_SUBSECOND(SubSecondValue)); + /* Set the PTP Time Update High Register */ + ETH->PTPSECUP = SecondValue; + + /* Set the PTP Time Update Low Register with sign */ + ETH->PTPNSUP = Sign | SubSecondValue; +} + +/** + * @brief Sets the Time Stamp Addend value. + * @param Value specifies the PTP Time Stamp Addend Register value. + */ +void ETH_SetPtpTimeStampAddend(uint32_t Value) +{ + /* Set the PTP Time Stamp Addend Register */ + ETH->PTPTSADD = Value; +} + +/** + * @brief Sets the Target Time registers values. + * @param HighValue specifies the PTP Target Time High Register value. + * @param LowValue specifies the PTP Target Time Low Register value. + */ +void ETH_SetPtpTargetTime(uint32_t HighValue, uint32_t LowValue) +{ + /* Set the PTP Target Time High Register */ + ETH->PTPTTSEC = HighValue; + /* Set the PTP Target Time Low Register */ + ETH->PTPTTNS = LowValue; +} + +/** + * @brief Get the specified ETHERNET PTP register value. + * @param ETH_PTPReg specifies the ETHERNET PTP register. + * This parameter can be one of the following values: + * @arg ETH_PTPTSCTRL Sub-Second Increment Register + * @arg ETH_PTPSSINC Sub-Second Increment Register + * @arg ETH_PTPSEC Time Stamp High Register + * @arg ETH_PTPNS Time Stamp Low Register + * @arg ETH_PTPSECUP Time Stamp High Update Register + * @arg ETH_PTPNSUP Time Stamp Low Update Register + * @arg ETH_PTPTSADD Time Stamp Addend Register + * @arg ETH_PTPTTSEC Target Time High Register + * @arg ETH_PTPTTNS Target Time Low Register + * @return The value of ETHERNET PTP Register value. + */ +uint32_t ETH_GetPtpRegisterValue(uint32_t ETH_PTPReg) +{ + /* Check the parameters */ + assert_param(IS_ETH_PTP_REGISTER(ETH_PTPReg)); + + /* Return the selected register value */ + return (*(__IO uint32_t*)(ETH_MAC_BASE + ETH_PTPReg)); +} + +/** + * @brief Initializes the DMA Tx descriptors in chain mode with PTP. + * @param DMATxDescTab Pointer on the first Tx desc list + * @param DMAPTPTxDescTab Pointer on the first PTP Tx desc list + * @param TxBuff Pointer on the first TxBuffer list + * @param TxBuffCount Number of the used Tx desc in the list + */ +void ETH_ConfigDmaPtpTxDescInChainMode(ETH_DMADescType* DMATxDescTab, + ETH_DMADescType* DMAPTPTxDescTab, + uint8_t* TxBuff, + uint32_t TxBuffCount) +{ + uint32_t i = 0; + ETH_DMADescType* DMATxDesc; + + /* Set the DMATxDescToSet pointer with the first one of the DMATxDescTab list */ + DMATxDescToSet = DMATxDescTab; + DMAPTPTxDescToSet = DMAPTPTxDescTab; + /* Fill each DMATxDesc descriptor with the right values */ + for (i = 0; i < TxBuffCount; i++) + { + /* Get the pointer on the ith member of the Tx Desc list */ + DMATxDesc = DMATxDescTab + i; + /* Set Second Address Chained bit and enable PTP */ + DMATxDesc->Status = 0; + DMATxDesc->CtrlOrBufSize = ETH_DMA_TX_DESC_TCH | ETH_DMA_TX_DESC_TTSE; + + /* Set Buffer1 address pointer */ + DMATxDesc->Buf1Addr = (uint32_t)(&TxBuff[i * ETH_MAX_PACKET_SIZE]); + + /* Initialize the next descriptor with the Next Desciptor Polling Enable */ + if (i < (TxBuffCount - 1)) + { + /* Set next descriptor address register with next descriptor base address */ + DMATxDesc->Buf2OrNextDescAddr = (uint32_t)(DMATxDescTab + i + 1); + } + else + { + /* For last descriptor, set next descriptor address register equal to the first descriptor base address */ + DMATxDesc->Buf2OrNextDescAddr = (uint32_t)DMATxDescTab; + } + /* make DMAPTPTxDescTab points to the same addresses as DMATxDescTab */ + (&DMAPTPTxDescTab[i])->Buf1Addr = DMATxDesc->Buf1Addr; + (&DMAPTPTxDescTab[i])->Buf2OrNextDescAddr = DMATxDesc->Buf2OrNextDescAddr; + } + /* Store on the last DMAPTPTxDescTab desc status record the first list address */ + (&DMAPTPTxDescTab[i - 1])->Status = (uint32_t)DMAPTPTxDescTab; + + /* Set Transmit Desciptor List Address Register */ + ETH->DMATXDLADDR = (uint32_t)DMATxDescTab; +} + +/** + * @brief Initializes the DMA Rx descriptors in chain mode. + * @param DMARxDescTab Pointer on the first Rx desc list + * @param DMAPTPRxDescTab Pointer on the first PTP Rx desc list + * @param RxBuff Pointer on the first RxBuffer list + * @param RxBuffCount Number of the used Rx desc in the list + */ +void ETH_ConfigDmaPtpRxDescInChainMode(ETH_DMADescType* DMARxDescTab, + ETH_DMADescType* DMAPTPRxDescTab, + uint8_t* RxBuff, + uint32_t RxBuffCount) +{ + uint32_t i = 0; + ETH_DMADescType* DMARxDesc; + + /* Set the DMARxDescToGet pointer with the first one of the DMARxDescTab list */ + DMARxDescToGet = DMARxDescTab; + DMAPTPRxDescToGet = DMAPTPRxDescTab; + /* Fill each DMARxDesc descriptor with the right values */ + for (i = 0; i < RxBuffCount; i++) + { + /* Get the pointer on the ith member of the Rx Desc list */ + DMARxDesc = DMARxDescTab + i; + /* Set Own bit of the Rx descriptor Status */ + DMARxDesc->Status = ETH_DMA_RX_DESC_OWN; + + /* Set Buffer1 size and Second Address Chained bit */ + DMARxDesc->CtrlOrBufSize = ETH_DMA_RX_DESC_RCH | (uint32_t)ETH_MAX_PACKET_SIZE; + /* Set Buffer1 address pointer */ + DMARxDesc->Buf1Addr = (uint32_t)(&RxBuff[i * ETH_MAX_PACKET_SIZE]); + + /* Initialize the next descriptor with the Next Desciptor Polling Enable */ + if (i < (RxBuffCount - 1)) + { + /* Set next descriptor address register with next descriptor base address */ + DMARxDesc->Buf2OrNextDescAddr = (uint32_t)(DMARxDescTab + i + 1); + } + else + { + /* For last descriptor, set next descriptor address register equal to the first descriptor base address */ + DMARxDesc->Buf2OrNextDescAddr = (uint32_t)(DMARxDescTab); + } + /* Make DMAPTPRxDescTab points to the same addresses as DMARxDescTab */ + (&DMAPTPRxDescTab[i])->Buf1Addr = DMARxDesc->Buf1Addr; + (&DMAPTPRxDescTab[i])->Buf2OrNextDescAddr = DMARxDesc->Buf2OrNextDescAddr; + } + /* Store on the last DMAPTPRxDescTab desc status record the first list address */ + (&DMAPTPRxDescTab[i - 1])->Status = (uint32_t)DMAPTPRxDescTab; + + /* Set Receive Desciptor List Address Register */ + ETH->DMARXDLADDR = (uint32_t)DMARxDescTab; +} + +/** + * @brief Transmits a packet, from application buffer, pointed by ppkt with Time Stamp values. + * @param ppkt pointer to application packet buffer to transmit. + * @param FrameLength Tx Packet size. + * @param PTPTxTab Pointer on the first PTP Tx table to store Time stamp values. + * @return ETH_ERROR: in case of Tx desc owned by DMA + * ETH_SUCCESS: for correct transmission + */ +uint32_t ETH_TxPtpPacket(uint8_t* ppkt, uint16_t FrameLength, uint32_t* PTPTxTab) +{ + uint32_t offset = 0, timeout = 0; + /* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset) */ + if ((DMATxDescToSet->Status & ETH_DMA_TX_DESC_OWN) != (uint32_t)RESET) + { + /* Return ERROR: OWN bit set */ + return ETH_ERROR; + } + /* Copy the frame to be sent into memory pointed by the current ETHERNET DMA Tx descriptor */ + for (offset = 0; offset < FrameLength; offset++) + { + (*(__IO uint8_t*)((DMAPTPTxDescToSet->Buf1Addr) + offset)) = (*(ppkt + offset)); + } + /* Setting the Frame Length: bits[10:0] */ + DMATxDescToSet->CtrlOrBufSize &= (~ETH_DMA_TX_DESC_TBS1); + DMATxDescToSet->CtrlOrBufSize |= (FrameLength & ETH_DMA_TX_DESC_TBS1); + /* Setting the last segment and first segment bits (in this case a frame is transmitted in one descriptor) */ + DMATxDescToSet->CtrlOrBufSize |= ETH_DMA_TX_DESC_LS | ETH_DMA_TX_DESC_FS; + /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */ + DMATxDescToSet->Status |= ETH_DMA_TX_DESC_OWN; + /* When Tx Buffer unavailable flag is set: clear it and resume transmission */ + if ((ETH->DMASTS & ETH_DMASTS_TU) != (uint32_t)RESET) + { + /* Clear TBUS ETHERNET DMA flag */ + ETH->DMASTS = ETH_DMASTS_TU; + /* Resume DMA transmission*/ + ETH->DMATXPD = 0; + } + /* Wait for ETH_DMA_TX_DESC_TTSS flag to be set */ + do + { + timeout++; + } while (!(DMATxDescToSet->Status & ETH_DMA_TX_DESC_TTSS) && (timeout < 0xFFFF)); + /* Return ERROR in case of timeout */ + if (timeout == PHY_READ_TO) + { + return ETH_ERROR; + } + /* Clear the DMATxDescToSet status register TTSS flag */ + DMATxDescToSet->Status &= ~ETH_DMA_TX_DESC_TTSS; + *PTPTxTab++ = DMATxDescToSet->Buf1Addr; + *PTPTxTab = DMATxDescToSet->Buf2OrNextDescAddr; + /* Update the ENET DMA current descriptor */ + /* Chained Mode */ + if ((DMATxDescToSet->CtrlOrBufSize & ETH_DMA_TX_DESC_TCH) != (uint32_t)RESET) + { + /* Selects the next DMA Tx descriptor list for next buffer read */ + DMATxDescToSet = (ETH_DMADescType*)(DMAPTPTxDescToSet->Buf2OrNextDescAddr); + if (DMAPTPTxDescToSet->Status != 0) + { + DMAPTPTxDescToSet = (ETH_DMADescType*)(DMAPTPTxDescToSet->Status); + } + else + { + DMAPTPTxDescToSet++; + } + } + else /* Ring Mode */ + { + if ((DMATxDescToSet->CtrlOrBufSize & ETH_DMA_TX_DESC_TER) != (uint32_t)RESET) + { + /* Selects the next DMA Tx descriptor list for next buffer read: this will + be the first Tx descriptor in this case */ + DMATxDescToSet = (ETH_DMADescType*)(ETH->DMATXDLADDR); + DMAPTPTxDescToSet = (ETH_DMADescType*)(ETH->DMATXDLADDR); + } + else + { + /* Selects the next DMA Tx descriptor list for next buffer read */ + DMATxDescToSet = + (ETH_DMADescType*)((uint32_t)DMATxDescToSet + 0x10 + ((ETH->DMABUSMOD & ETH_DMABUSMOD_DSL))); + DMAPTPTxDescToSet = + (ETH_DMADescType*)((uint32_t)DMAPTPTxDescToSet + 0x10 + ((ETH->DMABUSMOD & ETH_DMABUSMOD_DSL))); + } + } + /* Return SUCCESS */ + return ETH_SUCCESS; +} + +/** + * @brief Receives a packet and copies it to memory pointed by ppkt with Time Stamp values. + * @param ppkt pointer to application packet receive buffer. + * @param PTPRxTab Pointer on the first PTP Rx table to store Time stamp values. + * @return ETH_ERROR: if there is error in reception + * framelength: received packet size if packet reception is correct + */ +uint32_t ETH_RxPtpPacket(uint8_t* ppkt, uint32_t* PTPRxTab) +{ + uint32_t offset = 0, framelength = 0; + /* Check if the descriptor is owned by the ENET or CPU */ + if ((DMARxDescToGet->Status & ETH_DMA_RX_DESC_OWN) != (uint32_t)RESET) + { + /* Return error: OWN bit set */ + return ETH_ERROR; + } + if (((DMARxDescToGet->Status & ETH_DMA_RX_DESC_ES) == (uint32_t)RESET) + && ((DMARxDescToGet->Status & ETH_DMA_RX_DESC_LS) != (uint32_t)RESET) + && ((DMARxDescToGet->Status & ETH_DMA_RX_DESC_FS) != (uint32_t)RESET)) + { + /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */ + framelength = ((DMARxDescToGet->Status & ETH_DMA_RX_DESC_FL) >> ETH_DMA_RX_DESC_FRAME_LEN_SHIFT) - 4; + /* Copy the received frame into buffer from memory pointed by the current ETHERNET DMA Rx descriptor */ + for (offset = 0; offset < framelength; offset++) + { + (*(ppkt + offset)) = (*(__IO uint8_t*)((DMAPTPRxDescToGet->Buf1Addr) + offset)); + } + } + else + { + /* Return ERROR */ + framelength = ETH_ERROR; + } + /* When Rx Buffer unavailable flag is set: clear it and resume reception */ + if ((ETH->DMASTS & ETH_DMASTS_RU) != (uint32_t)RESET) + { + /* Clear RBUS ETHERNET DMA flag */ + ETH->DMASTS = ETH_DMASTS_RU; + /* Resume DMA reception */ + ETH->DMARXPD = 0; + } + *PTPRxTab++ = DMARxDescToGet->Buf1Addr; + *PTPRxTab = DMARxDescToGet->Buf2OrNextDescAddr; + /* Set Own bit of the Rx descriptor Status: gives the buffer back to ETHERNET DMA */ + DMARxDescToGet->Status |= ETH_DMA_RX_DESC_OWN; + /* Update the ETHERNET DMA global Rx descriptor with next Rx decriptor */ + /* Chained Mode */ + if ((DMARxDescToGet->CtrlOrBufSize & ETH_DMA_RX_DESC_RCH) != (uint32_t)RESET) + { + /* Selects the next DMA Rx descriptor list for next buffer read */ + DMARxDescToGet = (ETH_DMADescType*)(DMAPTPRxDescToGet->Buf2OrNextDescAddr); + if (DMAPTPRxDescToGet->Status != 0) + { + DMAPTPRxDescToGet = (ETH_DMADescType*)(DMAPTPRxDescToGet->Status); + } + else + { + DMAPTPRxDescToGet++; + } + } + else /* Ring Mode */ + { + if ((DMARxDescToGet->CtrlOrBufSize & ETH_DMA_RX_DESC_RER) != (uint32_t)RESET) + { + /* Selects the first DMA Rx descriptor for next buffer to read: last Rx descriptor was used */ + DMARxDescToGet = (ETH_DMADescType*)(ETH->DMARXDLADDR); + } + else + { + /* Selects the next DMA Rx descriptor list for next buffer to read */ + DMARxDescToGet = + (ETH_DMADescType*)((uint32_t)DMARxDescToGet + 0x10 + ((ETH->DMABUSMOD & ETH_DMABUSMOD_DSL))); + } + } + /* Return Frame Length/ERROR */ + return (framelength); +} +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/src/n32g45x_exti.c b/src/n32g45x_exti.c new file mode 100644 index 0000000..94e3598 --- /dev/null +++ b/src/n32g45x_exti.c @@ -0,0 +1,286 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_exti.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_exti.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup EXTI + * @brief EXTI driver modules + * @{ + */ + +/** @addtogroup EXTI_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup EXTI_Private_Defines + * @{ + */ + +#define EXTI_LINENONE ((uint32_t)0x00000) /* No interrupt selected */ + +/** + * @} + */ + +/** @addtogroup EXTI_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup EXTI_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup EXTI_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup EXTI_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the EXTI peripheral registers to their default reset values. + */ +void EXTI_DeInit(void) +{ + EXTI->IMASK = 0x00000000; + EXTI->EMASK = 0x00000000; + EXTI->RT_CFG = 0x00000000; + EXTI->FT_CFG = 0x00000000; + EXTI->PEND = 0x000FFFFF; +} + +/** + * @brief Initializes the EXTI peripheral according to the specified + * parameters in the EXTI_InitStruct. + * @param EXTI_InitStruct pointer to a EXTI_InitType structure + * that contains the configuration information for the EXTI peripheral. + */ +void EXTI_InitPeripheral(EXTI_InitType* EXTI_InitStruct) +{ + uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_EXTI_MODE(EXTI_InitStruct->EXTI_Mode)); + assert_param(IS_EXTI_TRIGGER(EXTI_InitStruct->EXTI_Trigger)); + assert_param(IS_EXTI_LINE(EXTI_InitStruct->EXTI_Line)); + assert_param(IS_FUNCTIONAL_STATE(EXTI_InitStruct->EXTI_LineCmd)); + + tmp = (uint32_t)EXTI_BASE; + + if (EXTI_InitStruct->EXTI_LineCmd != DISABLE) + { + /* Clear EXTI line configuration */ + EXTI->IMASK &= ~EXTI_InitStruct->EXTI_Line; + EXTI->EMASK &= ~EXTI_InitStruct->EXTI_Line; + + tmp += EXTI_InitStruct->EXTI_Mode; + + *(__IO uint32_t*)tmp |= EXTI_InitStruct->EXTI_Line; + + /* Clear Rising Falling edge configuration */ + EXTI->RT_CFG &= ~EXTI_InitStruct->EXTI_Line; + EXTI->FT_CFG &= ~EXTI_InitStruct->EXTI_Line; + + /* Select the trigger for the selected external interrupts */ + if (EXTI_InitStruct->EXTI_Trigger == EXTI_Trigger_Rising_Falling) + { + /* Rising Falling edge */ + EXTI->RT_CFG |= EXTI_InitStruct->EXTI_Line; + EXTI->FT_CFG |= EXTI_InitStruct->EXTI_Line; + } + else + { + tmp = (uint32_t)EXTI_BASE; + tmp += EXTI_InitStruct->EXTI_Trigger; + + *(__IO uint32_t*)tmp |= EXTI_InitStruct->EXTI_Line; + } + } + else + { + tmp += EXTI_InitStruct->EXTI_Mode; + + /* Disable the selected external lines */ + *(__IO uint32_t*)tmp &= ~EXTI_InitStruct->EXTI_Line; + } +} + +/** + * @brief Fills each EXTI_InitStruct member with its reset value. + * @param EXTI_InitStruct pointer to a EXTI_InitType structure which will + * be initialized. + */ +void EXTI_InitStruct(EXTI_InitType* EXTI_InitStruct) +{ + EXTI_InitStruct->EXTI_Line = EXTI_LINENONE; + EXTI_InitStruct->EXTI_Mode = EXTI_Mode_Interrupt; + EXTI_InitStruct->EXTI_Trigger = EXTI_Trigger_Falling; + EXTI_InitStruct->EXTI_LineCmd = DISABLE; +} + +/** + * @brief Generates a Software interrupt. + * @param EXTI_Line specifies the EXTI lines to be enabled or disabled. + * This parameter can be any combination of EXTI_Linex where x can be (0..19). + */ +void EXTI_TriggerSWInt(uint32_t EXTI_Line) +{ + /* Check the parameters */ + assert_param(IS_EXTI_LINE(EXTI_Line)); + + EXTI->SWIE |= EXTI_Line; +} + +/** + * @brief Checks whether the specified EXTI line flag is set or not. + * @param EXTI_Line specifies the EXTI line flag to check. + * This parameter can be: + * @arg EXTI_Linex External interrupt line x where x(0..19) + * @return The new state of EXTI_Line (SET or RESET). + */ +FlagStatus EXTI_GetStatusFlag(uint32_t EXTI_Line) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_GET_EXTI_LINE(EXTI_Line)); + + if ((EXTI->PEND & EXTI_Line) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the EXTI's line pending flags. + * @param EXTI_Line specifies the EXTI lines flags to clear. + * This parameter can be any combination of EXTI_Linex where x can be (0..19). + */ +void EXTI_ClrStatusFlag(uint32_t EXTI_Line) +{ + /* Check the parameters */ + assert_param(IS_EXTI_LINE(EXTI_Line)); + + EXTI->PEND = EXTI_Line; +} + +/** + * @brief Checks whether the specified EXTI line is asserted or not. + * @param EXTI_Line specifies the EXTI line to check. + * This parameter can be: + * @arg EXTI_Linex External interrupt line x where x(0..19) + * @return The new state of EXTI_Line (SET or RESET). + */ +INTStatus EXTI_GetITStatus(uint32_t EXTI_Line) +{ + INTStatus bitstatus = RESET; + uint32_t enablestatus = 0; + /* Check the parameters */ + assert_param(IS_GET_EXTI_LINE(EXTI_Line)); + + enablestatus = EXTI->IMASK & EXTI_Line; + if (((EXTI->PEND & EXTI_Line) != (uint32_t)RESET) && (enablestatus != (uint32_t)RESET)) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the EXTI's line pending bits. + * @param EXTI_Line specifies the EXTI lines to clear. + * This parameter can be any combination of EXTI_Linex where x can be (0..19). + */ +void EXTI_ClrITPendBit(uint32_t EXTI_Line) +{ + /* Check the parameters */ + assert_param(IS_EXTI_LINE(EXTI_Line)); + + EXTI->PEND = EXTI_Line; +} + +/** + * @brief Select one of EXTI inputs to the RTC TimeStamp event. + * @param EXTI_TSSEL_Line specifies the EXTI lines to select. + * This parameter can be any combination of EXTI_TSSEL_Line where x can be (0..15). + */ +void EXTI_RTCTimeStampSel(uint32_t EXTI_TSSEL_Line) +{ + /* Check the parameters */ + assert_param(IS_EXTI_TSSEL_LINE(EXTI_TSSEL_Line)); + + EXTI->TSSEL &= EXTI_TSSEL_TSSEL_ALL; + EXTI->TSSEL |= EXTI_TSSEL_Line; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/src/n32g45x_flash.c b/src/n32g45x_flash.c new file mode 100644 index 0000000..236301e --- /dev/null +++ b/src/n32g45x_flash.c @@ -0,0 +1,1124 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_flash.c + * @author Nations + * @version v1.0.2 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_flash.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup FLASH + * @brief FLASH driver modules + * @{ + */ + +/** @addtogroup FLASH_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup FLASH_Private_Defines + * @{ + */ + +/* Flash Access Control Register bits */ +#define AC_LATENCY_MSK ((uint32_t)0x000000F8) +#define AC_PRFTBE_MSK ((uint32_t)0xFFFFFFEF) +#define AC_ICAHEN_MSK ((uint32_t)0xFFFFFF7F) + +/* Flash Access Control Register bits */ +#define AC_PRFTBS_MSK ((uint32_t)0x00000020) +#define AC_ICAHRST_MSK ((uint32_t)0x00000040) + +/* Flash Control Register bits */ +#define CTRL_Set_PG ((uint32_t)0x00000001) +#define CTRL_Reset_PG ((uint32_t)0x00003FFE) +#define CTRL_Set_PER ((uint32_t)0x00000002) +#define CTRL_Reset_PER ((uint32_t)0x00003FFD) +#define CTRL_Set_MER ((uint32_t)0x00000004) +#define CTRL_Reset_MER ((uint32_t)0x00003FFB) +#define CTRL_Set_OPTPG ((uint32_t)0x00000010) +#define CTRL_Reset_OPTPG ((uint32_t)0x00003FEF) +#define CTRL_Set_OPTER ((uint32_t)0x00000020) +#define CTRL_Reset_OPTER ((uint32_t)0x00003FDF) +#define CTRL_Set_START ((uint32_t)0x00000040) +#define CTRL_Set_LOCK ((uint32_t)0x00000080) +#define CTRL_Reset_SMPSEL ((uint32_t)0x00003EFF) +#define CTRL_SMPSEL_SMP1 ((uint32_t)0x00000000) +#define CTRL_SMPSEL_SMP2 ((uint32_t)0x00000100) + +/* FLASH Mask */ +#define RDPRTL1_MSK ((uint32_t)0x00000002) +#define RDPRTL2_MSK ((uint32_t)0x80000000) +#define OBR_USER_MSK ((uint32_t)0x0000001C) +#define WRP0_MSK ((uint32_t)0x000000FF) +#define WRP1_MSK ((uint32_t)0x0000FF00) +#define WRP2_MSK ((uint32_t)0x00FF0000) +#define WRP3_MSK ((uint32_t)0xFF000000) + +/* FLASH Keys */ +#define L1_RDP_Key ((uint32_t)0xFFFF00A5) +#define RDP_USER_Key ((uint32_t)0xFFF800A5) +#define L2_RDP_Key ((uint32_t)0xFFFF33CC) +#define FLASH_KEY1 ((uint32_t)0x45670123) +#define FLASH_KEY2 ((uint32_t)0xCDEF89AB) + +/* Delay definition */ +#define EraseTimeout ((uint32_t)0x000B0000) +#define ProgramTimeout ((uint32_t)0x00002000) +/** + * @} + */ + +/** @addtogroup FLASH_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup FLASH_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup FLASH_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup FLASH_Private_Functions + * @{ + */ + +/** + * @brief Sets the code latency value. + * @note This function can be used for N32G45X devices. + * @param FLASH_Latency specifies the FLASH Latency value. + * This parameter can be one of the following values: + * @arg FLASH_LATENCY_0 FLASH Zero Latency cycle + * @arg FLASH_LATENCY_1 FLASH One Latency cycle + * @arg FLASH_LATENCY_2 FLASH Two Latency cycles + * @arg FLASH_LATENCY_3 FLASH Three Latency cycles + * @arg FLASH_LATENCY_4 FLASH Four Latency cycles + */ +void FLASH_SetLatency(uint32_t FLASH_Latency) +{ + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_FLASH_LATENCY(FLASH_Latency)); + + /* Read the AC register */ + tmpregister = FLASH->AC; + + /* Sets the Latency value */ + tmpregister &= AC_LATENCY_MSK; + tmpregister |= FLASH_Latency; + + /* Write the AC register */ + FLASH->AC = tmpregister; +} + +/** + * @brief Enables or disables the Prefetch Buffer. + * @note This function can be used for N32G45X devices. + * @param FLASH_PrefetchBuf specifies the Prefetch buffer status. + * This parameter can be one of the following values: + * @arg FLASH_PrefetchBuf_EN FLASH Prefetch Buffer Enable + * @arg FLASH_PrefetchBuf_DIS FLASH Prefetch Buffer Disable + */ +void FLASH_PrefetchBufSet(uint32_t FLASH_PrefetchBuf) +{ + /* Check the parameters */ + assert_param(IS_FLASH_PREFETCHBUF_STATE(FLASH_PrefetchBuf)); + + /* Enable or disable the Prefetch Buffer */ + FLASH->AC &= AC_PRFTBE_MSK; + FLASH->AC |= FLASH_PrefetchBuf; +} + +/** + * @brief ICache Reset. + * @note This function can be used for N32G45X devices. + */ +void FLASH_iCacheRST(void) +{ + /* ICache Reset */ + FLASH->AC |= FLASH_AC_ICAHRST; +} + +/** + * @brief Enables or disables the iCache. + * @note This function can be used for N32G45X devices. + * @param FLASH_iCache specifies the iCache status. + * This parameter can be one of the following values: + * @arg FLASH_iCache_EN FLASH iCache Enable + * @arg FLASH_iCache_DIS FLASH iCache Disable + */ +void FLASH_iCacheCmd(uint32_t FLASH_iCache) +{ + /* Check the parameters */ + assert_param(IS_FLASH_ICACHE_STATE(FLASH_iCache)); + + /* Enable or disable the iCache */ + FLASH->AC &= AC_ICAHEN_MSK; + FLASH->AC |= FLASH_iCache; +} + +/** + * @brief Checks whether the FLASH SMPSEL is SMP1 or SMP2. + * @note This function can be used for N32G45X devices. + * @param FLASH_smpsel FLASH_SMP1 or FLASH_SMP2 + * @return FLASH_SMPSEL_SMP1 or FLASH_SMPSEL_SMP2. + */ +void FLASH_SetSMPSELStatus(uint32_t FLASH_smpsel) +{ + /* Check the parameters */ + assert_param(IS_FLASH_SMPSEL_STATE(FLASH_smpsel)); + + /* SMP1 or SMP2 */ + FLASH->CTRL &= CTRL_Reset_SMPSEL; + FLASH->CTRL |= FLASH_smpsel; +} + +/** + * @brief Unlocks the FLASH Program Erase Controller. + * @note This function can be used for N32G45X devices. + * - For N32G45X devices this function unlocks Bank1. + * to FLASH_UnlockBank1 function.. + */ +void FLASH_Unlock(void) +{ + /* Authorize the FPEC of Bank1 Access */ + FLASH->KEY = FLASH_KEY1; + FLASH->KEY = FLASH_KEY2; +} + +/** + * @brief Locks the FLASH Program Erase Controller. + * @note This function can be used for N32G45X devices. + * - For N32G45X devices this function Locks Bank1. + * to FLASH_LockBank1 function. + */ +void FLASH_Lock(void) +{ + /* Set the Lock Bit to lock the FPEC and the CTRL of Bank1 */ + FLASH->CTRL |= CTRL_Set_LOCK; +} + +/** + * @brief Erases a specified FLASH page. + * @note This function can be used for N32G45X devices. + * @param Page_Address The page address to be erased. + * @return FLASH Status: The returned value can be: FLASH_BUSY, + * FLASH_ERR_PG, FLASH_ERR_PV, FLASH_ERR_WRP, FLASH_COMPL, + * FLASH_ERR_EV or FLASH_TIMEOUT. + */ +FLASH_STS FLASH_EraseOnePage(uint32_t Page_Address) +{ + FLASH_STS status = FLASH_COMPL; + /* Check the parameters */ + assert_param(IS_FLASH_ADDRESS(Page_Address)); + + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + + if (status == FLASH_COMPL) + { + /* if the previous operation is completed, proceed to erase the page */ + FLASH->CTRL |= CTRL_Set_PER; + FLASH->ADD = Page_Address; + FLASH->CTRL |= CTRL_Set_START; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + + /* Disable the PER Bit */ + FLASH->CTRL &= CTRL_Reset_PER; + } + + /* Return the Erase Status */ + return status; +} + +/** + * @brief Erases all FLASH pages. + * @note This function can be used for all N32G45X devices. + * @return FLASH Status: The returned value can be: FLASH_BUSY, + * FLASH_ERR_PG, FLASH_ERR_PV, FLASH_ERR_WRP, FLASH_COMPL, + * FLASH_ERR_EV or FLASH_TIMEOUT. + */ +FLASH_STS FLASH_MassErase(void) +{ + FLASH_STS status = FLASH_COMPL; + + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + + if (status == FLASH_COMPL) + { + /* if the previous operation is completed, proceed to erase all pages */ + FLASH->CTRL |= CTRL_Set_MER; + FLASH->CTRL |= CTRL_Set_START; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + + /* Disable the MER Bit */ + FLASH->CTRL &= CTRL_Reset_MER; + } + + /* Return the Erase Status */ + return status; +} + +/** + * @brief Erases the FLASH option bytes. + * @note This functions erases all option bytes except the Read protection (RDP). + * @note This function can be used for N32G45X devices. + * @return FLASH Status: The returned value can be: FLASH_BUSY, + * FLASH_ERR_PG, FLASH_ERR_PV, FLASH_ERR_WRP, FLASH_COMPL, + * FLASH_ERR_EV, FLASH_ERR_RDP2 or FLASH_TIMEOUT. + */ +FLASH_STS FLASH_EraseOB(void) +{ + uint32_t rdptmp = L1_RDP_Key; + + FLASH_STS status = FLASH_COMPL; + + /* Get the actual read protection L2 Option Byte value */ + if (FLASH_GetReadOutProtectionL2STS() != RESET) + { + status = FLASH_ERR_RDP2; + return status; + } + + /* Get the actual read protection Option Byte value */ + if (FLASH_GetReadOutProtectionSTS() != RESET) + { + rdptmp = (L1_RDP_Key & FLASH_USER_USER); + } + + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + + if (status == FLASH_COMPL) + { + /* Authorize the small information block programming */ + FLASH->OPTKEY = FLASH_KEY1; + FLASH->OPTKEY = FLASH_KEY2; + + /* if the previous operation is completed, proceed to erase the option bytes */ + FLASH->CTRL |= CTRL_Set_OPTER; + FLASH->CTRL |= CTRL_Set_START; + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + + if (status == FLASH_COMPL) + { + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + + /* if the erase operation is completed, disable the OPTER Bit */ + FLASH->CTRL &= CTRL_Reset_OPTER; + + /* Enable the Option Bytes Programming operation */ + FLASH->CTRL |= CTRL_Set_OPTPG; + /* Restore the last read protection Option Byte value */ + OB->USER_RDP = (uint32_t)rdptmp; + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(ProgramTimeout); + + if (status != FLASH_TIMEOUT) + { + /* if the program operation is completed, disable the OPTPG Bit */ + FLASH->CTRL &= CTRL_Reset_OPTPG; + } + } + else + { + if (status != FLASH_TIMEOUT) + { + /* Disable the OPTER Bit */ + FLASH->CTRL &= CTRL_Reset_OPTER; + } + } + } + /* Return the erase status */ + return status; +} + +/** + * @brief Programs a word at a specified address. + * @note This function can be used for N32G45X devices. + * @param Address specifies the address to be programmed. + * @param Data specifies the data to be programmed. + * @return FLASH Status: The returned value can be: FLASH_BUSY, + * FLASH_ERR_PG, FLASH_ERR_PV, FLASH_ERR_WRP, FLASH_COMPL, + * FLASH_ERR_EV, FLASH_ERR_ADD or FLASH_TIMEOUT. + */ +FLASH_STS FLASH_ProgramWord(uint32_t Address, uint32_t Data) +{ + FLASH_STS status = FLASH_COMPL; + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_FLASH_ADDRESS(Address)); + + if((Address & (uint32_t)0x3) != 0) + { + /* The programming address is not a multiple of 4 */ + status = FLASH_ERR_ADD; + return status; + } + + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(ProgramTimeout); + + if (status == FLASH_COMPL) + { + /* if the previous operation is completed, proceed to program the new word */ + FLASH->CTRL |= CTRL_Set_PG; + + *(__IO uint32_t*)Address = (uint32_t)Data; + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(ProgramTimeout); + + /* Disable the PG Bit */ + FLASH->CTRL &= CTRL_Reset_PG; + } + + /* Return the Program Status */ + return status; +} + +/** + * @brief Programs a half word at a specified Option Byte Data address. + * @note This function can be used for N32G45X devices. + * @param Address specifies the address to be programmed. + * This parameter can be 0x1FFFF804. + * @param Data specifies the data to be programmed(Data0 and Data1). + * @return FLASH Status: The returned value can be: FLASH_BUSY, + * FLASH_ERR_PG, FLASH_ERR_PV, FLASH_ERR_WRP, FLASH_COMPL, + * FLASH_ERR_EV, FLASH_ERR_RDP2 or FLASH_TIMEOUT. + */ +FLASH_STS FLASH_ProgramOBData(uint32_t Address, uint32_t Data) +{ + FLASH_STS status = FLASH_COMPL; + /* Check the parameters */ + assert_param(IS_OB_DATA_ADDRESS(Address)); + + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(ProgramTimeout); + + /* Get the actual read protection L2 Option Byte value */ + if (FLASH_GetReadOutProtectionL2STS() != RESET) + { + status = FLASH_ERR_RDP2; + return status; + } + + if (status == FLASH_COMPL) + { + /* Authorize the small information block programming */ + FLASH->OPTKEY = FLASH_KEY1; + FLASH->OPTKEY = FLASH_KEY2; + /* Enables the Option Bytes Programming operation */ + FLASH->CTRL |= CTRL_Set_OPTPG; + *(__IO uint32_t*)Address = (uint32_t)Data; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(ProgramTimeout); + if (status != FLASH_TIMEOUT) + { + /* if the program operation is completed, disable the OPTPG Bit */ + FLASH->CTRL &= CTRL_Reset_OPTPG; + } + } + /* Return the Option Byte Data Program Status */ + return status; +} + +/** + * @brief Write protects the desired pages + * @note This function can be used for N32G45X devices. + * @param FLASH_Pages specifies the address of the pages to be write protected. + * This parameter can be: + * @arg For @b N32G45X_devices: value between FLASH_WRP_Pages0to1 and + * FLASH_WRP_Pages60to61 or FLASH_WRP_Pages62to255 + * @arg FLASH_WRP_AllPages + * @return FLASH Status: The returned value can be: FLASH_BUSY, + * FLASH_ERR_PG, FLASH_ERR_PV, FLASH_ERR_WRP, FLASH_COMPL, + * FLASH_ERR_EV, FLASH_ERR_RDP2 or FLASH_TIMEOUT. + */ +FLASH_STS FLASH_EnWriteProtection(uint32_t FLASH_Pages) +{ + uint16_t WRP0_Data = 0xFFFF, WRP1_Data = 0xFFFF, WRP2_Data = 0xFFFF, WRP3_Data = 0xFFFF; + + FLASH_STS status = FLASH_COMPL; + + /* Check the parameters */ + assert_param(IS_FLASH_WRP_PAGE(FLASH_Pages)); + + /* Get the actual read protection L2 Option Byte value */ + if (FLASH_GetReadOutProtectionL2STS() != RESET) + { + status = FLASH_ERR_RDP2; + return status; + } + + FLASH_Pages = (uint32_t)(~FLASH_Pages); + WRP0_Data = (uint16_t)(FLASH_Pages & WRP0_MSK); + WRP1_Data = (uint16_t)((FLASH_Pages & WRP1_MSK) >> 8); + WRP2_Data = (uint16_t)((FLASH_Pages & WRP2_MSK) >> 16); + WRP3_Data = (uint16_t)((FLASH_Pages & WRP3_MSK) >> 24); + + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(ProgramTimeout); + + if (status == FLASH_COMPL) + { + /* Authorizes the small information block programming */ + FLASH->OPTKEY = FLASH_KEY1; + FLASH->OPTKEY = FLASH_KEY2; + FLASH->CTRL |= CTRL_Set_OPTPG; + + if ((WRP0_Data != 0xFF) || (WRP1_Data != 0xFF)) + { + OB->WRP1_WRP0 = (((uint32_t)WRP0_Data) | (((uint32_t)WRP1_Data) << 16)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(ProgramTimeout); + } + + if (((WRP2_Data != 0xFF) || (WRP3_Data != 0xFF)) && (status == FLASH_COMPL)) + { + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + + OB->WRP3_WRP2 = (((uint32_t)WRP2_Data) | (((uint32_t)WRP3_Data) << 16)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(ProgramTimeout); + } + + if (status != FLASH_TIMEOUT) + { + /* if the program operation is completed, disable the OPTPG Bit */ + FLASH->CTRL &= CTRL_Reset_OPTPG; + } + } + /* Return the write protection operation Status */ + return status; +} + +/** + * @brief Enables or disables the read out protection. + * @note If the user has already programmed the other option bytes before calling + * this function, he must re-program them since this function erases all option bytes. + * @note This function can be used for N32G45X devices. + * @param Cmd new state of the ReadOut Protection. + * This parameter can be: ENABLE or DISABLE. + * @return FLASH Status: The returned value can be: FLASH_BUSY, + * FLASH_ERR_PG, FLASH_ERR_PV, FLASH_ERR_WRP, FLASH_COMPL, + * FLASH_ERR_EV, FLASH_ERR_RDP2 or FLASH_TIMEOUT. + */ +FLASH_STS FLASH_ReadOutProtectionL1(FunctionalState Cmd) +{ + uint32_t usertmp; + FLASH_STS status = FLASH_COMPL; + + usertmp = ((OBR_USER_MSK & FLASH->OBR) << 0x0E); + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + /* Get the actual read protection L2 Option Byte value */ + if (FLASH_GetReadOutProtectionL2STS() != RESET) + { + status = FLASH_ERR_RDP2; + return status; + } + + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + + if (status == FLASH_COMPL) + { + /* Authorizes the small information block programming */ + FLASH->OPTKEY = FLASH_KEY1; + FLASH->OPTKEY = FLASH_KEY2; + FLASH->CTRL |= CTRL_Set_OPTER; + FLASH->CTRL |= CTRL_Set_START; + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + if (status == FLASH_COMPL) + { + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + + /* if the erase operation is completed, disable the OPTER Bit */ + FLASH->CTRL &= CTRL_Reset_OPTER; + /* Enable the Option Bytes Programming operation */ + FLASH->CTRL |= CTRL_Set_OPTPG; + if (Cmd != DISABLE) + { + OB->USER_RDP = (FLASH_USER_USER & usertmp); + } + else + { + OB->USER_RDP = ((L1_RDP_Key & FLASH_RDP_RDP1) | usertmp); + } + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + + if (status != FLASH_TIMEOUT) + { + /* if the program operation is completed, disable the OPTPG Bit */ + FLASH->CTRL &= CTRL_Reset_OPTPG; + } + } + else + { + if (status != FLASH_TIMEOUT) + { + /* Disable the OPTER Bit */ + FLASH->CTRL &= CTRL_Reset_OPTER; + } + } + } + /* Return the protection operation Status */ + return status; +} + +/** + * @brief Enables or disables the read out protection L2. + * @note If the user has already programmed the other option bytes before calling + * this function, he must re-program them since this function erases all option bytes. + * @note This function can be used for N32G45X devices. + * @return FLASH Status: The returned value can be: FLASH_BUSY, + * FLASH_ERR_PG, FLASH_ERR_PV, FLASH_ERR_WRP, FLASH_COMPL, + * FLASH_ERR_EV, FLASH_ERR_RDP2 or FLASH_TIMEOUT. + */ +FLASH_STS FLASH_ReadOutProtectionL2_ENABLE(void) +{ + uint32_t usertmp; + FLASH_STS status = FLASH_COMPL; + + usertmp = ((OBR_USER_MSK & FLASH->OBR) << 0x0E); + + /* Get the actual read protection L1 Option Byte value */ + if (FLASH_GetReadOutProtectionSTS() == RESET) + { + usertmp |= (L1_RDP_Key & FLASH_RDP_RDP1); + } + /* Get the actual read protection L2 Option Byte value */ + if (FLASH_GetReadOutProtectionL2STS() != RESET) + { + status = FLASH_ERR_RDP2; + return status; + } + + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + + if (status == FLASH_COMPL) + { + /* Authorizes the small information block programming */ + FLASH->OPTKEY = FLASH_KEY1; + FLASH->OPTKEY = FLASH_KEY2; + FLASH->CTRL |= CTRL_Set_OPTER; + FLASH->CTRL |= CTRL_Set_START; + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + if (status == FLASH_COMPL) + { + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + + /* if the erase operation is completed, disable the OPTER Bit */ + FLASH->CTRL &= CTRL_Reset_OPTER; + /* Enable the Option Bytes Programming operation */ + FLASH->CTRL |= CTRL_Set_OPTPG; + + OB->USER_RDP = usertmp; + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + + if (status == FLASH_COMPL) + { + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + + /* Enables the read out protection L2 */ + OB->RDP2 = L2_RDP_Key; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + } + + if (status != FLASH_TIMEOUT) + { + /* if the program operation is completed, disable the OPTPG Bit */ + FLASH->CTRL &= CTRL_Reset_OPTPG; + } + } + else + { + if (status != FLASH_TIMEOUT) + { + /* Disable the OPTER Bit */ + FLASH->CTRL &= CTRL_Reset_OPTER; + } + } + } + /* Return the protection operation Status */ + return status; +} + +/** + * @brief Programs the FLASH User Option Byte: IWDG_SW / RST_STOP / RST_STDBY. + * @note This function can be used for N32G45X devices. + * @param OB_IWDG Selects the IWDG mode + * This parameter can be one of the following values: + * @arg OB_IWDG_SW Software IWDG selected + * @arg OB_IWDG_HW Hardware IWDG selected + * @param OB_STOP Reset event when entering STOP mode. + * This parameter can be one of the following values: + * @arg OB_STOP0_NORST No reset generated when entering in STOP + * @arg OB_STOP0_RST Reset generated when entering in STOP + * @param OB_STDBY Reset event when entering Standby mode. + * This parameter can be one of the following values: + * @arg OB_STDBY_NORST No reset generated when entering in STANDBY + * @arg OB_STDBY_RST Reset generated when entering in STANDBY + * @return FLASH Status: The returned value can be: FLASH_BUSY, + * FLASH_ERR_PG, FLASH_ERR_PV, FLASH_ERR_WRP, FLASH_COMPL, + * FLASH_ERR_EV, FLASH_ERR_RDP2 or FLASH_TIMEOUT. + */ +FLASH_STS FLASH_ConfigUserOB(uint16_t OB_IWDG, uint16_t OB_STOP, uint16_t OB_STDBY) +{ + uint32_t rdptmp = RDP_USER_Key; + + FLASH_STS status = FLASH_COMPL; + + /* Check the parameters */ + assert_param(IS_OB_IWDG_SOURCE(OB_IWDG)); + assert_param(IS_OB_STOP0_SOURCE(OB_STOP)); + assert_param(IS_OB_STDBY_SOURCE(OB_STDBY)); + + /* Get the actual read protection L2 Option Byte value */ + if (FLASH_GetReadOutProtectionL2STS() != RESET) + { + status = FLASH_ERR_RDP2; + return status; + } + + /* Get the actual read protection Option Byte value */ + if (FLASH_GetReadOutProtectionSTS() != RESET) + { + rdptmp = 0xFFF80000; + } + + /* Authorize the small information block programming */ + FLASH->OPTKEY = FLASH_KEY1; + FLASH->OPTKEY = FLASH_KEY2; + + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + + if (status == FLASH_COMPL) + { + /* if the previous operation is completed, proceed to erase the option bytes */ + FLASH->CTRL |= CTRL_Set_OPTER; + FLASH->CTRL |= CTRL_Set_START; + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(EraseTimeout); + + if (status == FLASH_COMPL) + { + /* Clears the FLASH's pending flags */ + FLASH_ClearFlag(FLASH_STS_CLRFLAG); + + /* if the erase operation is completed, disable the OPTER Bit */ + FLASH->CTRL &= CTRL_Reset_OPTER; + + /* Enable the Option Bytes Programming operation */ + FLASH->CTRL |= CTRL_Set_OPTPG; + /* Restore the last read protection Option Byte value */ + OB->USER_RDP = + (uint32_t)rdptmp + | ((uint32_t)(OB_IWDG | (uint32_t)(OB_STOP | (uint32_t)(OB_STDBY | ((uint32_t)0xF8)))) << 16); + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOpt(ProgramTimeout); + + if (status != FLASH_TIMEOUT) + { + /* if the program operation is completed, disable the OPTPG Bit */ + FLASH->CTRL &= CTRL_Reset_OPTPG; + } + } + else + { + if (status != FLASH_TIMEOUT) + { + /* Disable the OPTER Bit */ + FLASH->CTRL &= CTRL_Reset_OPTER; + } + } + } + + /* Return the Option Byte program Status */ + return status; +} + +/** + * @brief Returns the FLASH User Option Bytes values. + * @note This function can be used for N32G45X devices. + * @return The FLASH User Option Bytes values:IWDG_SW(Bit0), RST_STOP(Bit1) + * and RST_STDBY(Bit2). + */ +uint32_t FLASH_GetUserOB(void) +{ + /* Return the User Option Byte */ + return (uint32_t)((FLASH->OBR << 27) >> 29); +} + +/** + * @brief Returns the FLASH Write Protection Option Bytes Register value. + * @note This function can be used for N32G45X devices. + * @return The FLASH Write Protection Option Bytes Register value + */ +uint32_t FLASH_GetWriteProtectionOB(void) +{ + /* Return the Flash write protection Register value */ + return (uint32_t)(FLASH->WRP); +} + +/** + * @brief Checks whether the FLASH Read Out Protection Status is set or not. + * @note This function can be used for N32G45X devices. + * @return FLASH ReadOut Protection Status(SET or RESET) + */ +FlagStatus FLASH_GetReadOutProtectionSTS(void) +{ + FlagStatus readoutstatus = RESET; + if ((FLASH->OBR & RDPRTL1_MSK) != (uint32_t)RESET) + { + readoutstatus = SET; + } + else + { + readoutstatus = RESET; + } + return readoutstatus; +} + +/** + * @brief Checks whether the FLASH Read Out Protection L2 Status is set or not. + * @note This function can be used for N32G45x devices. + * @return FLASH ReadOut Protection L2 Status(SET or RESET) + */ +FlagStatus FLASH_GetReadOutProtectionL2STS(void) +{ + FlagStatus readoutstatus = RESET; + if ((FLASH->OBR & RDPRTL2_MSK) != (uint32_t)RESET) + { + readoutstatus = SET; + } + else + { + readoutstatus = RESET; + } + return readoutstatus; +} + +/** + * @brief Checks whether the FLASH Prefetch Buffer status is set or not. + * @note This function can be used for N32G45X devices. + * @return FLASH Prefetch Buffer Status (SET or RESET). + */ +FlagStatus FLASH_GetPrefetchBufSTS(void) +{ + FlagStatus bitstatus = RESET; + + if ((FLASH->AC & AC_PRFTBS_MSK) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + /* Return the new state of FLASH Prefetch Buffer Status (SET or RESET) */ + return bitstatus; +} + +/** + * @brief Checks whether the FLASH SMPSEL is SMP1 or SMP2. + * @note This function can be used for N32G45X devices. + * @return FLASH SMPSEL (FLASH_SMP1 or FLASH_SMP2). + */ +FLASH_SMPSEL FLASH_GetSMPSELStatus(void) +{ + FLASH_SMPSEL bitstatus = FLASH_SMP1; + + if ((FLASH->CTRL & CTRL_SMPSEL_SMP2) != (uint32_t)FLASH_SMP1) + { + bitstatus = FLASH_SMP2; + } + else + { + bitstatus = FLASH_SMP1; + } + /* Return the new state of FLASH SMPSEL (FLASH_SMP1 or FLASH_SMP2) */ + return bitstatus; +} + +/** + * @brief Enables or disables the specified FLASH interrupts. + * @note This function can be used for N32G45X devices. + * @param FLASH_INT specifies the FLASH interrupt sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg FLASH_IT_ERROR FLASH Error Interrupt + * @arg FLASH_INT_FERR EVERR PVERR Interrupt + * @arg FLASH_INT_EOP FLASH end of operation Interrupt + * @param Cmd new state of the specified Flash interrupts. + * This parameter can be: ENABLE or DISABLE. + */ +void FLASH_INTConfig(uint32_t FLASH_INT, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FLASH_INT(FLASH_INT)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the interrupt sources */ + FLASH->CTRL |= FLASH_INT; + } + else + { + /* Disable the interrupt sources */ + FLASH->CTRL &= ~(uint32_t)FLASH_INT; + } +} + +/** + * @brief Checks whether the specified FLASH flag is set or not. + * @note This function can be used for N32G45X devices. + * @param FLASH_FLAG specifies the FLASH flag to check. + * This parameter can be one of the following values: + * @arg FLASH_FLAG_BUSY FLASH Busy flag + * @arg FLASH_FLAG_PGERR FLASH Program error flag + * @arg FLASH_FLAG_PVERR FLASH Program Verify ERROR flag + * @arg FLASH_FLAG_WRPERR FLASH Write protected error flag + * @arg FLASH_FLAG_EOP FLASH End of Operation flag + * @arg FLASH_FLAG_EVERR FLASH Erase Verify ERROR flag + * @arg FLASH_FLAG_OBERR FLASH Option Byte error flag + * @return The new state of FLASH_FLAG (SET or RESET). + */ +FlagStatus FLASH_GetFlagSTS(uint32_t FLASH_FLAG) +{ + FlagStatus bitstatus = RESET; + + /* Check the parameters */ + assert_param(IS_FLASH_GET_FLAG(FLASH_FLAG)); + if (FLASH_FLAG == FLASH_FLAG_OBERR) + { + if ((FLASH->OBR & FLASH_FLAG_OBERR) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + } + else + { + if ((FLASH->STS & FLASH_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + } + + /* Return the new state of FLASH_FLAG (SET or RESET) */ + return bitstatus; +} + +/** + * @brief Clears the FLASH's pending flags. + * @note This function can be used for N32G45X devices. + * @param FLASH_FLAG specifies the FLASH flags to clear. + * This parameter can be any combination of the following values: + * @arg FLASH_FLAG_PGERR FLASH Program error flag + * @arg FLASH_FLAG_PVERR FLASH Program Verify ERROR flag + * @arg FLASH_FLAG_WRPERR FLASH Write protected error flag + * @arg FLASH_FLAG_EOP FLASH End of Operation flag + * @arg FLASH_FLAG_EVERR FLASH Erase Verify ERROR flag + */ +void FLASH_ClearFlag(uint32_t FLASH_FLAG) +{ + /* Check the parameters */ + assert_param(IS_FLASH_CLEAR_FLAG(FLASH_FLAG)); + + /* Clear the flags */ + FLASH->STS |= FLASH_FLAG; +} + +/** + * @brief Returns the FLASH Status. + * @note This function can be used for N32G45X devices, it is equivalent + * to FLASH_GetBank1Status function. + * @return FLASH Status: The returned value can be: FLASH_BUSY, + * FLASH_ERR_PG, FLASH_ERR_PV, FLASH_ERR_WRP, FLASH_COMPL, + * FLASH_ERR_EV or FLASH_TIMEOUT. + */ +FLASH_STS FLASH_GetSTS(void) +{ + FLASH_STS flashstatus = FLASH_COMPL; + + if ((FLASH->STS & FLASH_FLAG_BUSY) == FLASH_FLAG_BUSY) + { + flashstatus = FLASH_BUSY; + } + else + { + if ((FLASH->STS & FLASH_FLAG_PGERR) != 0) + { + flashstatus = FLASH_ERR_PG; + } + else + { + if ((FLASH->STS & FLASH_FLAG_PVERR) != 0) + { + flashstatus = FLASH_ERR_PV; + } + else + { + if ((FLASH->STS & FLASH_FLAG_WRPERR) != 0) + { + flashstatus = FLASH_ERR_WRP; + } + else + { + if ((FLASH->STS & FLASH_FLAG_EVERR) != 0) + { + flashstatus = FLASH_ERR_EV; + } + else + { + flashstatus = FLASH_COMPL; + } + } + } + } + } + + /* Return the Flash Status */ + return flashstatus; +} + +/** + * @brief Waits for a Flash operation to complete or a TIMEOUT to occur. + * @note This function can be used for N32G45X devices, + * it is equivalent to FLASH_WaitForLastBank1Operation.. + * @param Timeout FLASH programming Timeout + * @return FLASH Status: The returned value can be: FLASH_BUSY, + * FLASH_ERR_PG, FLASH_ERR_PV, FLASH_ERR_WRP, FLASH_COMPL, + * FLASH_ERR_EV or FLASH_TIMEOUT. + */ +FLASH_STS FLASH_WaitForLastOpt(uint32_t Timeout) +{ + FLASH_STS status = FLASH_COMPL; + + /* Check for the Flash Status */ + status = FLASH_GetSTS(); + /* Wait for a Flash operation to complete or a TIMEOUT to occur */ + while ((status == FLASH_BUSY) && (Timeout != 0x00)) + { + status = FLASH_GetSTS(); + Timeout--; + } + if (Timeout == 0x00) + { + status = FLASH_TIMEOUT; + } + /* Return the operation status */ + return status; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/src/n32g45x_gpio.c b/src/n32g45x_gpio.c new file mode 100644 index 0000000..8c1f054 --- /dev/null +++ b/src/n32g45x_gpio.c @@ -0,0 +1,870 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_gpio.c + * @author Nations + * @version v1.0.2 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_gpio.h" +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup GPIO + * @brief GPIO driver modules + * @{ + */ + +/** @addtogroup GPIO_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup GPIO_Private_Defines + * @{ + */ + +/* ------------ RCC registers bit address in the alias region ----------------*/ +#define AFIO_OFFSET (AFIO_BASE - PERIPH_BASE) + +/* --- Event control register -----*/ + +/* Alias word address of EVOE bit */ +#define EVCR_OFFSET (AFIO_OFFSET + 0x00) +#define EVOE_BitNumber ((uint8_t)0x07) +#define EVCR_EVOE_BB (PERIPH_BB_BASE + (EVCR_OFFSET * 32) + (EVOE_BitNumber * 4)) + +/* --- RMP_CFG Register ---*/ +/* Alias word address of MII_RMII_SEL bit */ +#define MAPR_OFFSET (AFIO_OFFSET + 0x04) +#define MII_RMII_SEL_BitNumber ((u8)0x17) +#define MAPR_MII_RMII_SEL_BB (PERIPH_BB_BASE + (MAPR_OFFSET * 32) + (MII_RMII_SEL_BitNumber * 4)) + +#define EVCR_PORTPINCONFIG_MASK ((uint16_t)0xFF80) +#define LSB_MASK ((uint16_t)0xFFFF) +#define DBGAFR_POSITION_MASK ((uint32_t)0x000F0000) +#define DBGAFR_SWJCFG_MASK ((uint32_t)0xF0FFFFFF) +#define DBGAFR_LOCATION_MASK ((uint32_t)0x00200000) +#define DBGAFR_NUMBITS_MASK ((uint32_t)0x00100000) +#define DBGAFR_NUMBITS_MAPR3_MASK ((uint32_t)0x40000000) +#define DBGAFR_NUMBITS_MAPR4_MASK ((uint32_t)0x20000000) +#define DBGAFR_NUMBITS_MAPR5_MASK ((uint32_t)0x10000000) +#define DBGAFR_NUMBITS_SPI1_MASK ((uint32_t)0x01000000) +#define DBGAFR_NUMBITS_USART2_MASK ((uint32_t)0x04000000) + +/** + * @} + */ + +/** @addtogroup GPIO_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup GPIO_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup GPIO_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup GPIO_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the GPIOx peripheral registers to their default reset values. + * @param GPIOx where x can be (A..G) to select the GPIO peripheral. + */ +void GPIO_DeInit(GPIO_Module* GPIOx) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + + if (GPIOx == GPIOA) + { + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_GPIOA, ENABLE); + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_GPIOA, DISABLE); + } + else if (GPIOx == GPIOB) + { + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_GPIOB, ENABLE); + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_GPIOB, DISABLE); + } + else if (GPIOx == GPIOC) + { + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_GPIOC, ENABLE); + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_GPIOC, DISABLE); + } + else if (GPIOx == GPIOD) + { + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_GPIOD, ENABLE); + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_GPIOD, DISABLE); + } + else if (GPIOx == GPIOE) + { + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_GPIOE, ENABLE); + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_GPIOE, DISABLE); + } + else if (GPIOx == GPIOF) + { + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_GPIOF, ENABLE); + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_GPIOF, DISABLE); + } + else if (GPIOx == GPIOG) + { + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_GPIOG, ENABLE); + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_GPIOG, DISABLE); + } + else + { + } +} + +/** + * @brief Deinitializes the Alternate Functions (remap, event control + * and EXTI configuration) registers to their default reset values. + */ +void GPIO_AFIOInitDefault(void) +{ + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_AFIO, ENABLE); + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_AFIO, DISABLE); +} + +/** + * @brief Initializes the GPIOx peripheral according to the specified + * parameters in the GPIO_InitStruct. + * @param GPIOx where x can be (A..G) to select the GPIO peripheral. + * @param GPIO_InitStruct pointer to a GPIO_InitType structure that + * contains the configuration information for the specified GPIO peripheral. + */ +void GPIO_InitPeripheral(GPIO_Module* GPIOx, GPIO_InitType* GPIO_InitStruct) +{ + uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00; + uint32_t tmpregister = 0x00, pinmask = 0x00; + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode)); + assert_param(IS_GPIO_PIN(GPIO_InitStruct->Pin)); + + /*---------------------------- GPIO Mode Configuration -----------------------*/ + currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F); + if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00) + { + /* Check the parameters */ + assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed)); + /* Output mode */ + currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed; + } + /*---------------------------- GPIO PL_CFG Configuration ------------------------*/ + /* Configure the eight low port pins */ + if (((uint32_t)GPIO_InitStruct->Pin & ((uint32_t)0x00FF)) != 0x00) + { + tmpregister = GPIOx->PL_CFG; + for (pinpos = 0x00; pinpos < 0x08; pinpos++) + { + pos = ((uint32_t)0x01) << pinpos; + /* Get the port pins position */ + currentpin = (GPIO_InitStruct->Pin) & pos; + if (currentpin == pos) + { + pos = pinpos << 2; + /* Clear the corresponding low control register bits */ + pinmask = ((uint32_t)0x0F) << pos; + tmpregister &= ~pinmask; + /* Write the mode configuration in the corresponding bits */ + tmpregister |= (currentmode << pos); + /* Reset the corresponding POD bit */ + if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD) + { + GPIOx->PBC = (((uint32_t)0x01) << pinpos); + } + else + { + /* Set the corresponding POD bit */ + if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU) + { + GPIOx->PBSC = (((uint32_t)0x01) << pinpos); + } + } + } + } + GPIOx->PL_CFG = tmpregister; + } + /*---------------------------- GPIO PH_CFG Configuration ------------------------*/ + /* Configure the eight high port pins */ + if (GPIO_InitStruct->Pin > 0x00FF) + { + tmpregister = GPIOx->PH_CFG; + for (pinpos = 0x00; pinpos < 0x08; pinpos++) + { + pos = (((uint32_t)0x01) << (pinpos + 0x08)); + /* Get the port pins position */ + currentpin = ((GPIO_InitStruct->Pin) & pos); + if (currentpin == pos) + { + pos = pinpos << 2; + /* Clear the corresponding high control register bits */ + pinmask = ((uint32_t)0x0F) << pos; + tmpregister &= ~pinmask; + /* Write the mode configuration in the corresponding bits */ + tmpregister |= (currentmode << pos); + /* Reset the corresponding POD bit */ + if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD) + { + GPIOx->PBC = (((uint32_t)0x01) << (pinpos + 0x08)); + } + /* Set the corresponding POD bit */ + if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU) + { + GPIOx->PBSC = (((uint32_t)0x01) << (pinpos + 0x08)); + } + } + } + GPIOx->PH_CFG = tmpregister; + } +} + +/** + * @brief Fills each GPIO_InitStruct member with its default value. + * @param GPIO_InitStruct pointer to a GPIO_InitType structure which will + * be initialized. + */ +void GPIO_InitStruct(GPIO_InitType* GPIO_InitStruct) +{ + /* Reset GPIO init structure parameters values */ + GPIO_InitStruct->Pin = GPIO_PIN_ALL; + GPIO_InitStruct->GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStruct->GPIO_Mode = GPIO_Mode_IN_FLOATING; +} + +/** + * @brief Reads the specified input port pin. + * @param GPIOx where x can be (A..G) to select the GPIO peripheral. + * @param Pin specifies the port bit to read. + * This parameter can be GPIO_Pin_x where x can be (0..15). + * @return The input port pin value. + */ +uint8_t GPIO_ReadInputDataBit(GPIO_Module* GPIOx, uint16_t Pin) +{ + uint8_t bitstatus = 0x00; + + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GET_GPIO_PIN(Pin)); + + if ((GPIOx->PID & Pin) != (uint32_t)Bit_RESET) + { + bitstatus = (uint8_t)Bit_SET; + } + else + { + bitstatus = (uint8_t)Bit_RESET; + } + return bitstatus; +} + +/** + * @brief Reads the specified GPIO input data port. + * @param GPIOx where x can be (A..G) to select the GPIO peripheral. + * @return GPIO input data port value. + */ +uint16_t GPIO_ReadInputData(GPIO_Module* GPIOx) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + + return ((uint16_t)GPIOx->PID); +} + +/** + * @brief Reads the specified output data port bit. + * @param GPIOx where x can be (A..G) to select the GPIO peripheral. + * @param Pin specifies the port bit to read. + * This parameter can be GPIO_Pin_x where x can be (0..15). + * @return The output port pin value. + */ +uint8_t GPIO_ReadOutputDataBit(GPIO_Module* GPIOx, uint16_t Pin) +{ + uint8_t bitstatus = 0x00; + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GET_GPIO_PIN(Pin)); + + if ((GPIOx->POD & Pin) != (uint32_t)Bit_RESET) + { + bitstatus = (uint8_t)Bit_SET; + } + else + { + bitstatus = (uint8_t)Bit_RESET; + } + return bitstatus; +} + +/** + * @brief Reads the specified GPIO output data port. + * @param GPIOx where x can be (A..G) to select the GPIO peripheral. + * @return GPIO output data port value. + */ +uint16_t GPIO_ReadOutputData(GPIO_Module* GPIOx) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + + return ((uint16_t)GPIOx->POD); +} + +/** + * @brief Sets the selected data port bits. + * @param GPIOx where x can be (A..G) to select the GPIO peripheral. + * @param Pin specifies the port bits to be written. + * This parameter can be any combination of GPIO_Pin_x where x can be (0..15). + */ +void GPIO_SetBits(GPIO_Module* GPIOx, uint16_t Pin) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GPIO_PIN(Pin)); + + GPIOx->PBSC = Pin; +} +void GPIO_SetBitsHigh16(GPIO_Module* GPIOx, uint32_t Pin) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + // assert_param(IS_GPIO_PIN(Pin)); + + GPIOx->PBSC = Pin; +} + +/** + * @brief Clears the selected data port bits. + * @param GPIOx where x can be (A..G) to select the GPIO peripheral. + * @param Pin specifies the port bits to be written. + * This parameter can be any combination of GPIO_Pin_x where x can be (0..15). + */ +void GPIO_ResetBits(GPIO_Module* GPIOx, uint16_t Pin) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GPIO_PIN(Pin)); + + GPIOx->PBC = Pin; +} + +/** + * @brief Sets or clears the selected data port bit. + * @param GPIOx where x can be (A..G) to select the GPIO peripheral. + * @param Pin specifies the port bit to be written. + * This parameter can be one of GPIO_Pin_x where x can be (0..15). + * @param BitCmd specifies the value to be written to the selected bit. + * This parameter can be one of the Bit_OperateType enum values: + * @arg Bit_RESET to clear the port pin + * @arg Bit_SET to set the port pin + */ +void GPIO_WriteBit(GPIO_Module* GPIOx, uint16_t Pin, Bit_OperateType BitCmd) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GET_GPIO_PIN(Pin)); + assert_param(IS_GPIO_BIT_OPERATE(BitCmd)); + + if (BitCmd != Bit_RESET) + { + GPIOx->PBSC = Pin; + } + else + { + GPIOx->PBC = Pin; + } +} + +/** + * @brief Writes data to the specified GPIO data port. + * @param GPIOx where x can be (A..G) to select the GPIO peripheral. + * @param PortVal specifies the value to be written to the port output data register. + */ +void GPIO_Write(GPIO_Module* GPIOx, uint16_t PortVal) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + + GPIOx->POD = PortVal; +} + +/** + * @brief Locks GPIO Pins configuration registers. + * @param GPIOx where x can be (A..G) to select the GPIO peripheral. + * @param Pin specifies the port bit to be written. + * This parameter can be any combination of GPIO_Pin_x where x can be (0..15). + */ +void GPIO_ConfigPinLock(GPIO_Module* GPIOx, uint16_t Pin) +{ + uint32_t tmp = 0x00010000; + + /* Check the parameters */ + assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); + assert_param(IS_GPIO_PIN(Pin)); + + tmp |= Pin; + /* Set LCKK bit */ + GPIOx->PLOCK_CFG = tmp; + /* Reset LCKK bit */ + GPIOx->PLOCK_CFG = Pin; + /* Set LCKK bit */ + GPIOx->PLOCK_CFG = tmp; + /* Read LCKK bit*/ + tmp = GPIOx->PLOCK_CFG; + /* Read LCKK bit*/ + tmp = GPIOx->PLOCK_CFG; +} + +/** + * @brief Selects the GPIO pin used as Event output. + * @param PortSource selects the GPIO port to be used as source + * for Event output. + * This parameter can be GPIO_PortSourceGPIOx where x can be (A..E). + * @param PinSource specifies the pin for the Event output. + * This parameter can be GPIO_PinSourcex where x can be (0..15). + */ +void GPIO_ConfigEventOutput(uint8_t PortSource, uint8_t PinSource) +{ + uint32_t tmpregister = 0x00; + /* Check the parameters */ + assert_param(IS_GPIO_EVENTOUT_PORT_SOURCE(PortSource)); + assert_param(IS_GPIO_PIN_SOURCE(PinSource)); + + tmpregister = AFIO->ECTRL; + /* Clear the PORT[6:4] and PIN[3:0] bits */ + tmpregister &= EVCR_PORTPINCONFIG_MASK; + tmpregister |= (uint32_t)PortSource << 0x04; + tmpregister |= PinSource; + AFIO->ECTRL = tmpregister; +} + +/** + * @brief Enables or disables the Event Output. + * @param Cmd new state of the Event output. + * This parameter can be: ENABLE or DISABLE. + */ +void GPIO_CtrlEventOutput(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + *(__IO uint32_t*)EVCR_EVOE_BB = (uint32_t)Cmd; +} + +/** + * @brief Changes the mapping of the specified pin. + * @param RmpPin selects the pin to remap. + * This parameter can be one of the following values: + * @arg GPIO_RMP_SPI1 SPI1 Alternate Function mapping + * @arg GPIO_RMP_I2C1 I2C1 Alternate Function mapping + * @arg GPIO_RMP_USART1 USART1 Alternate Function mapping + * @arg GPIO_RMP_USART2 USART2 Alternate Function mapping + * @arg GPIO_PART_RMP_USART3 USART3 Partial Alternate Function mapping + * @arg GPIO_ALL_RMP_USART3 USART3 Full Alternate Function mapping + * @arg GPIO_PART1_RMP_TIM1 TIM1 Partial Alternate Function mapping + * @arg GPIO_PART2_RMP_TIM1 TIM1 Partial Alternate Function mapping + * @arg GPIO_ALL_RMP_TIM1 TIM1 Full Alternate Function mapping + * @arg GPIO_PartialRemap1_TIM2 TIM2 Partial1 Alternate Function mapping + * @arg GPIO_PART2_RMP_TIM2 TIM2 Partial2 Alternate Function mapping + * @arg GPIO_ALL_RMP_TIM2 TIM2 Full Alternate Function mapping + * @arg GPIO_PART1_RMP_TIM3 TIM3 Partial Alternate Function mapping + * @arg GPIO_ALL_RMP_TIM3 TIM3 Full Alternate Function mapping + * @arg GPIO_RMP_TIM4 TIM4 Alternate Function mapping + * @arg GPIO_RMP1_CAN1 CAN1 Alternate Function mapping + * @arg GPIO_RMP2_CAN1 CAN1 Alternate Function mapping + * @arg GPIO_RMP3_CAN1 CAN1 Alternate Function mapping + * @arg GPIO_RMP_PD01 PD01 Alternate Function mapping + * @arg GPIO_RMP_TIM5CH4 LSI connected to TIM5 Channel4 input capture for calibration + * @arg GPIO_RMP_ADC1_ETRI ADC1 External Trigger Injected Conversion remapping + * @arg GPIO_RMP_ADC1_ETRR ADC1 External Trigger Regular Conversion remapping + * @arg GPIO_RMP_ADC2_ETRI ADC2 External Trigger Injected Conversion remapping + * @arg GPIO_RMP_ADC2_ETRR ADC2 External Trigger Regular Conversion remapping + * @arg GPIO_RMP_SW_JTAG_NO_NJTRST Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST + * @arg GPIO_RMP_SW_JTAG_SW_ENABLE JTAG-DP Disabled and SW-DP Enabled + * @arg GPIO_RMP_SW_JTAG_DISABLE Full SWJ Disabled (JTAG-DP + SW-DP) + * @arg GPIO_RMP_SDIO SDIO Alternate Function mapping + * @arg GPIO_RMP1_CAN2 CAN2 Alternate Function mapping + * @arg GPIO_RMP3_CAN2 CAN2 Alternate Function mapping + * @arg GPIO_RMP1_QSPI QSPI Alternate Function mapping + * @arg GPIO_RMP3_QSPI QSPI Alternate Function mapping + * @arg GPIO_RMP1_I2C2 I2C2 Alternate Function mapping + * @arg GPIO_RMP3_I2C2 I2C2 Alternate Function mapping + * @arg GPIO_RMP2_I2C3 I2C3 Alternate Function mapping + * @arg GPIO_RMP3_I2C3 I2C3 Alternate Function mapping + * @arg GPIO_RMP1_I2C4 I2C4 Alternate Function mapping + * @arg GPIO_RMP3_I2C4 I2C4 Alternate Function mapping + * @arg GPIO_RMP1_SPI2 SPI2 Alternate Function mapping + * @arg GPIO_RMP2_SPI2 SPI2 Alternate Function mapping + * @arg GPIO_RMP1_SPI3 SPI3 Alternate Function mapping + * @arg GPIO_RMP2_SPI3 SPI3 Alternate Function mapping + * @arg GPIO_RMP1_ETH ETH Alternate Function mapping + * @arg GPIO_RMP2_ETH ETH Alternate Function mapping + * @arg GPIO_RMP3_ETH ETH Alternate Function mapping + * @arg GPIO_RMP1_SPI1 SPI1 Alternate Function mapping + * @arg GPIO_RMP2_SPI1 SPI1 Alternate Function mapping + * @arg GPIO_RMP3_SPI1 SPI1 Alternate Function mapping + * @arg GPIO_RMP1_USART2 USART2 Alternate Function mapping + * @arg GPIO_RMP2_USART2 USART2 Alternate Function mapping + * @arg GPIO_RMP3_USART2 USART2 Alternate Function mapping + * @arg GPIO_RMP1_UART4 UART4 Alternate Function mapping + * @arg GPIO_RMP2_UART4 UART4 Alternate Function mapping + * @arg GPIO_RMP3_UART4 UART4 Alternate Function mapping + * @arg GPIO_RMP1_UART5 UART5 Alternate Function mapping + * @arg GPIO_RMP2_UART5 UART5 Alternate Function mapping + * @arg GPIO_RMP3_UART5 UART5 Alternate Function mapping + * @arg GPIO_RMP2_UART6 UART6 Alternate Function mapping + * @arg GPIO_RMP3_UART6 UART6 Alternate Function mapping + * @arg GPIO_RMP1_UART7 UART7 Alternate Function mapping + * @arg GPIO_RMP3_UART7 UART7 Alternate Function mapping + * @arg GPIO_RMP1_TIM8 TIM8 Alternate Function mapping + * @arg GPIO_RMP3_TIM8 TIM8 Alternate Function mapping + * @arg GPIO_RMP1_COMP1 COMP1 Alternate Function mapping + * @arg GPIO_RMP2_COMP1 COMP1 Alternate Function mapping + * @arg GPIO_RMP3_COMP1 COMP1 Alternate Function mapping + * @arg GPIO_RMP1_COMP2 COMP2 Alternate Function mapping + * @arg GPIO_RMP2_COMP2 COMP2 Alternate Function mapping + * @arg GPIO_RMP3_COMP2 COMP2 Alternate Function mapping + * @arg GPIO_RMP1_COMP3 COMP3 Alternate Function mapping + * @arg GPIO_RMP3_COMP3 COMP3 Alternate Function mapping + * @arg GPIO_RMP1_COMP4 COMP4 Alternate Function mapping + * @arg GPIO_RMP3_COMP4 COMP4 Alternate Function mapping + * @arg GPIO_RMP1_COMP5 COMP5 Alternate Function mapping + * @arg GPIO_RMP2_COMP5 COMP5 Alternate Function mapping + * @arg GPIO_RMP3_COMP5 COMP5 Alternate Function mapping + * @arg GPIO_RMP3_UART5 UART5 Alternate Function mapping + * @arg GPIO_RMP1_COMP6 COMP6 Alternate Function mapping + * @arg GPIO_RMP3_COMP6 COMP6 Alternate Function mapping + * @arg GPIO_RMP_COMP7 COMP7 Alternate Function mapping + * @arg GPIO_RMP_ADC3_ETRI ADC3_ETRGINJ Alternate Function mapping + * @arg GPIO_RMP_ADC3_ETRR ADC3_ETRGREG Alternate Function mapping + * @arg GPIO_RMP_ADC4_ETRI ADC4_ETRGINJ Alternate Function mapping + * @arg GPIO_RMP_ADC4_ETRR ADC4_ETRGREG Alternate Function mapping + * @arg GPIO_RMP_TSC_OUT_CTRL TSC_OUT_CTRL Alternate Function mapping + * @arg GPIO_RMP_QSPI_XIP_EN QSPI_XIP_EN Alternate Function mapping + * @arg GPIO_RMP1_DVP DVP Alternate Function mapping + * @arg GPIO_RMP3_DVP DVP Alternate Function mapping + * @arg GPIO_Remap_SPI1_NSS SPI1 NSS Alternate Function mapping + * @arg GPIO_Remap_SPI2_NSS SPI2 NSS Alternate Function mapping + * @arg GPIO_Remap_SPI3_NSS SPI3 NSS Alternate Function mapping + * @arg GPIO_Remap_QSPI_MISO QSPI MISO Alternate Function mapping + * @arg GPIO_Remap_DET_EN_EGB4 EGB4 Detect Alternate Function mapping + * @arg GPIO_Remap_DET_EN_EGB3 EGB3 Detect Alternate Function mapping + * @arg GPIO_Remap_DET_EN_EGB2 EGB2 Detect Alternate Function mapping + * @arg GPIO_Remap_DET_EN_EGB1 EGB1 Detect Alternate Function mapping + * @arg GPIO_Remap_DET_EN_EGBN4 EGBN4 Detect Alternate Function mapping + * @arg GPIO_Remap_DET_EN_EGBN3 EGBN3 Detect Alternate Function mapping + * @arg GPIO_Remap_DET_EN_EGBN2 EGBN2 Detect Alternate Function mapping + * @arg GPIO_Remap_DET_EN_EGBN1 EGBN1 Detect Alternate Function mapping + * @arg GPIO_Remap_DET_EN_ECLAMP4 ECLAMP4 Detect Alternate Function mapping + * @arg GPIO_Remap_DET_EN_ECLAMP3 ECLAMP3 Detect Alternate Function mapping + * @arg GPIO_Remap_DET_EN_ECLAMP2 ECLAMP2 Detect Alternate Function mapping + * @arg GPIO_Remap_DET_EN_ECLAMP1 ECLAMP1 Detect Alternate Function mapping + * @arg GPIO_Remap_RST_EN_EGB4 EGB4 Reset Alternate Function mapping + * @arg GPIO_Remap_RST_EN_EGB3 EGB3 Reset Alternate Function mapping + * @arg GPIO_Remap_RST_EN_EGB2 EGB2 Reset Alternate Function mapping + * @arg GPIO_Remap_RST_EN_EGB1 EGB1 Reset Alternate Function mapping + * @arg GPIO_Remap_RST_EN_EGBN4 EGBN4 Reset Alternate Function mapping + * @arg GPIO_Remap_RST_EN_EGBN3 EGBN3 Reset Alternate Function mapping + * @arg GPIO_Remap_RST_EN_EGBN2 EGBN2 Reset Alternate Function mapping + * @arg GPIO_Remap_RST_EN_EGBN1 EGBN1 Reset Alternate Function mapping + * @arg GPIO_Remap_RST_EN_ECLAMP4 ECLAMP4 Reset Alternate Function mapping + * @arg GPIO_Remap_RST_EN_ECLAMP3 ECLAMP3 Reset Alternate Function mapping + * @arg GPIO_Remap_RST_EN_ECLAMP2 ECLAMP2 Reset Alternate Function mapping + * @arg GPIO_Remap_RST_EN_ECLAMP1 ECLAMP1 Reset Alternate Function mapping + * @param Cmd new state of the port pin remapping. + * This parameter can be: ENABLE or DISABLE. + */ +void GPIO_ConfigPinRemap(uint32_t RmpPin, FunctionalState Cmd) +{ + uint32_t tmp = 0x00, tmp1 = 0x00, tmpregister = 0x00, tmpmask = 0x00, tmp2 = 0x00; + + /* Check the parameters */ + assert_param(IS_GPIO_REMAP(RmpPin)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + /* Check RmpPin relate AFIO RMP_CFG */ + if ((RmpPin & 0x40000000) == 0x40000000) + { + tmpregister = AFIO->RMP_CFG3; + } + else if ((RmpPin & 0x20000000) == 0x20000000) + { + tmpregister = AFIO->RMP_CFG4; + } + else if ((RmpPin & 0x10000000) == 0x10000000) + { + tmpregister = AFIO->RMP_CFG5; + } + else + { + tmpregister = AFIO->RMP_CFG; + } + + tmpmask = (RmpPin & DBGAFR_POSITION_MASK) >> 16; + tmp = RmpPin & LSB_MASK; + + if ((RmpPin + & (DBGAFR_NUMBITS_MAPR5_MASK | DBGAFR_NUMBITS_MAPR4_MASK | DBGAFR_NUMBITS_MAPR3_MASK | DBGAFR_LOCATION_MASK + | DBGAFR_NUMBITS_MASK)) + == (DBGAFR_LOCATION_MASK | DBGAFR_NUMBITS_MASK)) + { + tmpregister &= DBGAFR_SWJCFG_MASK; + AFIO->RMP_CFG &= DBGAFR_SWJCFG_MASK; + } + else if ((RmpPin & DBGAFR_NUMBITS_MASK) == DBGAFR_NUMBITS_MASK) + { + if ((RmpPin & DBGAFR_LOCATION_MASK) == DBGAFR_LOCATION_MASK) + { + tmp1 = (((uint32_t)0x03) << tmpmask) << 16; + } + else + { + tmp1 = ((uint32_t)0x03) << tmpmask; + } + tmpregister &= ~tmp1; + if ((RmpPin & 0x70000000) == 0x00000000) + { + tmpregister |= ~DBGAFR_SWJCFG_MASK; + } + } + else + {/*configuration AFIO RMP_CFG*/ + if ((RmpPin & DBGAFR_NUMBITS_SPI1_MASK) == DBGAFR_NUMBITS_SPI1_MASK) + { + if ((RmpPin & 0x00000004) == 0x00000004) + { + if ((RmpPin & 0x02000000) == 0x02000000) // GPIO_RMP3_SPI1 + { + tmpregister &= ~(tmp << (((RmpPin & 0x00200000) >> 21) * 16)); + if (Cmd != DISABLE) + { + tmp2 = AFIO->RMP_CFG; + tmp2 |= 0x00000001; + tmp2 |= ~DBGAFR_SWJCFG_MASK; + AFIO->RMP_CFG = tmp2; // Remap_SPI1 ENABLE + } + else + { + tmp2 = AFIO->RMP_CFG; + tmp2 &= 0xFFFFFFFE; + tmp2 |= ~DBGAFR_SWJCFG_MASK; + AFIO->RMP_CFG = tmp2; // Remap_SPI1 DISABLE + } + } + else + { + tmpregister &= ~(tmp << (((RmpPin & 0x00200000) >> 21) * 16)); // GPIO_RMP2_SPI1 + + tmp2 = AFIO->RMP_CFG; + tmp2 &= 0xFFFFFFFE; + tmp2 |= ~DBGAFR_SWJCFG_MASK; + AFIO->RMP_CFG = tmp2; // Remap_SPI1 DISABLE + } + } + else + { + tmpregister &= ~((tmp | 0x00000004) << (((RmpPin & 0x00200000) >> 21) * 16)); // clear + if (Cmd != DISABLE) // GPIO_RMP1_SPI1 + { + tmp2 = AFIO->RMP_CFG; + tmp2 |= 0x00000001; + tmp2 |= ~DBGAFR_SWJCFG_MASK; + AFIO->RMP_CFG = tmp2; // Remap_SPI1 ENABLE + } + else + { + tmp2 = AFIO->RMP_CFG; + tmp2 &= 0xFFFFFFFE; + tmp2 |= ~DBGAFR_SWJCFG_MASK; + AFIO->RMP_CFG = tmp2; // Remap_SPI1 DISABLE + } + } + } + else if ((RmpPin & DBGAFR_NUMBITS_USART2_MASK) == DBGAFR_NUMBITS_USART2_MASK) + { + if ((RmpPin & 0x00000008) == 0x00000008) + { + if ((RmpPin & 0x02000000) == 0x02000000) // GPIO_RMP3_USART2 + { + tmpregister &= ~(tmp << (((RmpPin & 0x00200000) >> 21) * 16)); + if (Cmd != DISABLE) + { + tmp2 = AFIO->RMP_CFG; + tmp2 |= 0x00000008; + tmp2 |= ~DBGAFR_SWJCFG_MASK; + AFIO->RMP_CFG = tmp2; // Remap_USART2 ENABLE + } + else + { + tmp2 = AFIO->RMP_CFG; + tmp2 &= 0xFFFFFFF7; + tmp2 |= ~DBGAFR_SWJCFG_MASK; + AFIO->RMP_CFG = tmp2; // Remap_USART2 DISABLE + } + } + else + { + tmpregister &= ~(tmp << (((RmpPin & 0x00200000) >> 21) * 16)); // GPIO_RMP2_USART2 + + tmp2 = AFIO->RMP_CFG; + tmp2 &= 0xFFFFFFF7; + tmp2 |= ~DBGAFR_SWJCFG_MASK; + AFIO->RMP_CFG = tmp2; // Remap_USART2 DISABLE + } + } + else // GPIO_RMP1_USART2 + { + tmpregister &= ~((tmp | 0x00000008) << (((RmpPin & 0x00200000) >> 21) * 16)); // clear + if (Cmd != DISABLE) + { + tmp2 = AFIO->RMP_CFG; + tmp2 |= 0x00000008; + tmp2 |= ~DBGAFR_SWJCFG_MASK; + AFIO->RMP_CFG = tmp2; // Remap_USART2 ENABLE + } + else + { + tmp2 = AFIO->RMP_CFG; + tmp2 &= 0xFFFFFFF7; + tmp2 |= ~DBGAFR_SWJCFG_MASK; + AFIO->RMP_CFG = tmp2; // Remap_USART2 DISABLE + } + } + } + else + { + tmpregister &= ~(tmp << (((RmpPin & 0x00200000) >> 21) * 16)); + if ((RmpPin & 0x70000000) == 0x00000000) + { + tmpregister |= ~DBGAFR_SWJCFG_MASK; + } + } + } + + /*configuration AFIO RMP_CFG~RMP_CFG5*/ + if (Cmd != DISABLE) + { + tmpregister |= (tmp << (((RmpPin & 0x00200000) >> 21) * 16)); + } + + if ((RmpPin & 0x40000000) == 0x40000000) + { + AFIO->RMP_CFG3 = tmpregister; + } + else if ((RmpPin & 0x20000000) == 0x20000000) + { + AFIO->RMP_CFG4 = tmpregister; + } + else if ((RmpPin & 0x10000000) == 0x10000000) + { + AFIO->RMP_CFG5 = tmpregister; + } + else + { + AFIO->RMP_CFG = tmpregister; + } +} + +/** + * @brief Selects the GPIO pin used as EXTI Line. + * @param PortSource selects the GPIO port to be used as source for EXTI lines. + * This parameter can be GPIO_PortSourceGPIOx where x can be (A..G). + * @param PinSource specifies the EXTI line to be configured. + * This parameter can be GPIO_PinSourcex where x can be (0..15). + */ +void GPIO_ConfigEXTILine(uint8_t PortSource, uint8_t PinSource) +{ + uint32_t tmp = 0x00; + /* Check the parameters */ + assert_param(IS_GPIO_EXTI_PORT_SOURCE(PortSource)); + assert_param(IS_GPIO_PIN_SOURCE(PinSource)); + + tmp = ((uint32_t)0x0F) << (0x04 * (PinSource & (uint8_t)0x03)); + AFIO->EXTI_CFG[PinSource >> 0x02] &= ~tmp; + AFIO->EXTI_CFG[PinSource >> 0x02] |= (((uint32_t)PortSource) << (0x04 * (PinSource & (uint8_t)0x03))); +} + +/** + * @brief Selects the Ethernet media interface. + * @note This function applies only to N32G45x Connectivity line devices. + * @param ETH_ConfigSel specifies the Media Interface mode. + * This parameter can be one of the following values: + * @arg GPIO_ETH_MII_CFG MII mode + * @arg GPIO_ETH_RMII_CFG RMII mode + */ +void GPIO_ETH_ConfigMediaInterface(uint32_t ETH_ConfigSel) +{ + /* Check the parameters */ + assert_param(IS_GPIO_ETH_MEDIA_INTERFACE(ETH_ConfigSel)); + + if (ETH_ConfigSel == GPIO_ETH_RMII_CFG) + { + *(__IO uint32_t*)MAPR_MII_RMII_SEL_BB = (uint32_t)1; + } + else + { + *(__IO uint32_t*)MAPR_MII_RMII_SEL_BB = (uint32_t)0; + } + +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/src/n32g45x_i2c.c b/src/n32g45x_i2c.c new file mode 100644 index 0000000..7212eb2 --- /dev/null +++ b/src/n32g45x_i2c.c @@ -0,0 +1,1306 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_i2c.c + * @author Nations + * @version v1.0.2 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_i2c.h" +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup I2C + * @brief I2C driver modules + * @{ + */ + +/** @addtogroup I2C_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup I2C_Private_Defines + * @{ + */ + +/* I2C SPE mask */ +#define CTRL1_SPEN_SET ((uint16_t)0x0001) +#define CTRL1_SPEN_RESET ((uint16_t)0xFFFE) + +/* I2C START mask */ +#define CTRL1_START_SET ((uint16_t)0x0100) +#define CTRL1_START_RESET ((uint16_t)0xFEFF) + +/* I2C STOP mask */ +#define CTRL1_STOP_SET ((uint16_t)0x0200) +#define CTRL1_STOP_RESET ((uint16_t)0xFDFF) + +/* I2C ACK mask */ +#define CTRL1_ACK_SET ((uint16_t)0x0400) +#define CTRL1_ACK_RESET ((uint16_t)0xFBFF) + +/* I2C ENGC mask */ +#define CTRL1_GCEN_SET ((uint16_t)0x0040) +#define CTRL1_GCEN_RESET ((uint16_t)0xFFBF) + +/* I2C SWRST mask */ +#define CTRL1_SWRESET_SET ((uint16_t)0x8000) +#define CTRL1_SWRESET_RESET ((uint16_t)0x7FFF) + +/* I2C PEC mask */ +#define CTRL1_PEC_SET ((uint16_t)0x1000) +#define CTRL1_PEC_RESET ((uint16_t)0xEFFF) + +/* I2C ENPEC mask */ +#define CTRL1_PECEN_SET ((uint16_t)0x0020) +#define CTRL1_PECEN_RESET ((uint16_t)0xFFDF) + +/* I2C ENARP mask */ +#define CTRL1_ARPEN_SET ((uint16_t)0x0010) +#define CTRL1_ARPEN_RESET ((uint16_t)0xFFEF) + +/* I2C NOSTRETCH mask */ +#define CTRL1_NOEXTEND_SET ((uint16_t)0x0080) +#define CTRL1_NOEXTEND_RESET ((uint16_t)0xFF7F) + +/* I2C registers Masks */ +#define CTRL1_CLR_MASK ((uint16_t)0xFBF5) + +/* I2C DMAEN mask */ +#define CTRL2_DMAEN_SET ((uint16_t)0x0800) +#define CTRL2_DMAEN_RESET ((uint16_t)0xF7FF) + +/* I2C LAST mask */ +#define CTRL2_DMALAST_SET ((uint16_t)0x1000) +#define CTRL2_DMALAST_RESET ((uint16_t)0xEFFF) + +/* I2C FREQ mask */ +#define CTRL2_CLKFREQ_RESET ((uint16_t)0xFFC0) + +/* I2C ADD0 mask */ +#define OADDR1_ADDR0_SET ((uint16_t)0x0001) +#define OADDR1_ADDR0_RESET ((uint16_t)0xFFFE) + +/* I2C ENDUAL mask */ +#define OADDR2_DUALEN_SET ((uint16_t)0x0001) +#define OADDR2_DUALEN_RESET ((uint16_t)0xFFFE) + +/* I2C ADD2 mask */ +#define OADDR2_ADDR2_RESET ((uint16_t)0xFF01) + +/* I2C F/S mask */ +#define CLKCTRL_FSMODE_SET ((uint16_t)0x8000) + +/* I2C CHCFG mask */ +#define CLKCTRL_CLKCTRL_SET ((uint16_t)0x0FFF) + +/* I2C FLAG mask */ +#define FLAG_MASK ((uint32_t)0x00FFFFFF) + +/* I2C Interrupt Enable mask */ +#define INTEN_MASK ((uint32_t)0x07000000) + +/** + * @} + */ + +/** @addtogroup I2C_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup I2C_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup I2C_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup I2C_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the I2Cx peripheral registers to their default reset values. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + */ +void I2C_DeInit(I2C_Module* I2Cx) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + + if (I2Cx == I2C1) + { + /* Enable I2C1 reset state */ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_I2C1, ENABLE); + /* Release I2C1 from reset state */ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_I2C1, DISABLE); + } + else + { + /* Enable I2C2 reset state */ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_I2C2, ENABLE); + /* Release I2C2 from reset state */ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_I2C2, DISABLE); + } +} + +/** + * @brief Initializes the I2Cx peripheral according to the specified + * parameters in the I2C_InitStruct. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_InitStruct pointer to a I2C_InitType structure that + * contains the configuration information for the specified I2C peripheral. + */ +void I2C_Init(I2C_Module* I2Cx, I2C_InitType* I2C_InitStruct) +{ + uint16_t tmpregister = 0, freqrange = 0; + uint16_t result = 0x04; + uint32_t pclk = 8000000; + RCC_ClocksType rcc_clocks; + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_I2C_CLK_SPEED(I2C_InitStruct->ClkSpeed)); + assert_param(IS_I2C_BUS_MODE(I2C_InitStruct->BusMode)); + assert_param(IS_I2C_FM_DUTY_CYCLE(I2C_InitStruct->FmDutyCycle)); + assert_param(IS_I2C_OWN_ADDR1(I2C_InitStruct->OwnAddr1)); + assert_param(IS_I2C_ACK_STATE(I2C_InitStruct->AckEnable)); + assert_param(IS_I2C_ADDR_MODE(I2C_InitStruct->AddrMode)); + + /*---------------------------- I2Cx CTRL2 Configuration ------------------------*/ + /* Get the I2Cx CTRL2 value */ + tmpregister = I2Cx->CTRL2; + /* Clear frequency FREQ[5:0] bits */ + tmpregister &= CTRL2_CLKFREQ_RESET; + /* Get APB1/2 frequency value */ + RCC_GetClocksFreqValue(&rcc_clocks); + + if ((I2Cx == I2C1) || (I2Cx == I2C2)) + { + pclk = rcc_clocks.Pclk1Freq; + } + else if ((I2Cx == I2C3) || (I2Cx == I2C4)) + { + pclk = rcc_clocks.Pclk2Freq; + } + + /* Set frequency bits depending on pclk1 value */ + freqrange = (uint16_t)(pclk / 1000000); + tmpregister |= freqrange; + /* Write to I2Cx CTRL2 */ + if (tmpregister > 36) + { + tmpregister = 36; + } + I2Cx->CTRL2 = tmpregister; + + /*---------------------------- I2Cx CHCFG Configuration ------------------------*/ + /* Disable the selected I2C peripheral to configure TMRISE */ + I2Cx->CTRL1 &= CTRL1_SPEN_RESET; + /* Reset tmpregister value */ + /* Clear F/S, DUTY and CHCFG[11:0] bits */ + tmpregister = 0; + + /* Configure speed in standard mode */ + if (I2C_InitStruct->ClkSpeed <= 100000) + { + /* Standard mode speed calculate */ + result = (uint16_t)(pclk / (I2C_InitStruct->ClkSpeed << 1)); + /* Test if CHCFG value is under 0x4*/ + if (result < 0x04) + { + /* Set minimum allowed value */ + result = 0x04; + } + /* Set speed value for standard mode */ + tmpregister |= result; + /* Set Maximum Rise Time for standard mode */ + I2Cx->TMRISE = freqrange + 1; + } + /* Configure speed in fast mode */ + else + { + if (I2C_InitStruct->FmDutyCycle == I2C_FMDUTYCYCLE_2) + { + /* Fast mode speed calculate: Tlow/Thigh = 2 */ + result = (uint16_t)(pclk / (I2C_InitStruct->ClkSpeed * 3)); + } + else /*I2C_InitStruct->FmDutyCycle == I2C_FMDUTYCYCLE_16_9*/ + { + /* Fast mode speed calculate: Tlow/Thigh = 16/9 */ + result = (uint16_t)(pclk / (I2C_InitStruct->ClkSpeed * 25)); + /* Set DUTY bit */ + result |= I2C_FMDUTYCYCLE_16_9; + } + + /* Test if CHCFG value is under 0x1*/ + if ((result & CLKCTRL_CLKCTRL_SET) == 0) + { + /* Set minimum allowed value */ + result |= (uint16_t)0x0001; + } + /* Set speed value and set F/S bit for fast mode */ + tmpregister |= (uint16_t)(result | CLKCTRL_FSMODE_SET); + + /* Set Maximum Rise Time for fast mode */ + I2Cx->TMRISE = (uint16_t)(((freqrange * (uint16_t)300) / (uint16_t)1000) + (uint16_t)1); + } + /* Write to I2Cx CHCFG */ + I2Cx->CLKCTRL = tmpregister; + /* Enable the selected I2C peripheral */ + I2Cx->CTRL1 |= CTRL1_SPEN_SET; + + /*---------------------------- I2Cx CTRL1 Configuration ------------------------*/ + /* Get the I2Cx CTRL1 value */ + tmpregister = I2Cx->CTRL1; + /* Clear ACK, SMBTYPE and SMBUS bits */ + tmpregister &= CTRL1_CLR_MASK; + /* Configure I2Cx: mode and acknowledgement */ + /* Set SMBTYPE and SMBUS bits according to BusMode value */ + /* Set ACK bit according to AckEnable value */ + tmpregister |= (uint16_t)((uint32_t)I2C_InitStruct->BusMode | I2C_InitStruct->AckEnable); + /* Write to I2Cx CTRL1 */ + I2Cx->CTRL1 = tmpregister; + + /*---------------------------- I2Cx OADDR1 Configuration -----------------------*/ + /* Set I2Cx Own Address1 and acknowledged address */ + I2Cx->OADDR1 = (I2C_InitStruct->AddrMode | I2C_InitStruct->OwnAddr1); +} + +/** + * @brief Fills each I2C_InitStruct member with its default value. + * @param I2C_InitStruct pointer to an I2C_InitType structure which will be initialized. + */ +void I2C_InitStruct(I2C_InitType* I2C_InitStruct) +{ + /*---------------- Reset I2C init structure parameters values ----------------*/ + /* initialize the ClkSpeed member */ + I2C_InitStruct->ClkSpeed = 5000; + /* Initialize the BusMode member */ + I2C_InitStruct->BusMode = I2C_BUSMODE_I2C; + /* Initialize the FmDutyCycle member */ + I2C_InitStruct->FmDutyCycle = I2C_FMDUTYCYCLE_2; + /* Initialize the OwnAddr1 member */ + I2C_InitStruct->OwnAddr1 = 0; + /* Initialize the AckEnable member */ + I2C_InitStruct->AckEnable = I2C_ACKDIS; + /* Initialize the AddrMode member */ + I2C_InitStruct->AddrMode = I2C_ADDR_MODE_7BIT; +} + +/** + * @brief Enables or disables the specified I2C peripheral. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Cmd new state of the I2Cx peripheral. + * This parameter can be: ENABLE or DISABLE. + */ +void I2C_Enable(I2C_Module* I2Cx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected I2C peripheral */ + I2Cx->CTRL1 |= CTRL1_SPEN_SET; + } + else + { + /* Disable the selected I2C peripheral */ + I2Cx->CTRL1 &= CTRL1_SPEN_RESET; + } +} + +/** + * @brief Enables or disables the specified I2C DMA requests. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Cmd new state of the I2C DMA transfer. + * This parameter can be: ENABLE or DISABLE. + */ +void I2C_EnableDMA(I2C_Module* I2Cx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected I2C DMA requests */ + I2Cx->CTRL2 |= CTRL2_DMAEN_SET; + } + else + { + /* Disable the selected I2C DMA requests */ + I2Cx->CTRL2 &= CTRL2_DMAEN_RESET; + } +} + +/** + * @brief Specifies if the next DMA transfer will be the last one. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Cmd new state of the I2C DMA last transfer. + * This parameter can be: ENABLE or DISABLE. + */ +void I2C_EnableDmaLastSend(I2C_Module* I2Cx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Next DMA transfer is the last transfer */ + I2Cx->CTRL2 |= CTRL2_DMALAST_SET; + } + else + { + /* Next DMA transfer is not the last transfer */ + I2Cx->CTRL2 &= CTRL2_DMALAST_RESET; + } +} + +/** + * @brief Generates I2Cx communication START condition. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Cmd new state of the I2C START condition generation. + * This parameter can be: ENABLE or DISABLE. + */ +void I2C_GenerateStart(I2C_Module* I2Cx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Generate a START condition */ + I2Cx->CTRL1 |= CTRL1_START_SET; + } + else + { + /* Disable the START condition generation */ + I2Cx->CTRL1 &= CTRL1_START_RESET; + } +} + +/** + * @brief Generates I2Cx communication STOP condition. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Cmd new state of the I2C STOP condition generation. + * This parameter can be: ENABLE or DISABLE. + */ +void I2C_GenerateStop(I2C_Module* I2Cx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Generate a STOP condition */ + I2Cx->CTRL1 |= CTRL1_STOP_SET; + } + else + { + /* Disable the STOP condition generation */ + I2Cx->CTRL1 &= CTRL1_STOP_RESET; + } +} + +/** + * @brief Enables or disables the specified I2C acknowledge feature. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Cmd new state of the I2C Acknowledgement. + * This parameter can be: ENABLE or DISABLE. + */ +void I2C_ConfigAck(I2C_Module* I2Cx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the acknowledgement */ + I2Cx->CTRL1 |= CTRL1_ACK_SET; + } + else + { + /* Disable the acknowledgement */ + I2Cx->CTRL1 &= CTRL1_ACK_RESET; + } +} + +/** + * @brief Configures the specified I2C own address2. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Address specifies the 7bit I2C own address2. + */ +void I2C_ConfigOwnAddr2(I2C_Module* I2Cx, uint8_t Address) +{ + uint16_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + + /* Get the old register value */ + tmpregister = I2Cx->OADDR2; + + /* Reset I2Cx Own address2 bit [7:1] */ + tmpregister &= OADDR2_ADDR2_RESET; + + /* Set I2Cx Own address2 */ + tmpregister |= (uint16_t)((uint16_t)Address & (uint16_t)0x00FE); + + /* Store the new register value */ + I2Cx->OADDR2 = tmpregister; +} + +/** + * @brief Enables or disables the specified I2C dual addressing mode. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Cmd new state of the I2C dual addressing mode. + * This parameter can be: ENABLE or DISABLE. + */ +void I2C_EnableDualAddr(I2C_Module* I2Cx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable dual addressing mode */ + I2Cx->OADDR2 |= OADDR2_DUALEN_SET; + } + else + { + /* Disable dual addressing mode */ + I2Cx->OADDR2 &= OADDR2_DUALEN_RESET; + } +} + +/** + * @brief Enables or disables the specified I2C general call feature. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Cmd new state of the I2C General call. + * This parameter can be: ENABLE or DISABLE. + */ +void I2C_EnableGeneralCall(I2C_Module* I2Cx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable generall call */ + I2Cx->CTRL1 |= CTRL1_GCEN_SET; + } + else + { + /* Disable generall call */ + I2Cx->CTRL1 &= CTRL1_GCEN_RESET; + } +} + +/** + * @brief Enables or disables the specified I2C interrupts. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_IT specifies the I2C interrupts sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg I2C_INT_BUF Buffer interrupt mask + * @arg I2C_INT_EVENT Event interrupt mask + * @arg I2C_INT_ERR Error interrupt mask + * @param Cmd new state of the specified I2C interrupts. + * This parameter can be: ENABLE or DISABLE. + */ +void I2C_ConfigInt(I2C_Module* I2Cx, uint16_t I2C_IT, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + assert_param(IS_I2C_CFG_INT(I2C_IT)); + + if (Cmd != DISABLE) + { + /* Enable the selected I2C interrupts */ + I2Cx->CTRL2 |= I2C_IT; + } + else + { + /* Disable the selected I2C interrupts */ + I2Cx->CTRL2 &= (uint16_t)~I2C_IT; + } +} + +/** + * @brief Sends a data byte through the I2Cx peripheral. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Data Byte to be transmitted.. + */ +void I2C_SendData(I2C_Module* I2Cx, uint8_t Data) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + /* Write in the DAT register the data to be sent */ + I2Cx->DAT = Data; +} + +/** + * @brief Returns the most recent received data by the I2Cx peripheral. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @return The value of the received data. + */ +uint8_t I2C_RecvData(I2C_Module* I2Cx) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + /* Return the data in the DAT register */ + return (uint8_t)I2Cx->DAT; +} + +/** + * @brief Transmits the address byte to select the slave device. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Address specifies the slave address which will be transmitted + * @param I2C_Direction specifies whether the I2C device will be a + * Transmitter or a Receiver. This parameter can be one of the following values + * @arg I2C_DIRECTION_SEND Transmitter mode + * @arg I2C_DIRECTION_RECV Receiver mode + */ +void I2C_SendAddr7bit(I2C_Module* I2Cx, uint8_t Address, uint8_t I2C_Direction) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_I2C_DIRECTION(I2C_Direction)); + /* Test on the direction to set/reset the read/write bit */ + if (I2C_Direction != I2C_DIRECTION_SEND) + { + /* Set the address bit0 for read */ + Address |= OADDR1_ADDR0_SET; + } + else + { + /* Reset the address bit0 for write */ + Address &= OADDR1_ADDR0_RESET; + } + /* Send the address */ + I2Cx->DAT = Address; +} + +/** + * @brief Reads the specified I2C register and returns its value. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_Register specifies the register to read. + * This parameter can be one of the following values: + * @arg I2C_REG_CTRL1 CTRL1 register. + * @arg I2C_REG_CTRL2 CTRL2 register. + * @arg I2C_REG_OADDR1 OADDR1 register. + * @arg I2C_REG_OADDR2 OADDR2 register. + * @arg I2C_REG_DAT DAT register. + * @arg I2C_REG_STS1 STS1 register. + * @arg I2C_REG_STS2 STS2 register. + * @arg I2C_REG_CLKCTRL CHCFG register. + * @arg I2C_REG_TMRISE TMRISE register. + * @return The value of the read register. + */ +uint16_t I2C_GetRegister(I2C_Module* I2Cx, uint8_t I2C_Register) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_I2C_REG(I2C_Register)); + + tmp = (uint32_t)I2Cx; + tmp += I2C_Register; + + /* Return the selected register value */ + return (*(__IO uint16_t*)tmp); +} + +/** + * @brief Enables or disables the specified I2C software reset. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Cmd new state of the I2C software reset. + * This parameter can be: ENABLE or DISABLE. + */ +void I2C_EnableSoftwareReset(I2C_Module* I2Cx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Peripheral under reset */ + I2Cx->CTRL1 |= CTRL1_SWRESET_SET; + } + else + { + /* Peripheral not under reset */ + I2Cx->CTRL1 &= CTRL1_SWRESET_RESET; + } +} + +/** + * @brief Selects the specified I2C NACK position in master receiver mode. + * This function is useful in I2C Master Receiver mode when the number + * of data to be received is equal to 2. In this case, this function + * should be called (with parameter I2C_NACK_POS_NEXT) before data + * reception starts,as described in the 2-byte reception procedure + * recommended in Reference Manual in Section: Master receiver. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_NACKPosition specifies the NACK position. + * This parameter can be one of the following values: + * @arg I2C_NACK_POS_NEXT indicates that the next byte will be the last + * received byte. + * @arg I2C_NACK_POS_CURRENT indicates that current byte is the last + * received byte. + * + * @note This function configures the same bit (POS) as I2C_ConfigPecLocation() + * but is intended to be used in I2C mode while I2C_ConfigPecLocation() + * is intended to used in SMBUS mode. + * + */ +void I2C_ConfigNackLocation(I2C_Module* I2Cx, uint16_t I2C_NACKPosition) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_I2C_NACK_POS(I2C_NACKPosition)); + + /* Check the input parameter */ + if (I2C_NACKPosition == I2C_NACK_POS_NEXT) + { + /* Next byte in shift register is the last received byte */ + I2Cx->CTRL1 |= I2C_NACK_POS_NEXT; + } + else + { + /* Current byte in shift register is the last received byte */ + I2Cx->CTRL1 &= I2C_NACK_POS_CURRENT; + } +} + +/** + * @brief Drives the SMBusAlert pin high or low for the specified I2C. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_SMBusAlert specifies SMBAlert pin level. + * This parameter can be one of the following values: + * @arg I2C_SMBALERT_LOW SMBAlert pin driven low + * @arg I2C_SMBALERT_HIGH SMBAlert pin driven high + */ +void I2C_ConfigSmbusAlert(I2C_Module* I2Cx, uint16_t I2C_SMBusAlert) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_I2C_SMB_ALERT(I2C_SMBusAlert)); + if (I2C_SMBusAlert == I2C_SMBALERT_LOW) + { + /* Drive the SMBusAlert pin Low */ + I2Cx->CTRL1 |= I2C_SMBALERT_LOW; + } + else + { + /* Drive the SMBusAlert pin High */ + I2Cx->CTRL1 &= I2C_SMBALERT_HIGH; + } +} + +/** + * @brief Enables or disables the specified I2C PEC transfer. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Cmd new state of the I2C PEC transmission. + * This parameter can be: ENABLE or DISABLE. + */ +void I2C_SendPEC(I2C_Module* I2Cx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected I2C PEC transmission */ + I2Cx->CTRL1 |= CTRL1_PEC_SET; + } + else + { + /* Disable the selected I2C PEC transmission */ + I2Cx->CTRL1 &= CTRL1_PEC_RESET; + } +} + +/** + * @brief Selects the specified I2C PEC position. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_PECPosition specifies the PEC position. + * This parameter can be one of the following values: + * @arg I2C_PEC_POS_NEXT indicates that the next byte is PEC + * @arg I2C_PEC_POS_CURRENT indicates that current byte is PEC + * + * @note This function configures the same bit (POS) as I2C_ConfigNackLocation() + * but is intended to be used in SMBUS mode while I2C_ConfigNackLocation() + * is intended to used in I2C mode. + * + */ +void I2C_ConfigPecLocation(I2C_Module* I2Cx, uint16_t I2C_PECPosition) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_I2C_PEC_POS(I2C_PECPosition)); + if (I2C_PECPosition == I2C_PEC_POS_NEXT) + { + /* Next byte in shift register is PEC */ + I2Cx->CTRL1 |= I2C_PEC_POS_NEXT; + } + else + { + /* Current byte in shift register is PEC */ + I2Cx->CTRL1 &= I2C_PEC_POS_CURRENT; + } +} + +/** + * @brief Enables or disables the PEC value calculation of the transferred bytes. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Cmd new state of the I2Cx PEC value calculation. + * This parameter can be: ENABLE or DISABLE. + */ +void I2C_ComputePec(I2C_Module* I2Cx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected I2C PEC calculation */ + I2Cx->CTRL1 |= CTRL1_PECEN_SET; + } + else + { + /* Disable the selected I2C PEC calculation */ + I2Cx->CTRL1 &= CTRL1_PECEN_RESET; + } +} + +/** + * @brief Returns the PEC value for the specified I2C. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @return The PEC value. + */ +uint8_t I2C_GetPec(I2C_Module* I2Cx) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + /* Return the selected I2C PEC value */ + return ((I2Cx->STS2) >> 8); +} + +/** + * @brief Enables or disables the specified I2C ARP. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Cmd new state of the I2Cx ARP. + * This parameter can be: ENABLE or DISABLE. + */ +void I2C_EnableArp(I2C_Module* I2Cx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected I2C ARP */ + I2Cx->CTRL1 |= CTRL1_ARPEN_SET; + } + else + { + /* Disable the selected I2C ARP */ + I2Cx->CTRL1 &= CTRL1_ARPEN_RESET; + } +} + +/** + * @brief Enables or disables the specified I2C Clock stretching. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param Cmd new state of the I2Cx Clock stretching. + * This parameter can be: ENABLE or DISABLE. + */ +void I2C_EnableExtendClk(I2C_Module* I2Cx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd == DISABLE) + { + /* Enable the selected I2C Clock stretching */ + I2Cx->CTRL1 |= CTRL1_NOEXTEND_SET; + } + else + { + /* Disable the selected I2C Clock stretching */ + I2Cx->CTRL1 &= CTRL1_NOEXTEND_RESET; + } +} + +/** + * @brief Selects the specified I2C fast mode duty cycle. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param FmDutyCycle specifies the fast mode duty cycle. + * This parameter can be one of the following values: + * @arg I2C_FMDUTYCYCLE_2 I2C fast mode Tlow/Thigh = 2 + * @arg I2C_FMDUTYCYCLE_16_9 I2C fast mode Tlow/Thigh = 16/9 + */ +void I2C_ConfigFastModeDutyCycle(I2C_Module* I2Cx, uint16_t FmDutyCycle) +{ + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_I2C_FM_DUTY_CYCLE(FmDutyCycle)); + if (FmDutyCycle != I2C_FMDUTYCYCLE_16_9) + { + /* I2C fast mode Tlow/Thigh=2 */ + I2Cx->CLKCTRL &= I2C_FMDUTYCYCLE_2; + } + else + { + /* I2C fast mode Tlow/Thigh=16/9 */ + I2Cx->CLKCTRL |= I2C_FMDUTYCYCLE_16_9; + } +} + +/** + * @brief + **************************************************************************************** + * + * I2C State Monitoring Functions + * + **************************************************************************************** + * This I2C driver provides three different ways for I2C state monitoring + * depending on the application requirements and constraints: + * + * + * 1) Basic state monitoring: + * Using I2C_CheckEvent() function: + * It compares the status registers (STS1 and STS2) content to a given event + * (can be the combination of one or more flags). + * It returns SUCCESS if the current status includes the given flags + * and returns ERROR if one or more flags are missing in the current status. + * - When to use: + * - This function is suitable for most applications as well as for startup + * activity since the events are fully described in the product reference manual + * (RM0008). + * - It is also suitable for users who need to define their own events. + * - Limitations: + * - If an error occurs (ie. error flags are set besides to the monitored flags), + * the I2C_CheckEvent() function may return SUCCESS despite the communication + * hold or corrupted real state. + * In this case, it is advised to use error interrupts to monitor the error + * events and handle them in the interrupt IRQ handler. + * + * @note + * For error management, it is advised to use the following functions: + * - I2C_ConfigInt() to configure and enable the error interrupts (I2C_INT_ERR). + * - I2Cx_ER_IRQHandler() which is called when the error interrupt occurs. + * Where x is the peripheral instance (I2C1, I2C2 ...) + * - I2C_GetFlag() or I2C_GetIntStatus() to be called into I2Cx_ER_IRQHandler() + * in order to determine which error occured. + * - I2C_ClrFlag() or I2C_ClrIntPendingBit() and/or I2C_EnableSoftwareReset() + * and/or I2C_GenerateStop() in order to clear the error flag and source, + * and return to correct communication status. + * + * + * 2) Advanced state monitoring: + * Using the function I2C_GetLastEvent() which returns the image of both status + * registers in a single word (uint32_t) (Status Register 2 value is shifted left + * by 16 bits and concatenated to Status Register 1). + * - When to use: + * - This function is suitable for the same applications above but it allows to + * overcome the mentioned limitation of I2C_GetFlag() function. + * The returned value could be compared to events already defined in the + * library (n32g45x_i2c.h) or to custom values defined by user. + * - This function is suitable when multiple flags are monitored at the same time. + * - At the opposite of I2C_CheckEvent() function, this function allows user to + * choose when an event is accepted (when all events flags are set and no + * other flags are set or just when the needed flags are set like + * I2C_CheckEvent() function). + * - Limitations: + * - User may need to define his own events. + * - Same remark concerning the error management is applicable for this + * function if user decides to check only regular communication flags (and + * ignores error flags). + * + * + * 3) Flag-based state monitoring: + * Using the function I2C_GetFlag() which simply returns the status of + * one single flag (ie. I2C_FLAG_RXDATNE ...). + * - When to use: + * - This function could be used for specific applications or in debug phase. + * - It is suitable when only one flag checking is needed (most I2C events + * are monitored through multiple flags). + * - Limitations: + * - When calling this function, the Status register is accessed. Some flags are + * cleared when the status register is accessed. So checking the status + * of one Flag, may clear other ones. + * - Function may need to be called twice or more in order to monitor one + * single event. + * + * For detailed description of Events, please refer to section I2C_Events in + * n32g45x_i2c.h file. + * + */ + +/** + * @brief Checks whether the last I2Cx Event is equal to the one passed + * as parameter. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_EVENT specifies the event to be checked. + * This parameter can be one of the following values: + * @arg I2C_EVT_SLAVE_SEND_ADDR_MATCHED EV1 + * @arg I2C_EVT_SLAVE_RECV_ADDR_MATCHED EV1 + * @arg I2C_EVT_SLAVE_SEND_ADDR2_MATCHED EV1 + * @arg I2C_EVT_SLAVE_RECV_ADDR2_MATCHED EV1 + * @arg I2C_EVT_SLAVE_GCALLADDR_MATCHED EV1 + * @arg I2C_EVT_SLAVE_DATA_RECVD EV2 + * @arg (I2C_EVT_SLAVE_DATA_RECVD | I2C_FLAG_DUALFLAG) EV2 + * @arg (I2C_EVT_SLAVE_DATA_RECVD | I2C_FLAG_GCALLADDR) EV2 + * @arg I2C_EVT_SLAVE_DATA_SENDED EV3 + * @arg (I2C_EVT_SLAVE_DATA_SENDED | I2C_FLAG_DUALFLAG) EV3 + * @arg (I2C_EVT_SLAVE_DATA_SENDED | I2C_FLAG_GCALLADDR) EV3 + * @arg I2C_EVT_SLAVE_ACK_MISS EV3_2 + * @arg I2C_EVT_SLAVE_STOP_RECVD EV4 + * @arg I2C_EVT_MASTER_MODE_FLAG EV5 + * @arg I2C_EVT_MASTER_TXMODE_FLAG EV6 + * @arg I2C_EVT_MASTER_RXMODE_FLAG EV6 + * @arg I2C_EVT_MASTER_DATA_RECVD_FLAG EV7 + * @arg I2C_EVT_MASTER_DATA_SENDING EV8 + * @arg I2C_EVT_MASTER_DATA_SENDED EV8_2 + * @arg I2C_EVT_MASTER_MODE_ADDRESS10_FLAG EV9 + * + * @note: For detailed description of Events, please refer to section + * I2C_Events in n32g45x_i2c.h file. + * + * @return An ErrorStatus enumeration value: + * - SUCCESS: Last event is equal to the I2C_EVENT + * - ERROR: Last event is different from the I2C_EVENT + */ +ErrorStatus I2C_CheckEvent(I2C_Module* I2Cx, uint32_t I2C_EVENT) +{ + uint32_t lastevent = 0; + uint32_t flag1 = 0, flag2 = 0; + ErrorStatus status = ERROR; + + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_I2C_EVT(I2C_EVENT)); + + /* Read the I2Cx status register */ + flag1 = I2Cx->STS1; + flag2 = I2Cx->STS2; + flag2 = flag2 << 16; + + /* Get the last event value from I2C status register */ + lastevent = (flag1 | flag2) & FLAG_MASK; + + /* Check whether the last event contains the I2C_EVENT */ + if ((lastevent & I2C_EVENT) == I2C_EVENT) + { + /* SUCCESS: last event is equal to I2C_EVENT */ + status = SUCCESS; + } + else + { + /* ERROR: last event is different from I2C_EVENT */ + status = ERROR; + } + /* Return status */ + return status; +} + +/** + * @brief Returns the last I2Cx Event. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * + * @note: For detailed description of Events, please refer to section + * I2C_Events in n32g45x_i2c.h file. + * + * @return The last event + */ +uint32_t I2C_GetLastEvent(I2C_Module* I2Cx) +{ + uint32_t lastevent = 0; + uint32_t flag1 = 0, flag2 = 0; + + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + + /* Read the I2Cx status register */ + flag1 = I2Cx->STS1; + flag2 = I2Cx->STS2; + flag2 = flag2 << 16; + + /* Get the last event value from I2C status register */ + lastevent = (flag1 | flag2) & FLAG_MASK; + + /* Return status */ + return lastevent; +} + +/** + * @brief Checks whether the specified I2C flag is set or not. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_FLAG specifies the flag to check. + * This parameter can be one of the following values: + * @arg I2C_FLAG_DUALFLAG Dual flag (Slave mode) + * @arg I2C_FLAG_SMBHADDR SMBus host header (Slave mode) + * @arg I2C_FLAG_SMBDADDR SMBus default header (Slave mode) + * @arg I2C_FLAG_GCALLADDR General call header flag (Slave mode) + * @arg I2C_FLAG_TRF Transmitter/Receiver flag + * @arg I2C_FLAG_BUSY Bus busy flag + * @arg I2C_FLAG_MSMODE Master/Slave flag + * @arg I2C_FLAG_SMBALERT SMBus Alert flag + * @arg I2C_FLAG_TIMOUT Timeout or Tlow error flag + * @arg I2C_FLAG_PECERR PEC error in reception flag + * @arg I2C_FLAG_OVERRUN Overrun/Underrun flag (Slave mode) + * @arg I2C_FLAG_ACKFAIL Acknowledge failure flag + * @arg I2C_FLAG_ARLOST Arbitration lost flag (Master mode) + * @arg I2C_FLAG_BUSERR Bus error flag + * @arg I2C_FLAG_TXDATE Data register empty flag (Transmitter) + * @arg I2C_FLAG_RXDATNE Data register not empty (Receiver) flag + * @arg I2C_FLAG_STOPF Stop detection flag (Slave mode) + * @arg I2C_FLAG_ADDR10F 10-bit header sent flag (Master mode) + * @arg I2C_FLAG_BYTEF Byte transfer finished flag + * @arg I2C_FLAG_ADDRF Address sent flag (Master mode) "ADSL" + * Address matched flag (Slave mode)"ENDA" + * @arg I2C_FLAG_STARTBF Start bit flag (Master mode) + * @return The new state of I2C_FLAG (SET or RESET). + */ +FlagStatus I2C_GetFlag(I2C_Module* I2Cx, uint32_t I2C_FLAG) +{ + FlagStatus bitstatus = RESET; + __IO uint32_t i2creg = 0, i2cxbase = 0; + + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_I2C_GET_FLAG(I2C_FLAG)); + + /* Get the I2Cx peripheral base address */ + i2cxbase = (uint32_t)I2Cx; + + /* Read flag register index */ + i2creg = I2C_FLAG >> 28; + + /* Get bit[23:0] of the flag */ + I2C_FLAG &= FLAG_MASK; + + if (i2creg != 0) + { + /* Get the I2Cx STS1 register address */ + i2cxbase += 0x14; + } + else + { + /* Flag in I2Cx STS2 Register */ + I2C_FLAG = (uint32_t)(I2C_FLAG >> 16); + /* Get the I2Cx STS2 register address */ + i2cxbase += 0x18; + } + + if (((*(__IO uint32_t*)i2cxbase) & I2C_FLAG) != (uint32_t)RESET) + { + /* I2C_FLAG is set */ + bitstatus = SET; + } + else + { + /* I2C_FLAG is reset */ + bitstatus = RESET; + } + + /* Return the I2C_FLAG status */ + return bitstatus; +} + +/** + * @brief Clears the I2Cx's pending flags. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_FLAG specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg I2C_FLAG_SMBALERT SMBus Alert flag + * @arg I2C_FLAG_TIMOUT Timeout or Tlow error flag + * @arg I2C_FLAG_PECERR PEC error in reception flag + * @arg I2C_FLAG_OVERRUN Overrun/Underrun flag (Slave mode) + * @arg I2C_FLAG_ACKFAIL Acknowledge failure flag + * @arg I2C_FLAG_ARLOST Arbitration lost flag (Master mode) + * @arg I2C_FLAG_BUSERR Bus error flag + * + * @note + * - STOPF (STOP detection) is cleared by software sequence: a read operation + * to I2C_STS1 register (I2C_GetFlag()) followed by a write operation + * to I2C_CTRL1 register (I2C_Enable() to re-enable the I2C peripheral). + * - ADD10 (10-bit header sent) is cleared by software sequence: a read + * operation to I2C_STS1 (I2C_GetFlag()) followed by writing the + * second byte of the address in DAT register. + * - BTF (Byte Transfer Finished) is cleared by software sequence: a read + * operation to I2C_STS1 register (I2C_GetFlag()) followed by a + * read/write to I2C_DAT register (I2C_SendData()). + * - ADDR (Address sent) is cleared by software sequence: a read operation to + * I2C_STS1 register (I2C_GetFlag()) followed by a read operation to + * I2C_STS2 register ((void)(I2Cx->STS2)). + * - SB (Start Bit) is cleared software sequence: a read operation to I2C_STS1 + * register (I2C_GetFlag()) followed by a write operation to I2C_DAT + * register (I2C_SendData()). + */ +void I2C_ClrFlag(I2C_Module* I2Cx, uint32_t I2C_FLAG) +{ + uint32_t flagpos = 0; + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_I2C_CLR_FLAG(I2C_FLAG)); + /* Get the I2C flag position */ + flagpos = I2C_FLAG & FLAG_MASK; + /* Clear the selected I2C flag */ + I2Cx->STS1 = (uint16_t)~flagpos; +} + +/** + * @brief Checks whether the specified I2C interrupt has occurred or not. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_IT specifies the interrupt source to check. + * This parameter can be one of the following values: + * @arg I2C_INT_SMBALERT SMBus Alert flag + * @arg I2C_INT_TIMOUT Timeout or Tlow error flag + * @arg I2C_INT_PECERR PEC error in reception flag + * @arg I2C_INT_OVERRUN Overrun/Underrun flag (Slave mode) + * @arg I2C_INT_ACKFAIL Acknowledge failure flag + * @arg I2C_INT_ARLOST Arbitration lost flag (Master mode) + * @arg I2C_INT_BUSERR Bus error flag + * @arg I2C_INT_TXDATE Data register empty flag (Transmitter) + * @arg I2C_INT_RXDATNE Data register not empty (Receiver) flag + * @arg I2C_INT_STOPF Stop detection flag (Slave mode) + * @arg I2C_INT_ADDR10F 10-bit header sent flag (Master mode) + * @arg I2C_INT_BYTEF Byte transfer finished flag + * @arg I2C_INT_ADDRF Address sent flag (Master mode) "ADSL" + * Address matched flag (Slave mode)"ENDAD" + * @arg I2C_INT_STARTBF Start bit flag (Master mode) + * @return The new state of I2C_IT (SET or RESET). + */ +INTStatus I2C_GetIntStatus(I2C_Module* I2Cx, uint32_t I2C_IT) +{ + INTStatus bitstatus = RESET; + uint32_t enablestatus = 0; + + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_I2C_GET_INT(I2C_IT)); + + /* Check if the interrupt source is enabled or not */ + enablestatus = (uint32_t)(((I2C_IT & INTEN_MASK) >> 16) & (I2Cx->CTRL2)); + + /* Get bit[23:0] of the flag */ + I2C_IT &= FLAG_MASK; + + /* Check the status of the specified I2C flag */ + if (((I2Cx->STS1 & I2C_IT) != (uint32_t)RESET) && enablestatus) + { + /* I2C_IT is set */ + bitstatus = SET; + } + else + { + /* I2C_IT is reset */ + bitstatus = RESET; + } + /* Return the I2C_IT status */ + return bitstatus; +} + +/** + * @brief Clears the I2Cx's interrupt pending bits. + * @param I2Cx where x can be 1 or 2 to select the I2C peripheral. + * @param I2C_IT specifies the interrupt pending bit to clear. + * This parameter can be any combination of the following values: + * @arg I2C_INT_SMBALERT SMBus Alert interrupt + * @arg I2C_INT_TIMOUT Timeout or Tlow error interrupt + * @arg I2C_INT_PECERR PEC error in reception interrupt + * @arg I2C_INT_OVERRUN Overrun/Underrun interrupt (Slave mode) + * @arg I2C_INT_ACKFAIL Acknowledge failure interrupt + * @arg I2C_INT_ARLOST Arbitration lost interrupt (Master mode) + * @arg I2C_INT_BUSERR Bus error interrupt + * + * @note + * - STOPF (STOP detection) is cleared by software sequence: a read operation + * to I2C_STS1 register (I2C_GetIntStatus()) followed by a write operation to + * I2C_CTRL1 register (I2C_Enable() to re-enable the I2C peripheral). + * - ADD10 (10-bit header sent) is cleared by software sequence: a read + * operation to I2C_STS1 (I2C_GetIntStatus()) followed by writing the second + * byte of the address in I2C_DAT register. + * - BTF (Byte Transfer Finished) is cleared by software sequence: a read + * operation to I2C_STS1 register (I2C_GetIntStatus()) followed by a + * read/write to I2C_DAT register (I2C_SendData()). + * - ADDR (Address sent) is cleared by software sequence: a read operation to + * I2C_STS1 register (I2C_GetIntStatus()) followed by a read operation to + * I2C_STS2 register ((void)(I2Cx->STS2)). + * - SB (Start Bit) is cleared by software sequence: a read operation to + * I2C_STS1 register (I2C_GetIntStatus()) followed by a write operation to + * I2C_DAT register (I2C_SendData()). + */ +void I2C_ClrIntPendingBit(I2C_Module* I2Cx, uint32_t I2C_IT) +{ + uint32_t flagpos = 0; + /* Check the parameters */ + assert_param(IS_I2C_PERIPH(I2Cx)); + assert_param(IS_I2C_CLR_INT(I2C_IT)); + /* Get the I2C flag position */ + flagpos = I2C_IT & FLAG_MASK; + /* Clear the selected I2C flag */ + I2Cx->STS1 = (uint16_t)~flagpos; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/src/n32g45x_iwdg.c b/src/n32g45x_iwdg.c new file mode 100644 index 0000000..36b2f42 --- /dev/null +++ b/src/n32g45x_iwdg.c @@ -0,0 +1,193 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_iwdg.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_iwdg.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup IWDG + * @brief IWDG driver modules + * @{ + */ + +/** @addtogroup IWDG_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup IWDG_Private_Defines + * @{ + */ + +/* ---------------------- IWDG registers bit mask ----------------------------*/ + +/* KEY register bit mask */ +#define KEY_ReloadKey ((uint16_t)0xAAAA) +#define KEY_EnableKey ((uint16_t)0xCCCC) + +/** + * @} + */ + +/** @addtogroup IWDG_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup IWDG_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup IWDG_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup IWDG_Private_Functions + * @{ + */ + +/** + * @brief Enables or disables write access to IWDG_PR and IWDG_RLR registers. + * @param IWDG_WriteAccess new state of write access to IWDG_PR and IWDG_RLR registers. + * This parameter can be one of the following values: + * @arg IWDG_WRITE_ENABLE Enable write access to IWDG_PR and IWDG_RLR registers + * @arg IWDG_WRITE_DISABLE Disable write access to IWDG_PR and IWDG_RLR registers + */ +void IWDG_WriteConfig(uint16_t IWDG_WriteAccess) +{ + /* Check the parameters */ + assert_param(IS_IWDG_WRITE(IWDG_WriteAccess)); + IWDG->KEY = IWDG_WriteAccess; +} + +/** + * @brief Sets IWDG Prescaler value. + * @param IWDG_Prescaler specifies the IWDG Prescaler value. + * This parameter can be one of the following values: + * @arg IWDG_PRESCALER_DIV4 IWDG prescaler set to 4 + * @arg IWDG_PRESCALER_DIV8 IWDG prescaler set to 8 + * @arg IWDG_PRESCALER_DIV16 IWDG prescaler set to 16 + * @arg IWDG_PRESCALER_DIV32 IWDG prescaler set to 32 + * @arg IWDG_PRESCALER_DIV64 IWDG prescaler set to 64 + * @arg IWDG_PRESCALER_DIV128 IWDG prescaler set to 128 + * @arg IWDG_PRESCALER_DIV256 IWDG prescaler set to 256 + */ +void IWDG_SetPrescalerDiv(uint8_t IWDG_Prescaler) +{ + /* Check the parameters */ + assert_param(IS_IWDG_PRESCALER_DIV(IWDG_Prescaler)); + IWDG->PREDIV = IWDG_Prescaler; +} + +/** + * @brief Sets IWDG Reload value. + * @param Reload specifies the IWDG Reload value. + * This parameter must be a number between 0 and 0x0FFF. + */ +void IWDG_CntReload(uint16_t Reload) +{ + /* Check the parameters */ + assert_param(IS_IWDG_RELOAD(Reload)); + IWDG->RELV = Reload; +} + +/** + * @brief Reloads IWDG counter with value defined in the reload register + * (write access to IWDG_PR and IWDG_RLR registers disabled). + */ +void IWDG_ReloadKey(void) +{ + IWDG->KEY = KEY_ReloadKey; +} + +/** + * @brief Enables IWDG (write access to IWDG_PR and IWDG_RLR registers disabled). + */ +void IWDG_Enable(void) +{ + IWDG->KEY = KEY_EnableKey; +} + +/** + * @brief Checks whether the specified IWDG flag is set or not. + * @param IWDG_FLAG specifies the flag to check. + * This parameter can be one of the following values: + * @arg IWDG_PVU_FLAG Prescaler Value Update on going + * @arg IWDG_CRVU_FLAG Reload Value Update on going + * @return The new state of IWDG_FLAG (SET or RESET). + */ +FlagStatus IWDG_GetStatus(uint16_t IWDG_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_IWDG_FLAG(IWDG_FLAG)); + if ((IWDG->STS & IWDG_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + /* Return the flag status */ + return bitstatus; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/src/n32g45x_opamp.c b/src/n32g45x_opamp.c new file mode 100644 index 0000000..d8dd50d --- /dev/null +++ b/src/n32g45x_opamp.c @@ -0,0 +1,201 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_opamp.c + * @author Nations + * @version v1.0.2 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_opamp.h" +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup OPAMP + * @brief OPAMP driver modules + * @{ + */ + +/** @addtogroup OPAMP_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup OPAMP_Private_Defines + * @{ + */ + +/** + * @} + */ + +/** @addtogroup OPAMP_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup OPAMP_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup OPAMP_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup OPAMP_Private_Functions + * @{ + */ +#define SetBitMsk(reg, bit, msk) ((reg) = ((reg) & ~(msk) | (bit))) +#define ClrBit(reg, bit) ((reg) &= ~(bit)) +#define SetBit(reg, bit) ((reg) |= (bit)) +#define GetBit(reg, bit) ((reg) & (bit)) +/** + * @brief Deinitializes the OPAMP peripheral registers to their default reset values. + */ +void OPAMP_DeInit(void) +{ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_OPAMP, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_OPAMP, DISABLE); +} + +void OPAMP_StructInit(OPAMP_InitType* OPAMP_InitStruct) +{ + OPAMP_InitStruct->Gain = OPAMP_CS_PGA_GAIN_2; + OPAMP_InitStruct->HighVolRangeEn = ENABLE; + OPAMP_InitStruct->TimeAutoMuxEn = DISABLE; + OPAMP_InitStruct->Mod = OPAMP_CS_PGA_EN; +} + +void OPAMP_Init(OPAMPX OPAMPx, OPAMP_InitType* OPAMP_InitStruct) +{ + __IO uint32_t* pCs = &OPAMP->CS1 + OPAMPx; + __IO uint32_t tmp = *pCs; + + SetBitMsk(tmp, OPAMP_InitStruct->Gain, OPAMP_CS_PGA_GAIN_MASK); + + if(OPAMP_InitStruct->HighVolRangeEn==ENABLE) + SetBitMsk(tmp, OPAMP_CS_RANGE_MASK, OPAMP_CS_RANGE_MASK); + else + ClrBit(tmp,OPAMP_CS_RANGE_MASK); + + if(OPAMP_InitStruct->TimeAutoMuxEn==ENABLE) + SetBitMsk(tmp,OPAMP_CS_TCMEN_MASK, OPAMP_CS_TCMEN_MASK); + else + ClrBit(tmp,OPAMP_CS_TCMEN_MASK); + + SetBitMsk(tmp, OPAMP_InitStruct->Mod, OPAMP_CS_MOD_MASK); + *pCs = tmp; +} +void OPAMP_Enable(OPAMPX OPAMPx, FunctionalState en) +{ + __IO uint32_t* pCs = &OPAMP->CS1 + OPAMPx; + if (en) + SetBit(*pCs, OPAMP_CS_EN_MASK); + else + ClrBit(*pCs, OPAMP_CS_EN_MASK); +} + +void OPAMP_SetPgaGain(OPAMPX OPAMPx, OPAMP_CS_PGA_GAIN Gain) +{ + __IO uint32_t* pCs = &OPAMP->CS1 + OPAMPx; + __IO uint32_t tmp = *pCs; + SetBitMsk(tmp, Gain, OPAMP_CS_PGA_GAIN_MASK); + *pCs = tmp; +} +void OPAMP_SetVpSecondSel(OPAMPX OPAMPx, OPAMP_CS_VPSSEL VpSSel) +{ + __IO uint32_t* pCs = &OPAMP->CS1 + OPAMPx; + __IO uint32_t tmp = *pCs; + SetBitMsk(tmp, VpSSel, OPAMP_CS_VPSEL_SECOND_MASK); + *pCs = tmp; +} +void OPAMP_SetVmSecondSel(OPAMPX OPAMPx, OPAMP_CS_VMSSEL VmSSel) +{ + __IO uint32_t* pCs = &OPAMP->CS1 + OPAMPx; + __IO uint32_t tmp = *pCs; + SetBitMsk(tmp, VmSSel, OPAMP_CS_VMSEL_SECOND_MASK); + *pCs = tmp; +} +void OPAMP_SetVpSel(OPAMPX OPAMPx, OPAMP_CS_VPSEL VpSel) +{ + __IO uint32_t* pCs = &OPAMP->CS1 + OPAMPx; + __IO uint32_t tmp = *pCs; + SetBitMsk(tmp, VpSel, OPAMP_CS_VPSEL_MASK); + *pCs = tmp; +} +void OPAMP_SetVmSel(OPAMPX OPAMPx, OPAMP_CS_VMSEL VmSel) +{ + __IO uint32_t* pCs = &OPAMP->CS1 + OPAMPx; + __IO uint32_t tmp = *pCs; + SetBitMsk(tmp, VmSel, OPAMP_CS_VMSEL_MASK); + *pCs = tmp; +} +bool OPAMP_IsCalOutHigh(OPAMPX OPAMPx) +{ + __IO uint32_t* pCs = &OPAMP->CS1 + OPAMPx; + return (GetBit(*pCs, OPAMP_CS_CALOUT_MASK)) ? true : false; +} +void OPAMP_CalibrationEnable(OPAMPX OPAMPx, FunctionalState en) +{ + __IO uint32_t* pCs = &OPAMP->CS1 + OPAMPx; + if (en) + SetBit(*pCs, OPAMP_CS_CALON_MASK); + else + ClrBit(*pCs, OPAMP_CS_CALON_MASK); +} +// Lock see @OPAMP_LOCK +void OPAMP_SetLock(uint32_t Lock) +{ + OPAMP->LOCK = Lock; +} +/** + * @} + */ +/** + * @} + */ +/** + * @} + */ diff --git a/src/n32g45x_pwr.c b/src/n32g45x_pwr.c new file mode 100644 index 0000000..c00be0e --- /dev/null +++ b/src/n32g45x_pwr.c @@ -0,0 +1,399 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_pwr.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_pwr.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup PWR + * @brief PWR driver modules + * @{ + */ + +/** @addtogroup PWR_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup PWR_Private_Defines + * @{ + */ + +/* --------- PWR registers bit address in the alias region ---------- */ +#define PWR_OFFSET (PWR_BASE - PERIPH_BASE) + +/* --- CTRL Register ---*/ + +/* Alias word address of DBKP bit */ +#define CTRL_OFFSET (PWR_OFFSET + 0x00) +#define DBKP_BITN 0x08 +#define CTRL_DBKP_BB (PERIPH_BB_BASE + (CTRL_OFFSET * 32) + (DBKP_BITN * 4)) + +/* Alias word address of PVDEN bit */ +#define PVDEN_BITN 0x04 +#define CTRL_PVDEN_BB (PERIPH_BB_BASE + (CTRL_OFFSET * 32) + (PVDEN_BITN * 4)) + +/* --- CTRLSTS Register ---*/ + +/* Alias word address of WKUPEN bit */ +#define CTRLSTS_OFFSET (PWR_OFFSET + 0x04) +#define WKUPEN_BITN 0x08 +#define CTRLSTS_WKUPEN_BB (PERIPH_BB_BASE + (CTRLSTS_OFFSET * 32) + (WKUPEN_BITN * 4)) + +/* ------------------ PWR registers bit mask ------------------------ */ + +/* CTRL register bit mask */ +#define CTRL_DS_MASK ((uint32_t)0xFFFFFFFC) +#define CTRL_PRS_MASK ((uint32_t)0xFFFFFD1F) + +/** + * @} + */ + +/** @addtogroup PWR_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup PWR_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup PWR_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup PWR_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the PWR peripheral registers to their default reset values. + */ +void PWR_DeInit(void) +{ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_PWR, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_PWR, DISABLE); +} + +/** + * @brief Enables or disables access to the RTC and backup registers. + * @param Cmd new state of the access to the RTC and backup registers. + * This parameter can be: ENABLE or DISABLE. + */ +void PWR_BackupAccessEnable(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + *(__IO uint32_t*)CTRL_DBKP_BB = (uint32_t)Cmd; +} + +/** + * @brief Enables or disables the Power Voltage Detector(PVD). + * @param Cmd new state of the PVD. + * This parameter can be: ENABLE or DISABLE. + */ +void PWR_PvdEnable(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + *(__IO uint32_t*)CTRL_PVDEN_BB = (uint32_t)Cmd; +} + +/** + * @brief Configures the voltage threshold detected by the Power Voltage Detector(PVD). + * @param PWR_PVDLevel specifies the PVD detection level + * This parameter can be one of the following values: + * @arg PWR_PVDRANGRE_2V2 PVD detection level set to 2.2V + * @arg PWR_PVDRANGRE_2V3 PVD detection level set to 2.3V + * @arg PWR_PVDRANGRE_2V4 PVD detection level set to 2.4V + * @arg PWR_PVDRANGRE_2V5 PVD detection level set to 2.5V + * @arg PWR_PVDRANGRE_2V6 PVD detection level set to 2.6V + * @arg PWR_PVDRANGRE_2V7 PVD detection level set to 2.7V + * @arg PWR_PVDRANGRE_2V8 PVD detection level set to 2.8V + * @arg PWR_PVDRANGRE_2V9 PVD detection level set to 2.9V + */ +void PWR_PvdRangeConfig(uint32_t PWR_PVDLevel) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_PWR_PVD_LEVEL(PWR_PVDLevel)); + tmpregister = PWR->CTRL; + /* Clear PRS[7:5] bits */ + tmpregister &= CTRL_PRS_MASK; + /* Set PRS[7:5] bits according to PWR_PVDLevel value */ + tmpregister |= PWR_PVDLevel; + /* Store the new value */ + PWR->CTRL = tmpregister; +} + +/** + * @brief Enables or disables the WakeUp Pin functionality. + * @param Cmd new state of the WakeUp Pin functionality. + * This parameter can be: ENABLE or DISABLE. + */ +void PWR_WakeUpPinEnable(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + *(__IO uint32_t*)CTRLSTS_WKUPEN_BB = (uint32_t)Cmd; +} + +/** + * @brief Enters SLEEP mode. + * @param SLEEPONEXIT specifies the SLEEPONEXIT state in SLEEP mode. + * This parameter can be one of the following values: + * @arg 0 SLEEP mode with SLEEPONEXIT disable + * @arg 1 SLEEP mode with SLEEPONEXIT enable + * @param PWR_STOPEntry specifies if SLEEP mode in entered with WFI or WFE instruction. + * This parameter can be one of the following values: + * @arg PWR_STOPENTRY_WFI enter SLEEP mode with WFI instruction + * @arg PWR_STOPENTRY_WFE enter SLEEP mode with WFE instruction + */ +void PWR_EnterSLEEPMode(uint8_t SLEEPONEXIT, uint8_t PWR_STOPEntry) +{ + // uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_PWR_STOP_ENTRY(PWR_STOPEntry)); + + /* CLEAR SLEEPDEEP bit of Cortex System Control Register */ + SCB->SCR &= (uint32_t) ~((uint32_t)SCB_SCR_SLEEPDEEP); + + /* Select SLEEPONEXIT mode entry --------------------------------------------------*/ + if (SLEEPONEXIT == 1) + { + /* the MCU enters Sleep mode as soon as it exits the lowest priority INTSTS */ + SCB->SCR |= SCB_SCR_SLEEPONEXIT; + } + else if (SLEEPONEXIT == 0) + { + /* Sleep-now */ + SCB->SCR &= (uint32_t) ~((uint32_t)SCB_SCR_SLEEPONEXIT); + } + + /* Select SLEEP mode entry --------------------------------------------------*/ + if (PWR_STOPEntry == PWR_STOPENTRY_WFI) + { + /* Request Wait For Interrupt */ + __WFI(); + } + else + { + /* Request Wait For Event */ + __SEV(); + __WFE(); + __WFE(); + } +} + +/** + * @brief Enters STOP mode. + * @param PWR_Regulator specifies the regulator state in STOP mode. + * This parameter can be one of the following values: + * @arg PWR_REGULATOR_ON STOP mode with regulator ON + * @arg PWR_REGULATOR_LOWPOWER STOP mode with regulator in low power mode + * @param PWR_STOPEntry specifies if STOP mode in entered with WFI or WFE instruction. + * This parameter can be one of the following values: + * @arg PWR_STOPENTRY_WFI enter STOP mode with WFI instruction + * @arg PWR_STOPENTRY_WFE enter STOP mode with WFE instruction + */ +void PWR_EnterStopState(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_PWR_REGULATOR(PWR_Regulator)); + assert_param(IS_PWR_STOP_ENTRY(PWR_STOPEntry)); + + /* Select the regulator state in STOP mode ---------------------------------*/ + tmpregister = PWR->CTRL; + /* Clear PDS and LPS bits */ + tmpregister &= CTRL_DS_MASK; + /* Set LPS bit according to PWR_Regulator value */ + tmpregister |= PWR_Regulator; + /* Store the new value */ + PWR->CTRL = tmpregister; + /* Set SLEEPDEEP bit of Cortex System Control Register */ + SCB->SCR |= SCB_SCR_SLEEPDEEP; + + /* Select STOP mode entry --------------------------------------------------*/ + if (PWR_STOPEntry == PWR_STOPENTRY_WFI) + { + /* Request Wait For Interrupt */ + __WFI(); + } + else + { + /* Request Wait For Event */ + __SEV(); + __WFE(); + __WFE(); + } + + /* Reset SLEEPDEEP bit of Cortex System Control Register */ + SCB->SCR &= (uint32_t) ~((uint32_t)SCB_SCR_SLEEPDEEP); +} + +/** + * @brief Enters STOP2 mode. + * @param PWR_STOPEntry specifies if STOP2 mode in entered with WFI or WFE instruction. + * This parameter can be one of the following values: + * @arg PWR_STOPENTRY_WFI enter STOP2 mode with WFI instruction + * @arg PWR_STOPENTRY_WFE enter STOP2 mode with WFE instruction + */ +void PWR_EnterSTOP2Mode(uint8_t PWR_STOPEntry) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_PWR_STOP_ENTRY(PWR_STOPEntry)); + + /* Select the regulator state in STOP2 mode ---------------------------------*/ + tmpregister = PWR->CTRL; + /* Clear PDS and LPS bits */ + tmpregister &= CTRL_DS_MASK; + /* Store the new value */ + PWR->CTRL = tmpregister; + /*STOP2 sleep mode control-stop2s*/ + PWR->CTRL2 |= PWR_CTRL2_STOP2S; + /* Set SLEEPDEEP bit of Cortex System Control Register */ + SCB->SCR |= SCB_SCR_SLEEPDEEP; + // PWR_CTRL2.BIT0 STOP2S need? + /* Select STOP mode entry --------------------------------------------------*/ + if (PWR_STOPEntry == PWR_STOPENTRY_WFI) + { + /* Request Wait For Interrupt */ + __WFI(); + } + else + { + /* Request Wait For Event */ + __SEV(); + __WFE(); + __WFE(); + } + + /* Reset SLEEPDEEP bit of Cortex System Control Register */ + SCB->SCR &= (uint32_t) ~((uint32_t)SCB_SCR_SLEEPDEEP); +} + +/** + * @brief Enters STANDBY mode. + */ +void PWR_EnterStandbyState(void) +{ + /* Clear Wake-up flag */ + PWR->CTRL |= PWR_CTRL_CWKUP; + /* Clear PDS and LPS bits */ + PWR->CTRL &= CTRL_DS_MASK; + /* Select STANDBY mode */ + PWR->CTRL |= PWR_CTRL_PDS; + /* Set SLEEPDEEP bit of Cortex System Control Register */ + SCB->SCR |= SCB_SCR_SLEEPDEEP; +/* This option is used to ensure that store operations are completed */ +#if defined(__CC_ARM) + __force_stores(); +#endif + /* Request Wait For Interrupt */ + __WFI(); +} + +/** + * @brief Checks whether the specified PWR flag is set or not. + * @param PWR_FLAG specifies the flag to check. + * This parameter can be one of the following values: + * @arg PWR_WU_FLAG Wake Up flag + * @arg PWR_SB_FLAG StandBy flag + * @arg PWR_PVDO_FLAG PVD Output + * @arg PWR_VBATF_FLAG VBAT flag + * @return The new state of PWR_FLAG (SET or RESET). + */ +FlagStatus PWR_GetFlagStatus(uint32_t PWR_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_PWR_GET_FLAG(PWR_FLAG)); + + if ((PWR->CTRLSTS & PWR_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + /* Return the flag status */ + return bitstatus; +} + +/** + * @brief Clears the PWR's pending flags. + * @param PWR_FLAG specifies the flag to clear. + * This parameter can be one of the following values: + * @arg PWR_WU_FLAG Wake Up flag + * @arg PWR_SB_FLAG StandBy and VBAT flag + */ +void PWR_ClearFlag(uint32_t PWR_FLAG) +{ + /* Check the parameters */ + assert_param(IS_PWR_CLEAR_FLAG(PWR_FLAG)); + + PWR->CTRL |= PWR_FLAG << 2; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/src/n32g45x_qspi.c b/src/n32g45x_qspi.c new file mode 100644 index 0000000..e51b063 --- /dev/null +++ b/src/n32g45x_qspi.c @@ -0,0 +1,612 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_qspi.c + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_qspi.h" + +/** + * @brief Control QSPI function switch. + * @param cmd select enable or disable QSPI. + */ +void QSPI_Cmd(bool cmd) +{ + if (cmd != DISABLE) + { + QSPI->SLAVE_EN = QSPI_SLAVE_EN_SEN; + QSPI->EN = QSPI_EN_QEN; + } + else + { + QSPI->SLAVE_EN &= ~QSPI_SLAVE_EN_SEN; + QSPI->EN &= ~QSPI_EN_QEN; + } +} +/** + * @brief Control QSPI XIP function switch. + * @param cmd select enable or disable QSPI XIP. + */ +void QSPI_XIP_Cmd(bool cmd) +{ + if (cmd != DISABLE) + { + QSPI->XIP_SLAVE_EN = QSPI_XIP_SLAVE_EN_SEN; + } + else + { + QSPI->XIP_SLAVE_EN &= ~QSPI_XIP_SLAVE_EN_SEN; + } +} +/** + * @brief Deinitializes the QSPI peripheral registers to its default reset values. + */ +void QSPI_DeInit(void) +{ + RCC_EnableAHBPeriphReset(RCC_AHB_PERIPH_QSPI, ENABLE); + RCC_EnableAHBPeriphReset(RCC_AHB_PERIPH_QSPI, DISABLE); +} +/** + * @brief Merge configuration from the buffer of QSPI para struct, then write it into related registers. + * @param QSPI_InitStruct pointer to buffer of QSPI para struct. + */ +void QspiInitConfig(QSPI_InitType* QSPI_InitStruct) +{ + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_QSPI_SPI_FRF(QSPI_InitStruct->SPI_FRF)); + assert_param(IS_QSPI_CFS(QSPI_InitStruct->CFS)); + assert_param(IS_QSPI_SSTE(QSPI_InitStruct->SSTE)); + assert_param(IS_QSPI_TMOD(QSPI_InitStruct->TMOD)); + assert_param(IS_QSPI_SCPOL(QSPI_InitStruct->SCPOL)); + assert_param(IS_QSPI_SCPH(QSPI_InitStruct->SCPH)); + assert_param(IS_QSPI_FRF(QSPI_InitStruct->FRF)); + assert_param(IS_QSPI_DFS(QSPI_InitStruct->DFS)); + assert_param(IS_QSPI_MWMOD(QSPI_InitStruct->MWMOD)); + assert_param(IS_QSPI_MC_DIR(QSPI_InitStruct->MC_DIR)); + assert_param(IS_QSPI_MHS_EN(QSPI_InitStruct->MHS_EN)); + assert_param(IS_QSPI_SES(QSPI_InitStruct->SES)); + assert_param(IS_QSPI_SDCN(QSPI_InitStruct->SDCN)); + + assert_param(IS_QSPI_ENH_CLK_STRETCH_EN(QSPI_InitStruct->ENHANCED_CLK_STRETCH_EN)); + assert_param(IS_QSPI_ENH_XIP_MBL(QSPI_InitStruct->ENHANCED_XIP_MBL)); + assert_param(IS_QSPI_ENH_XIP_CT_EN(QSPI_InitStruct->ENHANCED_XIP_CT_EN)); + assert_param(IS_QSPI_ENH_XIP_INST_EN(QSPI_InitStruct->ENHANCED_XIP_INST_EN)); + assert_param(IS_QSPI_ENH_XIP_DFS_HC(QSPI_InitStruct->ENHANCED_XIP_DFS_HC)); + assert_param(IS_QSPI_ENH_INST_DDR_EN(QSPI_InitStruct->ENHANCED_INST_DDR_EN)); + assert_param(IS_QSPI_ENH_SPI_DDR_EN(QSPI_InitStruct->ENHANCED_SPI_DDR_EN)); + assert_param(IS_QSPI_ENH_WAIT_CYCLES(QSPI_InitStruct->ENHANCED_WAIT_CYCLES)); + assert_param(IS_QSPI_ENH_INST_L(QSPI_InitStruct->ENHANCED_INST_L)); + assert_param(IS_QSPI_ENH_MD_BIT_EN(QSPI_InitStruct->ENHANCED_MD_BIT_EN)); + assert_param(IS_QSPI_ENH_ADDR_LEN(QSPI_InitStruct->ENHANCED_ADDR_LEN)); + assert_param(IS_QSPI_ENH_TRANS_TYPE(QSPI_InitStruct->ENHANCED_TRANS_TYPE)); + + assert_param(IS_QSPI_XIP_MBL(QSPI_InitStruct->XIP_MBL)); + assert_param(IS_QSPI_XIP_CT_EN(QSPI_InitStruct->XIP_CT_EN)); + assert_param(IS_QSPI_XIP_INST_EN(QSPI_InitStruct->XIP_INST_EN)); + assert_param(IS_QSPI_INST_DDR_EN(QSPI_InitStruct->XIP_INST_DDR_EN)); + assert_param(IS_QSPI_DDR_EN(QSPI_InitStruct->XIP_DDR_EN)); + assert_param(IS_QSPI_XIP_DFS_HC(QSPI_InitStruct->XIP_DFS_HC)); + assert_param(IS_QSPI_XIP_WAIT_CYCLES(QSPI_InitStruct->XIP_WAIT_CYCLES)); + assert_param(IS_QSPI_XIP_MD_BIT_EN(QSPI_InitStruct->XIP_MD_BITS_EN)); + assert_param(IS_QSPI_XIP_INST_L(QSPI_InitStruct->XIP_INST_L)); + assert_param(IS_QSPI_XIP_ADDR_LEN(QSPI_InitStruct->XIP_ADDR_LEN)); + assert_param(IS_QSPI_XIP_TRANS_TYPE(QSPI_InitStruct->XIP_TRANS_TYPE)); + assert_param(IS_QSPI_XIP_FRF(QSPI_InitStruct->XIP_FRF)); + + assert_param(IS_QSPI_XIP_MODE(QSPI_InitStruct->XIP_MD_BITS)); + assert_param(IS_QSPI_XIP_INCR_TOC(QSPI_InitStruct->ITOC)); + assert_param(IS_QSPI_XIP_WRAP_TOC(QSPI_InitStruct->WTOC)); + assert_param(IS_QSPI_XIP_TOUT(QSPI_InitStruct->XTOUT)); + + assert_param(IS_QSPI_NDF(QSPI_InitStruct->NDF)); + assert_param(IS_QSPI_CLK_DIV(QSPI_InitStruct->CLK_DIV)); + assert_param(IS_QSPI_TXFT(QSPI_InitStruct->TXFT)); + assert_param(IS_QSPI_RXFT(QSPI_InitStruct->RXFT)); + assert_param(IS_QSPI_TXFN(QSPI_InitStruct->TXFN)); + assert_param(IS_QSPI_RXFN(QSPI_InitStruct->RXFN)); + assert_param(IS_QSPI_DDR_TXDE(QSPI_InitStruct->TXDE)); + + if((QSPI_InitStruct->SPI_FRF) == QSPI_CTRL0_SPI_FRF_STANDARD_FORMAT) + { + tmpregister = (uint32_t)(QSPI_InitStruct->SPI_FRF | QSPI_InitStruct->CFS | QSPI_InitStruct->SSTE | QSPI_InitStruct->TMOD + | QSPI_InitStruct->SCPOL | QSPI_InitStruct->SCPH | QSPI_InitStruct->FRF | QSPI_InitStruct->DFS); + QSPI->CTRL0 = tmpregister; + + tmpregister = 0; + tmpregister = (uint32_t)(QSPI_InitStruct->MWMOD | QSPI_InitStruct->MC_DIR | QSPI_InitStruct->MHS_EN); + QSPI->MW_CTRL = tmpregister; + + tmpregister = 0; + tmpregister = (uint32_t)(QSPI_InitStruct->SES | QSPI_InitStruct->SDCN); + QSPI->RS_DELAY = tmpregister; + } + else if((QSPI_InitStruct->SPI_FRF == QSPI_CTRL0_SPI_FRF_DUAL_FORMAT) || (QSPI_InitStruct->SPI_FRF == QSPI_CTRL0_SPI_FRF_QUAD_FORMAT)) + { + tmpregister = (uint32_t)(QSPI_InitStruct->SPI_FRF | QSPI_InitStruct->CFS | QSPI_InitStruct->SSTE | QSPI_InitStruct->TMOD + | QSPI_InitStruct->SCPOL | QSPI_InitStruct->SCPH | QSPI_InitStruct->FRF | QSPI_InitStruct->DFS); + QSPI->CTRL0 = tmpregister; + + tmpregister = 0; + tmpregister = (uint32_t)(QSPI_InitStruct->MWMOD | QSPI_InitStruct->MC_DIR | QSPI_InitStruct->MHS_EN); + QSPI->MW_CTRL = tmpregister; + + tmpregister = 0; + tmpregister = (uint32_t)(QSPI_InitStruct->SES | QSPI_InitStruct->SDCN); + QSPI->RS_DELAY = tmpregister; + + tmpregister = 0; + tmpregister = (uint32_t)(QSPI_InitStruct->ENHANCED_CLK_STRETCH_EN | QSPI_InitStruct->ENHANCED_XIP_MBL | QSPI_InitStruct->ENHANCED_XIP_CT_EN + | QSPI_InitStruct->ENHANCED_XIP_INST_EN | QSPI_InitStruct->ENHANCED_XIP_DFS_HC | QSPI_InitStruct->ENHANCED_INST_DDR_EN + | QSPI_InitStruct->ENHANCED_SPI_DDR_EN | QSPI_InitStruct->ENHANCED_WAIT_CYCLES | QSPI_InitStruct->ENHANCED_INST_L + | QSPI_InitStruct->ENHANCED_MD_BIT_EN | QSPI_InitStruct->ENHANCED_ADDR_LEN | QSPI_InitStruct->ENHANCED_TRANS_TYPE); + QSPI->ENH_CTRL0 = tmpregister; + + tmpregister = 0; + tmpregister = (uint32_t)(QSPI_InitStruct->XIP_MBL | QSPI_InitStruct->XIP_CT_EN | QSPI_InitStruct->XIP_INST_EN | QSPI_InitStruct->XIP_INST_DDR_EN + | QSPI_InitStruct->XIP_DDR_EN | QSPI_InitStruct->XIP_DFS_HC | QSPI_InitStruct->XIP_WAIT_CYCLES | QSPI_InitStruct->XIP_MD_BITS_EN + | QSPI_InitStruct->XIP_INST_L | QSPI_InitStruct->XIP_ADDR_LEN | QSPI_InitStruct->XIP_TRANS_TYPE | QSPI_InitStruct->XIP_FRF); + QSPI->XIP_CTRL = tmpregister; + + QSPI->XIP_MODE = QSPI_InitStruct->XIP_MD_BITS; + QSPI->XIP_INCR_TOC = QSPI_InitStruct->ITOC; + QSPI->XIP_WRAP_TOC = QSPI_InitStruct->WTOC; + QSPI->XIP_TOUT = QSPI_InitStruct->XTOUT; + } + QSPI->CTRL1 = QSPI_InitStruct->NDF; + QSPI->BAUD = QSPI_InitStruct->CLK_DIV; + QSPI->TXFT = QSPI_InitStruct->TXFT; + QSPI->RXFT = QSPI_InitStruct->RXFT; + QSPI->TXFN = QSPI_InitStruct->TXFN; + QSPI->RXFN = QSPI_InitStruct->RXFN; + QSPI->DDR_TXDE = QSPI_InitStruct->TXDE; +} +/** + * @brief Configure single GPIO port as GPIO_Mode_AF_PP. + * @param GPIOx x can be A to G to select the GPIO port. + * @param Pin This parameter can be GPIO_PIN_0~GPIO_PIN_15. + */ +static void QSPI_SingleGpioConfig(GPIO_Module* GPIOx, uint16_t Pin) +{ + GPIO_InitType GPIO_InitStructure; + + GPIO_InitStructure.Pin = Pin; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitPeripheral(GPIOx, &GPIO_InitStructure); +} +/** + * @brief Remap QSPI AFIO group by selecting the pin of NSS. + * @param qspi_nss_port_sel select the pin of NSS. + QSPI_NSS_PORTA_SEL:QSPI remap by PA4~PA7 and PC4~PC5. + QSPI_NSS_PORTC_SEL:QSPI remap by PC10~PC12 and PD0~PD2. + QSPI_NSS_PORTF_SEL:QSPI remap by PF0~PF5. + * @param IO1_Input IO1 Configure as input or not. + * @param IO3_Output IO3 Configure as output or not. + */ +void QSPI_GPIO(QSPI_NSS_PORT_SEL qspi_nss_port_sel, bool IO1_Input, bool IO3_Output) +{ + GPIO_InitType GPIO_InitStructure; + + switch (qspi_nss_port_sel) + { + case QSPI_NSS_PORTA_SEL: + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA | RCC_APB2_PERIPH_GPIOC | RCC_APB2_PERIPH_AFIO, ENABLE); + RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_QSPI, ENABLE); + GPIO_ConfigPinRemap(GPIO_RMP3_QSPI, DISABLE); //clear two bits of qspi + + QSPI_SingleGpioConfig(GPIOA, GPIO_PIN_4); // NSS + QSPI_SingleGpioConfig(GPIOA, GPIO_PIN_5); // SCK + QSPI_SingleGpioConfig(GPIOA, GPIO_PIN_6); // IO0 + if (IO1_Input) + { + GPIO_InitStructure.Pin = GPIO_PIN_7; // IO1 + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_INPUT; + GPIO_InitPeripheral(GPIOC, &GPIO_InitStructure); + } + else + { + QSPI_SingleGpioConfig(GPIOA, GPIO_PIN_7); // IO1 + } + + if (IO3_Output) + { + GPIO_InitStructure.Pin = GPIO_PIN_4 | GPIO_PIN_5; // IO2 and IO3 + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitPeripheral(GPIOC, &GPIO_InitStructure); + + GPIOC->PBSC |= GPIO_PIN_4 | GPIO_PIN_5; + } + else + { + QSPI_SingleGpioConfig(GPIOC, GPIO_PIN_4); // IO2 + QSPI_SingleGpioConfig(GPIOC, GPIO_PIN_5); // IO3 + } + break; + case QSPI_NSS_PORTC_SEL: + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC | RCC_APB2_PERIPH_GPIOD | RCC_APB2_PERIPH_AFIO, ENABLE); + + RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_QSPI, ENABLE); + GPIO_ConfigPinRemap(GPIO_RMP3_QSPI, ENABLE); + GPIO_ConfigPinRemap(GPIO_RMP_QSPI_XIP_EN, ENABLE); + + QSPI_SingleGpioConfig(GPIOC, GPIO_PIN_10); // NSS + QSPI_SingleGpioConfig(GPIOC, GPIO_PIN_11); // SCK + QSPI_SingleGpioConfig(GPIOC, GPIO_PIN_12); // IO0 + if (IO1_Input) + { + GPIO_InitStructure.Pin = GPIO_PIN_0; // IO1 + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_INPUT; + GPIO_InitPeripheral(GPIOD, &GPIO_InitStructure); + } + else + { + QSPI_SingleGpioConfig(GPIOD, GPIO_PIN_0); // IO1 + } + + if (IO3_Output) + { + GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2; // IO2 and IO3 + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitPeripheral(GPIOD, &GPIO_InitStructure); + + GPIOD->PBSC |= GPIO_PIN_1 | GPIO_PIN_2; + } + else + { + QSPI_SingleGpioConfig(GPIOD, GPIO_PIN_1); // IO2 + QSPI_SingleGpioConfig(GPIOD, GPIO_PIN_2); // IO3 + } + break; + case QSPI_NSS_PORTF_SEL: + RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOF | RCC_APB2_PERIPH_AFIO, ENABLE); + RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_QSPI, ENABLE); + GPIO_ConfigPinRemap(GPIO_RMP1_QSPI, ENABLE); + + QSPI_SingleGpioConfig(GPIOF, GPIO_PIN_0); // NSS + QSPI_SingleGpioConfig(GPIOF, GPIO_PIN_1); // SCK + QSPI_SingleGpioConfig(GPIOF, GPIO_PIN_2); // IO0 + if (IO1_Input) + { + GPIO_InitStructure.Pin = GPIO_PIN_3; // IO1 + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_INPUT; + GPIO_InitPeripheral(GPIOF, &GPIO_InitStructure); + } + else + { + QSPI_SingleGpioConfig(GPIOF, GPIO_PIN_3); // IO1 + } + + if (IO3_Output) + { + GPIO_InitStructure.Pin = GPIO_PIN_4 | GPIO_PIN_5; // IO2 and IO3 + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitPeripheral(GPIOF, &GPIO_InitStructure); + + GPIOF->PBSC |= GPIO_PIN_4 | GPIO_PIN_5; + } + else + { + QSPI_SingleGpioConfig(GPIOF, GPIO_PIN_4); // IO2 + QSPI_SingleGpioConfig(GPIOF, GPIO_PIN_5); // IO3 + } + break; + default: + break; + } +} +/** + * @brief Configuration of QSPI DMA. + * @param TxRx transmit or receive data. + QSPI_DMA_CTRL_TX_DMA_EN:transmit data + QSPI_DMA_CTRL_RX_DMA_EN:receive data + * @param TxDataLevel dma transmit data level. + * @param RxDataLevel dma receive data level. + */ +void QSPI_DMA_CTRL_Config(uint8_t TxRx,uint8_t TxDataLevel,uint8_t RxDataLevel) +{ + assert_param(IS_QSPI_DMA_CTRL(TxRx)); + assert_param(IS_QSPI_DMATDL_CTRL(TxDataLevel)); + assert_param(IS_QSPI_DMARDL_CTRL(RxDataLevel)); + + QSPI->DMA_CTRL = 0x00; + + if (TxRx & QSPI_DMA_CTRL_TX_DMA_EN) + { + QSPI->DMATDL_CTRL = TxDataLevel; + QSPI->DMA_CTRL |= QSPI_DMA_CTRL_TX_DMA_EN; + } + if (TxRx & QSPI_DMA_CTRL_RX_DMA_EN) + { + QSPI->DMARDL_CTRL = RxDataLevel; + QSPI->DMA_CTRL |= QSPI_DMA_CTRL_RX_DMA_EN; + } +} +/** + * @brief Get the flag of interrupt status register. + * @param FLAG flag of related interrupt register. + */ +uint16_t QSPI_GetITStatus(uint16_t FLAG) +{ + uint16_t tmp = 0; + tmp = QSPI->ISTS & FLAG; + if (tmp) + return 1; + else + return 0; +} +/** + * @brief Clear the flag of related interrupt register. + * @param FLAG flag of related interrupt register. + */ +void QSPI_ClearITFLAG(uint16_t FLAG) +{ + volatile uint16_t tmp = 0; + + if (FLAG == QSPI_ISTS_TXFOIS) + tmp = QSPI->TXFOI_CLR; + if (FLAG == QSPI_ISTS_RXFOIS) + tmp = QSPI->RXFOI_CLR; + if (FLAG == QSPI_ISTS_RXFUIS) + tmp = QSPI->RXFUI_CLR; + if (FLAG == QSPI_ISTS_MMCIS) + tmp = QSPI->MMC_CLR; + if (FLAG == QSPI_ISTS) + tmp = QSPI->ICLR; +} +/** + * @brief Clear the flag of related interrupt register. + * @param FLAG flag of XRXFOIC interrupt register. + */ +void QSPI_XIP_ClearITFLAG(uint16_t FLAG) +{ + volatile uint16_t tmp = 0; + + if (FLAG == QSPI_XIP_RXFOI_CLR_XRXFOIC) + tmp = QSPI->XIP_RXFOI_CLR; +} +/** + * @brief Get QSPI status,busy or not. + * @return 1:QSPI busy;0:QSPI idle. + */ +bool GetQspiBusyStatus(void) +{ + if ((QSPI->STS & 0x01) == 0x01) + return 1; + return 0; +} +/** + * @brief Check transmit fifo full or not. + * @return 1: Transmit fifo full;0: Transmit fifo not full. + */ +bool GetQspiTxDataBusyStatus(void) +{ + if ((QSPI->STS & 0x02) == 0x00) + return 1; + return 0; +} +/** + * @brief Check transmit fifo empty or not. + * @return 1: Transmit fifo empty;0: Transmit fifo not empty. + */ +bool GetQspiTxDataEmptyStatus(void) +{ + if ((QSPI->STS & 0x04) == 0x04) + return 1; + return 0; +} +/** + * @brief Check receive fifo have data or not. + * @return 1:Receive fifo have data;0:Receive fifo empty. + */ +bool GetQspiRxHaveDataStatus(void) +{ + if ((QSPI->STS & 0x08) == 0x08) + return 1; + return 0; +} +/** + * @brief Check receive fifo full or not. + * @return 1: Receive fifo full;0: Receive fifo not full. + */ +bool GetQspiRxDataFullStatus(void) +{ + if ((QSPI->STS & 0x10) == 0x10) + return 1; + return 0; +} +/** + * @brief Check transmit error or not. + * @return 1: Transmit error;0: No transmit error. + */ +bool GetQspiTransmitErrorStatus(void) +{ + if ((QSPI->STS & 0x20) == 0x20) + return 1; + return 0; +} +/** + * @brief Check data conflict error or not. + * @return 1: Data conflict error;0: No data conflict error. + */ +bool GetQspiDataConflictErrorStatus(void) +{ + if ((QSPI->STS & 0x40) == 0x40) + return 1; + return 0; +} +/** + * @brief Write one data direct to QSPI DAT0 register to send. + * @param SendData: data to be send. + */ +void QspiSendWord(uint32_t SendData) +{ + QSPI->DAT0 = SendData; +} +/** + * @brief Read one data from QSPI DAT0 register. + * @return the value of QSPI DAT0 register. + */ +uint32_t QspiReadWord(void) +{ + return QSPI->DAT0; +} +/** + * @brief Get Pointer of QSPI DAT0 register. + * @return the pointer of QSPI DAT0 register. + */ +uint32_t QspiGetDataPointer(void) +{ + return (uint32_t)&QSPI->DAT0; +} +/** + * @brief Read value from QSPI RXFN register which shows the number of the data from receive fifo. + * @return the number of the data from receive fifo. + */ +uint32_t QspiReadRxFifoNum(void) +{ + return QSPI->RXFN; +} +/** + * @brief Read DAT0 register to clear fifo. + */ +void ClrFifo(void) +{ + uint32_t timeout = 0; + + while (GetQspiRxHaveDataStatus()) + { + QspiReadWord(); + if(++timeout >= 200) + { + break; + } + } +} +/** + * @brief Get data from fifo. + * @param pData pointer to buffer of getting fifo data. + * @param Len length of getting fifo data. + */ +uint32_t GetFifoData(uint32_t* pData, uint32_t Len) +{ + uint32_t cnt; + for (cnt = 0; cnt < Len; cnt++) + { + if (GetQspiRxHaveDataStatus()) + { + *pData++ = QspiReadWord(); + } + else + { + return QSPI_NULL; + } + } + + return QSPI_SUCCESS; +} +/** + * @brief Send words out from source data buffer and get returned datas into destination data buffer. + * @param pSrcData pointer to buffer of sending datas. + * @param pDstData pointer to buffer of getting returned datas. + * @param cnt number of sending datas. + */ +void QspiSendAndGetWords(uint32_t* pSrcData, uint32_t* pDstData, uint32_t cnt) +{ + uint32_t num = 0; + uint32_t timeout = 0; + + while (num < cnt) + { + QspiSendWord(*(pSrcData++)); + num++; + } + while (!GetQspiRxHaveDataStatus()) + { + if(++timeout >= QSPI_TIME_OUT_CNT) + { + break; + } + } + timeout = 0; + while (QSPI->RXFN < cnt) + { + if(++timeout >= QSPI_TIME_OUT_CNT) + { + break; + } + } + num = 0; + while (num < cnt) + { + *(pDstData++) = QspiReadWord(); + num++; + } +} +/** + * @brief Send one word data and get returned words into destination data buffer. + * @param WrData one word to be sent. + * @param pRdData pointer to buffer of getting returned datas. + * @param LastRd whether go on to get returned datas. + 1:go on to get returned datas. + 0:end to get returned datas. + */ +uint32_t QspiSendWordAndGetWords(uint32_t WrData, uint32_t* pRdData, uint8_t LastRd) +{ + uint32_t timeout1 = 0; + + QspiSendWord(WrData); //trammit + *pRdData = QspiReadWord(); + if(LastRd != 0) + { + while(!GetQspiRxHaveDataStatus()) //wait for data + { + if(++timeout1 >= QSPI_TIME_OUT_CNT) + { + return QSPI_NULL; //time out + } + } + + *pRdData = QspiReadWord(); //read data + return QSPI_SUCCESS; + } + + return QSPI_NULL; +} + + diff --git a/src/n32g45x_rcc.c b/src/n32g45x_rcc.c new file mode 100644 index 0000000..914a7f2 --- /dev/null +++ b/src/n32g45x_rcc.c @@ -0,0 +1,1364 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_rcc.c + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup RCC + * @brief RCC driver modules + * @{ + */ + +/** @addtogroup RCC_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup RCC_Private_Defines + * @{ + */ + +/* ------------ RCC registers bit address in the alias region ----------- */ +#define RCC_OFFSET (RCC_BASE - PERIPH_BASE) + +/* --- CTRL Register ---*/ + +/* Alias word address of HSIEN bit */ +#define CTRL_OFFSET (RCC_OFFSET + 0x00) +#define HSIEN_BITN 0x00 +#define CTRL_HSIEN_BB (PERIPH_BB_BASE + (CTRL_OFFSET * 32) + (HSIEN_BITN * 4)) + +/* Alias word address of PLLEN bit */ +#define PLLEN_BITN 0x18 +#define CTRL_PLLEN_BB (PERIPH_BB_BASE + (CTRL_OFFSET * 32) + (PLLEN_BITN * 4)) + +/* Alias word address of CLKSSEN bit */ +#define CLKSSEN_BITN 0x13 +#define CTRL_CLKSSEN_BB (PERIPH_BB_BASE + (CTRL_OFFSET * 32) + (CLKSSEN_BITN * 4)) + +/* --- CFG Register ---*/ + +/* Alias word address of USBPRES bit */ +#define CFG_OFFSET (RCC_OFFSET + 0x04) + +#define USBPRES_BITN 0x16 +#define CFG_USBPRES_BB (PERIPH_BB_BASE + (CFG_OFFSET * 32) + (USBPRES_BITN * 4)) + +#define USBPRE_Bit1Number 0x17 +#define CFGR_USBPRE_BB_BIT1 (PERIPH_BB_BASE + (CFG_OFFSET * 32) + (USBPRE_Bit1Number * 4)) + +/* --- BDCTRL Register ---*/ + +/* Alias word address of RTCEN bit */ +#define BDCTRL_OFFSET (RCC_OFFSET + 0x20) +#define RTCEN_BITN 0x0F +#define BDCTRL_RTCEN_BB (PERIPH_BB_BASE + (BDCTRL_OFFSET * 32) + (RTCEN_BITN * 4)) + +/* Alias word address of BDSFTRST bit */ +#define BDSFTRST_BITN 0x10 +#define BDCTRL_BDSFTRST_BB (PERIPH_BB_BASE + (BDCTRL_OFFSET * 32) + (BDSFTRST_BITN * 4)) + +/* --- CTRLSTS Register ---*/ + +/* Alias word address of LSIEN bit */ +#define CTRLSTS_OFFSET (RCC_OFFSET + 0x24) +#define LSIEN_BITNUMBER 0x00 +#define CTRLSTS_LSIEN_BB (PERIPH_BB_BASE + (CTRLSTS_OFFSET * 32) + (LSIEN_BITNUMBER * 4)) + +/* ---------------------- RCC registers bit mask ------------------------ */ + +/* CTRL register bit mask */ +#define CTRL_HSEBP_RESET ((uint32_t)0xFFFBFFFF) +#define CTRL_HSEBP_SET ((uint32_t)0x00040000) +#define CTRL_HSEEN_RESET ((uint32_t)0xFFFEFFFF) +#define CTRL_HSEEN_SET ((uint32_t)0x00010000) +#define CTRL_HSITRIM_MASK ((uint32_t)0xFFFFFF07) + +/* CFG register bit mask */ +#define CFG_PLL_MASK ((uint32_t)0xF7C0FFFF) + +#define CFG_PLLMULFCT_MASK ((uint32_t)0x083C0000) +#define CFG_PLLSRC_MASK ((uint32_t)0x00010000) +#define CFG_PLLHSEPRES_MASK ((uint32_t)0x00020000) +#define CFG_SCLKSTS_MASK ((uint32_t)0x0000000C) +#define CFG_SCLKSW_MASK ((uint32_t)0xFFFFFFFC) +#define CFG_AHBPRES_RESET_MASK ((uint32_t)0xFFFFFF0F) +#define CFG_AHBPRES_SET_MASK ((uint32_t)0x000000F0) +#define CFG_APB1PRES_RESET_MASK ((uint32_t)0xFFFFF8FF) +#define CFG_APB1PRES_SET_MASK ((uint32_t)0x00000700) +#define CFG_APB2PRES_RESET_MASK ((uint32_t)0xFFFFC7FF) +#define CFG_APB2PRES_SET_MASK ((uint32_t)0x00003800) + +/* CFG2 register bit mask */ +#define CFG2_TIM18CLKSEL_SET_MASK ((uint32_t)0x20000000) +#define CFG2_TIM18CLKSEL_RESET_MASK ((uint32_t)0xDFFFFFFF) +#define CFG2_RNGCPRES_SET_MASK ((uint32_t)0x1F000000) +#define CFG2_RNGCPRES_RESET_MASK ((uint32_t)0xE0FFFFFF) +#define CFG2_ADC1MSEL_SET_MASK ((uint32_t)0x00000400) +#define CFG2_ADC1MSEL_RESET_MASK ((uint32_t)0xFFFFFBFF) +#define CFG2_ADC1MPRES_SET_MASK ((uint32_t)0x0000F800) +#define CFG2_ADC1MPRES_RESET_MASK ((uint32_t)0xFFFF07FF) +#define CFG2_ADCPLLPRES_SET_MASK ((uint32_t)0x000001F0) +#define CFG2_ADCPLLPRES_RESET_MASK ((uint32_t)0xFFFFFE0F) +#define CFG2_ADCHPRES_SET_MASK ((uint32_t)0x0000000F) +#define CFG2_ADCHPRES_RESET_MASK ((uint32_t)0xFFFFFFF0) + +/* CFG3 register bit mask */ +#define CFGR3_TRNG1MSEL_SET_MASK ((uint32_t)0x00020000) +#define CFGR3_TRNG1MSEL_RESET_MASK ((uint32_t)0xFFFDFFFF) +#define CFGR3_TRNG1MPRES_SET_MASK ((uint32_t)0x0000F800) +#define CFGR3_TRNG1MPRES_RESET_MASK ((uint32_t)0xFFFF07FF) + +/* CTRLSTS register bit mask */ +#define CSR_RMRSTF_SET ((uint32_t)0x01000000) +#define CSR_RMVF_Reset ((uint32_t)0xfeffffff) + +/* RCC Flag Mask */ +#define FLAG_MASK ((uint8_t)0x1F) + +/* CLKINT register byte 2 (Bits[15:8]) base address */ +#define CLKINT_BYTE2_ADDR ((uint32_t)0x40021009) + +/* CLKINT register byte 3 (Bits[23:16]) base address */ +#define CLKINT_BYTE3_ADDR ((uint32_t)0x4002100A) + +/* CFG register byte 4 (Bits[31:24]) base address */ +#define CFG_BYTE4_ADDR ((uint32_t)0x40021007) + +/* BDCTRL register base address */ +#define BDCTRL_ADDR (PERIPH_BASE + BDCTRL_OFFSET) + +/** + * @} + */ + +/** @addtogroup RCC_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup RCC_Private_Variables + * @{ + */ + +static const uint8_t s_ApbAhbPresTable[16] = {0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9}; +static const uint8_t s_AdcHclkPresTable[16] = {1, 2, 4, 6, 8, 10, 12, 16, 32, 32, 32, 32, 32, 32, 32, 32}; +static const uint16_t s_AdcPllClkPresTable[16] = {1, 2, 4, 6, 8, 10, 12, 16, 32, 64, 128, 256, 256, 256, 256, 256}; + +/** + * @} + */ + +/** @addtogroup RCC_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup RCC_Private_Functions + * @{ + */ + +/** + * @brief Resets the RCC clock configuration to the default reset state. + */ +void RCC_DeInit(void) +{ + /* Set HSIEN bit */ + RCC->CTRL |= (uint32_t)0x00000001; + + /* Reset SW, HPRE, PPRE1, PPRE2 and MCO bits */ + RCC->CFG &= (uint32_t)0xF8FFC000; + + /* Reset HSEON, CLKSSEN and PLLEN bits */ + RCC->CTRL &= (uint32_t)0xFEF6FFFF; + + /* Reset HSEBYP bit */ + RCC->CTRL &= (uint32_t)0xFFFBFFFF; + + /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRES/OTGFSPRE bits */ + RCC->CFG &= (uint32_t)0xF700FFFF; + + /* Reset CFG2 register */ + RCC->CFG2 = 0x00003800; + + /* Reset CFG3 register */ + RCC->CFG3 = 0x00003800; + + /* Disable all interrupts and clear pending bits */ + RCC->CLKINT = 0x009F0000; +} + +/** + * @brief Configures the External High Speed oscillator (HSE). + * @note HSE can not be stopped if it is used directly or through the PLL as system clock. + * @param RCC_HSE specifies the new state of the HSE. + * This parameter can be one of the following values: + * @arg RCC_HSE_DISABLE HSE oscillator OFF + * @arg RCC_HSE_ENABLE HSE oscillator ON + * @arg RCC_HSE_BYPASS HSE oscillator bypassed with external clock + */ +void RCC_ConfigHse(uint32_t RCC_HSE) +{ + /* Check the parameters */ + assert_param(IS_RCC_HSE(RCC_HSE)); + /* Reset HSEON and HSEBYP bits before configuring the HSE ------------------*/ + /* Reset HSEON bit */ + RCC->CTRL &= CTRL_HSEEN_RESET; + /* Reset HSEBYP bit */ + RCC->CTRL &= CTRL_HSEBP_RESET; + /* Configure HSE (RC_HSE_DISABLE is already covered by the code section above) */ + switch (RCC_HSE) + { + case RCC_HSE_ENABLE: + /* Set HSEON bit */ + RCC->CTRL |= CTRL_HSEEN_SET; + break; + + case RCC_HSE_BYPASS: + /* Set HSEBYP and HSEON bits */ + RCC->CTRL |= CTRL_HSEBP_SET | CTRL_HSEEN_SET; + break; + + default: + break; + } +} + +/** + * @brief Waits for HSE start-up. + * @return An ErrorStatus enumuration value: + * - SUCCESS: HSE oscillator is stable and ready to use + * - ERROR: HSE oscillator not yet ready + */ +ErrorStatus RCC_WaitHseStable(void) +{ + __IO uint32_t StartUpCounter = 0; + ErrorStatus status = ERROR; + FlagStatus HSEStatus = RESET; + + /* Wait till HSE is ready and if Time out is reached exit */ + do + { + HSEStatus = RCC_GetFlagStatus(RCC_FLAG_HSERD); + StartUpCounter++; + } while ((StartUpCounter != HSE_STARTUP_TIMEOUT) && (HSEStatus == RESET)); + + if (RCC_GetFlagStatus(RCC_FLAG_HSERD) != RESET) + { + status = SUCCESS; + } + else + { + status = ERROR; + } + return (status); +} + +/** + * @brief Adjusts the Internal High Speed oscillator (HSI) calibration value. + * @param HSICalibrationValue specifies the calibration trimming value. + * This parameter must be a number between 0 and 0x1F. + */ +void RCC_SetHsiCalibValue(uint8_t HSICalibrationValue) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_RCC_CALIB_VALUE(HSICalibrationValue)); + tmpregister = RCC->CTRL; + /* Clear HSITRIM[4:0] bits */ + tmpregister &= CTRL_HSITRIM_MASK; + /* Set the HSITRIM[4:0] bits according to HSICalibrationValue value */ + tmpregister |= (uint32_t)HSICalibrationValue << 3; + /* Store the new value */ + RCC->CTRL = tmpregister; +} + +/** + * @brief Enables or disables the Internal High Speed oscillator (HSI). + * @note HSI can not be stopped if it is used directly or through the PLL as system clock. + * @param Cmd new state of the HSI. This parameter can be: ENABLE or DISABLE. + */ +void RCC_EnableHsi(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + *(__IO uint32_t*)CTRL_HSIEN_BB = (uint32_t)Cmd; +} + +/** + * @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_PLL_SRC_HSI_DIV2 HSI oscillator clock divided by 2 selected as PLL clock entry + * @arg RCC_PLL_SRC_HSE_DIV1 HSE oscillator clock selected as PLL clock entry + * @arg RCC_PLL_SRC_HSE_DIV2 HSE oscillator clock divided by 2 selected as PLL clock entry + * @param RCC_PLLMul specifies the PLL multiplication factor. + * this parameter can be RCC_PLLMul_x where x:[2,32] + */ +void RCC_ConfigPll(uint32_t RCC_PLLSource, uint32_t RCC_PLLMul) +{ + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_RCC_PLL_SRC(RCC_PLLSource)); + assert_param(IS_RCC_PLL_MUL(RCC_PLLMul)); + + tmpregister = RCC->CFG; + /* Clear PLLSRC, PLLXTPRE and PLLMUL[4:0] bits */ + tmpregister &= CFG_PLL_MASK; + /* Set the PLL configuration bits */ + tmpregister |= RCC_PLLSource | RCC_PLLMul; + /* Store the new value */ + RCC->CFG = tmpregister; +} + +/** + * @brief Enables or disables the PLL. + * @note The PLL can not be disabled if it is used as system clock. + * @param Cmd new state of the PLL. This parameter can be: ENABLE or DISABLE. + */ +void RCC_EnablePll(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + *(__IO uint32_t*)CTRL_PLLEN_BB = (uint32_t)Cmd; +} + +/** + * @brief Configures the system clock (SYSCLK). + * @param RCC_SYSCLKSource specifies the clock source used as system clock. + * This parameter can be one of the following values: + * @arg RCC_SYSCLK_SRC_HSI HSI selected as system clock + * @arg RCC_SYSCLK_SRC_HSE HSE selected as system clock + * @arg RCC_SYSCLK_SRC_PLLCLK PLL selected as system clock + */ +void RCC_ConfigSysclk(uint32_t RCC_SYSCLKSource) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_RCC_SYSCLK_SRC(RCC_SYSCLKSource)); + tmpregister = RCC->CFG; + /* Clear SW[1:0] bits */ + tmpregister &= CFG_SCLKSW_MASK; + /* Set SW[1:0] bits according to RCC_SYSCLKSource value */ + tmpregister |= RCC_SYSCLKSource; + /* Store the new value */ + RCC->CFG = tmpregister; +} + +/** + * @brief Returns the clock source used as system clock. + * @return The clock source used as system clock. The returned value can + * be one of the following: + * - 0x00: HSI used as system clock + * - 0x04: HSE used as system clock + * - 0x08: PLL used as system clock + */ +uint8_t RCC_GetSysclkSrc(void) +{ + return ((uint8_t)(RCC->CFG & CFG_SCLKSTS_MASK)); +} + +/** + * @brief Configures the AHB clock (HCLK). + * @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 + */ +void RCC_ConfigHclk(uint32_t RCC_SYSCLK) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_RCC_SYSCLK_DIV(RCC_SYSCLK)); + tmpregister = RCC->CFG; + /* Clear HPRE[3:0] bits */ + tmpregister &= CFG_AHBPRES_RESET_MASK; + /* Set HPRE[3:0] bits according to RCC_SYSCLK value */ + tmpregister |= RCC_SYSCLK; + /* Store the new value */ + RCC->CFG = tmpregister; +} + +/** + * @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 + */ +void RCC_ConfigPclk1(uint32_t RCC_HCLK) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_RCC_HCLK_DIV(RCC_HCLK)); + tmpregister = RCC->CFG; + /* Clear PPRE1[2:0] bits */ + tmpregister &= CFG_APB1PRES_RESET_MASK; + /* Set PPRE1[2:0] bits according to RCC_HCLK value */ + tmpregister |= RCC_HCLK; + /* Store the new value */ + RCC->CFG = tmpregister; +} + +/** + * @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 + */ +void RCC_ConfigPclk2(uint32_t RCC_HCLK) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_RCC_HCLK_DIV(RCC_HCLK)); + tmpregister = RCC->CFG; + /* Clear PPRE2[2:0] bits */ + tmpregister &= CFG_APB2PRES_RESET_MASK; + /* Set PPRE2[2:0] bits according to RCC_HCLK value */ + tmpregister |= RCC_HCLK << 3; + /* Store the new value */ + RCC->CFG = tmpregister; +} + +/** + * @brief Enables or disables the specified RCC interrupts. + * @param RccInt specifies the RCC interrupt sources to be enabled or disabled. + * + * this parameter can be any combination of the following values + * @arg RCC_INT_LSIRDIF LSI ready interrupt + * @arg RCC_INT_LSERDIF LSE ready interrupt + * @arg RCC_INT_HSIRDIF HSI ready interrupt + * @arg RCC_INT_HSERDIF HSE ready interrupt + * @arg RCC_INT_PLLRDIF PLL ready interrupt + * + * @param Cmd new state of the specified RCC interrupts. + * This parameter can be: ENABLE or DISABLE. + */ +void RCC_ConfigInt(uint8_t RccInt, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_RCC_INT(RccInt)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Perform Byte access to RCC_CLKINT bits to enable the selected interrupts */ + *(__IO uint8_t*)CLKINT_BYTE2_ADDR |= RccInt; + } + else + { + /* Perform Byte access to RCC_CLKINT bits to disable the selected interrupts */ + *(__IO uint8_t*)CLKINT_BYTE2_ADDR &= (uint8_t)~RccInt; + } +} + +/** + * @brief Configures the USB clock (USBCLK). + * @param RCC_USBCLKSource specifies the USB clock source. This clock is + * derived from the PLL output. + * This parameter can be one of the following values: + * @arg RCC_USBCLK_SRC_PLLCLK_DIV1_5 PLL clock divided by 1,5 selected as USB clock source + * @arg RCC_USBCLK_SRC_PLLCLK_DIV1 PLL clock selected as USB clock source + * @arg RCC_USBCLK_SRC_PLLCLK_DIV2 PLL clock divided by 2 selected as USB clock source + * @arg RCC_USBCLK_SRC_PLLCLK_DIV3 PLL clock divided by 3 selected as USB clock source + */ +void RCC_ConfigUsbClk(uint32_t RCC_USBCLKSource) +{ + /* Check the parameters */ + assert_param(IS_RCC_USBCLK_SRC(RCC_USBCLKSource)); + + *(__IO uint32_t*)CFG_USBPRES_BB = RCC_USBCLKSource; + *(__IO uint32_t*)CFGR_USBPRE_BB_BIT1 = RCC_USBCLKSource >> 1; +} + +/** + * @brief Configures the TIM1/8 clock (TIM1/8CLK). + * @param RCC_TIM18CLKSource specifies the TIM1/8 clock source. + * This parameter can be one of the following values: + * @arg RCC_TIM18CLK_SRC_TIM18CLK + * @arg RCC_TIM18CLKSource_AHBCLK + */ +void RCC_ConfigTim18Clk(uint32_t RCC_TIM18CLKSource) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_RCC_TIM18CLKSRC(RCC_TIM18CLKSource)); + + tmpregister = RCC->CFG2; + /* Clear TIMCLK_SEL bits */ + tmpregister &= CFG2_TIM18CLKSEL_RESET_MASK; + /* Set TIMCLK_SEL bits according to RCC_TIM18CLKSource value */ + tmpregister |= RCC_TIM18CLKSource; + + /* Store the new value */ + RCC->CFG2 = tmpregister; +} + +/** + * @brief Configures the RNGCCLK prescaler. + * @param RCC_RNGCCLKPrescaler specifies the RNGCCLK prescaler. + * This parameter can be one of the following values: + * @arg RCC_RNGCCLK_SYSCLK_DIV1 RNGCPRE[24:28] = 00000, SYSCLK Divided By 1 + * @arg RCC_RNGCCLK_SYSCLK_DIV2 RNGCPRE[24:28] = 00001, SYSCLK Divided By 2 + * @arg RCC_RNGCCLK_SYSCLK_DIV3 RNGCPRE[24:28] = 00002, SYSCLK Divided By 3 + * ... + * @arg RCC_RNGCCLK_SYSCLK_DIV31 RNGCPRE[24:28] = 11110, SYSCLK Divided By 31 + * @arg RCC_RNGCCLK_SYSCLK_DIV32 RNGCPRE[24:28] = 11111, SYSCLK Divided By 32 + */ +void RCC_ConfigRngcClk(uint32_t RCC_RNGCCLKPrescaler) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_RCC_RNGCCLKPRE(RCC_RNGCCLKPrescaler)); + + tmpregister = RCC->CFG2; + /* Clear RNGCPRE[3:0] bits */ + tmpregister &= CFG2_RNGCPRES_RESET_MASK; + /* Set RNGCPRE[3:0] bits according to RCC_RNGCCLKPrescaler value */ + tmpregister |= RCC_RNGCCLKPrescaler; + + /* Store the new value */ + RCC->CFG2 = tmpregister; +} + +/** + * @brief Configures the ADCx 1M clock (ADC1MCLK). + * @param RCC_ADC1MCLKSource specifies the ADC1M clock source. + * This parameter can be on of the following values: + * @arg RCC_ADC1MCLK_SRC_HSI + * @arg RCC_ADC1MCLK_SRC_HSE + * + * @param RCC_ADC1MPrescaler specifies the ADC1M clock prescaler. + * This parameter can be on of the following values: + * @arg RCC_ADC1MCLK_DIV1 ADC1M clock = RCC_ADC1MCLKSource_xxx/1 + * @arg RCC_ADC1MCLK_DIV2 ADC1M clock = RCC_ADC1MCLKSource_xxx/2 + * @arg RCC_ADC1MCLK_DIV3 ADC1M clock = RCC_ADC1MCLKSource_xxx/3 + * ... + * @arg RCC_ADC1MCLK_DIV31 ADC1M clock = RCC_ADC1MCLKSource_xxx/31 + * @arg RCC_ADC1MCLK_DIV32 ADC1M clock = RCC_ADC1MCLKSource_xxx/32 + */ +void RCC_ConfigAdc1mClk(uint32_t RCC_ADC1MCLKSource, uint32_t RCC_ADC1MPrescaler) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_RCC_ADC1MCLKSRC(RCC_ADC1MCLKSource)); + assert_param(IS_RCC_ADC1MCLKPRE(RCC_ADC1MPrescaler)); + + tmpregister = RCC->CFG2; + /* Clear ADC1MSEL and ADC1MPRE[4:0] bits */ + tmpregister &= CFG2_ADC1MSEL_RESET_MASK; + tmpregister &= CFG2_ADC1MPRES_RESET_MASK; + /* Set ADC1MSEL bits according to RCC_ADC1MCLKSource value */ + tmpregister |= RCC_ADC1MCLKSource; + /* Set ADC1MPRE[4:0] bits according to RCC_ADC1MPrescaler value */ + tmpregister |= RCC_ADC1MPrescaler; + + /* Store the new value */ + RCC->CFG2 = tmpregister; +} + +/** + * @brief Configures the ADCPLLCLK prescaler, and enable/disable ADCPLLCLK. + * @param RCC_ADCPLLCLKPrescaler specifies the ADCPLLCLK prescaler. + * This parameter can be on of the following values: + * @arg RCC_ADCPLLCLK_DISABLE ADCPLLCLKPRES[4:0] = 0xxxx, ADC Pll Clock Disable + * @arg RCC_ADCPLLCLK_DIV1 ADCPLLCLKPRES[4:0] = 10000, Pll Clock Divided By 1 + * @arg RCC_ADCPLLCLK_DIV2 ADCPLLCLKPRES[4:0] = 10001, Pll Clock Divided By 2 + * @arg RCC_ADCPLLCLK_DIV4 ADCPLLCLKPRES[4:0] = 10010, Pll Clock Divided By 4 + * @arg RCC_ADCPLLCLK_DIV6 ADCPLLCLKPRES[4:0] = 10011, Pll Clock Divided By 6 + * @arg RCC_ADCPLLCLK_DIV8 ADCPLLCLKPRES[4:0] = 10100, Pll Clock Divided By 8 + * @arg RCC_ADCPLLCLK_DIV10 ADCPLLCLKPRES[4:0] = 10101, Pll Clock Divided By 10 + * @arg RCC_ADCPLLCLK_DIV12 ADCPLLCLKPRES[4:0] = 10110, Pll Clock Divided By 12 + * @arg RCC_ADCPLLCLK_DIV16 ADCPLLCLKPRES[4:0] = 10111, Pll Clock Divided By 16 + * @arg RCC_ADCPLLCLK_DIV32 ADCPLLCLKPRES[4:0] = 11000, Pll Clock Divided By 32 + * @arg RCC_ADCPLLCLK_DIV64 ADCPLLCLKPRES[4:0] = 11001, Pll Clock Divided By 64 + * @arg RCC_ADCPLLCLK_DIV128 ADCPLLCLKPRES[4:0] = 11010, Pll Clock Divided By 128 + * @arg RCC_ADCPLLCLK_DIV256 ADCPLLCLKPRES[4:0] = 11011, Pll Clock Divided By 256 + * @arg RCC_ADCPLLCLK_DIV256 ADCPLLCLKPRES[4:0] = others, Pll Clock Divided By 256 + * + * @param Cmd specifies the ADCPLLCLK enable/disable selection. + * This parameter can be on of the following values: + * @arg ENABLE enable ADCPLLCLK + * @arg DISABLE disable ADCPLLCLK + */ +void RCC_ConfigAdcPllClk(uint32_t RCC_ADCPLLCLKPrescaler, FunctionalState Cmd) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_RCC_ADCPLLCLKPRE(RCC_ADCPLLCLKPrescaler)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + tmpregister = RCC->CFG2; + /* Clear ADCPLLPRES[4:0] bits */ + tmpregister &= CFG2_ADCPLLPRES_RESET_MASK; + + if (Cmd != DISABLE) + { + tmpregister |= RCC_ADCPLLCLKPrescaler; + } + else + { + tmpregister |= RCC_ADCPLLCLKPrescaler; + tmpregister &= RCC_ADCPLLCLK_DISABLE; + } + + /* Store the new value */ + RCC->CFG2 = tmpregister; +} + +/** + * @brief Configures the ADCHCLK prescaler. + * @param RCC_ADCHCLKPrescaler specifies the ADCHCLK prescaler. + * This parameter can be on of the following values: + * @arg RCC_ADCHCLK_DIV1 ADCHCLKPRE[3:0] = 0000, HCLK Clock Divided By 1 + * @arg RCC_ADCHCLK_DIV2 ADCHCLKPRE[3:0] = 0001, HCLK Clock Divided By 2 + * @arg RCC_ADCHCLK_DIV4 ADCHCLKPRE[3:0] = 0010, HCLK Clock Divided By 4 + * @arg RCC_ADCHCLK_DIV6 ADCHCLKPRE[3:0] = 0011, HCLK Clock Divided By 6 + * @arg RCC_ADCHCLK_DIV8 ADCHCLKPRE[3:0] = 0100, HCLK Clock Divided By 8 + * @arg RCC_ADCHCLK_DIV10 ADCHCLKPRE[3:0] = 0101, HCLK Clock Divided By 10 + * @arg RCC_ADCHCLK_DIV12 ADCHCLKPRE[3:0] = 0110, HCLK Clock Divided By 12 + * @arg RCC_ADCHCLK_DIV16 ADCHCLKPRE[3:0] = 0111, HCLK Clock Divided By 16 + * @arg RCC_ADCHCLK_DIV32 ADCHCLKPRE[3:0] = 1000, HCLK Clock Divided By 32 + * @arg RCC_ADCHCLK_DIV32 ADCHCLKPRE[3:0] = others, HCLK Clock Divided By 32 + */ +void RCC_ConfigAdcHclk(uint32_t RCC_ADCHCLKPrescaler) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_RCC_ADCHCLKPRE(RCC_ADCHCLKPrescaler)); + + tmpregister = RCC->CFG2; + /* Clear ADCHPRE[3:0] bits */ + tmpregister &= CFG2_ADCHPRES_RESET_MASK; + /* Set ADCHPRE[3:0] bits according to RCC_ADCHCLKPrescaler value */ + tmpregister |= RCC_ADCHCLKPrescaler; + + /* Store the new value */ + RCC->CFG2 = tmpregister; +} + +/** + * @brief Configures the TRNG 1M clock (TRNG1MCLK). + * @param RCC_TRNG1MCLKSource specifies the TRNG1M clock source. + * This parameter can be on of the following values: + * @arg RCC_TRNG1MCLK_SRC_HSI + * @arg RCC_TRNG1MCLK_SRC_HSE + * + * @param RCC_TRNG1MPrescaler specifies the TRNG1M prescaler. + * This parameter can be on of the following values: + * @arg RCC_TRNG1MCLKDiv_2 TRNG1M clock = RCC_TRNG1MCLKSource_xxx/2 + * @arg RCC_TRNG1MCLKDiv_4 TRNG1M clock = RCC_TRNG1MCLKSource_xxx/4 + * @arg RCC_TRNG1MCLKDiv_6 TRNG1M clock = RCC_TRNG1MCLKSource_xxx/6 + * ... + * @arg RCC_TRNG1MCLKDiv_30 TRNG1M clock = RCC_TRNG1MCLKSource_xxx/30 + * @arg RCC_TRNG1MCLKDiv_32 TRNG1M clock = RCC_TRNG1MCLKSource_xxx/32 + */ +void RCC_ConfigTrng1mClk(uint32_t RCC_TRNG1MCLKSource, uint32_t RCC_TRNG1MPrescaler) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_RCC_TRNG1MCLK_SRC(RCC_TRNG1MCLKSource)); + assert_param(IS_RCC_TRNG1MCLKPRE(RCC_TRNG1MPrescaler)); + + tmpregister = RCC->CFG3; + /* Clear TRNG1MSEL and TRNG1MPRE[4:0] bits */ + tmpregister &= CFGR3_TRNG1MSEL_RESET_MASK; + tmpregister &= CFGR3_TRNG1MPRES_RESET_MASK; + /* Set TRNG1MSEL bits according to RCC_TRNG1MCLKSource value */ + tmpregister |= RCC_TRNG1MCLKSource; + /* Set TRNG1MPRE[4:0] bits according to RCC_TRNG1MPrescaler value */ + tmpregister |= RCC_TRNG1MPrescaler; + + /* Store the new value */ + RCC->CFG3 = tmpregister; +} + +/** + * @brief Enable/disable TRNG clock (TRNGCLK). + * @param Cmd specifies the TRNGCLK enable/disable selection. + * This parameter can be on of the following values: + * @arg ENABLE enable TRNGCLK + * @arg DISABLE disable TRNGCLK + */ +void RCC_EnableTrng1mClk(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + RCC->CFG3 |= RCC_TRNG1MCLK_ENABLE; + } + else + { + RCC->CFG3 &= RCC_TRNG1MCLK_DISABLE; + } +} + +/** + * @brief Configures the External Low Speed oscillator (LSE). + * @param RCC_LSE specifies the new state of the LSE. + * This parameter can be one of the following values: + * @arg RCC_LSE_DISABLE LSE oscillator OFF + * @arg RCC_LSE_ENABLE LSE oscillator ON + * @arg RCC_LSE_BYPASS LSE oscillator bypassed with external clock + */ +void RCC_ConfigLse(uint8_t RCC_LSE) +{ + /* Check the parameters */ + assert_param(IS_RCC_LSE(RCC_LSE)); + /* Reset LSEON and LSEBYP bits before configuring the LSE ------------------*/ + /* Reset LSEON bit */ + *(__IO uint8_t*)BDCTRL_ADDR = RCC_LSE_DISABLE; + /* Reset LSEBYP bit */ + *(__IO uint8_t*)BDCTRL_ADDR = RCC_LSE_DISABLE; + /* Configure LSE (RCC_LSE_DISABLE is already covered by the code section above) */ + switch (RCC_LSE) + { + case RCC_LSE_ENABLE: + /* Set LSEON bit */ + *(__IO uint8_t*)BDCTRL_ADDR = RCC_LSE_ENABLE; + break; + + case RCC_LSE_BYPASS: + /* Set LSEBYP and LSEON bits */ + *(__IO uint8_t*)BDCTRL_ADDR = RCC_LSE_BYPASS | RCC_LSE_ENABLE; + break; + + default: + break; + } +} + +/** + * @brief Enables or disables the Internal Low Speed oscillator (LSI). + * @note LSI can not be disabled if the IWDG is running. + * @param Cmd new state of the LSI. This parameter can be: ENABLE or DISABLE. + */ +void RCC_EnableLsi(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + *(__IO uint32_t*)CTRLSTS_LSIEN_BB = (uint32_t)Cmd; +} + +/** + * @brief Configures the RTC clock (RTCCLK). + * @note Once the RTC clock is selected it can't be changed unless the Backup domain is reset. + * @param RCC_RTCCLKSource specifies the RTC clock source. + * This parameter can be one of the following values: + * @arg RCC_RTCCLK_SRC_LSE LSE selected as RTC clock + * @arg RCC_RTCCLK_SRC_LSI LSI selected as RTC clock + * @arg RCC_RTCCLK_SRC_HSE_DIV128 HSE clock divided by 128 selected as RTC clock + */ +void RCC_ConfigRtcClk(uint32_t RCC_RTCCLKSource) +{ + /* Check the parameters */ + assert_param(IS_RCC_RTCCLK_SRC(RCC_RTCCLKSource)); + + /* Clear the RTC clock source */ + RCC->BDCTRL &= (~0x00000300); + + /* Select the RTC clock source */ + RCC->BDCTRL |= RCC_RTCCLKSource; +} + +/** + * @brief Enables or disables the RTC clock. + * @note This function must be used only after the RTC clock was selected using the RCC_ConfigRtcClk function. + * @param Cmd new state of the RTC clock. This parameter can be: ENABLE or DISABLE. + */ +void RCC_EnableRtcClk(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + *(__IO uint32_t*)BDCTRL_RTCEN_BB = (uint32_t)Cmd; +} + +/** + * @brief Returns the frequencies of different on chip clocks. + * @param RCC_Clocks pointer to a RCC_ClocksType structure which will hold + * the clocks frequencies. + * @note The result of this function could be not correct when using + * fractional value for HSE crystal. + */ +void RCC_GetClocksFreqValue(RCC_ClocksType* RCC_Clocks) +{ + uint32_t tmp = 0, pllclk = 0, pllmull = 0, pllsource = 0, presc = 0; + + /* Get PLL clock source and multiplication factor ----------------------*/ + pllmull = RCC->CFG & CFG_PLLMULFCT_MASK; + pllsource = RCC->CFG & CFG_PLLSRC_MASK; + + if ((pllmull & RCC_CFG_PLLMULFCT_4) == 0) + { + pllmull = (pllmull >> 18) + 2; // PLLMUL[4]=0 + } + else + { + pllmull = ((pllmull >> 18) - 496) + 1; // PLLMUL[4]=1 + } + + if (pllsource == 0x00) + { /* HSI oscillator clock divided by 2 selected as PLL clock entry */ + pllclk = (HSI_VALUE >> 1) * pllmull; + } + else + { + /* HSE selected as PLL clock entry */ + if ((RCC->CFG & CFG_PLLHSEPRES_MASK) != (uint32_t)RESET) + { /* HSE oscillator clock divided by 2 */ + pllclk = (HSE_VALUE >> 1) * pllmull; + } + else + { + pllclk = HSE_VALUE * pllmull; + } + } + + /* Get SYSCLK source -------------------------------------------------------*/ + tmp = RCC->CFG & CFG_SCLKSTS_MASK; + + switch (tmp) + { + case 0x00: /* HSI used as system clock */ + RCC_Clocks->SysclkFreq = HSI_VALUE; + break; + case 0x04: /* HSE used as system clock */ + RCC_Clocks->SysclkFreq = HSE_VALUE; + break; + case 0x08: /* PLL used as system clock */ + RCC_Clocks->SysclkFreq = pllclk; + break; + + default: + RCC_Clocks->SysclkFreq = HSI_VALUE; + break; + } + + /* Compute HCLK, PCLK1, PCLK2 and ADCCLK clocks frequencies ----------------*/ + /* Get HCLK prescaler */ + tmp = RCC->CFG & CFG_AHBPRES_SET_MASK; + tmp = tmp >> 4; + presc = s_ApbAhbPresTable[tmp]; + /* HCLK clock frequency */ + RCC_Clocks->HclkFreq = RCC_Clocks->SysclkFreq >> presc; + /* Get PCLK1 prescaler */ + tmp = RCC->CFG & CFG_APB1PRES_SET_MASK; + tmp = tmp >> 8; + presc = s_ApbAhbPresTable[tmp]; + /* PCLK1 clock frequency */ + RCC_Clocks->Pclk1Freq = RCC_Clocks->HclkFreq >> presc; + /* Get PCLK2 prescaler */ + tmp = RCC->CFG & CFG_APB2PRES_SET_MASK; + tmp = tmp >> 11; + presc = s_ApbAhbPresTable[tmp]; + /* PCLK2 clock frequency */ + RCC_Clocks->Pclk2Freq = RCC_Clocks->HclkFreq >> presc; + + /* Get ADCHCLK prescaler */ + tmp = RCC->CFG2 & CFG2_ADCHPRES_SET_MASK; + presc = s_AdcHclkPresTable[tmp]; + /* ADCHCLK clock frequency */ + RCC_Clocks->AdcHclkFreq = RCC_Clocks->HclkFreq / presc; + /* Get ADCPLLCLK prescaler */ + tmp = RCC->CFG2 & CFG2_ADCPLLPRES_SET_MASK; + tmp = tmp >> 4; + presc = s_AdcPllClkPresTable[(tmp & 0xF)]; // ignore BIT5 + /* ADCPLLCLK clock frequency */ + RCC_Clocks->AdcPllClkFreq = pllclk / presc; +} + +/** + * @brief Enables or disables the AHB peripheral clock. + * @param RCC_AHBPeriph specifies the AHB peripheral to gates its clock. + * + * this parameter can be any combination of the following values: + * @arg RCC_AHB_PERIPH_DMA1 + * @arg RCC_AHB_PERIPH_DMA2 + * @arg RCC_AHB_PERIPH_SRAM + * @arg RCC_AHB_PERIPH_FLITF + * @arg RCC_AHB_PERIPH_CRC + * @arg RCC_AHB_PERIPH_RNGC + * @arg RCC_AHB_PERIPH_SDIO + * @arg RCC_AHB_PERIPH_SAC + * @arg RCC_AHB_PERIPH_ADC1 + * @arg RCC_AHB_PERIPH_ADC2 + * @arg RCC_AHB_PERIPH_ADC3 + * @arg RCC_AHB_PERIPH_ADC4 + * @arg RCC_AHB_PERIPH_ETHMAC + * @arg RCC_AHB_PERIPH_QSPI + * + * @note SRAM and FLITF clock can be disabled only during sleep mode. + * @param Cmd new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + */ +void RCC_EnableAHBPeriphClk(uint32_t RCC_AHBPeriph, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_RCC_AHB_PERIPH(RCC_AHBPeriph)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + RCC->AHBPCLKEN |= RCC_AHBPeriph; + } + else + { + RCC->AHBPCLKEN &= ~RCC_AHBPeriph; + } +} + +/** + * @brief Enables or disables the High Speed APB (APB2) peripheral clock. + * @param RCC_APB2Periph specifies the APB2 peripheral to gates its clock. + * This parameter can be any combination of the following values: + * @arg RCC_APB2_PERIPH_AFIO, RCC_APB2_PERIPH_GPIOA, RCC_APB2_PERIPH_GPIOB, + * RCC_APB2_PERIPH_GPIOC, RCC_APB2_PERIPH_GPIOD, RCC_APB2_PERIPH_GPIOE, + * RCC_APB2_PERIPH_GPIOF, RCC_APB2_PERIPH_GPIOG, RCC_APB2_PERIPH_TIM1, + * RCC_APB2_PERIPH_SPI1, RCC_APB2_PERIPH_TIM8, RCC_APB2_PERIPH_USART1, + * RCC_APB2_PERIPH_DVP, RCC_APB2_PERIPH_UART6, RCC_APB2_PERIPH_UART7, + * RCC_APB2_PERIPH_I2C3, RCC_APB2_PERIPH_I2C4 + * @param Cmd new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + */ +void RCC_EnableAPB2PeriphClk(uint32_t RCC_APB2Periph, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + RCC->APB2PCLKEN |= RCC_APB2Periph; + } + else + { + RCC->APB2PCLKEN &= ~RCC_APB2Periph; + } +} + +/** + * @brief Enables or disables the Low Speed APB (APB1) peripheral clock. + * @param RCC_APB1Periph specifies the APB1 peripheral to gates its clock. + * This parameter can be any combination of the following values: + * @arg RCC_APB1_PERIPH_TIM2, RCC_APB1_PERIPH_TIM3, RCC_APB1_PERIPH_TIM4, + * RCC_APB1_PERIPH_TIM5, RCC_APB1_PERIPH_TIM6, RCC_APB1_PERIPH_TIM7, + * RCC_APB1_PERIPH_COMP, RCC_APB1_PERIPH_COMP_FILT, RCC_APB1_PERIPH_TSC, + * RCC_APB1_PERIPH_WWDG, RCC_APB1_PERIPH_SPI2, RCC_APB1_PERIPH_SPI3, + * RCC_APB1_PERIPH_USART2, RCC_APB1_PERIPH_USART3, RCC_APB1_PERIPH_UART4, + * RCC_APB1_PERIPH_UART5, RCC_APB1_PERIPH_I2C1, RCC_APB1_PERIPH_I2C2, + * RCC_APB1_PERIPH_USB, RCC_APB1_PERIPH_CAN1, RCC_APB1_PERIPH_CAN2, RCC_APB1_PERIPH_BKP, + * RCC_APB1_PERIPH_PWR, RCC_APB1_PERIPH_DAC, RCC_APB1_PERIPH_OPAMP + * + * @param Cmd new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + */ +void RCC_EnableAPB1PeriphClk(uint32_t RCC_APB1Periph, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_RCC_APB1_PERIPH(RCC_APB1Periph)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + RCC->APB1PCLKEN |= RCC_APB1Periph; + } + else + { + RCC->APB1PCLKEN &= ~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_AHB_PERIPH_QSPI. + * RCC_AHB_PERIPH_ETHMAC. + * RCC_AHB_PERIPH_ADC4. + * RCC_AHB_PERIPH_ADC3. + * RCC_AHB_PERIPH_ADC2. + * RCC_AHB_PERIPH_ADC1. + * RCC_AHB_PERIPH_SAC. + * RCC_AHB_PERIPH_RNGC. + * @param Cmd new state of the specified peripheral reset. This parameter can be ENABLE or DISABLE. + */ +void RCC_EnableAHBPeriphReset(uint32_t RCC_AHBPeriph, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_RCC_AHB_PERIPH(RCC_AHBPeriph)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + RCC->AHBPRST |= RCC_AHBPeriph; + } + else + { + RCC->AHBPRST &= ~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_APB2_PERIPH_AFIO, RCC_APB2_PERIPH_GPIOA, RCC_APB2_PERIPH_GPIOB, + * RCC_APB2_PERIPH_GPIOC, RCC_APB2_PERIPH_GPIOD, RCC_APB2_PERIPH_GPIOE, + * RCC_APB2_PERIPH_GPIOF, RCC_APB2_PERIPH_GPIOG, RCC_APB2_PERIPH_TIM1, + * RCC_APB2_PERIPH_SPI1, RCC_APB2_PERIPH_TIM8, RCC_APB2_PERIPH_USART1, + * RCC_APB2_PERIPH_DVP, RCC_APB2_PERIPH_UART6, RCC_APB2_PERIPH_UART7, + * RCC_APB2_PERIPH_I2C3, RCC_APB2_PERIPH_I2C4 + * @param Cmd new state of the specified peripheral reset. + * This parameter can be: ENABLE or DISABLE. + */ +void RCC_EnableAPB2PeriphReset(uint32_t RCC_APB2Periph, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + RCC->APB2PRST |= RCC_APB2Periph; + } + else + { + RCC->APB2PRST &= ~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_APB1_PERIPH_TIM2, RCC_APB1_PERIPH_TIM3, RCC_APB1_PERIPH_TIM4, + * RCC_APB1_PERIPH_TIM5, RCC_APB1_PERIPH_TIM6, RCC_APB1_PERIPH_TIM7, + * RCC_APB1_PERIPH_TSC, RCC_APB1_PERIPH_WWDG, RCC_APB1_PERIPH_SPI2, + * RCC_APB1_PERIPH_SPI3, RCC_APB1_PERIPH_USART2, RCC_APB1_PERIPH_USART3, + * RCC_APB1_PERIPH_UART4, RCC_APB1_PERIPH_UART5, RCC_APB1_PERIPH_I2C1, + * RCC_APB1_PERIPH_I2C2, RCC_APB1_PERIPH_USB, RCC_APB1_PERIPH_CAN1, + * RCC_APB1_PERIPH_CAN2, RCC_APB1_PERIPH_BKP, RCC_APB1_PERIPH_PWR, + * RCC_APB1_PERIPH_DAC + * @param Cmd new state of the specified peripheral clock. + * This parameter can be: ENABLE or DISABLE. + */ +void RCC_EnableAPB1PeriphReset(uint32_t RCC_APB1Periph, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_RCC_APB1_PERIPH(RCC_APB1Periph)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + RCC->APB1PRST |= RCC_APB1Periph; + } + else + { + RCC->APB1PRST &= ~RCC_APB1Periph; + } +} + +/** + * @brief BOR reset enable. + * @param Cmd new state of the BOR reset. + * This parameter can be: ENABLE or DISABLE. + */ +void RCC_EnableBORReset(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + RCC->CFG3 |= RCC_BOR_RST_ENABLE; + } + else + { + RCC->CFG3 &= ~RCC_BOR_RST_ENABLE; + } +} + +/** + * @brief Forces or releases the Backup domain reset. + * @param Cmd new state of the Backup domain reset. + * This parameter can be: ENABLE or DISABLE. + */ +void RCC_EnableBackupReset(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + *(__IO uint32_t*)BDCTRL_BDSFTRST_BB = (uint32_t)Cmd; +} + +/** + * @brief Enables or disables the Clock Security System. + * @param Cmd new state of the Clock Security System.. + * This parameter can be: ENABLE or DISABLE. + */ +void RCC_EnableClockSecuritySystem(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + *(__IO uint32_t*)CTRL_CLKSSEN_BB = (uint32_t)Cmd; +} + +/** + * @brief Configures the MCO PLL clock prescaler. + * @param RCC_MCOPLLCLKPrescaler specifies the MCO PLL clock prescaler. + * This parameter can be on of the following values: + * @arg RCC_MCO_PLLCLK_DIV2 MCOPRE[3:0] = 0010, PLL Clock Divided By 2 + * @arg RCC_MCO_PLLCLK_DIV3 MCOPRE[3:0] = 0011, PLL Clock Divided By 3 + * @arg RCC_MCO_PLLCLK_DIV4 MCOPRE[3:0] = 0100, PLL Clock Divided By 4 + * @arg RCC_MCO_PLLCLK_DIV5 MCOPRE[3:0] = 0101, PLL Clock Divided By 5 + * ... + * @arg RCC_MCO_PLLCLK_DIV13 MCOPRE[3:0] = 1101, PLL Clock Divided By 13 + * @arg RCC_MCO_PLLCLK_DIV14 MCOPRE[3:0] = 1110, PLL Clock Divided By 14 + * @arg RCC_MCO_PLLCLK_DIV15 MCOPRE[3:0] = 1111, PLL Clock Divided By 15 + */ +void RCC_ConfigMcoPllClk(uint32_t RCC_MCOPLLCLKPrescaler) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_RCC_MCOPLLCLKPRE(RCC_MCOPLLCLKPrescaler)); + + tmpregister = RCC->CFG; + /* Clear MCOPRE[3:0] bits */ + tmpregister &= ((uint32_t)0x0FFFFFFF); + /* Set MCOPRE[3:0] bits according to RCC_ADCHCLKPrescaler value */ + tmpregister |= RCC_MCOPLLCLKPrescaler; + + /* Store the new value */ + RCC->CFG = tmpregister; +} + +/** + * @brief Selects the clock source to output on MCO pin. + * @param RCC_MCO specifies the clock source to output. + * + * this parameter can be one of the following values: + * @arg RCC_MCO_NOCLK No clock selected + * @arg RCC_MCO_SYSCLK System clock selected + * @arg RCC_MCO_HSI HSI oscillator clock selected + * @arg RCC_MCO_HSE HSE oscillator clock selected + * @arg RCC_MCO_PLLCLK PLL clock divided by xx selected + * + */ +void RCC_ConfigMco(uint8_t RCC_MCO) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_RCC_MCO(RCC_MCO)); + + tmpregister = RCC->CFG; + /* Clear MCO[2:0] bits */ + tmpregister &= ((uint32_t)0xF8FFFFFF); + /* Set MCO[2:0] bits according to RCC_MCO value */ + tmpregister |= ((uint32_t)(RCC_MCO << 24)); + + /* Store the new value */ + RCC->CFG = tmpregister; +} + +/** + * @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_HSIRD HSI oscillator clock ready + * @arg RCC_FLAG_HSERD HSE oscillator clock ready + * @arg RCC_FLAG_PLLRD PLL clock ready + * @arg RCC_FLAG_LSERD LSE oscillator clock ready + * @arg RCC_FLAG_LSIRD LSI oscillator clock ready + * @arg RCC_FLAG_BORRST BOR reset flag + * @arg RCC_FLAG_RETEMC Retention EMC reset flag + * @arg RCC_FLAG_BKPEMC BackUp EMC reset flag + * @arg RCC_FLAG_RAMRST RAM reset flag + * @arg RCC_FLAG_MMURST Mmu reset flag + * @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 + * + * @return 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 CTRL register */ + { + statusreg = RCC->CTRL; + } + else if (tmp == 2) /* The flag to check is in BDCTRL register */ + { + statusreg = RCC->BDCTRL; + } + else /* The flag to check is in CTRLSTS register */ + { + statusreg = RCC->CTRLSTS; + } + + /* 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. + * @note The reset flags are: RCC_FLAG_PINRST, RCC_FLAG_PORRST, RCC_FLAG_SFTRST, + * RCC_FLAG_IWDGRST, RCC_FLAG_WWDGRST, RCC_FLAG_LPWRRST + */ +void RCC_ClrFlag(void) +{ + /* Set RMVF bit to clear the reset flags */ + RCC->CTRLSTS |= CSR_RMRSTF_SET; + /* RMVF bit should be reset */ + RCC->CTRLSTS &= CSR_RMVF_Reset; +} + +/** + * @brief Checks whether the specified RCC interrupt has occurred or not. + * @param RccInt specifies the RCC interrupt source to check. + * + * this parameter can be one of the following values: + * @arg RCC_INT_LSIRDIF LSI ready interrupt + * @arg RCC_INT_LSERDIF LSE ready interrupt + * @arg RCC_INT_HSIRDIF HSI ready interrupt + * @arg RCC_INT_HSERDIF HSE ready interrupt + * @arg RCC_INT_PLLRDIF PLL ready interrupt + * + * @arg RCC_INT_CLKSSIF Clock Security System interrupt + * + * @return The new state of RccInt (SET or RESET). + */ +INTStatus RCC_GetIntStatus(uint8_t RccInt) +{ + INTStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_RCC_GET_INT(RccInt)); + + /* Check the status of the specified RCC interrupt */ + if ((RCC->CLKINT & RccInt) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + /* Return the RccInt status */ + return bitstatus; +} + +/** + * @brief Clears the RCC's interrupt pending bits. + * @param RccInt specifies the interrupt pending bit to clear. + * + * this parameter can be any combination of the + * following values: + * @arg RCC_INT_LSIRDIF LSI ready interrupt + * @arg RCC_INT_LSERDIF LSE ready interrupt + * @arg RCC_INT_HSIRDIF HSI ready interrupt + * @arg RCC_INT_HSERDIF HSE ready interrupt + * @arg RCC_INT_PLLRDIF PLL ready interrupt + * + * @arg RCC_INT_CLKSSIF Clock Security System interrupt + */ +void RCC_ClrIntPendingBit(uint8_t RccInt) +{ + /* Check the parameters */ + assert_param(IS_RCC_CLR_INT(RccInt)); + + /* Perform Byte access to RCC_CLKINT[23:16] bits to clear the selected interrupt + pending bits */ + *(__IO uint8_t*)CLKINT_BYTE3_ADDR = RccInt; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/src/n32g45x_rtc.c b/src/n32g45x_rtc.c new file mode 100644 index 0000000..7f2629b --- /dev/null +++ b/src/n32g45x_rtc.c @@ -0,0 +1,2007 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_rtc.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_rtc.h" +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup RTC + * @brief RTC driver modules + * @{ + */ + +/* Masks Definition */ +#define RTC_TR_RESERVED_MASK ((uint32_t)0x007F7F7F) +#define RTC_DATE_RESERVED_MASK ((uint32_t)0x00FFFF3F) + +#define RTC_RSF_MASK ((uint32_t)0xFFFFFFDF) +#define RTC_FLAGS_MASK \ + ((uint32_t)(RTC_FLAG_TISOVF | RTC_FLAG_TISF | RTC_FLAG_WTF | RTC_FLAG_ALBF | RTC_FLAG_ALAF | RTC_FLAG_INITF \ + | RTC_FLAG_RSYF | RTC_FLAG_INITSF | RTC_FLAG_WTWF | RTC_FLAG_ALBWF | RTC_FLAG_ALAWF | RTC_FLAG_RECPF \ + | RTC_FLAG_SHOPF)) + +#define INITMODE_TIMEOUT ((uint32_t)0x00002000) +#define SYNCHRO_TIMEOUT ((uint32_t)0x00008000) +#define RECALPF_TIMEOUT ((uint32_t)0x00001000) +#define SHPF_TIMEOUT ((uint32_t)0x00002000) + +static uint8_t RTC_ByteToBcd2(uint8_t Value); +static uint8_t RTC_Bcd2ToByte(uint8_t Value); + +/** @addtogroup RTC_Private_Functions + * @{ + */ + +/** @addtogroup RTC_Group1 Initialization and Configuration functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and Configuration functions ##### + =============================================================================== + [..] This section provide functions allowing to initialize and configure the + RTC Prescaler (Synchronous and Asynchronous), RTC Hour format, disable + RTC registers Write protection, enter and exit the RTC initialization mode, + RTC registers synchronization check and reference clock detection enable. + (#) The RTC Prescaler is programmed to generate the RTC 1Hz time base. + It is split into 2 programmable prescalers to minimize power consumption. + (++) A 7-bit asynchronous prescaler and A 13-bit synchronous prescaler. + (++) When both prescalers are used, it is recommended to configure the + asynchronous prescaler to a high value to minimize consumption. + (#) All RTC registers are Write protected. Writing to the RTC registers + is enabled by writing a key into the Write Protection register, RTC_WRP. + (#) To Configure the RTC Calendar, user application should enter + initialization mode. In this mode, the calendar counter is stopped + and its value can be updated. When the initialization sequence is + complete, the calendar restarts counting after 4 RTCCLK cycles. + (#) To read the calendar through the shadow registers after Calendar + initialization, calendar update or after wakeup from low power modes + the software must first clear the RSYF flag. The software must then + wait until it is set again before reading the calendar, which means + that the calendar registers have been correctly copied into the + RTC_TSH and RTC_DATE shadow registers.The RTC_WaitForSynchro() function + implements the above software sequence (RSYF clear and RSYF check). + +@endverbatim + * @{ + */ + +/** + * @brief Deinitializes the RTC registers to their default reset values. + * @note This function doesn't reset the RTC Clock source + * @return An ErrorStatus enumeration value: + * - SUCCESS: RTC registers are deinitialized + * - ERROR: RTC registers are not deinitialized + */ +ErrorStatus RTC_DeInit(void) +{ + __IO uint32_t wutcounter = 0x00; + uint32_t wutwfstatus = 0x00; + ErrorStatus status = ERROR; + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* Set Initialization mode */ + if (RTC_EnterInitMode() == ERROR) + { + status = ERROR; + } + else + { + /* Reset TSH, DAT and CTRL registers */ + RTC->TSH = (uint32_t)0x00000000; + RTC->DATE = (uint32_t)0x00002101; + + /* Reset All CTRL bits except CTRL[2:0] */ + RTC->CTRL &= (uint32_t)0x00000007; + + /* Wait till RTC WTWF flag is set and if Time out is reached exit */ + do + { + wutwfstatus = RTC->INITSTS & RTC_INITSTS_WTWF; + wutcounter++; + } while ((wutcounter != INITMODE_TIMEOUT) && (wutwfstatus == 0x00)); + + if ((RTC->INITSTS & RTC_INITSTS_WTWF) == RESET) + { + status = ERROR; + } + else + { + /* Reset all RTC CTRL register bits */ + RTC->CTRL &= (uint32_t)0x00000000; + RTC->WKUPT = (uint32_t)0x0000FFFF; + RTC->PRE = (uint32_t)0x007F00FF; + RTC->ALARMA = (uint32_t)0x00000000; + RTC->ALARMB = (uint32_t)0x00000000; + RTC->SCTRL = (uint32_t)0x00000000; + RTC->CALIB = (uint32_t)0x00000000; + RTC->ALRMASS = (uint32_t)0x00000000; + RTC->ALRMBSS = (uint32_t)0x00000000; + + /* Reset INTSTS register and exit initialization mode */ + RTC->INITSTS = (uint32_t)0x00000000; + + RTC->OPT = (uint32_t)0x00000000; + RTC->TSCWKUPCTRL = (uint32_t)0x00000008; + RTC->TSCWKUPCNT = (uint32_t)0x000002FE; + + /* Wait till the RTC RSYF flag is set */ + if (RTC_WaitForSynchro() == ERROR) + { + status = ERROR; + } + else + { + status = SUCCESS; + } + } + } + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; + + return status; +} + +/** + * @brief Initializes the RTC registers according to the specified parameters + * in RTC_InitStruct. + * @param RTC_InitStruct pointer to a RTC_InitType structure that contains + * the configuration information for the RTC peripheral. + * @note The RTC Prescaler register is write protected and can be written in + * initialization mode only. + * @return An ErrorStatus enumeration value: + * - SUCCESS: RTC registers are initialized + * - ERROR: RTC registers are not initialized + */ +ErrorStatus RTC_Init(RTC_InitType* RTC_InitStruct) +{ + ErrorStatus status = ERROR; + uint32_t i =0; + /* Check the parameters */ + assert_param(IS_RTC_HOUR_FORMAT(RTC_InitStruct->RTC_HourFormat)); + assert_param(IS_RTC_PREDIV_ASYNCH(RTC_InitStruct->RTC_AsynchPrediv)); + assert_param(IS_RTC_PREDIV_SYNCH(RTC_InitStruct->RTC_SynchPrediv)); + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* Set Initialization mode */ + if (RTC_EnterInitMode() == ERROR) + { + status = ERROR; + } + else + { + /* Clear RTC CTRL HFMT Bit */ + RTC->CTRL &= ((uint32_t) ~(RTC_CTRL_HFMT)); + /* Set RTC_CTRL register */ + RTC->CTRL |= ((uint32_t)(RTC_InitStruct->RTC_HourFormat)); + + /* Configure the RTC PRE */ + RTC->PRE = (uint32_t)(RTC_InitStruct->RTC_SynchPrediv); + RTC->PRE |= (uint32_t)(RTC_InitStruct->RTC_AsynchPrediv << 16); + + /* Exit Initialization mode */ + RTC_ExitInitMode(); + + status = SUCCESS; + } + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; + /* Delay for the RTC prescale effect */ + for(i=0;i<0x2FF;i++); + return status; +} + +/** + * @brief Fills each RTC_InitStruct member with its default value. + * @param RTC_InitStruct pointer to a RTC_InitType structure which will be + * initialized. + */ +void RTC_StructInit(RTC_InitType* RTC_InitStruct) +{ + /* Initialize the RTC_HourFormat member */ + RTC_InitStruct->RTC_HourFormat = RTC_24HOUR_FORMAT; + + /* Initialize the RTC_AsynchPrediv member */ + RTC_InitStruct->RTC_AsynchPrediv = (uint32_t)0x7F; + + /* Initialize the RTC_SynchPrediv member */ + RTC_InitStruct->RTC_SynchPrediv = (uint32_t)0xFF; +} + +/** + * @brief Enables or disables the RTC registers write protection. + * @note All the RTC registers are write protected except for RTC_INITSTS[13:8]. + * @note Writing a wrong key reactivates the write protection. + * @note The protection mechanism is not affected by system reset. + * @param Cmd new state of the write protection. + * This parameter can be: ENABLE or DISABLE. + */ +void RTC_EnableWriteProtection(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; + } + else + { + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + } +} + +/** + * @brief Enters the RTC Initialization mode. + * @note The RTC Initialization mode is write protected, use the + * RTC_EnableWriteProtection(DISABLE) before calling this function. + * @return An ErrorStatus enumeration value: + * - SUCCESS: RTC is in Init mode + * - ERROR: RTC is not in Init mode + */ +ErrorStatus RTC_EnterInitMode(void) +{ + __IO uint32_t initcounter = 0x00; + ErrorStatus status = ERROR; + uint32_t initstatus = 0x00; + + /* Check if the Initialization mode is set */ + if ((RTC->INITSTS & RTC_INITSTS_INITF) == (uint32_t)RESET) + { + /* Set the Initialization mode */ + RTC->INITSTS = (uint32_t)RTC_INITSTS_INITM; + + /* Wait till RTC is in INIT state and if Time out is reached exit */ + do + { + initstatus = RTC->INITSTS & RTC_INITSTS_INITF; + initcounter++; + } while ((initcounter != INITMODE_TIMEOUT) && (initstatus == 0x00)); + + if ((RTC->INITSTS & RTC_INITSTS_INITF) != RESET) + { + status = SUCCESS; + } + else + { + status = ERROR; + } + } + else + { + status = SUCCESS; + } + + return (status); +} + +/** + * @brief Exits the RTC Initialization mode. + * @note When the initialization sequence is complete, the calendar restarts + * counting after 4 RTCCLK cycles. + * @note The RTC Initialization mode is write protected, use the + * RTC_EnableWriteProtection(DISABLE) before calling this function. + */ +void RTC_ExitInitMode(void) +{ + /* Exit Initialization mode */ + RTC->INITSTS &= (uint32_t)~RTC_INITSTS_INITM; +} + +/** + * @brief Waits until the RTC Time and Date registers (RTC_TSH and RTC_DATE) are + * synchronized with RTC APB clock. + * @note The RTC Resynchronization mode is write protected, use the + * RTC_EnableWriteProtection(DISABLE) before calling this function. + * @note To read the calendar through the shadow registers after Calendar + * initialization, calendar update or after wakeup from low power modes + * the software must first clear the RSYF flag. + * The software must then wait until it is set again before reading + * the calendar, which means that the calendar registers have been + * correctly copied into the RTC_TSH and RTC_DATE shadow registers. + * @return An ErrorStatus enumeration value: + * - SUCCESS: RTC registers are synchronised + * - ERROR: RTC registers are not synchronised + */ +ErrorStatus RTC_WaitForSynchro(void) +{ + __IO uint32_t synchrocounter = 0; + ErrorStatus status = ERROR; + uint32_t synchrostatus = 0x00; + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* Clear RSYF flag */ + RTC->INITSTS &= (uint32_t)RTC_RSF_MASK; + + /* Wait the registers to be synchronised */ + do + { + synchrostatus = RTC->INITSTS & RTC_INITSTS_RSYF; + synchrocounter++; + } while ((synchrocounter != SYNCHRO_TIMEOUT) && (synchrostatus == 0x00)); + + if ((RTC->INITSTS & RTC_INITSTS_RSYF) != RESET) + { + status = SUCCESS; + } + else + { + status = ERROR; + } + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; + + return (status); +} + + + +/** + * @brief Enables or Disables the Bypass Shadow feature. + * @note When the Bypass Shadow is enabled the calendar value are taken + * directly from the Calendar counter. + * @param Cmd new state of the Bypass Shadow feature. + * This parameter can be: ENABLE or DISABLE. + */ +void RTC_EnableBypassShadow(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + if (Cmd != DISABLE) + { + /* Set the BYPS bit */ + RTC->CTRL |= (uint8_t)RTC_CTRL_BYPS; + } + else + { + /* Reset the BYPS bit */ + RTC->CTRL &= (uint8_t)~RTC_CTRL_BYPS; + } + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; +} + +/** + * @} + */ + +/** @addtogroup RTC_Group2 Time and Date configuration functions + * @brief Time and Date configuration functions + * +@verbatim + =============================================================================== + ##### Time and Date configuration functions ##### + =============================================================================== + [..] This section provide functions allowing to program and read the RTC + Calendar (Time and Date). + +@endverbatim + * @{ + */ + +/** + * @brief Set the RTC current time. + * @param RTC_Format specifies the format of the entered parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN Binary data format. + * @arg RTC_FORMAT_BCD BCD data format. + * @param RTC_TimeStruct pointer to a RTC_TimeType structure that contains + * the time configuration information for the RTC. + * @return An ErrorStatus enumeration value: + * - SUCCESS: RTC Time register is configured + * - ERROR: RTC Time register is not configured + */ +ErrorStatus RTC_ConfigTime(uint32_t RTC_Format, RTC_TimeType* RTC_TimeStruct) +{ + uint32_t tmpregister = 0; + ErrorStatus status = ERROR; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(RTC_Format)); + + if (RTC_Format == RTC_FORMAT_BIN) + { + if ((RTC->CTRL & RTC_CTRL_HFMT) != (uint32_t)RESET) + { + assert_param(IS_RTC_12HOUR(RTC_TimeStruct->Hours)); + assert_param(IS_RTC_H12(RTC_TimeStruct->H12)); + } + else + { + RTC_TimeStruct->H12 = 0x00; + assert_param(IS_RTC_24HOUR(RTC_TimeStruct->Hours)); + } + assert_param(IS_RTC_MINUTES(RTC_TimeStruct->Minutes)); + assert_param(IS_RTC_SECONDS(RTC_TimeStruct->Seconds)); + } + else + { + if ((RTC->CTRL & RTC_CTRL_HFMT) != (uint32_t)RESET) + { + tmpregister = RTC_Bcd2ToByte(RTC_TimeStruct->Hours); + assert_param(IS_RTC_12HOUR(tmpregister)); + assert_param(IS_RTC_H12(RTC_TimeStruct->H12)); + } + else + { + RTC_TimeStruct->H12 = 0x00; + assert_param(IS_RTC_24HOUR(RTC_Bcd2ToByte(RTC_TimeStruct->Hours))); + } + assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(RTC_TimeStruct->Minutes))); + assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(RTC_TimeStruct->Seconds))); + } + + /* Check the input parameters format */ + if (RTC_Format != RTC_FORMAT_BIN) + { + tmpregister = (((uint32_t)(RTC_TimeStruct->Hours) << 16) | ((uint32_t)(RTC_TimeStruct->Minutes) << 8) + | ((uint32_t)RTC_TimeStruct->Seconds) | ((uint32_t)(RTC_TimeStruct->H12) << 16)); + } + else + { + tmpregister = + (uint32_t)(((uint32_t)RTC_ByteToBcd2(RTC_TimeStruct->Hours) << 16) + | ((uint32_t)RTC_ByteToBcd2(RTC_TimeStruct->Minutes) << 8) + | ((uint32_t)RTC_ByteToBcd2(RTC_TimeStruct->Seconds)) | (((uint32_t)RTC_TimeStruct->H12) << 16)); + } + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* Set Initialization mode */ + if (RTC_EnterInitMode() == ERROR) + { + status = ERROR; + } + else + { + /* Set the RTC_TSH register */ + RTC->TSH = (uint32_t)(tmpregister & RTC_TR_RESERVED_MASK); + + /* Exit Initialization mode */ + RTC_ExitInitMode(); + + /* If RTC_CTRL_BYPS bit = 0, wait for synchro else this check is not needed */ + if ((RTC->CTRL & RTC_CTRL_BYPS) == RESET) + { + if (RTC_WaitForSynchro() == ERROR) + { + status = ERROR; + } + else + { + status = SUCCESS; + } + } + else + { + status = SUCCESS; + } + } + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; + /* Waits until the RTC Time and Date registers + (RTC_TSH and RTC_DATE) are synchronized with RTC APB clock. */ + status=RTC_WaitForSynchro(); + return status; +} + +/** + * @brief Fills each RTC_TimeStruct member with its default value + * (Time = 00h:00min:00sec). + * @param RTC_TimeStruct pointer to a RTC_TimeType structure which will be + * initialized. + */ +void RTC_TimeStructInit(RTC_TimeType* RTC_TimeStruct) +{ + /* Time = 00h:00min:00sec */ + RTC_TimeStruct->H12 = RTC_AM_H12; + RTC_TimeStruct->Hours = 0; + RTC_TimeStruct->Minutes = 0; + RTC_TimeStruct->Seconds = 0; +} + +/** + * @brief Get the RTC current Time. + * @param RTC_Format specifies the format of the returned parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN Binary data format. + * @arg RTC_FORMAT_BCD BCD data format. + * @param RTC_TimeStruct pointer to a RTC_TimeType structure that will + * contain the returned current time configuration. + */ +void RTC_GetTime(uint32_t RTC_Format, RTC_TimeType* RTC_TimeStruct) +{ + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(RTC_Format)); + + /* Get the RTC_TSH register */ + tmpregister = (uint32_t)(RTC->TSH & RTC_TR_RESERVED_MASK); + + /* Fill the structure fields with the read parameters */ + RTC_TimeStruct->Hours = (uint8_t)((tmpregister & (RTC_TSH_HOT | RTC_TSH_HOU)) >> 16); + RTC_TimeStruct->Minutes = (uint8_t)((tmpregister & (RTC_TSH_MIT | RTC_TSH_MIU)) >> 8); + RTC_TimeStruct->Seconds = (uint8_t)(tmpregister & (RTC_TSH_SCT | RTC_TSH_SCU)); + RTC_TimeStruct->H12 = (uint8_t)((tmpregister & (RTC_TSH_APM)) >> 16); + + /* Check the input parameters format */ + if (RTC_Format == RTC_FORMAT_BIN) + { + /* Convert the structure parameters to Binary format */ + RTC_TimeStruct->Hours = (uint8_t)RTC_Bcd2ToByte(RTC_TimeStruct->Hours); + RTC_TimeStruct->Minutes = (uint8_t)RTC_Bcd2ToByte(RTC_TimeStruct->Minutes); + RTC_TimeStruct->Seconds = (uint8_t)RTC_Bcd2ToByte(RTC_TimeStruct->Seconds); + } +} + +/** + * @brief Gets the RTC current Calendar Subseconds value. + * @return RTC current Calendar Subseconds value. + */ +uint32_t RTC_GetSubSecond(void) +{ + uint32_t tmpregister = 0; + + /* Get subseconds values from the correspondent registers*/ + tmpregister = (uint32_t)(RTC->SUBS); + + return (tmpregister); +} + +/** + * @brief Set the RTC current date. + * @param RTC_Format specifies the format of the entered parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN Binary data format. + * @arg RTC_FORMAT_BCD BCD data format. + * @param RTC_DateStruct pointer to a RTC_DateType structure that contains + * the date configuration information for the RTC. + * @return An ErrorStatus enumeration value: + * - SUCCESS: RTC Date register is configured + * - ERROR: RTC Date register is not configured + */ +ErrorStatus RTC_SetDate(uint32_t RTC_Format, RTC_DateType* RTC_DateStruct) +{ + uint32_t tmpregister = 0; + ErrorStatus status = ERROR; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(RTC_Format)); + + if ((RTC_Format == RTC_FORMAT_BIN) && ((RTC_DateStruct->Month & 0x10) == 0x10)) + { + RTC_DateStruct->Month = (RTC_DateStruct->Month & (uint32_t) ~(0x10)) + 0x0A; + } + if (RTC_Format == RTC_FORMAT_BIN) + { + assert_param(IS_RTC_YEAR(RTC_DateStruct->Year)); + assert_param(IS_RTC_MONTH(RTC_DateStruct->Month)); + assert_param(IS_RTC_DATE(RTC_DateStruct->Date)); + } + else + { + assert_param(IS_RTC_YEAR(RTC_Bcd2ToByte(RTC_DateStruct->Year))); + tmpregister = RTC_Bcd2ToByte(RTC_DateStruct->Month); + assert_param(IS_RTC_MONTH(tmpregister)); + tmpregister = RTC_Bcd2ToByte(RTC_DateStruct->Date); + assert_param(IS_RTC_DATE(tmpregister)); + } + assert_param(IS_RTC_WEEKDAY(RTC_DateStruct->WeekDay)); + + /* Check the input parameters format */ + if (RTC_Format != RTC_FORMAT_BIN) + { + tmpregister = ((((uint32_t)RTC_DateStruct->Year) << 16) | (((uint32_t)RTC_DateStruct->Month) << 8) + | ((uint32_t)RTC_DateStruct->Date) | (((uint32_t)RTC_DateStruct->WeekDay) << 13)); + } + else + { + tmpregister = (((uint32_t)RTC_ByteToBcd2(RTC_DateStruct->Year) << 16) + | ((uint32_t)RTC_ByteToBcd2(RTC_DateStruct->Month) << 8) + | ((uint32_t)RTC_ByteToBcd2(RTC_DateStruct->Date)) | ((uint32_t)RTC_DateStruct->WeekDay << 13)); + } + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* Set Initialization mode */ + if (RTC_EnterInitMode() == ERROR) + { + status = ERROR; + } + else + { + /* Set the RTC_DATE register */ + RTC->DATE = (uint32_t)(tmpregister & RTC_DATE_RESERVED_MASK); + + /* Exit Initialization mode */ + RTC_ExitInitMode(); + + /* If RTC_CTRL_BYPS bit = 0, wait for synchro else this check is not needed */ + if ((RTC->CTRL & RTC_CTRL_BYPS) == RESET) + { + if (RTC_WaitForSynchro() == ERROR) + { + status = ERROR; + } + else + { + status = SUCCESS; + } + } + else + { + status = SUCCESS; + } + } + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; + /* Waits until the RTC Time and Date registers + (RTC_TSH and RTC_DATE) are synchronized with RTC APB clock. */ + status=RTC_WaitForSynchro(); + return status; +} + +/** + * @brief Fills each RTC_DateStruct member with its default value + * (Monday, January 01 xx00). + * @param RTC_DateStruct pointer to a RTC_DateType structure which will be + * initialized. + */ +void RTC_DateStructInit(RTC_DateType* RTC_DateStruct) +{ + /* Monday, January 01 xx00 */ + RTC_DateStruct->WeekDay = RTC_WEEKDAY_MONDAY; + RTC_DateStruct->Date = 1; + RTC_DateStruct->Month = RTC_MONTH_JANUARY; + RTC_DateStruct->Year = 0; +} + +/** + * @brief Get the RTC current date. + * @param RTC_Format specifies the format of the returned parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN Binary data format. + * @arg RTC_FORMAT_BCD BCD data format. + * @param RTC_DateStruct pointer to a RTC_DateType structure that will + * contain the returned current date configuration. + */ +void RTC_GetDate(uint32_t RTC_Format, RTC_DateType* RTC_DateStruct) +{ + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(RTC_Format)); + + /* Get the RTC_TSH register */ + tmpregister = (uint32_t)(RTC->DATE & RTC_DATE_RESERVED_MASK); + + /* Fill the structure fields with the read parameters */ + RTC_DateStruct->Year = (uint8_t)((tmpregister & (RTC_DATE_YRT | RTC_DATE_YRU)) >> 16); + RTC_DateStruct->Month = (uint8_t)((tmpregister & (RTC_DATE_MOT | RTC_DATE_MOU)) >> 8); + RTC_DateStruct->Date = (uint8_t)(tmpregister & (RTC_DATE_DAT | RTC_DATE_DAU)); + RTC_DateStruct->WeekDay = (uint8_t)((tmpregister & (RTC_DATE_WDU)) >> 13); + + /* Check the input parameters format */ + if (RTC_Format == RTC_FORMAT_BIN) + { + /* Convert the structure parameters to Binary format */ + RTC_DateStruct->Year = (uint8_t)RTC_Bcd2ToByte(RTC_DateStruct->Year); + RTC_DateStruct->Month = (uint8_t)RTC_Bcd2ToByte(RTC_DateStruct->Month); + RTC_DateStruct->Date = (uint8_t)RTC_Bcd2ToByte(RTC_DateStruct->Date); + } +} + +/** + * @} + */ + +/** @addtogroup RTC_Group3 Alarms configuration functions + * @brief Alarms (Alarm A and Alarm B) configuration functions + * +@verbatim + =============================================================================== + ##### Alarms (Alarm A and Alarm B) configuration functions ##### + =============================================================================== + [..] This section provide functions allowing to program and read the RTC + Alarms. + +@endverbatim + * @{ + */ + +/** + * @brief Set the specified RTC Alarm. + * @note The Alarm register can only be written when the corresponding Alarm + * is disabled (Use the RTC_EnableAlarm(DISABLE)). + * @param RTC_Format specifies the format of the returned parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN Binary data format. + * @arg RTC_FORMAT_BCD BCD data format. + * @param RTC_Alarm specifies the alarm to be configured. + * This parameter can be one of the following values: + * @arg RTC_A_ALARM to select Alarm A. + * @arg RTC_B_ALARM to select Alarm B. + * @param RTC_AlarmStruct pointer to a RTC_AlarmType structure that + * contains the alarm configuration parameters. + */ +void RTC_SetAlarm(uint32_t RTC_Format, uint32_t RTC_Alarm, RTC_AlarmType* RTC_AlarmStruct) +{ + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(RTC_Format)); + assert_param(IS_RTC_ALARM_SEL(RTC_Alarm)); + assert_param(IS_ALARM_MASK(RTC_AlarmStruct->AlarmMask)); + assert_param(IS_RTC_ALARM_WEEKDAY_SEL(RTC_AlarmStruct->DateWeekMode)); + + if (RTC_Format == RTC_FORMAT_BIN) + { + if ((RTC->CTRL & RTC_CTRL_HFMT) != (uint32_t)RESET) + { + assert_param(IS_RTC_12HOUR(RTC_AlarmStruct->AlarmTime.Hours)); + assert_param(IS_RTC_H12(RTC_AlarmStruct->AlarmTime.H12)); + } + else + { + RTC_AlarmStruct->AlarmTime.H12 = 0x00; + assert_param(IS_RTC_24HOUR(RTC_AlarmStruct->AlarmTime.Hours)); + } + assert_param(IS_RTC_MINUTES(RTC_AlarmStruct->AlarmTime.Minutes)); + assert_param(IS_RTC_SECONDS(RTC_AlarmStruct->AlarmTime.Seconds)); + + if (RTC_AlarmStruct->DateWeekMode == RTC_ALARM_SEL_WEEKDAY_DATE) + { + assert_param(IS_RTC_ALARM_WEEKDAY_DATE(RTC_AlarmStruct->DateWeekValue)); + } + else + { + assert_param(IS_RTC_ALARM_WEEKDAY_WEEKDAY(RTC_AlarmStruct->DateWeekValue)); + } + } + else + { + if ((RTC->CTRL & RTC_CTRL_HFMT) != (uint32_t)RESET) + { + tmpregister = RTC_Bcd2ToByte(RTC_AlarmStruct->AlarmTime.Hours); + assert_param(IS_RTC_12HOUR(tmpregister)); + assert_param(IS_RTC_H12(RTC_AlarmStruct->AlarmTime.H12)); + } + else + { + RTC_AlarmStruct->AlarmTime.H12 = 0x00; + assert_param(IS_RTC_24HOUR(RTC_Bcd2ToByte(RTC_AlarmStruct->AlarmTime.Hours))); + } + + assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(RTC_AlarmStruct->AlarmTime.Minutes))); + assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(RTC_AlarmStruct->AlarmTime.Seconds))); + + if (RTC_AlarmStruct->DateWeekMode == RTC_ALARM_SEL_WEEKDAY_DATE) + { + tmpregister = RTC_Bcd2ToByte(RTC_AlarmStruct->DateWeekValue); + assert_param(IS_RTC_ALARM_WEEKDAY_DATE(tmpregister)); + } + else + { + tmpregister = RTC_Bcd2ToByte(RTC_AlarmStruct->DateWeekValue); + assert_param(IS_RTC_ALARM_WEEKDAY_WEEKDAY(tmpregister)); + } + } + + /* Check the input parameters format */ + if (RTC_Format != RTC_FORMAT_BIN) + { + tmpregister = + (((uint32_t)(RTC_AlarmStruct->AlarmTime.Hours) << 16) + | ((uint32_t)(RTC_AlarmStruct->AlarmTime.Minutes) << 8) | ((uint32_t)RTC_AlarmStruct->AlarmTime.Seconds) + | ((uint32_t)(RTC_AlarmStruct->AlarmTime.H12) << 16) | ((uint32_t)(RTC_AlarmStruct->DateWeekValue) << 24) + | ((uint32_t)RTC_AlarmStruct->DateWeekMode) | ((uint32_t)RTC_AlarmStruct->AlarmMask)); + } + else + { + tmpregister = (((uint32_t)RTC_ByteToBcd2(RTC_AlarmStruct->AlarmTime.Hours) << 16) + | ((uint32_t)RTC_ByteToBcd2(RTC_AlarmStruct->AlarmTime.Minutes) << 8) + | ((uint32_t)RTC_ByteToBcd2(RTC_AlarmStruct->AlarmTime.Seconds)) + | ((uint32_t)(RTC_AlarmStruct->AlarmTime.H12) << 16) + | ((uint32_t)RTC_ByteToBcd2(RTC_AlarmStruct->DateWeekValue) << 24) + | ((uint32_t)RTC_AlarmStruct->DateWeekMode) | ((uint32_t)RTC_AlarmStruct->AlarmMask)); + } + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* Configure the Alarm register */ + if (RTC_Alarm == RTC_A_ALARM) + { + RTC->ALARMA = (uint32_t)tmpregister; + } + else + { + RTC->ALARMB = (uint32_t)tmpregister; + } + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; +} + +/** + * @brief Fills each RTC_AlarmStruct member with its default value + * (Time = 00h:00mn:00sec / Date = 1st day of the month/Mask = + * all fields are masked). + * @param RTC_AlarmStruct pointer to a @ref RTC_AlarmType structure which + * will be initialized. + */ +void RTC_AlarmStructInit(RTC_AlarmType* RTC_AlarmStruct) +{ + /* Alarm Time Settings : Time = 00h:00mn:00sec */ + RTC_AlarmStruct->AlarmTime.H12 = RTC_AM_H12; + RTC_AlarmStruct->AlarmTime.Hours = 0; + RTC_AlarmStruct->AlarmTime.Minutes = 0; + RTC_AlarmStruct->AlarmTime.Seconds = 0; + + /* Alarm Date Settings : Date = 1st day of the month */ + RTC_AlarmStruct->DateWeekMode = RTC_ALARM_SEL_WEEKDAY_DATE; + RTC_AlarmStruct->DateWeekValue = 1; + + /* Alarm Masks Settings : Mask = all fields are not masked */ + RTC_AlarmStruct->AlarmMask = RTC_ALARMMASK_NONE; +} + +/** + * @brief Get the RTC Alarm value and masks. + * @param RTC_Format specifies the format of the output parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN Binary data format. + * @arg RTC_FORMAT_BCD BCD data format. + * @param RTC_Alarm specifies the alarm to be read. + * This parameter can be one of the following values: + * @arg RTC_A_ALARM to select Alarm A. + * @arg RTC_B_ALARM to select Alarm B. + * @param RTC_AlarmStruct pointer to a RTC_AlarmType structure that will + * contains the output alarm configuration values. + */ +void RTC_GetAlarm(uint32_t RTC_Format, uint32_t RTC_Alarm, RTC_AlarmType* RTC_AlarmStruct) +{ + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(RTC_Format)); + assert_param(IS_RTC_ALARM_SEL(RTC_Alarm)); + + /* Get the RTC_ALARMx register */ + if (RTC_Alarm == RTC_A_ALARM) + { + tmpregister = (uint32_t)(RTC->ALARMA); + } + else + { + tmpregister = (uint32_t)(RTC->ALARMB); + } + + /* Fill the structure with the read parameters */ + RTC_AlarmStruct->AlarmTime.Hours = (uint32_t)((tmpregister & (RTC_ALARMA_HOT | RTC_ALARMA_HOU)) >> 16); + RTC_AlarmStruct->AlarmTime.Minutes = (uint32_t)((tmpregister & (RTC_ALARMA_MIT | RTC_ALARMA_MIU)) >> 8); + RTC_AlarmStruct->AlarmTime.Seconds = (uint32_t)(tmpregister & (RTC_ALARMA_SET | RTC_ALARMA_SEU)); + RTC_AlarmStruct->AlarmTime.H12 = (uint32_t)((tmpregister & RTC_ALARMA_APM) >> 16); + RTC_AlarmStruct->DateWeekValue = (uint32_t)((tmpregister & (RTC_ALARMA_DTT | RTC_ALARMA_DTU)) >> 24); + RTC_AlarmStruct->DateWeekMode = (uint32_t)(tmpregister & RTC_ALARMA_WKDSEL); + RTC_AlarmStruct->AlarmMask = (uint32_t)(tmpregister & RTC_ALARMMASK_ALL); + + if (RTC_Format == RTC_FORMAT_BIN) + { + RTC_AlarmStruct->AlarmTime.Hours = RTC_Bcd2ToByte(RTC_AlarmStruct->AlarmTime.Hours); + RTC_AlarmStruct->AlarmTime.Minutes = RTC_Bcd2ToByte(RTC_AlarmStruct->AlarmTime.Minutes); + RTC_AlarmStruct->AlarmTime.Seconds = RTC_Bcd2ToByte(RTC_AlarmStruct->AlarmTime.Seconds); + RTC_AlarmStruct->DateWeekValue = RTC_Bcd2ToByte(RTC_AlarmStruct->DateWeekValue); + } +} + +/** + * @brief Enables or disables the specified RTC Alarm. + * @param RTC_Alarm specifies the alarm to be configured. + * This parameter can be any combination of the following values: + * @arg RTC_A_ALARM to select Alarm A. + * @arg RTC_B_ALARM to select Alarm B. + * @param Cmd new state of the specified alarm. + * This parameter can be: ENABLE or DISABLE. + * @return An ErrorStatus enumeration value: + * - SUCCESS: RTC Alarm is enabled/disabled + * - ERROR: RTC Alarm is not enabled/disabled + */ +ErrorStatus RTC_EnableAlarm(uint32_t RTC_Alarm, FunctionalState Cmd) +{ + __IO uint32_t alarmcounter = 0x00; + uint32_t alarmstatus = 0x00; + ErrorStatus status = ERROR; + + /* Check the parameters */ + assert_param(IS_RTC_ALARM_ENABLE(RTC_Alarm)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* Configure the Alarm state */ + if (Cmd != DISABLE) + { + RTC->CTRL |= (uint32_t)RTC_Alarm; + + status = SUCCESS; + } + else + { + /* Disable the Alarm in RTC_CTRL register */ + RTC->CTRL &= (uint32_t)~RTC_Alarm; + + /* Wait till RTC ALxWF flag is set and if Time out is reached exit */ + do + { + alarmstatus = RTC->INITSTS & (RTC_Alarm >> 8); + alarmcounter++; + } while ((alarmcounter != INITMODE_TIMEOUT) && (alarmstatus == 0x00)); + + if ((RTC->INITSTS & (RTC_Alarm >> 8)) == RESET) + { + status = ERROR; + } + else + { + status = SUCCESS; + } + } + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; + + return status; +} + +/** + * @brief Configure the RTC AlarmA/B Subseconds value and mask.* + * @note This function is performed only when the Alarm is disabled. + * @param RTC_Alarm specifies the alarm to be configured. + * This parameter can be one of the following values: + * @arg RTC_A_ALARM to select Alarm A. + * @arg RTC_B_ALARM to select Alarm B. + * @param RTC_AlarmSubSecondValue specifies the Subseconds value. + * This parameter can be a value from 0 to 0x00007FFF. + * @param RTC_AlarmSubSecondMask specifies the Subseconds Mask. + * This parameter can be any combination of the following values: + * @arg RTC_SUBS_MASK_ALL All Alarm SS fields are masked. + * There is no comparison on sub seconds for Alarm. + * @arg RTC_SUBS_MASK_SS14_1 SS[14:1] are don't care in Alarm comparison. + * Only SS[0] is compared + * @arg RTC_SUBS_MASK_SS14_2 SS[14:2] are don't care in Alarm comparison. + * Only SS[1:0] are compared + * @arg RTC_SUBS_MASK_SS14_3 SS[14:3] are don't care in Alarm comparison. + * Only SS[2:0] are compared + * @arg RTC_SUBS_MASK_SS14_4 SS[14:4] are don't care in Alarm comparison. + * Only SS[3:0] are compared + * @arg RTC_SUBS_MASK_SS14_5 SS[14:5] are don't care in Alarm comparison. + * Only SS[4:0] are compared. + * @arg RTC_SUBS_MASK_SS14_6 SS[14:6] are don't care in Alarm comparison. + * Only SS[5:0] are compared. + * @arg RTC_SUBS_MASK_SS14_7 SS[14:7] are don't care in Alarm comparison. + * Only SS[6:0] are compared. + * @arg RTC_SUBS_MASK_SS14_8 SS[14:8] are don't care in Alarm comparison. + * Only SS[7:0] are compared. + * @arg RTC_SUBS_MASK_SS14_9 SS[14:9] are don't care in Alarm comparison. + * Only SS[8:0] are compared. + * @arg RTC_SUBS_MASK_SS14_10 SS[14:10] are don't care in Alarm comparison. + * Only SS[9:0] are compared. + * @arg RTC_SUBS_MASK_SS14_11 SS[14:11] are don't care in Alarm comparison. + * Only SS[10:0] are compared. + * @arg RTC_SUBS_MASK_SS14_12 SS[14:12] are don't care in Alarm comparison. + * Only SS[11:0] are compared. + * @arg RTC_SUBS_MASK_SS14_13 SS[14:13] are don't care in Alarm comparison. + * Only SS[12:0] are compared. + * @arg RTC_SUBS_MASK_SS14_14 SS[14] is don't care in Alarm comparison. + * Only SS[13:0] are compared. + * @arg RTC_SUBS_MASK_NONE SS[14:0] are compared and must match + * to activate alarm. + */ +void RTC_ConfigAlarmSubSecond(uint32_t RTC_Alarm, uint32_t RTC_AlarmSubSecondValue, uint32_t RTC_AlarmSubSecondMask) +{ + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_RTC_ALARM_SEL(RTC_Alarm)); + assert_param(IS_RTC_ALARM_SUB_SECOND_VALUE(RTC_AlarmSubSecondValue)); + assert_param(IS_RTC_ALARM_SUB_SECOND_MASK_MODE(RTC_AlarmSubSecondMask)); + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* Configure the Alarm A or Alarm B SubSecond registers */ + tmpregister = (uint32_t)(uint32_t)(RTC_AlarmSubSecondValue) | (uint32_t)(RTC_AlarmSubSecondMask); + + if (RTC_Alarm == RTC_A_ALARM) + { + /* Configure the AlarmA SubSecond register */ + RTC->ALRMASS = tmpregister; + } + else + { + /* Configure the Alarm B SubSecond register */ + RTC->ALRMBSS = tmpregister; + } + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; +} + +/** + * @brief Gets the RTC Alarm Subseconds value. + * @param RTC_Alarm specifies the alarm to be read. + * This parameter can be one of the following values: + * @arg RTC_A_ALARM to select Alarm A. + * @arg RTC_B_ALARM to select Alarm B. + * @return RTC Alarm Subseconds value. + */ +uint32_t RTC_GetAlarmSubSecond(uint32_t RTC_Alarm) +{ + uint32_t tmpregister = 0; + + /* Get the RTC_ALARMx register */ + if (RTC_Alarm == RTC_A_ALARM) + { + tmpregister = (uint32_t)((RTC->ALRMASS) & RTC_ALRMASS_SSV); + } + else + { + tmpregister = (uint32_t)((RTC->ALRMBSS) & RTC_ALRMBSS_SSV); + } + + return (tmpregister); +} + +/** + * @} + */ + +/** @addtogroup RTC_Group4 WakeUp Timer configuration functions + * @brief WakeUp Timer configuration functions + * +@verbatim + =============================================================================== + ##### WakeUp Timer configuration functions ##### + =============================================================================== + [..] This section provide functions allowing to program and read the RTC WakeUp. + +@endverbatim + * @{ + */ + +/** + * @brief Configures the RTC Wakeup clock source. + * @note The WakeUp Clock source can only be changed when the RTC WakeUp + * is disabled (Use the RTC_EnableWakeUp(DISABLE)). + * @param RTC_WakeUpClock Wakeup Clock source. + * This parameter can be one of the following values: + * @arg RTC_WKUPCLK_RTCCLK_DIV16 RTC Wakeup Counter Clock = RTCCLK/16. + * @arg RTC_WKUPCLK_RTCCLK_DIV8 RTC Wakeup Counter Clock = RTCCLK/8. + * @arg RTC_WKUPCLK_RTCCLK_DIV4 RTC Wakeup Counter Clock = RTCCLK/4. + * @arg RTC_WKUPCLK_RTCCLK_DIV2 RTC Wakeup Counter Clock = RTCCLK/2. + * @arg RTC_WKUPCLK_CK_SPRE_16BITS RTC Wakeup Counter Clock = CK_SPRE. + */ +void RTC_ConfigWakeUpClock(uint32_t RTC_WakeUpClock) +{ + /* Check the parameters */ + assert_param(IS_RTC_WKUP_CLOCK(RTC_WakeUpClock)); + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* Clear the Wakeup Timer clock source bits in CTRL register */ + RTC->CTRL &= (uint32_t)~RTC_CTRL_WKUPSEL; + + /* Configure the clock source */ + RTC->CTRL |= (uint32_t)RTC_WakeUpClock; + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; +} + +/** + * @brief Configures the RTC Wakeup counter. + * @note The RTC WakeUp counter can only be written when the RTC WakeUp. + * is disabled (Use the RTC_EnableWakeUp(DISABLE)). + * @param RTC_WakeUpCounter specifies the WakeUp counter. + * This parameter can be a value from 0x0000 to 0xFFFF. + */ +void RTC_SetWakeUpCounter(uint32_t RTC_WakeUpCounter) +{ + /* Check the parameters */ + assert_param(IS_RTC_WKUP_COUNTER(RTC_WakeUpCounter)); + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* Configure the Wakeup Timer counter */ + RTC->WKUPT = (uint32_t)RTC_WakeUpCounter; + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; +} + +/** + * @brief Returns the RTC WakeUp timer counter value. + * @return The RTC WakeUp Counter value. + */ +uint32_t RTC_GetWakeUpCounter(void) +{ + /* Get the counter value */ + return ((uint32_t)(RTC->WKUPT & RTC_WKUPT_WKUPT)); +} + +/** + * @brief Enables or Disables the RTC WakeUp timer. + * @param Cmd new state of the WakeUp timer. + * This parameter can be: ENABLE or DISABLE. + */ +ErrorStatus RTC_EnableWakeUp(FunctionalState Cmd) +{ + __IO uint32_t wutcounter = 0x00; + uint32_t wutwfstatus = 0x00; + ErrorStatus status = ERROR; + + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + if (Cmd != DISABLE) + { + /* Enable the Wakeup Timer */ + RTC->CTRL |= (uint32_t)RTC_CTRL_WTEN; + status = SUCCESS; + } + else + { + /* Disable the Wakeup Timer */ + RTC->CTRL &= (uint32_t)~RTC_CTRL_WTEN; + /* Wait till RTC WTWF flag is set and if Time out is reached exit */ + do + { + wutwfstatus = RTC->INITSTS & RTC_INITSTS_WTWF; + wutcounter++; + } while ((wutcounter != INITMODE_TIMEOUT) && (wutwfstatus == 0x00)); + + if ((RTC->INITSTS & RTC_INITSTS_WTWF) == RESET) + { + status = ERROR; + } + else + { + status = SUCCESS; + } + } + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; + + return status; +} + +/** + * @} + */ + +/** @addtogroup RTC_Group5 Daylight Saving configuration functions + * @brief Daylight Saving configuration functions + * +@verbatim + =============================================================================== + ##### Daylight Saving configuration functions ##### + =============================================================================== + [..] This section provide functions allowing to configure the RTC DayLight Saving. + +@endverbatim + * @{ + */ + +/** + * @brief Adds or substract one hour from the current time. + * @param RTC_DayLightSaving the value of hour adjustment. + * This parameter can be one of the following values: + * @arg RTC_DAYLIGHT_SAVING_SUB1H Substract one hour (winter time). + * @arg RTC_DAYLIGHT_SAVING_ADD1H Add one hour (summer time). + * @param RTC_StoreOperation Specifies the value to be written in the BCK bit + * in CTRL register to store the operation. + * This parameter can be one of the following values: + * @arg RTC_STORE_OPERATION_RESET BCK Bit Reset. + * @arg RTC_STORE_OPERATION_SET BCK Bit Set. + */ +void RTC_ConfigDayLightSaving(uint32_t RTC_DayLightSaving, uint32_t RTC_StoreOperation) +{ + /* Check the parameters */ + assert_param(IS_RTC_DAYLIGHT_SAVING(RTC_DayLightSaving)); + assert_param(IS_RTC_STORE_OPERATION(RTC_StoreOperation)); + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* Clear the bits to be configured */ + RTC->CTRL &= (uint32_t) ~(RTC_CTRL_BAKP); + /* Clear the SU1H and AD1H bits to be configured */ + RTC->CTRL &= (uint32_t) ~(RTC_CTRL_SU1H & RTC_CTRL_AD1H); + /* Configure the RTC_CTRL register */ + RTC->CTRL |= (uint32_t)(RTC_DayLightSaving | RTC_StoreOperation); + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; +} + +/** + * @brief Returns the RTC Day Light Saving stored operation. + * @return RTC Day Light Saving stored operation. + * - RTC_STORE_OPERATION_RESET + * - RTC_STORE_OPERATION_SET + */ +uint32_t RTC_GetStoreOperation(void) +{ + return (RTC->CTRL & RTC_CTRL_BAKP); +} + +/** + * @} + */ + +/** @addtogroup RTC_Group6 Output pin Configuration function + * @brief Output pin Configuration function + * +@verbatim + =============================================================================== + ##### Output pin Configuration function ##### + =============================================================================== + [..] This section provide functions allowing to configure the RTC Output source. + +@endverbatim + * @{ + */ + + + +/** + * @brief Configures the RTC output source (AFO_ALARM). + * @param RTC_Output Specifies which signal will be routed to the RTC output. + * This parameter can be one of the following values: + * @arg RTC_OUTPUT_DIS No output selected + * @arg RTC_OUTPUT_ALA signal of AlarmA mapped to output. + * @arg RTC_OUTPUT_ALB signal of AlarmB mapped to output. + * @arg RTC_OUTPUT_WKUP signal of WakeUp mapped to output. + * @param RTC_OutputPolarity Specifies the polarity of the output signal. + * This parameter can be one of the following: + * @arg RTC_OUTPOL_HIGH The output pin is high when the + * ALRAF/ALRBF/WUTF is high (depending on OSEL). + * @arg RTC_OUTPOL_LOW The output pin is low when the + * ALRAF/ALRBF/WUTF is high (depending on OSEL). + */ +void RTC_ConfigOutput(uint32_t RTC_Output, uint32_t RTC_OutputPolarity) +{ + __IO uint32_t temp = 0; + /* Check the parameters */ + assert_param(IS_RTC_OUTPUT_MODE(RTC_Output)); + assert_param(IS_RTC_OUTPUT_POL(RTC_OutputPolarity)); + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* Clear the bits to be configured */ + RTC->CTRL &= (uint32_t) ~(RTC_CTRL_OUTSEL | RTC_CTRL_OPOL); + + /* Configure the output selection and polarity */ + RTC->CTRL |= (uint32_t)(RTC_Output | RTC_OutputPolarity); + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; +} + +/** + * @} + */ + +/** @addtogroup RTC_Group7 Coarse and Smooth Calibrations configuration functions + * @brief Coarse and Smooth Calibrations configuration functions + * +@verbatim + =============================================================================== + ##### Coarse and Smooth Calibrations configuration functions ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Enables or disables the RTC clock to be output through the relative + * pin. + * @param Cmd new state of the coarse calibration Output. + * This parameter can be: ENABLE or DISABLE. + */ +void RTC_EnableCalibOutput(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + if (Cmd != DISABLE) + { + /* Enable the RTC clock output */ + RTC->CTRL |= (uint32_t)RTC_CTRL_COEN; + } + else + { + /* Disable the RTC clock output */ + RTC->CTRL &= (uint32_t)~RTC_CTRL_COEN; + } + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; +} + +/** + * @brief Configure the Calibration Pinout (RTC_CALIB) Selection (1Hz or 512Hz). + * @param RTC_CalibOutput Select the Calibration output Selection . + * This parameter can be one of the following values: + * @arg RTC_CALIB_OUTPUT_256HZ A signal has a regular waveform at 256Hz. + * @arg RTC_CALIB_OUTPUT_1HZ A signal has a regular waveform at 1Hz. + */ +void RTC_ConfigCalibOutput(uint32_t RTC_CalibOutput) +{ + /* Check the parameters */ + assert_param(IS_RTC_CALIB_OUTPUT(RTC_CalibOutput)); + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /*clear flags before config*/ + RTC->CTRL &= (uint32_t) ~(RTC_CTRL_CALOSEL); + + /* Configure the RTC_CTRL register */ + RTC->CTRL |= (uint32_t)RTC_CalibOutput; + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; +} + +/** + * @brief Configures the Smooth Calibration Settings. + * @param RTC_SmoothCalibPeriod Select the Smooth Calibration Period. + * This parameter can be can be one of the following values: + * @arg SMOOTH_CALIB_32SEC The smooth calibration periode is 32s. + * @arg SMOOTH_CALIB_16SEC The smooth calibration periode is 16s. + * @arg SMOOTH_CALIB_8SEC The smooth calibartion periode is 8s. + * @param RTC_SmoothCalibPlusPulses Select to Set or reset the CALP bit. + * This parameter can be one of the following values: + * @arg RTC_SMOOTH_CALIB_PLUS_PULSES_SET Add one RTCCLK puls every 2**11 pulses. + * @arg RTC_SMOOTH_CALIB_PLUS_PULSES__RESET No RTCCLK pulses are added. + * @param RTC_SmouthCalibMinusPulsesValue Select the value of CALM[8:0] bits. + * This parameter can be one any value from 0 to 0x000001FF. + * @return An ErrorStatus enumeration value: + * - SUCCESS: RTC Calib registers are configured + * - ERROR: RTC Calib registers are not configured + */ +ErrorStatus RTC_ConfigSmoothCalib(uint32_t RTC_SmoothCalibPeriod, + uint32_t RTC_SmoothCalibPlusPulses, + uint32_t RTC_SmouthCalibMinusPulsesValue) +{ + ErrorStatus status = ERROR; + uint32_t recalpfcount = 0; + + /* Check the parameters */ + assert_param(IS_RTC_SMOOTH_CALIB_PERIOD_SEL(RTC_SmoothCalibPeriod)); + assert_param(IS_RTC_SMOOTH_CALIB_PLUS(RTC_SmoothCalibPlusPulses)); + assert_param(IS_RTC_SMOOTH_CALIB_MINUS(RTC_SmouthCalibMinusPulsesValue)); + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* check if a calibration is pending*/ + if ((RTC->INITSTS & RTC_INITSTS_RECPF) != RESET) + { + /* wait until the Calibration is completed*/ + while (((RTC->INITSTS & RTC_INITSTS_RECPF) != RESET) && (recalpfcount != RECALPF_TIMEOUT)) + { + recalpfcount++; + } + } + + /* check if the calibration pending is completed or if there is no calibration operation at all*/ + if ((RTC->INITSTS & RTC_INITSTS_RECPF) == RESET) + { + /* Configure the Smooth calibration settings */ + RTC->CALIB = (uint32_t)((uint32_t)RTC_SmoothCalibPeriod | (uint32_t)RTC_SmoothCalibPlusPulses + | (uint32_t)RTC_SmouthCalibMinusPulsesValue); + + status = SUCCESS; + } + else + { + status = ERROR; + } + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; + + return (ErrorStatus)(status); +} + +/** + * @} + */ + +/** @addtogroup RTC_Group8 TimeStamp configuration functions + * @brief TimeStamp configuration functions + * +@verbatim + =============================================================================== + ##### TimeStamp configuration functions ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Enables or Disables the RTC TimeStamp functionality with the + * specified time stamp pin stimulating edge. + * @param RTC_TimeStampEdge Specifies the pin edge on which the TimeStamp is + * activated. + * This parameter can be one of the following: + * @arg RTC_TIMESTAMP_EDGE_RISING the Time stamp event occurs on the rising + * edge of the related pin. + * @arg RTC_TIMESTAMP_EDGE_FALLING the Time stamp event occurs on the + * falling edge of the related pin. + * @param Cmd new state of the TimeStamp. + * This parameter can be: ENABLE or DISABLE. + */ +void RTC_EnableTimeStamp(uint32_t RTC_TimeStampEdge, FunctionalState Cmd) +{ + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_RTC_TIMESTAMP_EDGE_MODE(RTC_TimeStampEdge)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + /* Get the RTC_CTRL register and clear the bits to be configured */ + tmpregister = (uint32_t)(RTC->CTRL & (uint32_t) ~(RTC_CTRL_TSPOL | RTC_CTRL_TSEN)); + + /* Get the new configuration */ + if (Cmd != DISABLE) + { + tmpregister |= (uint32_t)(RTC_TimeStampEdge | RTC_CTRL_TSEN); + } + else + { + tmpregister |= (uint32_t)(RTC_TimeStampEdge); + } + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* Configure the Time Stamp TSEDGE and Enable bits */ + RTC->CTRL = (uint32_t)tmpregister; + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; +} + +/** + * @brief Get the RTC TimeStamp value and masks. + * @param RTC_Format specifies the format of the output parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN Binary data format + * @arg RTC_FORMAT_BCD BCD data format + * @param RTC_StampTimeStruct pointer to a RTC_TimeType structure that will + * contains the TimeStamp time values. + * @param RTC_StampDateStruct pointer to a RTC_DateType structure that will + * contains the TimeStamp date values. + */ +void RTC_GetTimeStamp(uint32_t RTC_Format, RTC_TimeType* RTC_StampTimeStruct, RTC_DateType* RTC_StampDateStruct) +{ + uint32_t tmptime = 0, tmpdate = 0; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(RTC_Format)); + + /* Get the TimeStamp time and date registers values */ + tmptime = (uint32_t)(RTC->TST & RTC_TR_RESERVED_MASK); + tmpdate = (uint32_t)(RTC->TSD & RTC_DATE_RESERVED_MASK); + + /* Fill the Time structure fields with the read parameters */ + RTC_StampTimeStruct->Hours = (uint8_t)((tmptime & (RTC_TSH_HOT | RTC_TSH_HOU)) >> 16); + RTC_StampTimeStruct->Minutes = (uint8_t)((tmptime & (RTC_TSH_MIT | RTC_TSH_MIU)) >> 8); + RTC_StampTimeStruct->Seconds = (uint8_t)(tmptime & (RTC_TSH_SCT | RTC_TSH_SCU)); + RTC_StampTimeStruct->H12 = (uint8_t)((tmptime & (RTC_TSH_APM)) >> 16); + + /* Fill the Date structure fields with the read parameters */ + RTC_StampDateStruct->Year = (uint8_t)((tmpdate & (RTC_DATE_YRT | RTC_DATE_YRU)) >> 16); + RTC_StampDateStruct->Month = (uint8_t)((tmpdate & (RTC_DATE_MOT | RTC_DATE_MOU)) >> 8); + RTC_StampDateStruct->Date = (uint8_t)(tmpdate & (RTC_DATE_DAT | RTC_DATE_DAU)); + RTC_StampDateStruct->WeekDay = (uint8_t)((tmpdate & (RTC_DATE_WDU)) >> 13); + + /* Check the input parameters format */ + if (RTC_Format == RTC_FORMAT_BIN) + { + /* Convert the Time structure parameters to Binary format */ + RTC_StampTimeStruct->Hours = (uint8_t)RTC_Bcd2ToByte(RTC_StampTimeStruct->Hours); + RTC_StampTimeStruct->Minutes = (uint8_t)RTC_Bcd2ToByte(RTC_StampTimeStruct->Minutes); + RTC_StampTimeStruct->Seconds = (uint8_t)RTC_Bcd2ToByte(RTC_StampTimeStruct->Seconds); + + /* Convert the Date structure parameters to Binary format */ + RTC_StampDateStruct->Month = (uint8_t)RTC_Bcd2ToByte(RTC_StampDateStruct->Month); + RTC_StampDateStruct->Date = (uint8_t)RTC_Bcd2ToByte(RTC_StampDateStruct->Date); + RTC_StampDateStruct->WeekDay = (uint8_t)RTC_Bcd2ToByte(RTC_StampDateStruct->WeekDay); + } +} + +/** + * @brief Get the RTC timestamp Subseconds value. + * @return RTC current timestamp Subseconds value. + */ +uint32_t RTC_GetTimeStampSubSecond(void) +{ + /* Get timestamp subseconds values from the correspondent registers */ + return (uint32_t)(RTC->TSSS); +} + +/** + * @} + */ + +/** @addtogroup RTC_Group11 Output Type Config configuration functions + * @brief Output Type Config configuration functions + * +@verbatim + =============================================================================== + ##### Output Type Config configuration functions ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Configures the RTC Output Pin mode. + * @param RTC_OutputType specifies the RTC Output (PC13) pin mode. + * This parameter can be one of the following values: + * @arg RTC_OUTPUT_OPENDRAIN RTC Output (PC13) is configured in + * Open Drain mode. + * @arg RTC_OUTPUT_PUSHPULL RTC Output (PC13) is configured in + * Push Pull mode. + */ +void RTC_ConfigOutputType(uint32_t RTC_OutputType) +{ + /* Check the parameters */ + assert_param(IS_RTC_OUTPUT_TYPE(RTC_OutputType)); + + RTC->OPT &= (uint32_t) ~(RTC_OPT_TYPE); + RTC->OPT |= (uint32_t)(RTC_OutputType); +} + +/** + * @} + */ + +/** @addtogroup RTC_Group12 Shift control synchronisation functions + * @brief Shift control synchronisation functions + * +@verbatim + =============================================================================== + ##### Shift control synchronisation functions ##### + =============================================================================== + +@endverbatim + * @{ + */ + +/** + * @brief Configures the Synchronization Shift Control Settings. + * @param RTC_ShiftAdd1S Select to add or not 1 second to the time Calendar. + * This parameter can be one of the following values : + * @arg RTC_SHIFT_SUB1S_DISABLE Add one second to the clock calendar. + * @arg RTC_SHIFT_SUB1S_ENABLE No effect. + * @param RTC_ShiftAddFS Select the number of Second Fractions to Substitute. + * This parameter can be one any value from 0 to 0x7FFF. + * @return An ErrorStatus enumeration value: + * - SUCCESS: RTC Shift registers are configured + * - ERROR: RTC Shift registers are not configured + */ +ErrorStatus RTC_ConfigSynchroShift(uint32_t RTC_ShiftAddFS, uint32_t RTC_ShiftSub1s) +{ + ErrorStatus status = ERROR; + uint32_t shpfcount = 0; + + /* Check the parameters */ + assert_param(IS_RTC_SHIFT_ADFS(RTC_ShiftAddFS)); + assert_param(IS_RTC_SHIFT_SUB1S(RTC_ShiftSub1s)); + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + /* Check if a Shift is pending*/ + if ((RTC->INITSTS & RTC_INITSTS_SHOPF) != RESET) + { + /* Wait until the shift is completed*/ + while (((RTC->INITSTS & RTC_INITSTS_SHOPF) != RESET) && (shpfcount != SHPF_TIMEOUT)) + { + shpfcount++; + } + } + + /* Check if the Shift pending is completed or if there is no Shift operation at all*/ + if ((RTC->INITSTS & RTC_INITSTS_SHOPF) == RESET) + { + + { + /* Configure the Shift settings */ + RTC->SCTRL = (uint32_t)(uint32_t)(RTC_ShiftAddFS) | (uint32_t)(RTC_ShiftSub1s); + + if (RTC_WaitForSynchro() == ERROR) + { + status = ERROR; + } + else + { + status = SUCCESS; + } + } + + } + else + { + status = ERROR; + } + + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; + + return (ErrorStatus)(status); +} + +/** + * @} + */ + +/** @addtogroup RTC_Group13 Interrupts and flags management functions + * @brief Interrupts and flags management functions + * +@verbatim + =============================================================================== + ##### Interrupts and flags management functions ##### + =============================================================================== + [..] All RTC interrupts are connected to the EXTI controller. + (+) To enable the RTC Alarm interrupt, the following sequence is required: + (+) Configure and enable the EXTI Line 17 in interrupt mode and select + the rising edge sensitivity using the EXTI_InitPeripheral() function. + (+) Configure and enable the RTC_Alarm IRQ channel in the NVIC using + the NVIC_Init() function. + (+) Configure the RTC to generate RTC alarms (Alarm A and/or Alarm B) + using the RTC_SetAlarm() and RTC_EnableAlarm() functions. + + (+) To enable the RTC Wakeup interrupt, the following sequence is required: + (+) Configure and enable the EXTI Line 20 in interrupt mode and select + the rising edge sensitivity using the EXTI_InitPeripheral() function. + (+) Configure and enable the RTC_WKUP IRQ channel in the NVIC using the + NVIC_Init() function. + (+) Configure the RTC to generate the RTC wakeup timer event using the + RTC_ConfigWakeUpClock(), RTC_SetWakeUpCounter() and RTC_EnableWakeUp() + functions. + + (+) To enable the RTC Tamper interrupt, the following sequence is required: + (+) Configure and enable the EXTI Line 19 in interrupt mode and select + the rising edge sensitivity using the EXTI_InitPeripheral() function. + (+) Configure and enable the TAMP_STAMP IRQ channel in the NVIC using + the NVIC_Init() function. + (+) Configure the RTC to detect the RTC tamper event using the + RTC_TamperTriggerConfig() and RTC_TamperCmd() functions. + + (+) To enable the RTC TimeStamp interrupt, the following sequence is + required: + (+) Configure and enable the EXTI Line 19 in interrupt mode and select + the rising edge sensitivity using the EXTI_InitPeripheral() function. + (+) Configure and enable the TAMP_STAMP IRQ channel in the NVIC using + the NVIC_Init() function. + (+) Configure the RTC to detect the RTC time-stamp event using the + RTC_EnableTimeStamp() functions. + +@endverbatim + * @{ + */ + +/** + * @brief Enables or disables the specified RTC interrupts. + * @param RTC_INT specifies the RTC interrupt sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg RTC_INT_WUT WakeUp Timer interrupt mask. + * @arg RTC_INT_ALRB Alarm B interrupt mask. + * @arg RTC_INT_ALRA Alarm A interrupt mask. + * @param Cmd new state of the specified RTC interrupts. + * This parameter can be: ENABLE or DISABLE. + */ +void RTC_ConfigInt(uint32_t RTC_INT, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_RTC_CONFIG_INT(RTC_INT)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + /* Disable the write protection for RTC registers */ + RTC->WRP = 0xCA; + RTC->WRP = 0x53; + + if (Cmd != DISABLE) + { + /* Configure the Interrupts in the RTC_CTRL register */ + RTC->CTRL |= RTC_INT ; + } + else + { + /* Configure the Interrupts in the RTC_CTRL register */ + RTC->CTRL &= (uint32_t) ~(RTC_INT); + } + /* Enable the write protection for RTC registers */ + RTC->WRP = 0xFF; +} + +/** + * @brief Checks whether the specified RTC flag is set or not. + * @param RTC_FLAG specifies the flag to check. + * This parameter can be one of the following values: + * @arg RTC_FLAG_RECPF RECALPF event flag. + * @arg RTC_FLAG_TISOVF Time Stamp OverFlow flag. + * @arg RTC_FLAG_TISF Time Stamp event flag. + * @arg RTC_FLAG_WTF WakeUp Timer flag. + * @arg RTC_FLAG_ALBF Alarm B flag. + * @arg RTC_FLAG_ALAF Alarm A flag. + * @arg RTC_FLAG_INITF Initialization mode flag. + * @arg RTC_FLAG_RSYF Registers Synchronized flag. + * @arg RTC_FLAG_INITSF Registers Configured flag. + * @arg RTC_FLAG_SHOPF Shift operation pending flag. + * @arg RTC_FLAG_WTWF WakeUp Timer Write flag. + * @arg RTC_FLAG_ALBWF Alarm B Write flag. + * @arg RTC_FLAG_ALAWF Alarm A write flag. + * @return The new state of RTC_FLAG (SET or RESET). + */ +FlagStatus RTC_GetFlagStatus(uint32_t RTC_FLAG) +{ + FlagStatus bitstatus = RESET; + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_RTC_GET_FLAG(RTC_FLAG)); + + /* Get all the flags */ + tmpregister = (uint32_t)(RTC->INITSTS & RTC_FLAGS_MASK); + + /* Return the status of the flag */ + if ((tmpregister & RTC_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the RTC's pending flags. + * @param RTC_FLAG specifies the RTC flag to clear. + * This parameter can be any combination of the following values:. + * @arg RTC_FLAG_TISOVF Time Stamp Overflow flag. + * @arg RTC_FLAG_TISF Time Stamp event flag. + * @arg RTC_FLAG_WTF WakeUp Timer flag. + * @arg RTC_FLAG_ALBF Alarm B flag. + * @arg RTC_FLAG_ALAF Alarm A flag. + * @arg RTC_FLAG_RSYF Registers Synchronized flag. + */ +void RTC_ClrFlag(uint32_t RTC_FLAG) +{ + /* Check the parameters */ + assert_param(IS_RTC_CLEAR_FLAG(RTC_FLAG)); + + /* Clear the Flags in the RTC_INITSTS register */ + RTC->INITSTS = (uint32_t)( + (uint32_t)(~((RTC_FLAG | RTC_INITSTS_INITM) & 0x00011FFF) | (uint32_t)(RTC->INITSTS & RTC_INITSTS_INITM))); +} + +/** + * @brief Checks whether the specified RTC interrupt has occurred or not. + * @param RTC_INT specifies the RTC interrupt source to check. + * This parameter can be one of the following values: + * @arg RTC_INT_WUT WakeUp Timer interrupt. + * @arg RTC_INT_ALRB Alarm B interrupt. + * @arg RTC_INT_ALRA Alarm A interrupt. + * @return The new state of RTC_INT (SET or RESET). + */ +INTStatus RTC_GetITStatus(uint32_t RTC_INT) +{ + INTStatus bitstatus = RESET; + uint32_t tmpregister = 0, enablestatus = 0; + + /* Check the parameters */ + assert_param(IS_RTC_GET_INT(RTC_INT)); + + /* Get the Interrupt enable Status */ + enablestatus = (uint32_t)((RTC->CTRL & RTC_INT)); + + /* Get the Interrupt pending bit */ + tmpregister = (uint32_t)((RTC->INITSTS & (uint32_t)(RTC_INT >> 4))); + + /* Get the status of the Interrupt */ + if ((enablestatus != (uint32_t)RESET) && ((tmpregister & 0x0000FFFF) != (uint32_t)RESET)) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the RTC's interrupt pending bits. + * @param RTC_INT specifies the RTC interrupt pending bit to clear. + * This parameter can be any combination of the following values: + * @arg RTC_INT_WUT WakeUp Timer interrupt + * @arg RTC_INT_ALRB Alarm B interrupt + * @arg RTC_INT_ALRA Alarm A interrupt + */ +void RTC_ClrIntPendingBit(uint32_t RTC_INT) +{ + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_RTC_CLEAR_INT(RTC_INT)); + + /* Get the RTC_INITSTS Interrupt pending bits mask */ + tmpregister = (uint32_t)(RTC_INT >> 4); + + /* Clear the interrupt pending bits in the RTC_INITSTS register */ + RTC->INITSTS = (uint32_t)( + (uint32_t)(~((tmpregister | RTC_INITSTS_INITM) & 0x0000FFFF) | (uint32_t)(RTC->INITSTS & RTC_INITSTS_INITM))); +} + +/** + * @} + */ + +/** + * @brief Converts a 2 digit decimal to BCD format. + * @param Value Byte to be converted. + * @return Converted byte + */ +static uint8_t RTC_ByteToBcd2(uint8_t Value) +{ + uint8_t bcdhigh = 0; + + while (Value >= 10) + { + bcdhigh++; + Value -= 10; + } + + return ((uint8_t)(bcdhigh << 4) | Value); +} + +/** + * @brief Convert from 2 digit BCD to Binary. + * @param Value BCD value to be converted. + * @return Converted word + */ +static uint8_t RTC_Bcd2ToByte(uint8_t Value) +{ + uint8_t tmp = 0; + tmp = ((uint8_t)(Value & (uint8_t)0xF0) >> (uint8_t)0x4) * 10; + return (tmp + (Value & (uint8_t)0x0F)); +} +/** + * @brief Enable wakeup tsc functionand wakeup by the set time + * @param count wakeup time. + */ +void RTC_EnableWakeUpTsc(uint32_t count) +{ + // Wait until bit RTC_TSCWKUPCTRL_WKUPOFF is 1 + while (!(RTC->TSCWKUPCTRL & RTC_TSCWKUPCTRL_WKUPOFF)) + { + } + // enter config wakeup cnt mode + RTC->TSCWKUPCTRL = RTC_TSCWKUPCTRL_WKUPCNF; + // config tsc wakeup cnt ,tsc wakeup module counting cycle = WAKUPCNT * LSE/LSI + RTC->TSCWKUPCNT = count; + // exit config wakeup cnt mode + RTC->TSCWKUPCTRL &= ~(RTC_TSCWKUPCTRL_WKUPCNF); + while (!(RTC->TSCWKUPCTRL & RTC_TSCWKUPCTRL_WKUPOFF)) + { + } + // TSC wakeup enable + RTC->TSCWKUPCTRL = RTC_TSCWKUPCTRL_WKUPEN; +} +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/src/n32g45x_sdio.c b/src/n32g45x_sdio.c new file mode 100644 index 0000000..cff0be4 --- /dev/null +++ b/src/n32g45x_sdio.c @@ -0,0 +1,789 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_sdio.c + * @author Nations + * @version v1.0.1 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_sdio.h" +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup SDIO + * @brief SDIO driver modules + * @{ + */ + +/** @addtogroup SDIO_Private_TypesDefinitions + * @{ + */ + +/* ------------ SDIO registers bit address in the alias region ----------- */ +#define SDIO_OFFSET (SDIO_BASE - PERIPH_BASE) + +/* --- CLKCTRL Register ---*/ + +/* Alias word address of CLKEN bit */ +#define CLKCTRL_OFFSET (SDIO_OFFSET + 0x04) +#define CLKEN_BIT_NUMBER 0x08 +#define CLKCTRL_CLKEN_BB (PERIPH_BB_BASE + (CLKCTRL_OFFSET * 32) + (CLKEN_BIT_NUMBER * 4)) + +/* --- CMDCTRL Register ---*/ + +/* Alias word address of SDIOSUSPEND bit */ +#define CMD_OFFSET (SDIO_OFFSET + 0x0C) +#define SDIO_SUSPEND_BIT_NUMBER 0x0B +#define CMD_SDIO_SUSPEND_BB (PERIPH_BB_BASE + (CMD_OFFSET * 32) + (SDIO_SUSPEND_BIT_NUMBER * 4)) + +/* Alias word address of ENCMDCOMPL bit */ +#define EN_CMD_COMPL_BIT_NUMBER 0x0C +#define EN_CMD_COMPL_BB (PERIPH_BB_BASE + (CMD_OFFSET * 32) + (EN_CMD_COMPL_BIT_NUMBER * 4)) + +/* Alias word address of NIEN bit */ +#define NIEN_BIT_NUMBER 0x0D +#define CMD_NIEN_BB (PERIPH_BB_BASE + (CMD_OFFSET * 32) + (NIEN_BIT_NUMBER * 4)) + +/* Alias word address of ATACMD bit */ +#define ATACMD_BIT_NUMBER 0x0E +#define CMD_ATACMD_BB (PERIPH_BB_BASE + (CMD_OFFSET * 32) + (ATACMD_BIT_NUMBER * 4)) + +/* --- DATCTRL Register ---*/ + +/* Alias word address of DMAEN bit */ +#define DCTRL_OFFSET (SDIO_OFFSET + 0x2C) +#define DMAEN_BIT_NUMBER 0x03 +#define DCTRL_DMAEN_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (DMAEN_BIT_NUMBER * 4)) + +/* Alias word address of RWSTART bit */ +#define RWSTART_BIT_NUMBER 0x08 +#define DCTRL_RWSTART_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (RWSTART_BIT_NUMBER * 4)) + +/* Alias word address of RWSTOP bit */ +#define RWSTOP_BIT_NUMBER 0x09 +#define DCTRL_RWSTOP_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (RWSTOP_BIT_NUMBER * 4)) + +/* Alias word address of RWMOD bit */ +#define RWMOD_BIT_NUMBER 0x0A +#define DCTRL_RWMOD_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (RWMOD_BIT_NUMBER * 4)) + +/* Alias word address of SDIOEN bit */ +#define SDIOEN_BIT_NUMBER 0x0B +#define DCTRL_SDIOEN_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (SDIOEN_BIT_NUMBER * 4)) + +/* ---------------------- SDIO registers bit mask ------------------------ */ + +/* --- CLKCTRL Register ---*/ + +/* CLKCTRL register clear mask */ +#define CLKCTRL_CLR_MASK ((uint32_t)0xFFFF8100) + +/* --- PWRCTRL Register ---*/ + +/* SDIO PWRCTRL Mask */ +#define POWER_PWRCTRL_MASK ((uint32_t)0xFFFFFFFC) + +/* --- DATCTRL Register ---*/ + +/* SDIO DATCTRL Clear Mask */ +#define DATCTRL_CLR_MASK ((uint32_t)0xFFFFFF08) + +/* --- CMDCTRL Register ---*/ + +/* CMDCTRL Register clear mask */ +#define CMD_CLR_MASK ((uint32_t)0xFFFFF800) + +/* SDIO RESP Registers Address */ +#define SDID_RESPONSE_ADDR ((uint32_t)(SDIO_BASE + 0x14)) + +/** + * @} + */ + +/** @addtogroup SDIO_Private_Defines + * @{ + */ + +/** + * @} + */ + +/** @addtogroup SDIO_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup SDIO_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup SDIO_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup SDIO_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the SDIO peripheral registers to their default reset values. + */ +void SDIO_DeInit(void) +{ + SDIO->PWRCTRL = 0x00000000; + SDIO->CLKCTRL = 0x00000000; + SDIO->CMDARG = 0x00000000; + SDIO->CMDCTRL = 0x00000000; + SDIO->DTIMER = 0x00000000; + SDIO->DATLEN = 0x00000000; + SDIO->DATCTRL = 0x00000000; + SDIO->INTCLR = 0x00C007FF; + SDIO->INTEN = 0x00000000; +} + +/** + * @brief Initializes the SDIO peripheral according to the specified + * parameters in the SDIO_InitStruct. + * @param SDIO_InitStruct pointer to a SDIO_InitType structure + * that contains the configuration information for the SDIO peripheral. + */ +void SDIO_Init(SDIO_InitType* SDIO_InitStruct) +{ + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_SDIO_CLK_EDGE(SDIO_InitStruct->ClkEdge)); + assert_param(IS_SDIO_CLK_BYPASS(SDIO_InitStruct->ClkBypass)); + assert_param(IS_SDIO_CLK_POWER_SAVE(SDIO_InitStruct->ClkPwrSave)); + assert_param(IS_SDIO_BUS_WIDTH(SDIO_InitStruct->BusWidth)); + assert_param(IS_SDIO_HARDWARE_CLKCTRL(SDIO_InitStruct->HardwareClkCtrl)); + + /*---------------------------- SDIO CLKCTRL Configuration ------------------------*/ + /* Get the SDIO CLKCTRL value */ + tmpregister = SDIO->CLKCTRL; + + /* Clear CLKDIV, PWRSAV, BYPASS, WIDBUS, NEGEDGE, HWFC_EN bits */ + tmpregister &= CLKCTRL_CLR_MASK; + + /* Set CLKDIV bits according to ClkDiv value */ + /* Set PWRSAV bit according to ClkPwrSave value */ + /* Set BYPASS bit according to ClkBypass value */ + /* Set WIDBUS bits according to BusWidth value */ + /* Set NEGEDGE bits according to ClkEdge value */ + /* Set HWFC_EN bits according to HardwareClkCtrl value */ + tmpregister |= (SDIO_InitStruct->ClkDiv | SDIO_InitStruct->ClkPwrSave | SDIO_InitStruct->ClkBypass + | SDIO_InitStruct->BusWidth | SDIO_InitStruct->ClkEdge | SDIO_InitStruct->HardwareClkCtrl); + + /* Write to SDIO CLKCTRL */ + SDIO->CLKCTRL = tmpregister; +} + +/** + * @brief Fills each SDIO_InitStruct member with its default value. + * @param SDIO_InitStruct pointer to an SDIO_InitType structure which + * will be initialized. + */ +void SDIO_InitStruct(SDIO_InitType* SDIO_InitStruct) +{ + /* SDIO_InitStruct members default value */ + SDIO_InitStruct->ClkDiv = 0x00; + SDIO_InitStruct->ClkEdge = SDIO_CLKEDGE_RISING; + SDIO_InitStruct->ClkBypass = SDIO_ClkBYPASS_DISABLE; + SDIO_InitStruct->ClkPwrSave = SDIO_CLKPOWERSAVE_DISABLE; + SDIO_InitStruct->BusWidth = SDIO_BUSWIDTH_1B; + SDIO_InitStruct->HardwareClkCtrl = SDIO_HARDWARE_CLKCTRL_DISABLE; +} + +/** + * @brief Enables or disables the SDIO Clock. + * @param Cmd new state of the SDIO Clock. This parameter can be: ENABLE or DISABLE. + */ +void SDIO_EnableClock(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + *(__IO uint32_t*)CLKCTRL_CLKEN_BB = (uint32_t)Cmd; +} + +/** + * @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_POWER_CTRL_OFF + * @arg SDIO_POWER_CTRL_ON + */ +void SDIO_SetPower(uint32_t SDIO_PowerState) +{ + /* Check the parameters */ + assert_param(IS_SDIO_POWER_CTRL(SDIO_PowerState)); + + SDIO->PWRCTRL &= POWER_PWRCTRL_MASK; + SDIO->PWRCTRL |= SDIO_PowerState; +} + +/** + * @brief Gets the power status of the controller. + * @return 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_GetPower(void) +{ + return (SDIO->PWRCTRL & (~POWER_PWRCTRL_MASK)); +} + +/** + * @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_INT_CCRCERR Command response received (CRC check failed) interrupt + * @arg SDIO_INT_DCRCERR Data block sent/received (CRC check failed) interrupt + * @arg SDIO_INT_CMDTIMEOUT Command response timeout interrupt + * @arg SDIO_INT_DATTIMEOUT Data timeout interrupt + * @arg SDIO_INT_TXURERR Transmit DATFIFO underrun error interrupt + * @arg SDIO_INT_RXORERR Received DATFIFO overrun error interrupt + * @arg SDIO_INT_CMDRESPRECV Command response received (CRC check passed) interrupt + * @arg SDIO_INT_CMDSEND Command sent (no response required) interrupt + * @arg SDIO_INT_DATEND Data end (data counter, SDIDCOUNT, is zero) interrupt + * @arg SDIO_INT_SBERR Start bit not detected on all data signals in wide + * bus mode interrupt + * @arg SDIO_INT_DATBLKEND Data block sent/received (CRC check passed) interrupt + * @arg SDIO_INT_CMDRUN Command transfer in progress interrupt + * @arg SDIO_INT_TXRUN Data transmit in progress interrupt + * @arg SDIO_INT_RXRUN Data receive in progress interrupt + * @arg SDIO_INT_TFIFOHE Transmit DATFIFO Half Empty interrupt + * @arg SDIO_INT_RFIFOHF Receive DATFIFO Half Full interrupt + * @arg SDIO_INT_TFIFOF Transmit DATFIFO full interrupt + * @arg SDIO_INT_RFIFOF Receive DATFIFO full interrupt + * @arg SDIO_INT_TFIFOE Transmit DATFIFO empty interrupt + * @arg SDIO_INT_RFIFOE Receive DATFIFO empty interrupt + * @arg SDIO_INT_TDATVALID Data available in transmit DATFIFO interrupt + * @arg SDIO_INT_RDATVALID Data available in receive DATFIFO interrupt + * @arg SDIO_INT_SDIOINT SD I/O interrupt received interrupt + * @arg SDIO_INT_CEATAF CE-ATA command completion signal received for CMD61 interrupt + * @param Cmd new state of the specified SDIO interrupts. + * This parameter can be: ENABLE or DISABLE. + */ +void SDIO_ConfigInt(uint32_t SDIO_IT, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_SDIO_INT(SDIO_IT)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the SDIO interrupts */ + SDIO->INTEN |= SDIO_IT; + } + else + { + /* Disable the SDIO interrupts */ + SDIO->INTEN &= ~SDIO_IT; + } +} + +/** + * @brief Enables or disables the SDIO DMA request. + * @param Cmd new state of the selected SDIO DMA request. + * This parameter can be: ENABLE or DISABLE. + */ +void SDIO_DMACmd(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + *(__IO uint32_t*)DCTRL_DMAEN_BB = (uint32_t)Cmd; +} + +/** + * @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_CmdInitType + * structure that contains the configuration information for the SDIO command. + */ +void SDIO_SendCmd(SDIO_CmdInitType* SDIO_CmdInitStruct) +{ + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_SDIO_CMD_INDEX(SDIO_CmdInitStruct->CmdIndex)); + assert_param(IS_SDIO_RESP(SDIO_CmdInitStruct->ResponseType)); + assert_param(IS_SDIO_WAIT(SDIO_CmdInitStruct->WaitType)); + assert_param(IS_SDIO_CPSM(SDIO_CmdInitStruct->CPSMConfig)); + + /*---------------------------- SDIO CMDARG Configuration ------------------------*/ + /* Set the SDIO Argument value */ + SDIO->CMDARG = SDIO_CmdInitStruct->CmdArgument; + + /*---------------------------- SDIO CMDCTRL Configuration ------------------------*/ + /* Get the SDIO CMDCTRL value */ + tmpregister = SDIO->CMDCTRL; + /* Clear CMDINDEX, WAITRESP, WAITINT, WAITPEND, CPSMEN bits */ + tmpregister &= CMD_CLR_MASK; + /* Set CMDINDEX bits according to CmdIndex value */ + /* Set WAITRESP bits according to ResponseType value */ + /* Set WAITINT and WAITPEND bits according to WaitType value */ + /* Set CPSMEN bits according to CPSMConfig value */ + tmpregister |= (uint32_t)SDIO_CmdInitStruct->CmdIndex | SDIO_CmdInitStruct->ResponseType + | SDIO_CmdInitStruct->WaitType | SDIO_CmdInitStruct->CPSMConfig; + + /* Write to SDIO CMDCTRL */ + SDIO->CMDCTRL = tmpregister; +} + +/** + * @brief Fills each SDIO_CmdInitStruct member with its default value. + * @param SDIO_CmdInitStruct pointer to an SDIO_CmdInitType + * structure which will be initialized. + */ +void SDIO_InitCmdStruct(SDIO_CmdInitType* SDIO_CmdInitStruct) +{ + /* SDIO_CmdInitStruct members default value */ + SDIO_CmdInitStruct->CmdArgument = 0x00; + SDIO_CmdInitStruct->CmdIndex = 0x00; + SDIO_CmdInitStruct->ResponseType = SDIO_RESP_NO; + SDIO_CmdInitStruct->WaitType = SDIO_WAIT_NO; + SDIO_CmdInitStruct->CPSMConfig = SDIO_CPSM_DISABLE; +} + +/** + * @brief Returns command index of last command for which response received. + * @return Returns the command index of the last command response received. + */ +uint8_t SDIO_GetCmdResp(void) +{ + return (uint8_t)(SDIO->CMDRESP); +} + +/** + * @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_RESPONSE_1 Response Register 1 + * @arg SDIO_RESPONSE_2 Response Register 2 + * @arg SDIO_RESPONSE_3 Response Register 3 + * @arg SDIO_RESPONSE_4 Response Register 4 + * @return The Corresponding response register value. + */ +uint32_t SDIO_GetResp(uint32_t SDIO_RESP) +{ + __IO uint32_t tmp = 0; + + /* Check the parameters */ + assert_param(IS_SDIO_RESPONSE(SDIO_RESP)); + + tmp = SDID_RESPONSE_ADDR + SDIO_RESP; + + return (*(__IO uint32_t*)tmp); +} + +/** + * @brief Initializes the SDIO data path according to the specified + * parameters in the SDIO_DataInitStruct. + * @param SDIO_DataInitStruct pointer to a SDIO_DataInitType structure that + * contains the configuration information for the SDIO command. + */ +void SDIO_ConfigData(SDIO_DataInitType* SDIO_DataInitStruct) +{ + uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_SDIO_DAT_LEN(SDIO_DataInitStruct->DatLen)); + assert_param(IS_SDIO_BLK_SIZE(SDIO_DataInitStruct->DatBlkSize)); + assert_param(IS_SDIO_TRANSFER_DIRECTION(SDIO_DataInitStruct->TransferDirection)); + assert_param(IS_SDIO_TRANS_MODE(SDIO_DataInitStruct->TransferMode)); + assert_param(IS_SDIO_DPSM(SDIO_DataInitStruct->DPSMConfig)); + + /*---------------------------- SDIO DATTIMEOUT Configuration ---------------------*/ + /* Set the SDIO Data TimeOut value */ + SDIO->DTIMER = SDIO_DataInitStruct->DatTimeout; + + /*---------------------------- SDIO DATLEN Configuration -----------------------*/ + /* Set the SDIO DataLength value */ + SDIO->DATLEN = SDIO_DataInitStruct->DatLen; + + /*---------------------------- SDIO DATCTRL Configuration ----------------------*/ + /* Get the SDIO DATCTRL value */ + tmpregister = SDIO->DATCTRL; + /* Clear DEN, DTMODE, DTDIR and DBCKSIZE bits */ + tmpregister &= DATCTRL_CLR_MASK; + /* Set DEN bit according to DPSMConfig value */ + /* Set DTMODE bit according to TransferMode value */ + /* Set DTDIR bit according to TransferDirection value */ + /* Set DBCKSIZE bits according to DatBlkSize value */ + tmpregister |= (uint32_t)SDIO_DataInitStruct->DatBlkSize | SDIO_DataInitStruct->TransferDirection + | SDIO_DataInitStruct->TransferMode | SDIO_DataInitStruct->DPSMConfig; + + if(SDIO_DataInitStruct->TransferDirection) + { + tmpregister &= ~(1<<12); + } + else + { + tmpregister |= 1<<12; + } + + /* Write to SDIO DATCTRL */ + SDIO->DATCTRL = tmpregister; +} + +/** + * @brief Fills each SDIO_DataInitStruct member with its default value. + * @param SDIO_DataInitStruct pointer to an SDIO_DataInitType structure which + * will be initialized. + */ +void SDIO_InitDataStruct(SDIO_DataInitType* SDIO_DataInitStruct) +{ + /* SDIO_DataInitStruct members default value */ + SDIO_DataInitStruct->DatTimeout = 0xFFFFFFFF; + SDIO_DataInitStruct->DatLen = 0x00; + SDIO_DataInitStruct->DatBlkSize = SDIO_DATBLK_SIZE_1B; + SDIO_DataInitStruct->TransferDirection = SDIO_TRANSDIR_TOCARD; + SDIO_DataInitStruct->TransferMode = SDIO_TRANSMODE_BLOCK; + SDIO_DataInitStruct->DPSMConfig = SDIO_DPSM_DISABLE; +} + +/** + * @brief Returns number of remaining data bytes to be transferred. + * @return Number of remaining data bytes to be transferred + */ +uint32_t SDIO_GetDataCountValue(void) +{ + return SDIO->DATCOUNT; +} + +/** + * @brief Read one data word from Rx DATFIFO. + * @return Data received + */ +uint32_t SDIO_ReadData(void) +{ + return SDIO->DATFIFO; +} + +/** + * @brief Write one data word to Tx DATFIFO. + * @param Data 32-bit data word to write. + */ +void SDIO_WriteData(uint32_t Data) +{ + SDIO->DATFIFO = Data; +} + +/** + * @brief Returns the number of words left to be written to or read from DATFIFO. + * @return Remaining number of words. + */ +uint32_t SDIO_GetFifoCounter(void) +{ + return SDIO->FIFOCOUNT; +} + +/** + * @brief Starts the SD I/O Read Wait operation. + * @param Cmd new state of the Start SDIO Read Wait operation. + * This parameter can be: ENABLE or DISABLE. + */ +void SDIO_EnableReadWait(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + *(__IO uint32_t*)DCTRL_RWSTART_BB = (uint32_t)Cmd; +} + +/** + * @brief Stops the SD I/O Read Wait operation. + * @param Cmd new state of the Stop SDIO Read Wait operation. + * This parameter can be: ENABLE or DISABLE. + */ +void SDIO_DisableReadWait(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + *(__IO uint32_t*)DCTRL_RWSTOP_BB = (uint32_t)Cmd; +} + +/** + * @brief Sets one of the two options of inserting read wait interval. + * @param SDIO_ReadWaitMode SD I/O Read Wait operation mode. + * This parameter can be: + * @arg SDIO_RDWAIT_MODE_CLK Read Wait control by stopping SDIOCLK + * @arg SDIO_RDWAIT_MODE_DAT2 Read Wait control using SDIO_DATA2 + */ +void SDIO_EnableSdioReadWaitMode(uint32_t SDIO_ReadWaitMode) +{ + /* Check the parameters */ + assert_param(IS_SDIO_RDWAIT_MODE(SDIO_ReadWaitMode)); + + *(__IO uint32_t*)DCTRL_RWMOD_BB = SDIO_ReadWaitMode; +} + +/** + * @brief Enables or disables the SD I/O Mode Operation. + * @param Cmd new state of SDIO specific operation. + * This parameter can be: ENABLE or DISABLE. + */ +void SDIO_EnableSdioOperation(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + *(__IO uint32_t*)DCTRL_SDIOEN_BB = (uint32_t)Cmd; +} + +/** + * @brief Enables or disables the SD I/O Mode suspend command sending. + * @param Cmd new state of the SD I/O Mode suspend command. + * This parameter can be: ENABLE or DISABLE. + */ +void SDIO_EnableSendSdioSuspend(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + *(__IO uint32_t*)CMD_SDIO_SUSPEND_BB = (uint32_t)Cmd; +} + +/** + * @brief Enables or disables the command completion signal. + * @param Cmd new state of command completion signal. + * This parameter can be: ENABLE or DISABLE. + */ +void SDIO_EnableCommandCompletion(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + *(__IO uint32_t*)EN_CMD_COMPL_BB = (uint32_t)Cmd; +} + +/** + * @brief Enables or disables the CE-ATA interrupt. + * @param Cmd new state of CE-ATA interrupt. This parameter can be: ENABLE or DISABLE. + */ +void SDIO_EnableCEATAInt(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + *(__IO uint32_t*)CMD_NIEN_BB = (uint32_t)((~((uint32_t)Cmd)) & ((uint32_t)0x1)); +} + +/** + * @brief Sends CE-ATA command (CMD61). + * @param Cmd new state of CE-ATA command. This parameter can be: ENABLE or DISABLE. + */ +void SDIO_EnableSendCEATA(FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + *(__IO uint32_t*)CMD_ATACMD_BB = (uint32_t)Cmd; +} + +/** + * @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_CCRCERR Command response received (CRC check failed) + * @arg SDIO_FLAG_DCRCERR Data block sent/received (CRC check failed) + * @arg SDIO_FLAG_CMDTIMEOUT Command response timeout + * @arg SDIO_FLAG_DATTIMEOUT Data timeout + * @arg SDIO_FLAG_TXURERR Transmit DATFIFO underrun error + * @arg SDIO_FLAG_RXORERR Received DATFIFO overrun error + * @arg SDIO_FLAG_CMDRESPRECV Command response received (CRC check passed) + * @arg SDIO_FLAG_CMDSEND Command sent (no response required) + * @arg SDIO_FLAG_DATEND Data end (data counter, SDIDCOUNT, is zero) + * @arg SDIO_FLAG_SBERR Start bit not detected on all data signals in wide + * bus mode. + * @arg SDIO_FLAG_DATBLKEND Data block sent/received (CRC check passed) + * @arg SDIO_FLAG_CMDRUN Command transfer in progress + * @arg SDIO_FLAG_TXRUN Data transmit in progress + * @arg SDIO_FLAG_RXRUN Data receive in progress + * @arg SDIO_FLAG_TFIFOHE Transmit DATFIFO Half Empty + * @arg SDIO_FLAG_RFIFOHF Receive DATFIFO Half Full + * @arg SDIO_FLAG_TFIFOF Transmit DATFIFO full + * @arg SDIO_FLAG_RFIFOF Receive DATFIFO full + * @arg SDIO_FLAG_TFIFOE Transmit DATFIFO empty + * @arg SDIO_FLAG_RFIFOE Receive DATFIFO empty + * @arg SDIO_FLAG_TDATVALID Data available in transmit DATFIFO + * @arg SDIO_FLAG_RDATVALID Data available in receive DATFIFO + * @arg SDIO_FLAG_SDIOINT SD I/O interrupt received + * @arg SDIO_FLAG_CEATAF CE-ATA command completion signal received for CMD61 + * @return The new state of SDIO_FLAG (SET or RESET). + */ +FlagStatus SDIO_GetFlag(uint32_t SDIO_FLAG) +{ + FlagStatus bitstatus = RESET; + + /* Check the parameters */ + assert_param(IS_SDIO_FLAG(SDIO_FLAG)); + + if ((SDIO->STS & 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_CCRCERR Command response received (CRC check failed) + * @arg SDIO_FLAG_DCRCERR Data block sent/received (CRC check failed) + * @arg SDIO_FLAG_CMDTIMEOUT Command response timeout + * @arg SDIO_FLAG_DATTIMEOUT Data timeout + * @arg SDIO_FLAG_TXURERR Transmit DATFIFO underrun error + * @arg SDIO_FLAG_RXORERR Received DATFIFO overrun error + * @arg SDIO_FLAG_CMDRESPRECV Command response received (CRC check passed) + * @arg SDIO_FLAG_CMDSEND Command sent (no response required) + * @arg SDIO_FLAG_DATEND Data end (data counter, SDIDCOUNT, is zero) + * @arg SDIO_FLAG_SBERR Start bit not detected on all data signals in wide + * bus mode + * @arg SDIO_FLAG_DATBLKEND Data block sent/received (CRC check passed) + * @arg SDIO_FLAG_SDIOINT SD I/O interrupt received + * @arg SDIO_FLAG_CEATAF CE-ATA command completion signal received for CMD61 + */ +void SDIO_ClrFlag(uint32_t SDIO_FLAG) +{ + /* Check the parameters */ + assert_param(IS_SDIO_CLR_FLAG(SDIO_FLAG)); + + SDIO->INTCLR = 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_INT_CCRCERR Command response received (CRC check failed) interrupt + * @arg SDIO_INT_DCRCERR Data block sent/received (CRC check failed) interrupt + * @arg SDIO_INT_CMDTIMEOUT Command response timeout interrupt + * @arg SDIO_INT_DATTIMEOUT Data timeout interrupt + * @arg SDIO_INT_TXURERR Transmit DATFIFO underrun error interrupt + * @arg SDIO_INT_RXORERR Received DATFIFO overrun error interrupt + * @arg SDIO_INT_CMDRESPRECV Command response received (CRC check passed) interrupt + * @arg SDIO_INT_CMDSEND Command sent (no response required) interrupt + * @arg SDIO_INT_DATEND Data end (data counter, SDIDCOUNT, is zero) interrupt + * @arg SDIO_INT_SBERR Start bit not detected on all data signals in wide + * bus mode interrupt + * @arg SDIO_INT_DATBLKEND Data block sent/received (CRC check passed) interrupt + * @arg SDIO_INT_CMDRUN Command transfer in progress interrupt + * @arg SDIO_INT_TXRUN Data transmit in progress interrupt + * @arg SDIO_INT_RXRUN Data receive in progress interrupt + * @arg SDIO_INT_TFIFOHE Transmit DATFIFO Half Empty interrupt + * @arg SDIO_INT_RFIFOHF Receive DATFIFO Half Full interrupt + * @arg SDIO_INT_TFIFOF Transmit DATFIFO full interrupt + * @arg SDIO_INT_RFIFOF Receive DATFIFO full interrupt + * @arg SDIO_INT_TFIFOE Transmit DATFIFO empty interrupt + * @arg SDIO_INT_RFIFOE Receive DATFIFO empty interrupt + * @arg SDIO_INT_TDATVALID Data available in transmit DATFIFO interrupt + * @arg SDIO_INT_RDATVALID Data available in receive DATFIFO interrupt + * @arg SDIO_INT_SDIOINT SD I/O interrupt received interrupt + * @arg SDIO_INT_CEATAF CE-ATA command completion signal received for CMD61 interrupt + * @return The new state of SDIO_IT (SET or RESET). + */ +INTStatus SDIO_GetIntStatus(uint32_t SDIO_IT) +{ + INTStatus bitstatus = RESET; + + /* Check the parameters */ + assert_param(IS_SDIO_GET_INT(SDIO_IT)); + if ((SDIO->STS & 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_INT_CCRCERR Command response received (CRC check failed) interrupt + * @arg SDIO_INT_DCRCERR Data block sent/received (CRC check failed) interrupt + * @arg SDIO_INT_CMDTIMEOUT Command response timeout interrupt + * @arg SDIO_INT_DATTIMEOUT Data timeout interrupt + * @arg SDIO_INT_TXURERR Transmit DATFIFO underrun error interrupt + * @arg SDIO_INT_RXORERR Received DATFIFO overrun error interrupt + * @arg SDIO_INT_CMDRESPRECV Command response received (CRC check passed) interrupt + * @arg SDIO_INT_CMDSEND Command sent (no response required) interrupt + * @arg SDIO_INT_DATEND Data end (data counter, SDIDCOUNT, is zero) interrupt + * @arg SDIO_INT_SBERR Start bit not detected on all data signals in wide + * bus mode interrupt + * @arg SDIO_INT_SDIOINT SD I/O interrupt received interrupt + * @arg SDIO_INT_CEATAF CE-ATA command completion signal received for CMD61 + */ +void SDIO_ClrIntPendingBit(uint32_t SDIO_IT) +{ + /* Check the parameters */ + assert_param(IS_SDIO_CLR_INT(SDIO_IT)); + + SDIO->INTCLR = SDIO_IT; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/src/n32g45x_spi.c b/src/n32g45x_spi.c new file mode 100644 index 0000000..d069e7f --- /dev/null +++ b/src/n32g45x_spi.c @@ -0,0 +1,862 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_spi.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_spi.h" +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup SPI + * @brief SPI driver modules + * @{ + */ + +/** @addtogroup SPI_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup SPI_Private_Defines + * @{ + */ + +/* SPI SPE mask */ +#define CTRL1_SPIEN_ENABLE ((uint16_t)0x0040) +#define CTRL1_SPIEN_DISABLE ((uint16_t)0xFFBF) + +/* I2S I2SE mask */ +#define I2SCFG_I2SEN_ENABLE ((uint16_t)0x0400) +#define I2SCFG_I2SEN_DISABLE ((uint16_t)0xFBFF) + +/* SPI CRCNext mask */ +#define CTRL1_CRCNEXT_ENABLE ((uint16_t)0x1000) + +/* SPI CRCEN mask */ +#define CTRL1_CRCEN_ENABLE ((uint16_t)0x2000) +#define CTRL1_CRCEN_DISABLE ((uint16_t)0xDFFF) + +/* SPI SSOE mask */ +#define CTRL2_SSOEN_ENABLE ((uint16_t)0x0004) +#define CTRL2_SSOEN_DISABLE ((uint16_t)0xFFFB) + +/* SPI registers Masks */ +#define CTRL1_CLR_MASK ((uint16_t)0x3040) +#define I2SCFG_CLR_MASK ((uint16_t)0xF040) + +/* SPI or I2S mode selection masks */ +#define SPI_MODE_ENABLE ((uint16_t)0xF7FF) +#define I2S_MODE_ENABLE ((uint16_t)0x0800) + +/* I2S clock source selection masks */ +#define I2S2_CLKSRC ((uint32_t)(0x00020000)) +#define I2S3_CLKSRC ((uint32_t)(0x00040000)) +#define I2S_MUL_MASK ((uint32_t)(0x0000F000)) +#define I2S_DIV_MASK ((uint32_t)(0x000000F0)) + +/** + * @} + */ + +/** @addtogroup SPI_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup SPI_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup SPI_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup SPI_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the SPIx peripheral registers to their default + * reset values (Affects also the I2Ss). + * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral. + */ +void SPI_I2S_DeInit(SPI_Module* SPIx) +{ + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + + if (SPIx == SPI1) + { + /* Enable SPI1 reset state */ + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_SPI1, ENABLE); + /* Release SPI1 from reset state */ + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_SPI1, DISABLE); + } + else if (SPIx == SPI2) + { + /* Enable SPI2 reset state */ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_SPI2, ENABLE); + /* Release SPI2 from reset state */ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_SPI2, DISABLE); + } + else + { + if (SPIx == SPI3) + { + /* Enable SPI3 reset state */ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_SPI3, ENABLE); + /* Release SPI3 from reset state */ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_SPI3, DISABLE); + } + } +} + +/** + * @brief Initializes the SPIx peripheral according to the specified + * parameters in the SPI_InitStruct. + * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral. + * @param SPI_InitStruct pointer to a SPI_InitType structure that + * contains the configuration information for the specified SPI peripheral. + */ +void SPI_Init(SPI_Module* SPIx, SPI_InitType* SPI_InitStruct) +{ + uint16_t tmpregister = 0; + + /* check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + + /* Check the SPI parameters */ + assert_param(IS_SPI_DIR_MODE(SPI_InitStruct->DataDirection)); + assert_param(IS_SPI_MODE(SPI_InitStruct->SpiMode)); + assert_param(IS_SPI_DATASIZE(SPI_InitStruct->DataLen)); + assert_param(IS_SPI_CLKPOL(SPI_InitStruct->CLKPOL)); + assert_param(IS_SPI_CLKPHA(SPI_InitStruct->CLKPHA)); + assert_param(IS_SPI_NSS(SPI_InitStruct->NSS)); + assert_param(IS_SPI_BR_PRESCALER(SPI_InitStruct->BaudRatePres)); + assert_param(IS_SPI_FIRST_BIT(SPI_InitStruct->FirstBit)); + assert_param(IS_SPI_CRC_POLYNOMIAL(SPI_InitStruct->CRCPoly)); + + /*---------------------------- SPIx CTRL1 Configuration ------------------------*/ + /* Get the SPIx CTRL1 value */ + tmpregister = SPIx->CTRL1; + /* Clear BIDIMode, BIDIOE, RxONLY, SSM, SSI, LSBFirst, BR, MSTR, CPOL and CPHA bits */ + tmpregister &= CTRL1_CLR_MASK; + /* Configure SPIx: direction, NSS management, first transmitted bit, BaudRate prescaler + master/salve mode, CPOL and CPHA */ + /* Set BIDImode, BIDIOE and RxONLY bits according to DataDirection value */ + /* Set SSM, SSI and MSTR bits according to SpiMode and NSS values */ + /* Set LSBFirst bit according to FirstBit value */ + /* Set BR bits according to BaudRatePres value */ + /* Set CPOL bit according to CLKPOL value */ + /* Set CPHA bit according to CLKPHA value */ + tmpregister |= (uint16_t)((uint32_t)SPI_InitStruct->DataDirection | SPI_InitStruct->SpiMode + | SPI_InitStruct->DataLen | SPI_InitStruct->CLKPOL | SPI_InitStruct->CLKPHA + | SPI_InitStruct->NSS | SPI_InitStruct->BaudRatePres | SPI_InitStruct->FirstBit); + /* Write to SPIx CTRL1 */ + SPIx->CTRL1 = tmpregister; + + /* Activate the SPI mode (Reset I2SMOD bit in I2SCFG register) */ + SPIx->I2SCFG &= SPI_MODE_ENABLE; + + /*---------------------------- SPIx CRCPOLY Configuration --------------------*/ + /* Write to SPIx CRCPOLY */ + SPIx->CRCPOLY = SPI_InitStruct->CRCPoly; +} + +/** + * @brief Initializes the SPIx peripheral according to the specified + * parameters in the I2S_InitStruct. + * @param SPIx where x can be 2 or 3 to select the SPI peripheral + * (configured in I2S mode). + * @param I2S_InitStruct pointer to an I2S_InitType structure that + * contains the configuration information for the specified SPI peripheral + * configured in I2S mode. + * @note + * The function calculates the optimal prescaler needed to obtain the most + * accurate audio frequency (depending on the I2S clock source, the PLL values + * and the product configuration). But in case the prescaler value is greater + * than 511, the default value (0x02) will be configured instead. * + */ +void I2S_Init(SPI_Module* SPIx, I2S_InitType* I2S_InitStruct) +{ + uint16_t tmpregister = 0, i2sdiv = 2, i2sodd = 0, packetlength = 1; + uint32_t tmp = 0; + RCC_ClocksType RCC_Clocks; + uint32_t sourceclock = 0; + + /* Check the I2S parameters */ + assert_param(IS_SPI_2OR3_PERIPH(SPIx)); + assert_param(IS_I2S_MODE(I2S_InitStruct->I2sMode)); + assert_param(IS_I2S_STANDARD(I2S_InitStruct->Standard)); + assert_param(IS_I2S_DATA_FMT(I2S_InitStruct->DataFormat)); + assert_param(IS_I2S_MCLK_ENABLE(I2S_InitStruct->MCLKEnable)); + assert_param(IS_I2S_AUDIO_FREQ(I2S_InitStruct->AudioFrequency)); + assert_param(IS_I2S_CLKPOL(I2S_InitStruct->CLKPOL)); + + /*----------------------- SPIx I2SCFG & I2SPREDIV Configuration -----------------*/ + /* Clear I2SMOD, I2SE, MODCFG, PCMSYNC, STDSEL, CKPOL, TDATLEN and CHLEN bits */ + SPIx->I2SCFG &= I2SCFG_CLR_MASK; + SPIx->I2SPREDIV = 0x0002; + + /* Get the I2SCFG register value */ + tmpregister = SPIx->I2SCFG; + + /* If the default value has to be written, reinitialize i2sdiv and i2sodd*/ + if (I2S_InitStruct->AudioFrequency == I2S_AUDIO_FREQ_DEFAULT) + { + i2sodd = (uint16_t)0; + i2sdiv = (uint16_t)2; + } + /* If the requested audio frequency is not the default, compute the prescaler */ + else + { + /* Check the frame length (For the Prescaler computing) */ + if (I2S_InitStruct->DataFormat == I2S_DATA_FMT_16BITS) + { + /* Packet length is 16 bits */ + packetlength = 1; + } + else + { + /* Packet length is 32 bits */ + packetlength = 2; + } + + /* Get the I2S clock source mask depending on the peripheral number */ + if (((uint32_t)SPIx) == SPI2_BASE) + { + /* The mask is relative to I2S2 */ + tmp = I2S2_CLKSRC; + } + else + { + /* The mask is relative to I2S3 */ + tmp = I2S3_CLKSRC; + } + + /* I2S Clock source is System clock: Get System Clock frequency */ + RCC_GetClocksFreqValue(&RCC_Clocks); + + /* Get the source clock value: based on System Clock value */ + sourceclock = RCC_Clocks.SysclkFreq; + + /* Compute the Real divider depending on the MCLK output state with a floating point */ + if (I2S_InitStruct->MCLKEnable == I2S_MCLK_ENABLE) + { + /* MCLK output is enabled */ + tmp = (uint16_t)(((((sourceclock / 256) * 10) / I2S_InitStruct->AudioFrequency)) + 5); + } + else + { + /* MCLK output is disabled */ + tmp = (uint16_t)(((((sourceclock / (32 * packetlength)) * 10) / I2S_InitStruct->AudioFrequency)) + 5); + } + + /* Remove the floating point */ + tmp = tmp / 10; + + /* Check the parity of the divider */ + i2sodd = (uint16_t)(tmp & (uint16_t)0x0001); + + /* Compute the i2sdiv prescaler */ + i2sdiv = (uint16_t)((tmp - i2sodd) / 2); + + /* Get the Mask for the Odd bit (SPI_I2SPREDIV[8]) register */ + i2sodd = (uint16_t)(i2sodd << 8); + } + + /* Test if the divider is 1 or 0 or greater than 0xFF */ + if ((i2sdiv < 2) || (i2sdiv > 0xFF)) + { + /* Set the default values */ + i2sdiv = 2; + i2sodd = 0; + } + + /* Write to SPIx I2SPREDIV register the computed value */ + SPIx->I2SPREDIV = (uint16_t)(i2sdiv | (uint16_t)(i2sodd | (uint16_t)I2S_InitStruct->MCLKEnable)); + + /* Configure the I2S with the SPI_InitStruct values */ + tmpregister |= (uint16_t)( + I2S_MODE_ENABLE + | (uint16_t)(I2S_InitStruct->I2sMode + | (uint16_t)(I2S_InitStruct->Standard + | (uint16_t)(I2S_InitStruct->DataFormat | (uint16_t)I2S_InitStruct->CLKPOL)))); + + /* Write to SPIx I2SCFG */ + SPIx->I2SCFG = tmpregister; +} + +/** + * @brief Fills each SPI_InitStruct member with its default value. + * @param SPI_InitStruct pointer to a SPI_InitType structure which will be initialized. + */ +void SPI_InitStruct(SPI_InitType* SPI_InitStruct) +{ + /*--------------- Reset SPI init structure parameters values -----------------*/ + /* Initialize the DataDirection member */ + SPI_InitStruct->DataDirection = SPI_DIR_DOUBLELINE_FULLDUPLEX; + /* initialize the SpiMode member */ + SPI_InitStruct->SpiMode = SPI_MODE_SLAVE; + /* initialize the DataLen member */ + SPI_InitStruct->DataLen = SPI_DATA_SIZE_8BITS; + /* Initialize the CLKPOL member */ + SPI_InitStruct->CLKPOL = SPI_CLKPOL_LOW; + /* Initialize the CLKPHA member */ + SPI_InitStruct->CLKPHA = SPI_CLKPHA_FIRST_EDGE; + /* Initialize the NSS member */ + SPI_InitStruct->NSS = SPI_NSS_HARD; + /* Initialize the BaudRatePres member */ + SPI_InitStruct->BaudRatePres = SPI_BR_PRESCALER_2; + /* Initialize the FirstBit member */ + SPI_InitStruct->FirstBit = SPI_FB_MSB; + /* Initialize the CRCPoly member */ + SPI_InitStruct->CRCPoly = 7; +} + +/** + * @brief Fills each I2S_InitStruct member with its default value. + * @param I2S_InitStruct pointer to a I2S_InitType structure which will be initialized. + */ +void I2S_InitStruct(I2S_InitType* I2S_InitStruct) +{ + /*--------------- Reset I2S init structure parameters values -----------------*/ + /* Initialize the I2sMode member */ + I2S_InitStruct->I2sMode = I2S_MODE_SlAVE_TX; + + /* Initialize the Standard member */ + I2S_InitStruct->Standard = I2S_STD_PHILLIPS; + + /* Initialize the DataFormat member */ + I2S_InitStruct->DataFormat = I2S_DATA_FMT_16BITS; + + /* Initialize the MCLKEnable member */ + I2S_InitStruct->MCLKEnable = I2S_MCLK_DISABLE; + + /* Initialize the AudioFrequency member */ + I2S_InitStruct->AudioFrequency = I2S_AUDIO_FREQ_DEFAULT; + + /* Initialize the CLKPOL member */ + I2S_InitStruct->CLKPOL = I2S_CLKPOL_LOW; +} + +/** + * @brief Enables or disables the specified SPI peripheral. + * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral. + * @param Cmd new state of the SPIx peripheral. + * This parameter can be: ENABLE or DISABLE. + */ +void SPI_Enable(SPI_Module* SPIx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected SPI peripheral */ + SPIx->CTRL1 |= CTRL1_SPIEN_ENABLE; + } + else + { + /* Disable the selected SPI peripheral */ + SPIx->CTRL1 &= CTRL1_SPIEN_DISABLE; + } +} + +/** + * @brief Enables or disables the specified SPI peripheral (in I2S mode). + * @param SPIx where x can be 2 or 3 to select the SPI peripheral. + * @param Cmd new state of the SPIx peripheral. + * This parameter can be: ENABLE or DISABLE. + */ +void I2S_Enable(SPI_Module* SPIx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_SPI_2OR3_PERIPH(SPIx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected SPI peripheral (in I2S mode) */ + SPIx->I2SCFG |= I2SCFG_I2SEN_ENABLE; + } + else + { + /* Disable the selected SPI peripheral (in I2S mode) */ + SPIx->I2SCFG &= I2SCFG_I2SEN_DISABLE; + } +} + +/** + * @brief Enables or disables the specified SPI/I2S interrupts. + * @param SPIx where x can be + * - 1, 2 or 3 in SPI mode + * - 2 or 3 in I2S mode + * @param SPI_I2S_IT specifies the SPI/I2S interrupt source to be enabled or disabled. + * This parameter can be one of the following values: + * @arg SPI_I2S_INT_TE Tx buffer empty interrupt mask + * @arg SPI_I2S_INT_RNE Rx buffer not empty interrupt mask + * @arg SPI_I2S_INT_ERR Error interrupt mask + * @param Cmd new state of the specified SPI/I2S interrupt. + * This parameter can be: ENABLE or DISABLE. + */ +void SPI_I2S_EnableInt(SPI_Module* SPIx, uint8_t SPI_I2S_IT, FunctionalState Cmd) +{ + uint16_t itpos = 0, itmask = 0; + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + assert_param(IS_SPI_I2S_CONFIG_INT(SPI_I2S_IT)); + + /* Get the SPI/I2S IT index */ + itpos = SPI_I2S_IT >> 4; + + /* Set the IT mask */ + itmask = (uint16_t)1 << (uint16_t)itpos; + + if (Cmd != DISABLE) + { + /* Enable the selected SPI/I2S interrupt */ + SPIx->CTRL2 |= itmask; + } + else + { + /* Disable the selected SPI/I2S interrupt */ + SPIx->CTRL2 &= (uint16_t)~itmask; + } +} + +/** + * @brief Enables or disables the SPIx/I2Sx DMA interface. + * @param SPIx where x can be + * - 1, 2 or 3 in SPI mode + * - 2 or 3 in I2S mode + * @param SPI_I2S_DMAReq specifies the SPI/I2S DMA transfer request to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg SPI_I2S_DMA_TX Tx buffer DMA transfer request + * @arg SPI_I2S_DMA_RX Rx buffer DMA transfer request + * @param Cmd new state of the selected SPI/I2S DMA transfer request. + * This parameter can be: ENABLE or DISABLE. + */ +void SPI_I2S_EnableDma(SPI_Module* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + assert_param(IS_SPI_I2S_DMA(SPI_I2S_DMAReq)); + if (Cmd != DISABLE) + { + /* Enable the selected SPI/I2S DMA requests */ + SPIx->CTRL2 |= SPI_I2S_DMAReq; + } + else + { + /* Disable the selected SPI/I2S DMA requests */ + SPIx->CTRL2 &= (uint16_t)~SPI_I2S_DMAReq; + } +} + +/** + * @brief Transmits a Data through the SPIx/I2Sx peripheral. + * @param SPIx where x can be + * - 1, 2 or 3 in SPI mode + * - 2 or 3 in I2S mode + * @param Data Data to be transmitted. + */ +void SPI_I2S_TransmitData(SPI_Module* SPIx, uint16_t Data) +{ + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + + /* Write in the DAT register the data to be sent */ + SPIx->DAT = Data; +} + +/** + * @brief Returns the most recent received data by the SPIx/I2Sx peripheral. + * @param SPIx where x can be + * - 1, 2 or 3 in SPI mode + * - 2 or 3 in I2S mode + * @return The value of the received data. + */ +uint16_t SPI_I2S_ReceiveData(SPI_Module* SPIx) +{ + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + + /* Return the data in the DAT register */ + return SPIx->DAT; +} + +/** + * @brief Configures internally by software the NSS pin for the selected SPI. + * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral. + * @param SPI_NSSInternalSoft specifies the SPI NSS internal state. + * This parameter can be one of the following values: + * @arg SPI_NSS_HIGH Set NSS pin internally + * @arg SPI_NSS_LOW Reset NSS pin internally + */ +void SPI_SetNssLevel(SPI_Module* SPIx, uint16_t SPI_NSSInternalSoft) +{ + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + assert_param(IS_SPI_NSS_LEVEL(SPI_NSSInternalSoft)); + if (SPI_NSSInternalSoft != SPI_NSS_LOW) + { + /* Set NSS pin internally by software */ + SPIx->CTRL1 |= SPI_NSS_HIGH; + } + else + { + /* Reset NSS pin internally by software */ + SPIx->CTRL1 &= SPI_NSS_LOW; + } +} + +/** + * @brief Enables or disables the SS output for the selected SPI. + * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral. + * @param Cmd new state of the SPIx SS output. + * This parameter can be: ENABLE or DISABLE. + */ +void SPI_SSOutputEnable(SPI_Module* SPIx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected SPI SS output */ + SPIx->CTRL2 |= CTRL2_SSOEN_ENABLE; + } + else + { + /* Disable the selected SPI SS output */ + SPIx->CTRL2 &= CTRL2_SSOEN_DISABLE; + } +} + +/** + * @brief Configures the data size for the selected SPI. + * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral. + * @param DataLen specifies the SPI data size. + * This parameter can be one of the following values: + * @arg SPI_DATA_SIZE_16BITS Set data frame format to 16bit + * @arg SPI_DATA_SIZE_8BITS Set data frame format to 8bit + */ +void SPI_ConfigDataLen(SPI_Module* SPIx, uint16_t DataLen) +{ + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + assert_param(IS_SPI_DATASIZE(DataLen)); + /* Clear DFF bit */ + SPIx->CTRL1 &= (uint16_t)~SPI_DATA_SIZE_16BITS; + /* Set new DFF bit value */ + SPIx->CTRL1 |= DataLen; +} + +/** + * @brief Transmit the SPIx CRC value. + * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral. + */ +void SPI_TransmitCrcNext(SPI_Module* SPIx) +{ + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + + /* Enable the selected SPI CRC transmission */ + SPIx->CTRL1 |= CTRL1_CRCNEXT_ENABLE; +} + +/** + * @brief Enables or disables the CRC value calculation of the transferred bytes. + * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral. + * @param Cmd new state of the SPIx CRC value calculation. + * This parameter can be: ENABLE or DISABLE. + */ +void SPI_EnableCalculateCrc(SPI_Module* SPIx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the selected SPI CRC calculation */ + SPIx->CTRL1 |= CTRL1_CRCEN_ENABLE; + } + else + { + /* Disable the selected SPI CRC calculation */ + SPIx->CTRL1 &= CTRL1_CRCEN_DISABLE; + } +} + +/** + * @brief Returns the transmit or the receive CRC register value for the specified SPI. + * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral. + * @param SPI_CRC specifies the CRC register to be read. + * This parameter can be one of the following values: + * @arg SPI_CRC_TX Selects Tx CRC register + * @arg SPI_CRC_RX Selects Rx CRC register + * @return The selected CRC register value.. + */ +uint16_t SPI_GetCRCDat(SPI_Module* SPIx, uint8_t SPI_CRC) +{ + uint16_t crcreg = 0; + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + assert_param(IS_SPI_CRC(SPI_CRC)); + if (SPI_CRC != SPI_CRC_RX) + { + /* Get the Tx CRC register */ + crcreg = SPIx->CRCTDAT; + } + else + { + /* Get the Rx CRC register */ + crcreg = SPIx->CRCRDAT; + } + /* Return the selected CRC register */ + return crcreg; +} + +/** + * @brief Returns the CRC Polynomial register value for the specified SPI. + * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral. + * @return The CRC Polynomial register value. + */ +uint16_t SPI_GetCRCPoly(SPI_Module* SPIx) +{ + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + + /* Return the CRC polynomial register */ + return SPIx->CRCPOLY; +} + +/** + * @brief Selects the data transfer direction in bi-directional mode for the specified SPI. + * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral. + * @param DataDirection specifies the data transfer direction in bi-directional mode. + * This parameter can be one of the following values: + * @arg SPI_BIDIRECTION_TX Selects Tx transmission direction + * @arg SPI_BIDIRECTION_RX Selects Rx receive direction + */ +void SPI_ConfigBidirectionalMode(SPI_Module* SPIx, uint16_t DataDirection) +{ + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + assert_param(IS_SPI_BIDIRECTION(DataDirection)); + if (DataDirection == SPI_BIDIRECTION_TX) + { + /* Set the Tx only mode */ + SPIx->CTRL1 |= SPI_BIDIRECTION_TX; + } + else + { + /* Set the Rx only mode */ + SPIx->CTRL1 &= SPI_BIDIRECTION_RX; + } +} + +/** + * @brief Checks whether the specified SPI/I2S flag is set or not. + * @param SPIx where x can be + * - 1, 2 or 3 in SPI mode + * - 2 or 3 in I2S mode + * @param SPI_I2S_FLAG specifies the SPI/I2S flag to check. + * This parameter can be one of the following values: + * @arg SPI_I2S_TE_FLAG Transmit buffer empty flag. + * @arg SPI_I2S_RNE_FLAG Receive buffer not empty flag. + * @arg SPI_I2S_BUSY_FLAG Busy flag. + * @arg SPI_I2S_OVER_FLAG Overrun flag. + * @arg SPI_MODERR_FLAG Mode Fault flag. + * @arg SPI_CRCERR_FLAG CRC Error flag. + * @arg I2S_UNDER_FLAG Underrun Error flag. + * @arg I2S_CHSIDE_FLAG Channel Side flag. + * @return The new state of SPI_I2S_FLAG (SET or RESET). + */ +FlagStatus SPI_I2S_GetStatus(SPI_Module* SPIx, uint16_t SPI_I2S_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + assert_param(IS_SPI_I2S_GET_FLAG(SPI_I2S_FLAG)); + /* Check the status of the specified SPI/I2S flag */ + if ((SPIx->STS & SPI_I2S_FLAG) != (uint16_t)RESET) + { + /* SPI_I2S_FLAG is set */ + bitstatus = SET; + } + else + { + /* SPI_I2S_FLAG is reset */ + bitstatus = RESET; + } + /* Return the SPI_I2S_FLAG status */ + return bitstatus; +} + +/** + * @brief Clears the SPIx CRC Error (CRCERR) flag. + * @param SPIx where x can be + * - 1, 2 or 3 in SPI mode + * @param SPI_I2S_FLAG specifies the SPI flag to clear. + * This function clears only CRCERR flag. + * @note + * - OVR (OverRun error) flag is cleared by software sequence: a read + * operation to SPI_DAT register (SPI_I2S_ReceiveData()) followed by a read + * operation to SPI_STS register (SPI_I2S_GetStatus()). + * - UDR (UnderRun error) flag is cleared by a read operation to + * SPI_STS register (SPI_I2S_GetStatus()). + * - MODF (Mode Fault) flag is cleared by software sequence: a read/write + * operation to SPI_STS register (SPI_I2S_GetStatus()) followed by a + * write operation to SPI_CTRL1 register (SPI_Enable() to enable the SPI). + */ +void SPI_I2S_ClrCRCErrFlag(SPI_Module* SPIx, uint16_t SPI_I2S_FLAG) +{ + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + assert_param(IS_SPI_I2S_CLR_FLAG(SPI_I2S_FLAG)); + + /* Clear the selected SPI CRC Error (CRCERR) flag */ + SPIx->STS = (uint16_t)~SPI_I2S_FLAG; +} + +/** + * @brief Checks whether the specified SPI/I2S interrupt has occurred or not. + * @param SPIx where x can be + * - 1, 2 or 3 in SPI mode + * - 2 or 3 in I2S mode + * @param SPI_I2S_IT specifies the SPI/I2S interrupt source to check. + * This parameter can be one of the following values: + * @arg SPI_I2S_INT_TE Transmit buffer empty interrupt. + * @arg SPI_I2S_INT_RNE Receive buffer not empty interrupt. + * @arg SPI_I2S_INT_OVER Overrun interrupt. + * @arg SPI_INT_MODERR Mode Fault interrupt. + * @arg SPI_INT_CRCERR CRC Error interrupt. + * @arg I2S_INT_UNDER Underrun Error interrupt. + * @return The new state of SPI_I2S_IT (SET or RESET). + */ +INTStatus SPI_I2S_GetIntStatus(SPI_Module* SPIx, uint8_t SPI_I2S_IT) +{ + INTStatus bitstatus = RESET; + uint16_t itpos = 0, itmask = 0, enablestatus = 0; + + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + assert_param(IS_SPI_I2S_GET_INT(SPI_I2S_IT)); + + /* Get the SPI/I2S IT index */ + itpos = 0x01 << (SPI_I2S_IT & 0x0F); + + /* Get the SPI/I2S IT mask */ + itmask = SPI_I2S_IT >> 4; + + /* Set the IT mask */ + itmask = 0x01 << itmask; + + /* Get the SPI_I2S_IT enable bit status */ + enablestatus = (SPIx->CTRL2 & itmask); + + /* Check the status of the specified SPI/I2S interrupt */ + if (((SPIx->STS & itpos) != (uint16_t)RESET) && enablestatus) + { + /* SPI_I2S_IT is set */ + bitstatus = SET; + } + else + { + /* SPI_I2S_IT is reset */ + bitstatus = RESET; + } + /* Return the SPI_I2S_IT status */ + return bitstatus; +} + +/** + * @brief Clears the SPIx CRC Error (CRCERR) interrupt pending bit. + * @param SPIx where x can be + * - 1, 2 or 3 in SPI mode + * @param SPI_I2S_IT specifies the SPI interrupt pending bit to clear. + * This function clears only CRCERR interrupt pending bit. + * @note + * - OVR (OverRun Error) interrupt pending bit is cleared by software + * sequence: a read operation to SPI_DAT register (SPI_I2S_ReceiveData()) + * followed by a read operation to SPI_STS register (SPI_I2S_GetIntStatus()). + * - UDR (UnderRun Error) interrupt pending bit is cleared by a read + * operation to SPI_STS register (SPI_I2S_GetIntStatus()). + * - MODF (Mode Fault) interrupt pending bit is cleared by software sequence: + * a read/write operation to SPI_STS register (SPI_I2S_GetIntStatus()) + * followed by a write operation to SPI_CTRL1 register (SPI_Enable() to enable + * the SPI). + */ +void SPI_I2S_ClrITPendingBit(SPI_Module* SPIx, uint8_t SPI_I2S_IT) +{ + uint16_t itpos = 0; + /* Check the parameters */ + assert_param(IS_SPI_PERIPH(SPIx)); + assert_param(IS_SPI_I2S_CLR_INT(SPI_I2S_IT)); + + /* Get the SPI IT index */ + itpos = 0x01 << (SPI_I2S_IT & 0x0F); + + /* Clear the selected SPI CRC Error (CRCERR) interrupt pending bit */ + SPIx->STS = (uint16_t)~itpos; +} +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/src/n32g45x_tim.c b/src/n32g45x_tim.c new file mode 100644 index 0000000..ad9370c --- /dev/null +++ b/src/n32g45x_tim.c @@ -0,0 +1,3307 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_tim.c + * @author Nations + * @version v1.0.3 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_tim.h" +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup TIM + * @brief TIM driver modules + * @{ + */ + +/** @addtogroup TIM_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup TIM_Private_Defines + * @{ + */ + +/* ---------------------- TIM registers bit mask ------------------------ */ +#define SMCTRL_ETR_MASK ((uint16_t)0x00FF) +#define CAPCMPMOD_OFFSET ((uint16_t)0x0018) +#define CAPCMPEN_CCE_SET ((uint16_t)0x0001) +#define CAPCMPEN_CCNE_SET ((uint16_t)0x0004) + +/** + * @} + */ + +/** @addtogroup TIM_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup TIM_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup TIM_Private_FunctionPrototypes + * @{ + */ + +static void ConfigTI1(TIM_Module* TIMx, uint16_t IcPolarity, uint16_t IcSelection, uint16_t IcFilter); +static void ConfigTI2(TIM_Module* TIMx, uint16_t IcPolarity, uint16_t IcSelection, uint16_t IcFilter); +static void ConfigTI3(TIM_Module* TIMx, uint16_t IcPolarity, uint16_t IcSelection, uint16_t IcFilter); +static void ConfigTI4(TIM_Module* TIMx, uint16_t IcPolarity, uint16_t IcSelection, uint16_t IcFilter); +/** + * @} + */ + +/** @addtogroup TIM_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup TIM_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup TIM_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup TIM_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the TIMx peripheral registers to their default reset values. + * @param TIMx where x can be 1 to 8 to select the TIM peripheral. + */ +void TIM_DeInit(TIM_Module* TIMx) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + + if (TIMx == TIM1) + { + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_TIM1, ENABLE); + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_TIM1, DISABLE); + } + else if (TIMx == TIM2) + { + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_TIM2, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_TIM2, DISABLE); + } + else if (TIMx == TIM3) + { + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_TIM3, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_TIM3, DISABLE); + } + else if (TIMx == TIM4) + { + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_TIM4, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_TIM4, DISABLE); + } + else if (TIMx == TIM5) + { + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_TIM5, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_TIM5, DISABLE); + } + else if (TIMx == TIM6) + { + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_TIM6, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_TIM6, DISABLE); + } + else if (TIMx == TIM7) + { + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_TIM7, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_TIM7, DISABLE); + } + else if (TIMx == TIM8) + { + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_TIM8, ENABLE); + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_TIM8, DISABLE); + } +} + +/** + * @brief Initializes the TIMx Time Base Unit peripheral according to + * the specified parameters in the TIM_TimeBaseInitStruct. + * @param TIMx where x can be 1 to 8 to select the TIM peripheral. + * @param TIM_TimeBaseInitStruct pointer to a TIM_TimeBaseInitType + * structure that contains the configuration information for the + * specified TIM peripheral. + */ +void TIM_InitTimeBase(TIM_Module* TIMx, TIM_TimeBaseInitType* TIM_TimeBaseInitStruct) +{ + uint32_t tmpcr1 = 0; + + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + assert_param(IsTimCntMode(TIM_TimeBaseInitStruct->CntMode)); + assert_param(IsTimClkDiv(TIM_TimeBaseInitStruct->ClkDiv)); + + tmpcr1 = TIMx->CTRL1; + + if ((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM2) || (TIMx == TIM3) || (TIMx == TIM4) || (TIMx == TIM5)) + { + /* Select the Counter Mode */ + tmpcr1 &= (uint32_t)(~((uint32_t)(TIM_CTRL1_DIR | TIM_CTRL1_CAMSEL))); + tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->CntMode; + } + + if ((TIMx != TIM6) && (TIMx != TIM7)) + { + /* Set the clock division */ + tmpcr1 &= (uint32_t)(~((uint32_t)TIM_CTRL1_CLKD)); + tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->ClkDiv; + } + + TIMx->CTRL1 = tmpcr1; + + /* Set the Autoreload value */ + TIMx->AR = TIM_TimeBaseInitStruct->Period; + + /* Set the Prescaler value */ + TIMx->PSC = TIM_TimeBaseInitStruct->Prescaler; + + if ((TIMx == TIM1) || (TIMx == TIM8)) + { + /* Set the Repetition Counter value */ + TIMx->REPCNT = TIM_TimeBaseInitStruct->RepetCnt; + } + + /* Generate an update event to reload the Prescaler and the Repetition counter + values immediately */ + TIMx->EVTGEN = TIM_PSC_RELOAD_MODE_IMMEDIATE; + + /*channel input from comp or iom*/ + tmpcr1 = TIMx->CTRL1; + if ((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM2) || (TIMx == TIM3) || (TIMx == TIM4) || (TIMx == TIM5)) + { + if (TIM_TimeBaseInitStruct->CapCh1FromCompEn) + tmpcr1 |= (0x01L << 11); + else + tmpcr1 &= ~(0x01L << 11); + } + if ((TIMx == TIM2) || (TIMx == TIM3) || (TIMx == TIM4) || (TIMx == TIM5)) + { + if (TIM_TimeBaseInitStruct->CapCh2FromCompEn) + tmpcr1 |= (0x01L << 12); + else + tmpcr1 &= ~(0x01L << 12); + if (TIM_TimeBaseInitStruct->CapCh3FromCompEn) + tmpcr1 |= (0x01L << 13); + else + tmpcr1 &= ~(0x01L << 13); + } + if ((TIMx == TIM2) || (TIMx == TIM3) || (TIMx == TIM4)) + { + if (TIM_TimeBaseInitStruct->CapCh4FromCompEn) + tmpcr1 |= (0x01L << 14); + else + tmpcr1 &= ~(0x01L << 14); + } + /*etr input from comp or iom*/ + if ((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM2) || (TIMx == TIM3) || (TIMx == TIM4)) + { + if (TIM_TimeBaseInitStruct->CapEtrClrFromCompEn) + tmpcr1 |= (0x01L << 15); + else + tmpcr1 &= ~(0x01L << 15); + } + TIMx->CTRL1 = tmpcr1; + /*sel etr from iom or tsc*/ + tmpcr1 = TIMx->CTRL2; + if ((TIMx == TIM2) || (TIMx == TIM4)) + { + if (TIM_TimeBaseInitStruct->CapEtrSelFromTscEn) + tmpcr1 |= (0x01L << 8); + else + tmpcr1 &= ~(0x01L << 8); + } + TIMx->CTRL2 = tmpcr1; +} + +/** + * @brief Initializes the TIMx Channel1 according to the specified + * parameters in the TIM_OCInitStruct. + * @param TIMx where x can be 1 to 8 except 6 and 7 to select the TIM peripheral. + * @param TIM_OCInitStruct pointer to a OCInitType structure + * that contains the configuration information for the specified TIM peripheral. + */ +void TIM_InitOc1(TIM_Module* TIMx, OCInitType* TIM_OCInitStruct) +{ + uint16_t tmpccmrx = 0; + uint32_t tmpccer = 0, tmpcr2 = 0; + + /* Check the parameters */ + assert_param(IsTimList8Module(TIMx)); + assert_param(IsTimOcMode(TIM_OCInitStruct->OcMode)); + assert_param(IsTimOutputState(TIM_OCInitStruct->OutputState)); + assert_param(IsTimOcPolarity(TIM_OCInitStruct->OcPolarity)); + /* Disable the Channel 1: Reset the CC1E Bit */ + TIMx->CCEN &= (uint32_t)(~(uint32_t)TIM_CCEN_CC1EN); + /* Get the TIMx CCEN register value */ + tmpccer = TIMx->CCEN; + /* Get the TIMx CTRL2 register value */ + tmpcr2 = TIMx->CTRL2; + + /* Get the TIMx CCMOD1 register value */ + tmpccmrx = TIMx->CCMOD1; + + /* Reset the Output Compare Mode Bits */ + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMOD1_OC1M)); + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMOD1_CC1SEL)); + + /* Select the Output Compare Mode */ + tmpccmrx |= TIM_OCInitStruct->OcMode; + + /* Reset the Output Polarity level */ + tmpccer &= (uint32_t)(~((uint32_t)TIM_CCEN_CC1P)); + /* Set the Output Compare Polarity */ + tmpccer |= TIM_OCInitStruct->OcPolarity; + + /* Set the Output State */ + tmpccer |= TIM_OCInitStruct->OutputState; + + if ((TIMx == TIM1) || (TIMx == TIM8)) + { + assert_param(IsTimOutputNState(TIM_OCInitStruct->OutputNState)); + assert_param(IsTimOcnPolarity(TIM_OCInitStruct->OcNPolarity)); + assert_param(IsTimOcnIdleState(TIM_OCInitStruct->OcNIdleState)); + assert_param(IsTimOcIdleState(TIM_OCInitStruct->OcIdleState)); + + /* Reset the Output N Polarity level */ + tmpccer &= (uint32_t)(~((uint32_t)TIM_CCEN_CC1NP)); + /* Set the Output N Polarity */ + tmpccer |= TIM_OCInitStruct->OcNPolarity; + + /* Reset the Output N State */ + tmpccer &= (uint32_t)(~((uint32_t)TIM_CCEN_CC1NEN)); + /* Set the Output N State */ + tmpccer |= TIM_OCInitStruct->OutputNState; + + /* Reset the Output Compare and Output Compare N IDLE State */ + tmpcr2 &= (uint32_t)(~((uint32_t)TIM_CTRL2_OI1)); + tmpcr2 &= (uint32_t)(~((uint32_t)TIM_CTRL2_OI1N)); + + /* Set the Output Idle state */ + tmpcr2 |= TIM_OCInitStruct->OcIdleState; + /* Set the Output N Idle state */ + tmpcr2 |= TIM_OCInitStruct->OcNIdleState; + } + /* Write to TIMx CTRL2 */ + TIMx->CTRL2 = tmpcr2; + + /* Write to TIMx CCMOD1 */ + TIMx->CCMOD1 = tmpccmrx; + + /* Set the Capture Compare Register value */ + TIMx->CCDAT1 = TIM_OCInitStruct->Pulse; + + /* Write to TIMx CCEN */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Initializes the TIMx Channel2 according to the specified + * parameters in the TIM_OCInitStruct. + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 to select + * the TIM peripheral. + * @param TIM_OCInitStruct pointer to a OCInitType structure + * that contains the configuration information for the specified TIM peripheral. + */ +void TIM_InitOc2(TIM_Module* TIMx, OCInitType* TIM_OCInitStruct) +{ + uint16_t tmpccmrx = 0; + uint32_t tmpccer = 0, tmpcr2 = 0; + + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + assert_param(IsTimOcMode(TIM_OCInitStruct->OcMode)); + assert_param(IsTimOutputState(TIM_OCInitStruct->OutputState)); + assert_param(IsTimOcPolarity(TIM_OCInitStruct->OcPolarity)); + /* Disable the Channel 2: Reset the CC2E Bit */ + TIMx->CCEN &= (uint32_t)(~((uint32_t)TIM_CCEN_CC2EN)); + + /* Get the TIMx CCEN register value */ + tmpccer = TIMx->CCEN; + /* Get the TIMx CTRL2 register value */ + tmpcr2 = TIMx->CTRL2; + + /* Get the TIMx CCMOD1 register value */ + tmpccmrx = TIMx->CCMOD1; + + /* Reset the Output Compare mode and Capture/Compare selection Bits */ + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMOD1_OC2M)); + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMOD1_CC2SEL)); + + /* Select the Output Compare Mode */ + tmpccmrx |= (uint16_t)(TIM_OCInitStruct->OcMode << 8); + + /* Reset the Output Polarity level */ + tmpccer &= (uint32_t)(~((uint32_t)TIM_CCEN_CC2P)); + /* Set the Output Compare Polarity */ + tmpccer |= (uint32_t)(TIM_OCInitStruct->OcPolarity << 4); + + /* Set the Output State */ + tmpccer |= (uint32_t)(TIM_OCInitStruct->OutputState << 4); + + if ((TIMx == TIM1) || (TIMx == TIM8)) + { + assert_param(IsTimOutputNState(TIM_OCInitStruct->OutputNState)); + assert_param(IsTimOcnPolarity(TIM_OCInitStruct->OcNPolarity)); + assert_param(IsTimOcnIdleState(TIM_OCInitStruct->OcNIdleState)); + assert_param(IsTimOcIdleState(TIM_OCInitStruct->OcIdleState)); + + /* Reset the Output N Polarity level */ + tmpccer &= (uint32_t)(~((uint32_t)TIM_CCEN_CC2NP)); + /* Set the Output N Polarity */ + tmpccer |= (uint32_t)(TIM_OCInitStruct->OcNPolarity << 4); + + /* Reset the Output N State */ + tmpccer &= (uint32_t)(~((uint16_t)TIM_CCEN_CC2NEN)); + /* Set the Output N State */ + tmpccer |= (uint32_t)(TIM_OCInitStruct->OutputNState << 4); + + /* Reset the Output Compare and Output Compare N IDLE State */ + tmpcr2 &= (uint32_t)(~((uint32_t)TIM_CTRL2_OI2)); + tmpcr2 &= (uint32_t)(~((uint32_t)TIM_CTRL2_OI2N)); + + /* Set the Output Idle state */ + tmpcr2 |= (uint32_t)(TIM_OCInitStruct->OcIdleState << 2); + /* Set the Output N Idle state */ + tmpcr2 |= (uint32_t)(TIM_OCInitStruct->OcNIdleState << 2); + } + /* Write to TIMx CTRL2 */ + TIMx->CTRL2 = tmpcr2; + + /* Write to TIMx CCMOD1 */ + TIMx->CCMOD1 = tmpccmrx; + + /* Set the Capture Compare Register value */ + TIMx->CCDAT2 = TIM_OCInitStruct->Pulse; + + /* Write to TIMx CCEN */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Initializes the TIMx Channel3 according to the specified + * parameters in the TIM_OCInitStruct. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_OCInitStruct pointer to a OCInitType structure + * that contains the configuration information for the specified TIM peripheral. + */ +void TIM_InitOc3(TIM_Module* TIMx, OCInitType* TIM_OCInitStruct) +{ + uint16_t tmpccmrx = 0; + uint32_t tmpccer = 0, tmpcr2 = 0; + + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimOcMode(TIM_OCInitStruct->OcMode)); + assert_param(IsTimOutputState(TIM_OCInitStruct->OutputState)); + assert_param(IsTimOcPolarity(TIM_OCInitStruct->OcPolarity)); + /* Disable the Channel 2: Reset the CC2E Bit */ + TIMx->CCEN &= (uint32_t)(~((uint32_t)TIM_CCEN_CC3EN)); + + /* Get the TIMx CCEN register value */ + tmpccer = TIMx->CCEN; + /* Get the TIMx CTRL2 register value */ + tmpcr2 = TIMx->CTRL2; + + /* Get the TIMx CCMOD2 register value */ + tmpccmrx = TIMx->CCMOD2; + + /* Reset the Output Compare mode and Capture/Compare selection Bits */ + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMOD2_OC3MD)); + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMOD2_CC3SEL)); + /* Select the Output Compare Mode */ + tmpccmrx |= TIM_OCInitStruct->OcMode; + + /* Reset the Output Polarity level */ + tmpccer &= (uint32_t)(~((uint16_t)TIM_CCEN_CC3P)); + /* Set the Output Compare Polarity */ + tmpccer |= (uint32_t)(TIM_OCInitStruct->OcPolarity << 8); + + /* Set the Output State */ + tmpccer |= (uint32_t)(TIM_OCInitStruct->OutputState << 8); + + if ((TIMx == TIM1) || (TIMx == TIM8)) + { + assert_param(IsTimOutputNState(TIM_OCInitStruct->OutputNState)); + assert_param(IsTimOcnPolarity(TIM_OCInitStruct->OcNPolarity)); + assert_param(IsTimOcnIdleState(TIM_OCInitStruct->OcNIdleState)); + assert_param(IsTimOcIdleState(TIM_OCInitStruct->OcIdleState)); + + /* Reset the Output N Polarity level */ + tmpccer &= (uint32_t)(~((uint32_t)TIM_CCEN_CC3NP)); + /* Set the Output N Polarity */ + tmpccer |= (uint32_t)(TIM_OCInitStruct->OcNPolarity << 8); + /* Reset the Output N State */ + tmpccer &= (uint32_t)(~((uint32_t)TIM_CCEN_CC3NEN)); + + /* Set the Output N State */ + tmpccer |= (uint32_t)(TIM_OCInitStruct->OutputNState << 8); + /* Reset the Output Compare and Output Compare N IDLE State */ + tmpcr2 &= (uint32_t)(~((uint32_t)TIM_CTRL2_OI3)); + tmpcr2 &= (uint32_t)(~((uint32_t)TIM_CTRL2_OI3N)); + /* Set the Output Idle state */ + tmpcr2 |= (uint32_t)(TIM_OCInitStruct->OcIdleState << 4); + /* Set the Output N Idle state */ + tmpcr2 |= (uint32_t)(TIM_OCInitStruct->OcNIdleState << 4); + } + /* Write to TIMx CTRL2 */ + TIMx->CTRL2 = tmpcr2; + + /* Write to TIMx CCMOD2 */ + TIMx->CCMOD2 = tmpccmrx; + + /* Set the Capture Compare Register value */ + TIMx->CCDAT3 = TIM_OCInitStruct->Pulse; + + /* Write to TIMx CCEN */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Initializes the TIMx Channel4 according to the specified + * parameters in the TIM_OCInitStruct. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_OCInitStruct pointer to a OCInitType structure + * that contains the configuration information for the specified TIM peripheral. + */ +void TIM_InitOc4(TIM_Module* TIMx, OCInitType* TIM_OCInitStruct) +{ + uint16_t tmpccmrx = 0; + uint32_t tmpccer = 0, tmpcr2 = 0; + + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimOcMode(TIM_OCInitStruct->OcMode)); + assert_param(IsTimOutputState(TIM_OCInitStruct->OutputState)); + assert_param(IsTimOcPolarity(TIM_OCInitStruct->OcPolarity)); + /* Disable the Channel 2: Reset the CC4E Bit */ + TIMx->CCEN &= (uint32_t)(~((uint32_t)TIM_CCEN_CC4EN)); + + /* Get the TIMx CCEN register value */ + tmpccer = TIMx->CCEN; + /* Get the TIMx CTRL2 register value */ + tmpcr2 = TIMx->CTRL2; + + /* Get the TIMx CCMOD2 register value */ + tmpccmrx = TIMx->CCMOD2; + + /* Reset the Output Compare mode and Capture/Compare selection Bits */ + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMOD2_OC4MD)); + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMOD2_CC4SEL)); + + /* Select the Output Compare Mode */ + tmpccmrx |= (uint16_t)(TIM_OCInitStruct->OcMode << 8); + + /* Reset the Output Polarity level */ + tmpccer &= (uint32_t)(~((uint32_t)TIM_CCEN_CC4P)); + /* Set the Output Compare Polarity */ + tmpccer |= (uint32_t)(TIM_OCInitStruct->OcPolarity << 12); + + /* Set the Output State */ + tmpccer |= (uint32_t)(TIM_OCInitStruct->OutputState << 12); + + if ((TIMx == TIM1) || (TIMx == TIM8)) + { + assert_param(IsTimOcIdleState(TIM_OCInitStruct->OcIdleState)); + /* Reset the Output Compare IDLE State */ + tmpcr2 &= (uint32_t)(~((uint32_t)TIM_CTRL2_OI4)); + /* Set the Output Idle state */ + tmpcr2 |= (uint32_t)(TIM_OCInitStruct->OcIdleState << 6); + } + /* Write to TIMx CTRL2 */ + TIMx->CTRL2 = tmpcr2; + + /* Write to TIMx CCMOD2 */ + TIMx->CCMOD2 = tmpccmrx; + + /* Set the Capture Compare Register value */ + TIMx->CCDAT4 = TIM_OCInitStruct->Pulse; + + /* Write to TIMx CCEN */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Initializes the TIMx Channel5 according to the specified + * parameters in the TIM_OCInitStruct. + * @param TIMx where x can be 1 or 8 to select the TIM peripheral. + * @param TIM_OCInitStruct pointer to a OCInitType structure + * that contains the configuration information for the specified TIM peripheral. + */ +void TIM_InitOc5(TIM_Module* TIMx, OCInitType* TIM_OCInitStruct) +{ + uint16_t tmpccmrx = 0; + uint32_t tmpccer = 0, tmpcr2 = 0; + + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + assert_param(IsTimOcMode(TIM_OCInitStruct->OcMode)); + assert_param(IsTimOutputState(TIM_OCInitStruct->OutputState)); + assert_param(IsTimOcPolarity(TIM_OCInitStruct->OcPolarity)); + /* Disable the Channel 5: Reset the CC5E Bit */ + TIMx->CCEN &= (uint32_t)(~((uint32_t)TIM_CCEN_CC5EN)); + + /* Get the TIMx CCEN register value */ + tmpccer = TIMx->CCEN; + /* Get the TIMx CTRL2 register value */ + tmpcr2 = TIMx->CTRL2; + + /* Get the TIMx CCMOD3 register value */ + tmpccmrx = TIMx->CCMOD3; + + /* Reset the Output Compare mode and Capture/Compare selection Bits */ + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMOD3_OC5MD)); + + /* Select the Output Compare Mode */ + tmpccmrx |= (uint16_t)(TIM_OCInitStruct->OcMode); + + /* Reset the Output Polarity level */ + tmpccer &= (uint32_t)(~((uint32_t)TIM_CCEN_CC5P)); + /* Set the Output Compare Polarity */ + tmpccer |= (uint32_t)(TIM_OCInitStruct->OcPolarity << 16); + + /* Set the Output State */ + tmpccer |= (uint32_t)(TIM_OCInitStruct->OutputState << 16); + + if ((TIMx == TIM1) || (TIMx == TIM8)) + { + assert_param(IsTimOcIdleState(TIM_OCInitStruct->OcIdleState)); + /* Reset the Output Compare IDLE State */ + tmpcr2 &= (uint32_t)(~((uint32_t)TIM_CTRL2_OI5)); + /* Set the Output Idle state */ + tmpcr2 |= (uint32_t)(TIM_OCInitStruct->OcIdleState << 8); + } + /* Write to TIMx CTRL2 */ + TIMx->CTRL2 = tmpcr2; + + /* Write to TIMx CCMOD3 */ + TIMx->CCMOD3 = tmpccmrx; + + /* Set the Capture Compare Register value */ + TIMx->CCDAT5 = TIM_OCInitStruct->Pulse; + + /* Write to TIMx CCEN */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Initializes the TIMx Channel6 according to the specified + * parameters in the TIM_OCInitStruct. + * @param TIMx where x can be 1 or 8 to select the TIM peripheral. + * @param TIM_OCInitStruct pointer to a OCInitType structure + * that contains the configuration information for the specified TIM peripheral. + */ +void TIM_InitOc6(TIM_Module* TIMx, OCInitType* TIM_OCInitStruct) +{ + uint16_t tmpccmrx = 0; + uint32_t tmpccer = 0, tmpcr2 = 0; + + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + assert_param(IsTimOcMode(TIM_OCInitStruct->OcMode)); + assert_param(IsTimOutputState(TIM_OCInitStruct->OutputState)); + assert_param(IsTimOcPolarity(TIM_OCInitStruct->OcPolarity)); + /* Disable the Channel 6: Reset the CC6E Bit */ + TIMx->CCEN &= (uint32_t)(~((uint32_t)TIM_CCEN_CC6EN)); + + /* Get the TIMx CCEN register value */ + tmpccer = TIMx->CCEN; + /* Get the TIMx CTRL2 register value */ + tmpcr2 = TIMx->CTRL2; + + /* Get the TIMx CCMOD3 register value */ + tmpccmrx = TIMx->CCMOD3; + + /* Reset the Output Compare mode and Capture/Compare selection Bits */ + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMOD3_OC6MD)); + + /* Select the Output Compare Mode */ + tmpccmrx |= (uint16_t)(TIM_OCInitStruct->OcMode << 8); + + /* Reset the Output Polarity level */ + tmpccer &= (uint32_t)(~((uint32_t)TIM_CCEN_CC6P)); + /* Set the Output Compare Polarity */ + tmpccer |= (uint32_t)(TIM_OCInitStruct->OcPolarity << 20); + + /* Set the Output State */ + tmpccer |= (uint32_t)(TIM_OCInitStruct->OutputState << 20); + + if ((TIMx == TIM1) || (TIMx == TIM8)) + { + assert_param(IsTimOcIdleState(TIM_OCInitStruct->OcIdleState)); + /* Reset the Output Compare IDLE State */ + tmpcr2 &= (uint32_t)(~((uint32_t)TIM_CTRL2_OI6)); + /* Set the Output Idle state */ + tmpcr2 |= (uint32_t)(TIM_OCInitStruct->OcIdleState << 10); + } + /* Write to TIMx CTRL2 */ + TIMx->CTRL2 = tmpcr2; + + /* Write to TIMx CCMOD3 */ + TIMx->CCMOD3 = tmpccmrx; + + /* Set the Capture Compare Register value */ + TIMx->CCDAT6 = TIM_OCInitStruct->Pulse; + + /* Write to TIMx CCEN */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Initializes the TIM peripheral according to the specified + * parameters in the TIM_ICInitStruct. + * @param TIMx where x can be 1 to 8 except 6 and 7 to select the TIM peripheral. + * @param TIM_ICInitStruct pointer to a TIM_ICInitType structure + * that contains the configuration information for the specified TIM peripheral. + */ +void TIM_ICInit(TIM_Module* TIMx, TIM_ICInitType* TIM_ICInitStruct) +{ + /* Check the parameters */ + assert_param(IsTimCh(TIM_ICInitStruct->Channel)); + assert_param(IsTimIcSelection(TIM_ICInitStruct->IcSelection)); + assert_param(IsTimIcPrescaler(TIM_ICInitStruct->IcPrescaler)); + assert_param(IsTimInCapFilter(TIM_ICInitStruct->IcFilter)); + + if ((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM2) || (TIMx == TIM3) || (TIMx == TIM4) || (TIMx == TIM5)) + { + assert_param(IsTimIcPalaritySingleEdge(TIM_ICInitStruct->IcPolarity)); + } + else + { + assert_param(IsTimIcPolarityAnyEdge(TIM_ICInitStruct->IcPolarity)); + } + if (TIM_ICInitStruct->Channel == TIM_CH_1) + { + assert_param(IsTimList8Module(TIMx)); + /* TI1 Configuration */ + ConfigTI1(TIMx, TIM_ICInitStruct->IcPolarity, TIM_ICInitStruct->IcSelection, TIM_ICInitStruct->IcFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetInCap1Prescaler(TIMx, TIM_ICInitStruct->IcPrescaler); + } + else if (TIM_ICInitStruct->Channel == TIM_CH_2) + { + assert_param(IsTimList6Module(TIMx)); + /* TI2 Configuration */ + ConfigTI2(TIMx, TIM_ICInitStruct->IcPolarity, TIM_ICInitStruct->IcSelection, TIM_ICInitStruct->IcFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetInCap2Prescaler(TIMx, TIM_ICInitStruct->IcPrescaler); + } + else if (TIM_ICInitStruct->Channel == TIM_CH_3) + { + assert_param(IsTimList3Module(TIMx)); + /* TI3 Configuration */ + ConfigTI3(TIMx, TIM_ICInitStruct->IcPolarity, TIM_ICInitStruct->IcSelection, TIM_ICInitStruct->IcFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetInCap3Prescaler(TIMx, TIM_ICInitStruct->IcPrescaler); + } + else + { + assert_param(IsTimList3Module(TIMx)); + /* TI4 Configuration */ + ConfigTI4(TIMx, TIM_ICInitStruct->IcPolarity, TIM_ICInitStruct->IcSelection, TIM_ICInitStruct->IcFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetInCap4Prescaler(TIMx, TIM_ICInitStruct->IcPrescaler); + } +} + +/** + * @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 1, 2, 3, 4, 5, 8 to select the TIM peripheral. + * @param TIM_ICInitStruct pointer to a TIM_ICInitType structure + * that contains the configuration information for the specified TIM peripheral. + */ +void TIM_ConfigPwmIc(TIM_Module* TIMx, TIM_ICInitType* TIM_ICInitStruct) +{ + uint16_t icoppositepolarity = TIM_IC_POLARITY_RISING; + uint16_t icoppositeselection = TIM_IC_SELECTION_DIRECTTI; + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + /* Select the Opposite Input Polarity */ + if (TIM_ICInitStruct->IcPolarity == TIM_IC_POLARITY_RISING) + { + icoppositepolarity = TIM_IC_POLARITY_FALLING; + } + else + { + icoppositepolarity = TIM_IC_POLARITY_RISING; + } + /* Select the Opposite Input */ + if (TIM_ICInitStruct->IcSelection == TIM_IC_SELECTION_DIRECTTI) + { + icoppositeselection = TIM_IC_SELECTION_INDIRECTTI; + } + else + { + icoppositeselection = TIM_IC_SELECTION_DIRECTTI; + } + if (TIM_ICInitStruct->Channel == TIM_CH_1) + { + /* TI1 Configuration */ + ConfigTI1(TIMx, TIM_ICInitStruct->IcPolarity, TIM_ICInitStruct->IcSelection, TIM_ICInitStruct->IcFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetInCap1Prescaler(TIMx, TIM_ICInitStruct->IcPrescaler); + /* TI2 Configuration */ + ConfigTI2(TIMx, icoppositepolarity, icoppositeselection, TIM_ICInitStruct->IcFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetInCap2Prescaler(TIMx, TIM_ICInitStruct->IcPrescaler); + } + else + { + /* TI2 Configuration */ + ConfigTI2(TIMx, TIM_ICInitStruct->IcPolarity, TIM_ICInitStruct->IcSelection, TIM_ICInitStruct->IcFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetInCap2Prescaler(TIMx, TIM_ICInitStruct->IcPrescaler); + /* TI1 Configuration */ + ConfigTI1(TIMx, icoppositepolarity, icoppositeselection, TIM_ICInitStruct->IcFilter); + /* Set the Input Capture Prescaler value */ + TIM_SetInCap1Prescaler(TIMx, TIM_ICInitStruct->IcPrescaler); + } +} + +/** + * @brief Configures the: Break feature, dead time, Lock level, the OSSI, + * the OSSR State and the AOE(automatic output enable). + * @param TIMx where x can be 1 or 8 to select the TIM + * @param TIM_BDTRInitStruct pointer to a TIM_BDTRInitType structure that + * contains the BKDT Register configuration information for the TIM peripheral. + */ +void TIM_ConfigBkdt(TIM_Module* TIMx, TIM_BDTRInitType* TIM_BDTRInitStruct) +{ + uint32_t tmp; + /* Check the parameters */ + assert_param(IsTimList2Module(TIMx)); + assert_param(IsTimOssrState(TIM_BDTRInitStruct->OssrState)); + assert_param(IsTimOssiState(TIM_BDTRInitStruct->OssiState)); + assert_param(IsTimLockLevel(TIM_BDTRInitStruct->LockLevel)); + assert_param(IsTimBreakInState(TIM_BDTRInitStruct->Break)); + assert_param(IsTimBreakPalarity(TIM_BDTRInitStruct->BreakPolarity)); + assert_param(IsTimAutoOutputState(TIM_BDTRInitStruct->AutomaticOutput)); + /* Set the Lock level, the Break enable Bit and the Ploarity, the OSSR State, + the OSSI State, the dead time value and the Automatic Output Enable Bit */ + TIMx->BKDT = (uint32_t)TIM_BDTRInitStruct->OssrState | TIM_BDTRInitStruct->OssiState | TIM_BDTRInitStruct->LockLevel + | TIM_BDTRInitStruct->DeadTime | TIM_BDTRInitStruct->Break | TIM_BDTRInitStruct->BreakPolarity + | TIM_BDTRInitStruct->AutomaticOutput; + + /*cofigure other break in*/ + tmp = TIMx->CTRL1; + /*IOMBKPEN 0 meaning iom as break enable*/ + if (TIM_BDTRInitStruct->IomBreakEn) + tmp &= ~(0x01L << 10); + else + tmp |= (0x01L << 10); + if (TIM_BDTRInitStruct->LockUpBreakEn) + tmp |= (0x01L << 16); + else + tmp &= ~(0x01L << 16); + if (TIM_BDTRInitStruct->PvdBreakEn) + tmp |= (0x01L << 17); + else + tmp &= ~(0x01L << 17); + TIMx->CTRL1 = tmp; +} + +/** + * @brief Fills each TIM_TimeBaseInitStruct member with its default value. + * @param TIM_TimeBaseInitStruct pointer to a TIM_TimeBaseInitType + * structure which will be initialized. + */ +void TIM_InitTimBaseStruct(TIM_TimeBaseInitType* TIM_TimeBaseInitStruct) +{ + /* Set the default configuration */ + TIM_TimeBaseInitStruct->Period = 0xFFFF; + TIM_TimeBaseInitStruct->Prescaler = 0x0000; + TIM_TimeBaseInitStruct->ClkDiv = TIM_CLK_DIV1; + TIM_TimeBaseInitStruct->CntMode = TIM_CNT_MODE_UP; + TIM_TimeBaseInitStruct->RepetCnt = 0x0000; + + TIM_TimeBaseInitStruct->CapCh1FromCompEn = false; + TIM_TimeBaseInitStruct->CapCh2FromCompEn = false; + TIM_TimeBaseInitStruct->CapCh3FromCompEn = false; + TIM_TimeBaseInitStruct->CapCh4FromCompEn = false; + TIM_TimeBaseInitStruct->CapEtrClrFromCompEn = false; + TIM_TimeBaseInitStruct->CapEtrSelFromTscEn = false; +} + +/** + * @brief Fills each TIM_OCInitStruct member with its default value. + * @param TIM_OCInitStruct pointer to a OCInitType structure which will + * be initialized. + */ +void TIM_InitOcStruct(OCInitType* TIM_OCInitStruct) +{ + /* Set the default configuration */ + TIM_OCInitStruct->OcMode = TIM_OCMODE_TIMING; + TIM_OCInitStruct->OutputState = TIM_OUTPUT_STATE_DISABLE; + TIM_OCInitStruct->OutputNState = TIM_OUTPUT_NSTATE_DISABLE; + TIM_OCInitStruct->Pulse = 0x0000; + TIM_OCInitStruct->OcPolarity = TIM_OC_POLARITY_HIGH; + TIM_OCInitStruct->OcNPolarity = TIM_OC_POLARITY_HIGH; + TIM_OCInitStruct->OcIdleState = TIM_OC_IDLE_STATE_RESET; + TIM_OCInitStruct->OcNIdleState = TIM_OCN_IDLE_STATE_RESET; +} + +/** + * @brief Fills each TIM_ICInitStruct member with its default value. + * @param TIM_ICInitStruct pointer to a TIM_ICInitType structure which will + * be initialized. + */ +void TIM_InitIcStruct(TIM_ICInitType* TIM_ICInitStruct) +{ + /* Set the default configuration */ + TIM_ICInitStruct->Channel = TIM_CH_1; + TIM_ICInitStruct->IcPolarity = TIM_IC_POLARITY_RISING; + TIM_ICInitStruct->IcSelection = TIM_IC_SELECTION_DIRECTTI; + TIM_ICInitStruct->IcPrescaler = TIM_IC_PSC_DIV1; + TIM_ICInitStruct->IcFilter = 0x00; +} + +/** + * @brief Fills each TIM_BDTRInitStruct member with its default value. + * @param TIM_BDTRInitStruct pointer to a TIM_BDTRInitType structure which + * will be initialized. + */ +void TIM_InitBkdtStruct(TIM_BDTRInitType* TIM_BDTRInitStruct) +{ + /* Set the default configuration */ + TIM_BDTRInitStruct->OssrState = TIM_OSSR_STATE_DISABLE; + TIM_BDTRInitStruct->OssiState = TIM_OSSI_STATE_DISABLE; + TIM_BDTRInitStruct->LockLevel = TIM_LOCK_LEVEL_OFF; + TIM_BDTRInitStruct->DeadTime = 0x00; + TIM_BDTRInitStruct->Break = TIM_BREAK_IN_DISABLE; + TIM_BDTRInitStruct->BreakPolarity = TIM_BREAK_POLARITY_LOW; + TIM_BDTRInitStruct->AutomaticOutput = TIM_AUTO_OUTPUT_DISABLE; +} + +/** + * @brief Enables or disables the specified TIM peripheral. + * @param TIMx where x can be 1 to 8 to select the TIMx peripheral. + * @param Cmd new state of the TIMx peripheral. + * This parameter can be: ENABLE or DISABLE. + */ +void TIM_Enable(TIM_Module* TIMx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the TIM Counter */ + TIMx->CTRL1 |= TIM_CTRL1_CNTEN; + } + else + { + /* Disable the TIM Counter */ + TIMx->CTRL1 &= (uint32_t)(~((uint32_t)TIM_CTRL1_CNTEN)); + } +} + +/** + * @brief Enables or disables the TIM peripheral Main Outputs. + * @param TIMx where x can be 1, 8 to select the TIMx peripheral. + * @param Cmd new state of the TIM peripheral Main Outputs. + * This parameter can be: ENABLE or DISABLE. + */ +void TIM_EnableCtrlPwmOutputs(TIM_Module* TIMx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsTimList2Module(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the TIM Main Output */ + TIMx->BKDT |= TIM_BKDT_MOEN; + } + else + { + /* Disable the TIM Main Output */ + TIMx->BKDT &= (uint16_t)(~((uint16_t)TIM_BKDT_MOEN)); + } +} + +/** + * @brief Enables or disables the specified TIM interrupts. + * @param TIMx where x can be 1 to 8 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_INT_UPDATE TIM update Interrupt source + * @arg TIM_INT_CC1 TIM Capture Compare 1 Interrupt source + * @arg TIM_INT_CC2 TIM Capture Compare 2 Interrupt source + * @arg TIM_INT_CC3 TIM Capture Compare 3 Interrupt source + * @arg TIM_INT_CC4 TIM Capture Compare 4 Interrupt source + * @arg TIM_INT_COM TIM Commutation Interrupt source + * @arg TIM_INT_TRIG TIM Trigger Interrupt source + * @arg TIM_INT_BREAK TIM Break Interrupt source + * @note + * - TIM6 and TIM7 can only generate an update interrupt. + * - TIM_INT_BREAK is used only with TIM1, TIM8. + * - TIM_INT_COM is used only with TIM1, TIM8. + * @param Cmd new state of the TIM interrupts. + * This parameter can be: ENABLE or DISABLE. + */ +void TIM_ConfigInt(TIM_Module* TIMx, uint16_t TIM_IT, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + assert_param(IsTimInt(TIM_IT)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the Interrupt sources */ + TIMx->DINTEN |= TIM_IT; + } + else + { + /* Disable the Interrupt sources */ + TIMx->DINTEN &= (uint16_t)~TIM_IT; + } +} + +/** + * @brief Configures the TIMx event to be generate by software. + * @param TIMx where x can be 1 to 8 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_EVT_SRC_UPDATE Timer update Event source + * @arg TIM_EVT_SRC_CC1 Timer Capture Compare 1 Event source + * @arg TIM_EVT_SRC_CC2 Timer Capture Compare 2 Event source + * @arg TIM_EVT_SRC_CC3 Timer Capture Compare 3 Event source + * @arg TIM_EVT_SRC_CC4 Timer Capture Compare 4 Event source + * @arg TIM_EVT_SRC_COM Timer COM event source + * @arg TIM_EVT_SRC_TRIG Timer Trigger Event source + * @arg TIM_EVT_SRC_BREAK Timer Break event source + * @note + * - TIM6 and TIM7 can only generate an update event. + * - TIM_EVT_SRC_COM and TIM_EVT_SRC_BREAK are used only with TIM1 and TIM8. + */ +void TIM_GenerateEvent(TIM_Module* TIMx, uint16_t TIM_EventSource) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + assert_param(IsTimEvtSrc(TIM_EventSource)); + + /* Set the event sources */ + TIMx->EVTGEN = TIM_EventSource; +} + +/** + * @brief Configures the TIMx's DMA interface. + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 to select + * the TIM peripheral. + * @param TIM_DMABase DMA Base address. + * This parameter can be one of the following values: + * @arg TIM_DMABase_CR, TIM_DMABASE_CTRL2, TIM_DMABASE_SMCTRL, + * TIM_DMABASE_DMAINTEN, TIM1_DMABase_SR, TIM_DMABASE_EVTGEN, + * TIM_DMABASE_CAPCMPMOD1, TIM_DMABASE_CAPCMPMOD2, TIM_DMABASE_CAPCMPEN, + * TIM_DMABASE_CNT, TIM_DMABASE_PSC, TIM_DMABASE_AR, + * TIM_DMABASE_REPCNT, TIM_DMABASE_CAPCMPDAT1, TIM_DMABASE_CAPCMPDAT2, + * TIM_DMABASE_CAPCMPDAT3, TIM_DMABASE_CAPCMPDAT4, TIM_DMABASE_BKDT, + * TIM_DMABASE_CAPCMPMOD3, TIM_DMABASE_CAPCMPDAT5, TIM_DMABASE_CAPCMPDAT6, + * TIM_DMABASE_DMACTRL. + * @param TIM_DMABurstLength DMA Burst length. + * This parameter can be one value between: + * TIM_DMABURST_LENGTH_1TRANSFER and TIM_DMABURST_LENGTH_18TRANSFERS. + */ +void TIM_ConfigDma(TIM_Module* TIMx, uint16_t TIM_DMABase, uint16_t TIM_DMABurstLength) +{ + /* Check the parameters */ + assert_param(IsTimList4Module(TIMx)); + assert_param(IsTimDmaBase(TIM_DMABase)); + assert_param(IsTimDmaLength(TIM_DMABurstLength)); + /* Set the DMA Base and the DMA Burst Length */ + TIMx->DCTRL = TIM_DMABase | TIM_DMABurstLength; +} + +/** + * @brief Enables or disables the TIMx's DMA Requests. + * @param TIMx where x can be 1, 2, 3, 4, 5, 6, 7, 8 + * 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_COM TIM Commutation DMA source + * @arg TIM_DMA_TRIG TIM Trigger DMA source + * @param Cmd new state of the DMA Request sources. + * This parameter can be: ENABLE or DISABLE. + */ +void TIM_EnableDma(TIM_Module* TIMx, uint16_t TIM_DMASource, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsTimList9Module(TIMx)); + assert_param(IsTimDmaSrc(TIM_DMASource)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the DMA sources */ + TIMx->DINTEN |= TIM_DMASource; + } + else + { + /* Disable the DMA sources */ + TIMx->DINTEN &= (uint16_t)~TIM_DMASource; + } +} + +/** + * @brief Configures the TIMx internal Clock + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 + * to select the TIM peripheral. + */ +void TIM_ConfigInternalClk(TIM_Module* TIMx) +{ + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + /* Disable slave mode to clock the prescaler directly with the internal clock */ + TIMx->SMCTRL &= (uint16_t)(~((uint16_t)TIM_SMCTRL_SMSEL)); +} + +/** + * @brief Configures the TIMx Internal Trigger as External Clock + * @param TIMx where x can be 1, 2, 3, 4, 5 to select the TIM peripheral. + * @param TIM_InputTriggerSource Trigger source. + * This parameter can be one of the following values: + * @arg TIM_TRIG_SEL_IN_TR0 Internal Trigger 0 + * @arg TIM_TRIG_SEL_IN_TR1 Internal Trigger 1 + * @arg TIM_TRIG_SEL_IN_TR2 Internal Trigger 2 + * @arg TIM_TRIG_SEL_IN_TR3 Internal Trigger 3 + */ +void TIM_ConfigInternalTrigToExt(TIM_Module* TIMx, uint16_t TIM_InputTriggerSource) +{ + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + assert_param(IsTimInterTrigSel(TIM_InputTriggerSource)); + /* Select the Internal Trigger */ + TIM_SelectInputTrig(TIMx, TIM_InputTriggerSource); + /* Select the External clock mode1 */ + TIMx->SMCTRL |= TIM_SLAVE_MODE_EXT1; +} + +/** + * @brief Configures the TIMx Trigger as External Clock + * @param TIMx where x can be 1, 2, 3, 4, 5 to select the TIM peripheral. + * @param TIM_TIxExternalCLKSource Trigger source. + * This parameter can be one of the following values: + * @arg TIM_EXT_CLK_SRC_TI1ED TI1 Edge Detector + * @arg TIM_EXT_CLK_SRC_TI1 Filtered Timer Input 1 + * @arg TIM_EXT_CLK_SRC_TI2 Filtered Timer Input 2 + * @param IcPolarity specifies the TIx Polarity. + * This parameter can be one of the following values: + * @arg TIM_IC_POLARITY_RISING + * @arg TIM_IC_POLARITY_FALLING + * @param ICFilter specifies the filter value. + * This parameter must be a value between 0x0 and 0xF. + */ +void TIM_ConfigExtTrigAsClk(TIM_Module* TIMx, uint16_t TIM_TIxExternalCLKSource, uint16_t IcPolarity, uint16_t ICFilter) +{ + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + assert_param(IsTimExtClkSrc(TIM_TIxExternalCLKSource)); + assert_param(IsTimIcPalaritySingleEdge(IcPolarity)); + assert_param(IsTimInCapFilter(ICFilter)); + /* Configure the Timer Input Clock Source */ + if (TIM_TIxExternalCLKSource == TIM_EXT_CLK_SRC_TI2) + { + ConfigTI2(TIMx, IcPolarity, TIM_IC_SELECTION_DIRECTTI, ICFilter); + } + else + { + ConfigTI1(TIMx, IcPolarity, TIM_IC_SELECTION_DIRECTTI, ICFilter); + } + /* Select the Trigger source */ + TIM_SelectInputTrig(TIMx, TIM_TIxExternalCLKSource); + /* Select the External clock mode1 */ + TIMx->SMCTRL |= TIM_SLAVE_MODE_EXT1; +} + +/** + * @brief Configures the External clock Mode1 + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_ExtTRGPrescaler The external Trigger Prescaler. + * This parameter can be one of the following values: + * @arg TIM_EXT_TRG_PSC_OFF ETRP Prescaler OFF. + * @arg TIM_EXT_TRG_PSC_DIV2 ETRP frequency divided by 2. + * @arg TIM_EXT_TRG_PSC_DIV4 ETRP frequency divided by 4. + * @arg TIM_EXT_TRG_PSC_DIV8 ETRP frequency divided by 8. + * @param TIM_ExtTRGPolarity The external Trigger Polarity. + * This parameter can be one of the following values: + * @arg TIM_EXT_TRIG_POLARITY_INVERTED active low or falling edge active. + * @arg TIM_EXT_TRIG_POLARITY_NONINVERTED active high or rising edge active. + * @param ExtTRGFilter External Trigger Filter. + * This parameter must be a value between 0x00 and 0x0F + */ +void TIM_ConfigExtClkMode1(TIM_Module* TIMx, + uint16_t TIM_ExtTRGPrescaler, + uint16_t TIM_ExtTRGPolarity, + uint16_t ExtTRGFilter) +{ + uint16_t tmpsmcr = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimExtPreDiv(TIM_ExtTRGPrescaler)); + assert_param(IsTimExtTrigPolarity(TIM_ExtTRGPolarity)); + assert_param(IsTimExtTrigFilter(ExtTRGFilter)); + /* Configure the ETR Clock source */ + TIM_ConfigExtTrig(TIMx, TIM_ExtTRGPrescaler, TIM_ExtTRGPolarity, ExtTRGFilter); + + /* Get the TIMx SMCTRL register value */ + tmpsmcr = TIMx->SMCTRL; + /* Reset the SMS Bits */ + tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCTRL_SMSEL)); + /* Select the External clock mode1 */ + tmpsmcr |= TIM_SLAVE_MODE_EXT1; + /* Select the Trigger selection : ETRF */ + tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCTRL_TSEL)); + tmpsmcr |= TIM_TRIG_SEL_ETRF; + /* Write to TIMx SMCTRL */ + TIMx->SMCTRL = tmpsmcr; +} + +/** + * @brief Configures the External clock Mode2 + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_ExtTRGPrescaler The external Trigger Prescaler. + * This parameter can be one of the following values: + * @arg TIM_EXT_TRG_PSC_OFF ETRP Prescaler OFF. + * @arg TIM_EXT_TRG_PSC_DIV2 ETRP frequency divided by 2. + * @arg TIM_EXT_TRG_PSC_DIV4 ETRP frequency divided by 4. + * @arg TIM_EXT_TRG_PSC_DIV8 ETRP frequency divided by 8. + * @param TIM_ExtTRGPolarity The external Trigger Polarity. + * This parameter can be one of the following values: + * @arg TIM_EXT_TRIG_POLARITY_INVERTED active low or falling edge active. + * @arg TIM_EXT_TRIG_POLARITY_NONINVERTED active high or rising edge active. + * @param ExtTRGFilter External Trigger Filter. + * This parameter must be a value between 0x00 and 0x0F + */ +void TIM_ConfigExtClkMode2(TIM_Module* TIMx, + uint16_t TIM_ExtTRGPrescaler, + uint16_t TIM_ExtTRGPolarity, + uint16_t ExtTRGFilter) +{ + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimExtPreDiv(TIM_ExtTRGPrescaler)); + assert_param(IsTimExtTrigPolarity(TIM_ExtTRGPolarity)); + assert_param(IsTimExtTrigFilter(ExtTRGFilter)); + /* Configure the ETR Clock source */ + TIM_ConfigExtTrig(TIMx, TIM_ExtTRGPrescaler, TIM_ExtTRGPolarity, ExtTRGFilter); + /* Enable the External clock mode2 */ + TIMx->SMCTRL |= TIM_SMCTRL_EXCEN; +} + +/** + * @brief Configures the TIMx External Trigger (ETR). + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_ExtTRGPrescaler The external Trigger Prescaler. + * This parameter can be one of the following values: + * @arg TIM_EXT_TRG_PSC_OFF ETRP Prescaler OFF. + * @arg TIM_EXT_TRG_PSC_DIV2 ETRP frequency divided by 2. + * @arg TIM_EXT_TRG_PSC_DIV4 ETRP frequency divided by 4. + * @arg TIM_EXT_TRG_PSC_DIV8 ETRP frequency divided by 8. + * @param TIM_ExtTRGPolarity The external Trigger Polarity. + * This parameter can be one of the following values: + * @arg TIM_EXT_TRIG_POLARITY_INVERTED active low or falling edge active. + * @arg TIM_EXT_TRIG_POLARITY_NONINVERTED active high or rising edge active. + * @param ExtTRGFilter External Trigger Filter. + * This parameter must be a value between 0x00 and 0x0F + */ +void TIM_ConfigExtTrig(TIM_Module* TIMx, + uint16_t TIM_ExtTRGPrescaler, + uint16_t TIM_ExtTRGPolarity, + uint16_t ExtTRGFilter) +{ + uint16_t tmpsmcr = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimExtPreDiv(TIM_ExtTRGPrescaler)); + assert_param(IsTimExtTrigPolarity(TIM_ExtTRGPolarity)); + assert_param(IsTimExtTrigFilter(ExtTRGFilter)); + tmpsmcr = TIMx->SMCTRL; + /* Reset the ETR Bits */ + tmpsmcr &= SMCTRL_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 SMCTRL */ + TIMx->SMCTRL = tmpsmcr; +} + +/** + * @brief Configures the TIMx Prescaler. + * @param TIMx where x can be 1 to 8 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_PSC_RELOAD_MODE_UPDATE The Prescaler is loaded at the update event. + * @arg TIM_PSC_RELOAD_MODE_IMMEDIATE The Prescaler is loaded immediately. + */ +void TIM_ConfigPrescaler(TIM_Module* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + assert_param(IsTimPscReloadMode(TIM_PSCReloadMode)); + /* Set the Prescaler value */ + TIMx->PSC = Prescaler; + /* Set or reset the UG Bit */ + TIMx->EVTGEN = TIM_PSCReloadMode; +} + +/** + * @brief Specifies the TIMx Counter Mode to be used. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param CntMode specifies the Counter Mode to be used + * This parameter can be one of the following values: + * @arg TIM_CNT_MODE_UP TIM Up Counting Mode + * @arg TIM_CNT_MODE_DOWN TIM Down Counting Mode + * @arg TIM_CNT_MODE_CENTER_ALIGN1 TIM Center Aligned Mode1 + * @arg TIM_CNT_MODE_CENTER_ALIGN2 TIM Center Aligned Mode2 + * @arg TIM_CNT_MODE_CENTER_ALIGN3 TIM Center Aligned Mode3 + */ +void TIM_ConfigCntMode(TIM_Module* TIMx, uint16_t CntMode) +{ + uint32_t tmpcr1 = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimCntMode(CntMode)); + tmpcr1 = TIMx->CTRL1; + /* Reset the CMS and DIR Bits */ + tmpcr1 &= (uint32_t)(~((uint32_t)(TIM_CTRL1_DIR | TIM_CTRL1_CAMSEL))); + /* Set the Counter Mode */ + tmpcr1 |= CntMode; + /* Write to TIMx CTRL1 register */ + TIMx->CTRL1 = tmpcr1; +} + +/** + * @brief Selects the Input Trigger source + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 to select the TIM peripheral. + * @param TIM_InputTriggerSource The Input Trigger source. + * This parameter can be one of the following values: + * @arg TIM_TRIG_SEL_IN_TR0 Internal Trigger 0 + * @arg TIM_TRIG_SEL_IN_TR1 Internal Trigger 1 + * @arg TIM_TRIG_SEL_IN_TR2 Internal Trigger 2 + * @arg TIM_TRIG_SEL_IN_TR3 Internal Trigger 3 + * @arg TIM_TRIG_SEL_TI1F_ED TI1 Edge Detector + * @arg TIM_TRIG_SEL_TI1FP1 Filtered Timer Input 1 + * @arg TIM_TRIG_SEL_TI2FP2 Filtered Timer Input 2 + * @arg TIM_TRIG_SEL_ETRF External Trigger input + */ +void TIM_SelectInputTrig(TIM_Module* TIMx, uint16_t TIM_InputTriggerSource) +{ + uint16_t tmpsmcr = 0; + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + assert_param(IsTimTrigSel(TIM_InputTriggerSource)); + /* Get the TIMx SMCTRL register value */ + tmpsmcr = TIMx->SMCTRL; + /* Reset the TS Bits */ + tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCTRL_TSEL)); + /* Set the Input Trigger source */ + tmpsmcr |= TIM_InputTriggerSource; + /* Write to TIMx SMCTRL */ + TIMx->SMCTRL = tmpsmcr; +} + +/** + * @brief Configures the TIMx Encoder Interface. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param TIM_EncoderMode specifies the TIMx Encoder Mode. + * This parameter can be one of the following values: + * @arg TIM_ENCODE_MODE_TI1 Counter counts on TI1FP1 edge depending on TI2FP2 level. + * @arg TIM_ENCODE_MODE_TI2 Counter counts on TI2FP2 edge depending on TI1FP1 level. + * @arg TIM_ENCODE_MODE_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 parameter can be one of the following values: + * @arg TIM_IC_POLARITY_FALLING IC Falling edge. + * @arg TIM_IC_POLARITY_RISING IC Rising edge. + * @param TIM_IC2Polarity specifies the IC2 Polarity + * This parameter can be one of the following values: + * @arg TIM_IC_POLARITY_FALLING IC Falling edge. + * @arg TIM_IC_POLARITY_RISING IC Rising edge. + */ +void TIM_ConfigEncoderInterface(TIM_Module* TIMx, + uint16_t TIM_EncoderMode, + uint16_t TIM_IC1Polarity, + uint16_t TIM_IC2Polarity) +{ + uint16_t tmpsmcr = 0; + uint16_t tmpccmr1 = 0; + uint32_t tmpccer = 0; + + /* Check the parameters */ + assert_param(IsTimList5Module(TIMx)); + assert_param(IsTimEncodeMode(TIM_EncoderMode)); + assert_param(IsTimIcPalaritySingleEdge(TIM_IC1Polarity)); + assert_param(IsTimIcPalaritySingleEdge(TIM_IC2Polarity)); + + /* Get the TIMx SMCTRL register value */ + tmpsmcr = TIMx->SMCTRL; + + /* Get the TIMx CCMOD1 register value */ + tmpccmr1 = TIMx->CCMOD1; + + /* Get the TIMx CCEN register value */ + tmpccer = TIMx->CCEN; + + /* Set the encoder Mode */ + tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCTRL_SMSEL)); + tmpsmcr |= TIM_EncoderMode; + + /* Select the Capture Compare 1 and the Capture Compare 2 as input */ + tmpccmr1 &= (uint16_t)(((uint16_t) ~((uint16_t)TIM_CCMOD1_CC1SEL)) & (uint16_t)(~((uint16_t)TIM_CCMOD1_CC2SEL))); + tmpccmr1 |= TIM_CCMOD1_CC1SEL_0 | TIM_CCMOD1_CC2SEL_0; + + /* Set the TI1 and the TI2 Polarities */ + tmpccer &= (uint32_t)(((uint32_t) ~((uint32_t)TIM_CCEN_CC1P)) & ((uint32_t) ~((uint32_t)TIM_CCEN_CC2P))); + tmpccer |= (uint32_t)(TIM_IC1Polarity | (uint16_t)(TIM_IC2Polarity << (uint16_t)4)); + + /* Write to TIMx SMCTRL */ + TIMx->SMCTRL = tmpsmcr; + /* Write to TIMx CCMOD1 */ + TIMx->CCMOD1 = tmpccmr1; + /* Write to TIMx CCEN */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Forces the TIMx output 1 waveform to active or inactive level. + * @param TIMx where x can be 1 to 8 except 6 and 7 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_FORCED_ACTION_ACTIVE Force active level on OC1REF + * @arg TIM_FORCED_ACTION_INACTIVE Force inactive level on OC1REF. + */ +void TIM_ConfigForcedOc1(TIM_Module* TIMx, uint16_t TIM_ForcedAction) +{ + uint16_t tmpccmr1 = 0; + /* Check the parameters */ + assert_param(IsTimList8Module(TIMx)); + assert_param(IsTimForceActive(TIM_ForcedAction)); + tmpccmr1 = TIMx->CCMOD1; + /* Reset the OC1M Bits */ + tmpccmr1 &= (uint16_t) ~((uint16_t)TIM_CCMOD1_OC1M); + /* Configure The Forced output Mode */ + tmpccmr1 |= TIM_ForcedAction; + /* Write to TIMx CCMOD1 register */ + TIMx->CCMOD1 = tmpccmr1; +} + +/** + * @brief Forces the TIMx output 2 waveform to active or inactive level. + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 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_FORCED_ACTION_ACTIVE Force active level on OC2REF + * @arg TIM_FORCED_ACTION_INACTIVE Force inactive level on OC2REF. + */ +void TIM_ConfigForcedOc2(TIM_Module* TIMx, uint16_t TIM_ForcedAction) +{ + uint16_t tmpccmr1 = 0; + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + assert_param(IsTimForceActive(TIM_ForcedAction)); + tmpccmr1 = TIMx->CCMOD1; + /* Reset the OC2M Bits */ + tmpccmr1 &= (uint16_t) ~((uint16_t)TIM_CCMOD1_OC2M); + /* Configure The Forced output Mode */ + tmpccmr1 |= (uint16_t)(TIM_ForcedAction << 8); + /* Write to TIMx CCMOD1 register */ + TIMx->CCMOD1 = tmpccmr1; +} + +/** + * @brief Forces the TIMx output 3 waveform to active or inactive level. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 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_FORCED_ACTION_ACTIVE Force active level on OC3REF + * @arg TIM_FORCED_ACTION_INACTIVE Force inactive level on OC3REF. + */ +void TIM_ConfigForcedOc3(TIM_Module* TIMx, uint16_t TIM_ForcedAction) +{ + uint16_t tmpccmr2 = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimForceActive(TIM_ForcedAction)); + tmpccmr2 = TIMx->CCMOD2; + /* Reset the OC1M Bits */ + tmpccmr2 &= (uint16_t) ~((uint16_t)TIM_CCMOD2_OC3MD); + /* Configure The Forced output Mode */ + tmpccmr2 |= TIM_ForcedAction; + /* Write to TIMx CCMOD2 register */ + TIMx->CCMOD2 = tmpccmr2; +} + +/** + * @brief Forces the TIMx output 4 waveform to active or inactive level. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 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_FORCED_ACTION_ACTIVE Force active level on OC4REF + * @arg TIM_FORCED_ACTION_INACTIVE Force inactive level on OC4REF. + */ +void TIM_ConfigForcedOc4(TIM_Module* TIMx, uint16_t TIM_ForcedAction) +{ + uint16_t tmpccmr2 = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimForceActive(TIM_ForcedAction)); + tmpccmr2 = TIMx->CCMOD2; + /* Reset the OC2M Bits */ + tmpccmr2 &= (uint16_t) ~((uint16_t)TIM_CCMOD2_OC4MD); + /* Configure The Forced output Mode */ + tmpccmr2 |= (uint16_t)(TIM_ForcedAction << 8); + /* Write to TIMx CCMOD2 register */ + TIMx->CCMOD2 = tmpccmr2; +} + +/** + * @brief Forces the TIMx output 5 waveform to active or inactive level. + * @param TIMx where x can be 1 or 8 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_FORCED_ACTION_ACTIVE Force active level on OC5REF + * @arg TIM_FORCED_ACTION_INACTIVE Force inactive level on OC5REF. + */ +void TIM_ConfigForcedOc5(TIM_Module* TIMx, uint16_t TIM_ForcedAction) +{ + uint16_t tmpccmr3 = 0; + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + assert_param(IsTimForceActive(TIM_ForcedAction)); + tmpccmr3 = TIMx->CCMOD3; + /* Reset the OC2M Bits */ + tmpccmr3 &= (uint16_t) ~((uint16_t)TIM_CCMOD3_OC5MD); + /* Configure The Forced output Mode */ + tmpccmr3 |= (uint16_t)(TIM_ForcedAction); + /* Write to TIMx CCMOD2 register */ + TIMx->CCMOD3 = tmpccmr3; +} + +/** + * @brief Forces the TIMx output 6 waveform to active or inactive level. + * @param TIMx where x can be 1 or 8 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_FORCED_ACTION_ACTIVE Force active level on OC6REF + * @arg TIM_FORCED_ACTION_INACTIVE Force inactive level on OC6REF. + */ +void TIM_ConfigForcedOc6(TIM_Module* TIMx, uint16_t TIM_ForcedAction) +{ + uint16_t tmpccmr3 = 0; + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + assert_param(IsTimForceActive(TIM_ForcedAction)); + tmpccmr3 = TIMx->CCMOD3; + /* Reset the OC2M Bits */ + tmpccmr3 &= (uint16_t) ~((uint16_t)TIM_CCMOD3_OC6MD); + /* Configure The Forced output Mode */ + tmpccmr3 |= (uint16_t)(TIM_ForcedAction << 8); + /* Write to TIMx CCMOD2 register */ + TIMx->CCMOD3 = tmpccmr3; +} + +/** + * @brief Enables or disables TIMx peripheral Preload register on AR. + * @param TIMx where x can be 1 to 8 to select the TIM peripheral. + * @param Cmd new state of the TIMx peripheral Preload register + * This parameter can be: ENABLE or DISABLE. + */ +void TIM_ConfigArPreload(TIM_Module* TIMx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Set the AR Preload Bit */ + TIMx->CTRL1 |= TIM_CTRL1_ARPEN; + } + else + { + /* Reset the AR Preload Bit */ + TIMx->CTRL1 &= (uint32_t) ~((uint32_t)TIM_CTRL1_ARPEN); + } +} + +/** + * @brief Selects the TIM peripheral Commutation event. + * @param TIMx where x can be 1, 8 to select the TIMx peripheral + * @param Cmd new state of the Commutation event. + * This parameter can be: ENABLE or DISABLE. + */ +void TIM_SelectComEvt(TIM_Module* TIMx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsTimList2Module(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Set the COM Bit */ + TIMx->CTRL2 |= TIM_CTRL2_CCUSEL; + } + else + { + /* Reset the COM Bit */ + TIMx->CTRL2 &= (uint32_t) ~((uint32_t)TIM_CTRL2_CCUSEL); + } +} + +/** + * @brief Selects the TIMx peripheral Capture Compare DMA source. + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 to select + * the TIM peripheral. + * @param Cmd new state of the Capture Compare DMA source + * This parameter can be: ENABLE or DISABLE. + */ +void TIM_SelectCapCmpDmaSrc(TIM_Module* TIMx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsTimList4Module(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Set the CCDS Bit */ + TIMx->CTRL2 |= TIM_CTRL2_CCDSEL; + } + else + { + /* Reset the CCDS Bit */ + TIMx->CTRL2 &= (uint32_t) ~((uint32_t)TIM_CTRL2_CCDSEL); + } +} + +/** + * @brief Sets or Resets the TIM peripheral Capture Compare Preload Control bit. + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 + * to select the TIMx peripheral + * @param Cmd new state of the Capture Compare Preload Control bit + * This parameter can be: ENABLE or DISABLE. + */ +void TIM_EnableCapCmpPreloadControl(TIM_Module* TIMx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsTimList5Module(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Set the CCPC Bit */ + TIMx->CTRL2 |= TIM_CTRL2_CCPCTL; + } + else + { + /* Reset the CCPC Bit */ + TIMx->CTRL2 &= (uint32_t) ~((uint32_t)TIM_CTRL2_CCPCTL); + } +} + +/** + * @brief Enables or disables the TIMx peripheral Preload register on CCDAT1. + * @param TIMx where x can be 1 to 8 except 6 and 7 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_OC_PRE_LOAD_ENABLE + * @arg TIM_OC_PRE_LOAD_DISABLE + */ +void TIM_ConfigOc1Preload(TIM_Module* TIMx, uint16_t TIM_OCPreload) +{ + uint16_t tmpccmr1 = 0; + /* Check the parameters */ + assert_param(IsTimList8Module(TIMx)); + assert_param(IsTimOcPreLoadState(TIM_OCPreload)); + tmpccmr1 = TIMx->CCMOD1; + /* Reset the OC1PE Bit */ + tmpccmr1 &= (uint16_t) ~((uint16_t)TIM_CCMOD1_OC1PEN); + /* Enable or Disable the Output Compare Preload feature */ + tmpccmr1 |= TIM_OCPreload; + /* Write to TIMx CCMOD1 register */ + TIMx->CCMOD1 = tmpccmr1; +} + +/** + * @brief Enables or disables the TIMx peripheral Preload register on CCDAT2. + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 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_OC_PRE_LOAD_ENABLE + * @arg TIM_OC_PRE_LOAD_DISABLE + */ +void TIM_ConfigOc2Preload(TIM_Module* TIMx, uint16_t TIM_OCPreload) +{ + uint16_t tmpccmr1 = 0; + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + assert_param(IsTimOcPreLoadState(TIM_OCPreload)); + tmpccmr1 = TIMx->CCMOD1; + /* Reset the OC2PE Bit */ + tmpccmr1 &= (uint16_t) ~((uint16_t)TIM_CCMOD1_OC2PEN); + /* Enable or Disable the Output Compare Preload feature */ + tmpccmr1 |= (uint16_t)(TIM_OCPreload << 8); + /* Write to TIMx CCMOD1 register */ + TIMx->CCMOD1 = tmpccmr1; +} + +/** + * @brief Enables or disables the TIMx peripheral Preload register on CCDAT3. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 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_OC_PRE_LOAD_ENABLE + * @arg TIM_OC_PRE_LOAD_DISABLE + */ +void TIM_ConfigOc3Preload(TIM_Module* TIMx, uint16_t TIM_OCPreload) +{ + uint16_t tmpccmr2 = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimOcPreLoadState(TIM_OCPreload)); + tmpccmr2 = TIMx->CCMOD2; + /* Reset the OC3PE Bit */ + tmpccmr2 &= (uint16_t) ~((uint16_t)TIM_CCMOD2_OC3PEN); + /* Enable or Disable the Output Compare Preload feature */ + tmpccmr2 |= TIM_OCPreload; + /* Write to TIMx CCMOD2 register */ + TIMx->CCMOD2 = tmpccmr2; +} + +/** + * @brief Enables or disables the TIMx peripheral Preload register on CCDAT4. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 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_OC_PRE_LOAD_ENABLE + * @arg TIM_OC_PRE_LOAD_DISABLE + */ +void TIM_ConfigOc4Preload(TIM_Module* TIMx, uint16_t TIM_OCPreload) +{ + uint16_t tmpccmr2 = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimOcPreLoadState(TIM_OCPreload)); + tmpccmr2 = TIMx->CCMOD2; + /* Reset the OC4PE Bit */ + tmpccmr2 &= (uint16_t) ~((uint16_t)TIM_CCMOD2_OC4PEN); + /* Enable or Disable the Output Compare Preload feature */ + tmpccmr2 |= (uint16_t)(TIM_OCPreload << 8); + /* Write to TIMx CCMOD2 register */ + TIMx->CCMOD2 = tmpccmr2; +} + +/** + * @brief Enables or disables the TIMx peripheral Preload register on CCDAT5. + * @param TIMx where x can be 1 or 8 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_OC_PRE_LOAD_ENABLE + * @arg TIM_OC_PRE_LOAD_DISABLE + */ +void TIM_ConfigOc5Preload(TIM_Module* TIMx, uint16_t TIM_OCPreload) +{ + uint16_t tmpccmr3 = 0; + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + assert_param(IsTimOcPreLoadState(TIM_OCPreload)); + tmpccmr3 = TIMx->CCMOD3; + /* Reset the OC5PE Bit */ + tmpccmr3 &= (uint16_t) ~((uint16_t)TIM_CCMOD3_OC5PEN); + /* Enable or Disable the Output Compare Preload feature */ + tmpccmr3 |= (uint16_t)(TIM_OCPreload); + /* Write to TIMx CCMOD3 register */ + TIMx->CCMOD3 = tmpccmr3; +} + +/** + * @brief Enables or disables the TIMx peripheral Preload register on CCDAT6. + * @param TIMx where x can be 1 or 8 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_OC_PRE_LOAD_ENABLE + * @arg TIM_OC_PRE_LOAD_DISABLE + */ +void TIM_ConfigOc6Preload(TIM_Module* TIMx, uint16_t TIM_OCPreload) +{ + uint16_t tmpccmr3 = 0; + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + assert_param(IsTimOcPreLoadState(TIM_OCPreload)); + tmpccmr3 = TIMx->CCMOD3; + /* Reset the OC6PE Bit */ + tmpccmr3 &= (uint16_t) ~((uint16_t)TIM_CCMOD3_OC6PEN); + /* Enable or Disable the Output Compare Preload feature */ + tmpccmr3 |= (uint16_t)(TIM_OCPreload << 8); + /* Write to TIMx CCMOD3 register */ + TIMx->CCMOD3 = tmpccmr3; +} + +/** + * @brief Configures the TIMx Output Compare 1 Fast feature. + * @param TIMx where x can be 1 to 8 except 6 and 7 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_OC_FAST_ENABLE TIM output compare fast enable + * @arg TIM_OC_FAST_DISABLE TIM output compare fast disable + */ +void TIM_ConfigOc1Fast(TIM_Module* TIMx, uint16_t TIM_OCFast) +{ + uint16_t tmpccmr1 = 0; + /* Check the parameters */ + assert_param(IsTimList8Module(TIMx)); + assert_param(IsTimOcFastState(TIM_OCFast)); + /* Get the TIMx CCMOD1 register value */ + tmpccmr1 = TIMx->CCMOD1; + /* Reset the OC1FE Bit */ + tmpccmr1 &= (uint16_t) ~((uint16_t)TIM_CCMOD1_OC1FEN); + /* Enable or Disable the Output Compare Fast Bit */ + tmpccmr1 |= TIM_OCFast; + /* Write to TIMx CCMOD1 */ + TIMx->CCMOD1 = tmpccmr1; +} + +/** + * @brief Configures the TIMx Output Compare 2 Fast feature. + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 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_OC_FAST_ENABLE TIM output compare fast enable + * @arg TIM_OC_FAST_DISABLE TIM output compare fast disable + */ +void TIM_ConfigOc2Fast(TIM_Module* TIMx, uint16_t TIM_OCFast) +{ + uint16_t tmpccmr1 = 0; + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + assert_param(IsTimOcFastState(TIM_OCFast)); + /* Get the TIMx CCMOD1 register value */ + tmpccmr1 = TIMx->CCMOD1; + /* Reset the OC2FE Bit */ + tmpccmr1 &= (uint16_t) ~((uint16_t)TIM_CCMOD1_OC2FEN); + /* Enable or Disable the Output Compare Fast Bit */ + tmpccmr1 |= (uint16_t)(TIM_OCFast << 8); + /* Write to TIMx CCMOD1 */ + TIMx->CCMOD1 = tmpccmr1; +} + +/** + * @brief Configures the TIMx Output Compare 3 Fast feature. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 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_OC_FAST_ENABLE TIM output compare fast enable + * @arg TIM_OC_FAST_DISABLE TIM output compare fast disable + */ +void TIM_ConfigOc3Fast(TIM_Module* TIMx, uint16_t TIM_OCFast) +{ + uint16_t tmpccmr2 = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimOcFastState(TIM_OCFast)); + /* Get the TIMx CCMOD2 register value */ + tmpccmr2 = TIMx->CCMOD2; + /* Reset the OC3FE Bit */ + tmpccmr2 &= (uint16_t) ~((uint16_t)TIM_CCMOD2_OC3FEN); + /* Enable or Disable the Output Compare Fast Bit */ + tmpccmr2 |= TIM_OCFast; + /* Write to TIMx CCMOD2 */ + TIMx->CCMOD2 = tmpccmr2; +} + +/** + * @brief Configures the TIMx Output Compare 4 Fast feature. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 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_OC_FAST_ENABLE TIM output compare fast enable + * @arg TIM_OC_FAST_DISABLE TIM output compare fast disable + */ +void TIM_ConfigOc4Fast(TIM_Module* TIMx, uint16_t TIM_OCFast) +{ + uint16_t tmpccmr2 = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimOcFastState(TIM_OCFast)); + /* Get the TIMx CCMOD2 register value */ + tmpccmr2 = TIMx->CCMOD2; + /* Reset the OC4FE Bit */ + tmpccmr2 &= (uint16_t) ~((uint16_t)TIM_CCMOD2_OC4FEN); + /* Enable or Disable the Output Compare Fast Bit */ + tmpccmr2 |= (uint16_t)(TIM_OCFast << 8); + /* Write to TIMx CCMOD2 */ + TIMx->CCMOD2 = tmpccmr2; +} + +/** + * @brief Configures the TIMx Output Compare 5 Fast feature. + * @param TIMx where x can be 1 or 8 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_OC_FAST_ENABLE TIM output compare fast enable + * @arg TIM_OC_FAST_DISABLE TIM output compare fast disable + */ +void TIM_ConfigOc5Fast(TIM_Module* TIMx, uint16_t TIM_OCFast) +{ + uint16_t tmpccmr3 = 0; + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + assert_param(IsTimOcFastState(TIM_OCFast)); + /* Get the TIMx CCMOD2 register value */ + tmpccmr3 = TIMx->CCMOD3; + /* Reset the OC4FE Bit */ + tmpccmr3 &= (uint16_t) ~((uint16_t)TIM_CCMOD3_OC5FEN); + /* Enable or Disable the Output Compare Fast Bit */ + tmpccmr3 |= (uint16_t)(TIM_OCFast); + /* Write to TIMx CCMOD3 */ + TIMx->CCMOD3 = tmpccmr3; +} + +/** + * @brief Configures the TIMx Output Compare 6 Fast feature. + * @param TIMx where x can be 1 or 8 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_OC_FAST_ENABLE TIM output compare fast enable + * @arg TIM_OC_FAST_DISABLE TIM output compare fast disable + */ +void TIM_ConfigOc6Fast(TIM_Module* TIMx, uint16_t TIM_OCFast) +{ + uint16_t tmpccmr3 = 0; + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + assert_param(IsTimOcFastState(TIM_OCFast)); + /* Get the TIMx CCMOD2 register value */ + tmpccmr3 = TIMx->CCMOD3; + /* Reset the OC4FE Bit */ + tmpccmr3 &= (uint16_t) ~((uint16_t)TIM_CCMOD3_OC6FEN); + /* Enable or Disable the Output Compare Fast Bit */ + tmpccmr3 |= (uint16_t)(TIM_OCFast << 8); + /* Write to TIMx CCMOD3 */ + TIMx->CCMOD3 = tmpccmr3; +} + +/** + * @brief Clears or safeguards the OCREF1 signal on an external event + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 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_OC_CLR_ENABLE TIM Output clear enable + * @arg TIM_OC_CLR_DISABLE TIM Output clear disable + */ +void TIM_ClrOc1Ref(TIM_Module* TIMx, uint16_t TIM_OCClear) +{ + uint16_t tmpccmr1 = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimOcClrState(TIM_OCClear)); + + tmpccmr1 = TIMx->CCMOD1; + + /* Reset the OC1CE Bit */ + tmpccmr1 &= (uint16_t) ~((uint16_t)TIM_CCMOD1_OC1CEN); + /* Enable or Disable the Output Compare Clear Bit */ + tmpccmr1 |= TIM_OCClear; + /* Write to TIMx CCMOD1 register */ + TIMx->CCMOD1 = tmpccmr1; +} + +/** + * @brief Clears or safeguards the OCREF2 signal on an external event + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 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_OC_CLR_ENABLE TIM Output clear enable + * @arg TIM_OC_CLR_DISABLE TIM Output clear disable + */ +void TIM_ClrOc2Ref(TIM_Module* TIMx, uint16_t TIM_OCClear) +{ + uint16_t tmpccmr1 = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimOcClrState(TIM_OCClear)); + tmpccmr1 = TIMx->CCMOD1; + /* Reset the OC2CE Bit */ + tmpccmr1 &= (uint16_t) ~((uint16_t)TIM_CCMOD1_OC2CEN); + /* Enable or Disable the Output Compare Clear Bit */ + tmpccmr1 |= (uint16_t)(TIM_OCClear << 8); + /* Write to TIMx CCMOD1 register */ + TIMx->CCMOD1 = tmpccmr1; +} + +/** + * @brief Clears or safeguards the OCREF3 signal on an external event + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 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_OC_CLR_ENABLE TIM Output clear enable + * @arg TIM_OC_CLR_DISABLE TIM Output clear disable + */ +void TIM_ClrOc3Ref(TIM_Module* TIMx, uint16_t TIM_OCClear) +{ + uint16_t tmpccmr2 = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimOcClrState(TIM_OCClear)); + tmpccmr2 = TIMx->CCMOD2; + /* Reset the OC3CE Bit */ + tmpccmr2 &= (uint16_t) ~((uint16_t)TIM_CCMOD2_OC3CEN); + /* Enable or Disable the Output Compare Clear Bit */ + tmpccmr2 |= TIM_OCClear; + /* Write to TIMx CCMOD2 register */ + TIMx->CCMOD2 = tmpccmr2; +} + +/** + * @brief Clears or safeguards the OCREF4 signal on an external event + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 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_OC_CLR_ENABLE TIM Output clear enable + * @arg TIM_OC_CLR_DISABLE TIM Output clear disable + */ +void TIM_ClrOc4Ref(TIM_Module* TIMx, uint16_t TIM_OCClear) +{ + uint16_t tmpccmr2 = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimOcClrState(TIM_OCClear)); + tmpccmr2 = TIMx->CCMOD2; + /* Reset the OC4CE Bit */ + tmpccmr2 &= (uint16_t) ~((uint16_t)TIM_CCMOD2_OC4CEN); + /* Enable or Disable the Output Compare Clear Bit */ + tmpccmr2 |= (uint16_t)(TIM_OCClear << 8); + /* Write to TIMx CCMOD2 register */ + TIMx->CCMOD2 = tmpccmr2; +} + +/** + * @brief Clears or safeguards the OCREF5 signal on an external event + * @param TIMx where x can be 1 or 8 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_OC_CLR_ENABLE TIM Output clear enable + * @arg TIM_OC_CLR_DISABLE TIM Output clear disable + */ +void TIM_ClrOc5Ref(TIM_Module* TIMx, uint16_t TIM_OCClear) +{ + uint16_t tmpccmr3 = 0; + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + assert_param(IsTimOcClrState(TIM_OCClear)); + tmpccmr3 = TIMx->CCMOD3; + /* Reset the OC4CE Bit */ + tmpccmr3 &= (uint16_t) ~((uint16_t)TIM_CCMOD3_OC5CEN); + /* Enable or Disable the Output Compare Clear Bit */ + tmpccmr3 |= (uint16_t)(TIM_OCClear); + /* Write to TIMx CCMOD3 register */ + TIMx->CCMOD3 = tmpccmr3; +} + +/** + * @brief Clears or safeguards the OCREF6 signal on an external event + * @param TIMx where x can be 1 or 8 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_OC_CLR_ENABLE TIM Output clear enable + * @arg TIM_OC_CLR_DISABLE TIM Output clear disable + */ +void TIM_ClrOc6Ref(TIM_Module* TIMx, uint16_t TIM_OCClear) +{ + uint16_t tmpccmr3 = 0; + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + assert_param(IsTimOcClrState(TIM_OCClear)); + tmpccmr3 = TIMx->CCMOD3; + /* Reset the OC4CE Bit */ + tmpccmr3 &= (uint16_t) ~((uint16_t)TIM_CCMOD3_OC6CEN); + /* Enable or Disable the Output Compare Clear Bit */ + tmpccmr3 |= (uint16_t)(TIM_OCClear << 8); + /* Write to TIMx CCMOD3 register */ + TIMx->CCMOD3 = tmpccmr3; +} + +/** + * @brief Configures the TIMx channel 1 polarity. + * @param TIMx where x can be 1 to 8 except 6 and 7 to select the TIM peripheral. + * @param OcPolarity specifies the OC1 Polarity + * This parameter can be one of the following values: + * @arg TIM_OC_POLARITY_HIGH Output Compare active high + * @arg TIM_OC_POLARITY_LOW Output Compare active low + */ +void TIM_ConfigOc1Polarity(TIM_Module* TIMx, uint16_t OcPolarity) +{ + uint32_t tmpccer = 0; + /* Check the parameters */ + assert_param(IsTimList8Module(TIMx)); + assert_param(IsTimOcPolarity(OcPolarity)); + tmpccer = TIMx->CCEN; + /* Set or Reset the CC1P Bit */ + tmpccer &= (uint32_t) ~((uint32_t)TIM_CCEN_CC1P); + tmpccer |= OcPolarity; + /* Write to TIMx CCEN register */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Configures the TIMx Channel 1N polarity. + * @param TIMx where x can be 1, 8 to select the TIM peripheral. + * @param OcNPolarity specifies the OC1N Polarity + * This parameter can be one of the following values: + * @arg TIM_OCN_POLARITY_HIGH Output Compare active high + * @arg TIM_OCN_POLARITY_LOW Output Compare active low + */ +void TIM_ConfigOc1NPolarity(TIM_Module* TIMx, uint16_t OcNPolarity) +{ + uint32_t tmpccer = 0; + /* Check the parameters */ + assert_param(IsTimList2Module(TIMx)); + assert_param(IsTimOcnPolarity(OcNPolarity)); + + tmpccer = TIMx->CCEN; + /* Set or Reset the CC1NP Bit */ + tmpccer &= (uint32_t) ~((uint32_t)TIM_CCEN_CC1NP); + tmpccer |= OcNPolarity; + /* Write to TIMx CCEN register */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Configures the TIMx channel 2 polarity. + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 to select the TIM peripheral. + * @param OcPolarity specifies the OC2 Polarity + * This parameter can be one of the following values: + * @arg TIM_OC_POLARITY_HIGH Output Compare active high + * @arg TIM_OC_POLARITY_LOW Output Compare active low + */ +void TIM_ConfigOc2Polarity(TIM_Module* TIMx, uint16_t OcPolarity) +{ + uint32_t tmpccer = 0; + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + assert_param(IsTimOcPolarity(OcPolarity)); + tmpccer = TIMx->CCEN; + /* Set or Reset the CC2P Bit */ + tmpccer &= (uint32_t) ~((uint32_t)TIM_CCEN_CC2P); + tmpccer |= (uint32_t)(OcPolarity << 4); + /* Write to TIMx CCEN register */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Configures the TIMx Channel 2N polarity. + * @param TIMx where x can be 1 or 8 to select the TIM peripheral. + * @param OcNPolarity specifies the OC2N Polarity + * This parameter can be one of the following values: + * @arg TIM_OCN_POLARITY_HIGH Output Compare active high + * @arg TIM_OCN_POLARITY_LOW Output Compare active low + */ +void TIM_ConfigOc2NPolarity(TIM_Module* TIMx, uint16_t OcNPolarity) +{ + uint32_t tmpccer = 0; + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + assert_param(IsTimOcnPolarity(OcNPolarity)); + + tmpccer = TIMx->CCEN; + /* Set or Reset the CC2NP Bit */ + tmpccer &= (uint32_t) ~((uint32_t)TIM_CCEN_CC2NP); + tmpccer |= (uint32_t)(OcNPolarity << 4); + /* Write to TIMx CCEN register */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Configures the TIMx channel 3 polarity. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param OcPolarity specifies the OC3 Polarity + * This parameter can be one of the following values: + * @arg TIM_OC_POLARITY_HIGH Output Compare active high + * @arg TIM_OC_POLARITY_LOW Output Compare active low + */ +void TIM_ConfigOc3Polarity(TIM_Module* TIMx, uint16_t OcPolarity) +{ + uint32_t tmpccer = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimOcPolarity(OcPolarity)); + tmpccer = TIMx->CCEN; + /* Set or Reset the CC3P Bit */ + tmpccer &= (uint32_t) ~((uint32_t)TIM_CCEN_CC3P); + tmpccer |= (uint32_t)(OcPolarity << 8); + /* Write to TIMx CCEN register */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Configures the TIMx Channel 3N polarity. + * @param TIMx where x can be 1 or 8 to select the TIM peripheral. + * @param OcNPolarity specifies the OC3N Polarity + * This parameter can be one of the following values: + * @arg TIM_OCN_POLARITY_HIGH Output Compare active high + * @arg TIM_OCN_POLARITY_LOW Output Compare active low + */ +void TIM_ConfigOc3NPolarity(TIM_Module* TIMx, uint16_t OcNPolarity) +{ + uint32_t tmpccer = 0; + + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + assert_param(IsTimOcnPolarity(OcNPolarity)); + + tmpccer = TIMx->CCEN; + /* Set or Reset the CC3NP Bit */ + tmpccer &= (uint32_t) ~((uint32_t)TIM_CCEN_CC3NP); + tmpccer |= (uint32_t)(OcNPolarity << 8); + /* Write to TIMx CCEN register */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Configures the TIMx channel 4 polarity. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param OcPolarity specifies the OC4 Polarity + * This parameter can be one of the following values: + * @arg TIM_OC_POLARITY_HIGH Output Compare active high + * @arg TIM_OC_POLARITY_LOW Output Compare active low + */ +void TIM_ConfigOc4Polarity(TIM_Module* TIMx, uint16_t OcPolarity) +{ + uint32_t tmpccer = 0; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimOcPolarity(OcPolarity)); + tmpccer = TIMx->CCEN; + /* Set or Reset the CC4P Bit */ + tmpccer &= (uint32_t) ~((uint32_t)TIM_CCEN_CC4P); + tmpccer |= (uint32_t)(OcPolarity << 12); + /* Write to TIMx CCEN register */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Configures the TIMx channel 5 polarity. + * @param TIMx where x can be 1 or 8 to select the TIM peripheral. + * @param OcPolarity specifies the OC5 Polarity + * This parameter can be one of the following values: + * @arg TIM_OC_POLARITY_HIGH Output Compare active high + * @arg TIM_OC_POLARITY_LOW Output Compare active low + */ +void TIM_ConfigOc5Polarity(TIM_Module* TIMx, uint16_t OcPolarity) +{ + uint32_t tmpccer = 0; + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + assert_param(IsTimOcPolarity(OcPolarity)); + tmpccer = TIMx->CCEN; + /* Set or Reset the CC5P Bit */ + tmpccer &= (uint32_t) ~((uint32_t)TIM_CCEN_CC5P); + tmpccer |= (uint32_t)(OcPolarity << 16); + /* Write to TIMx CCEN register */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Configures the TIMx channel 6 polarity. + * @param TIMx where x can be 1 or 8 to select the TIM peripheral. + * @param OcPolarity specifies the OC6 Polarity + * This parameter can be one of the following values: + * @arg TIM_OC_POLARITY_HIGH Output Compare active high + * @arg TIM_OC_POLARITY_LOW Output Compare active low + */ +void TIM_ConfigOc6Polarity(TIM_Module* TIMx, uint16_t OcPolarity) +{ + uint32_t tmpccer = 0; + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + assert_param(IsTimOcPolarity(OcPolarity)); + tmpccer = TIMx->CCEN; + /* Set or Reset the CC6P Bit */ + tmpccer &= (uint32_t) ~((uint32_t)TIM_CCEN_CC6P); + tmpccer |= (uint32_t)(OcPolarity << 20); + /* Write to TIMx CCEN register */ + TIMx->CCEN = tmpccer; +} + +/** + * @brief Enables or disables the TIM Capture Compare Channel x. + * @param TIMx where x can be 1 to 8 except 6 and 7 to select the TIM peripheral. + * @param Channel specifies the TIM Channel + * This parameter can be one of the following values: + * @arg TIM_CH_1 TIM Channel 1 + * @arg TIM_CH_2 TIM Channel 2 + * @arg TIM_CH_3 TIM Channel 3 + * @arg TIM_CH_4 TIM Channel 4 + * @param TIM_CCx specifies the TIM Channel CCxE bit new state. + * This parameter can be: TIM_CAP_CMP_ENABLE or TIM_CAP_CMP_DISABLE. + */ +void TIM_EnableCapCmpCh(TIM_Module* TIMx, uint16_t Channel, uint32_t TIM_CCx) +{ + uint16_t tmp = 0; + + /* Check the parameters */ + assert_param(IsTimList8Module(TIMx)); + assert_param(IsTimCh(Channel)); + assert_param(IsTimCapCmpState(TIM_CCx)); + + tmp = CAPCMPEN_CCE_SET << Channel; + + /* Reset the CCxE Bit */ + TIMx->CCEN &= (uint32_t)~tmp; + + /* Set or reset the CCxE Bit */ + TIMx->CCEN |= (uint32_t)(TIM_CCx << Channel); +} + +/** + * @brief Enables or disables the TIM Capture Compare Channel xN. + * @param TIMx where x can be 1, 8 to select the TIM peripheral. + * @param Channel specifies the TIM Channel + * This parameter can be one of the following values: + * @arg TIM_CH_1 TIM Channel 1 + * @arg TIM_CH_2 TIM Channel 2 + * @arg TIM_CH_3 TIM Channel 3 + * @param TIM_CCxN specifies the TIM Channel CCxNE bit new state. + * This parameter can be: TIM_CAP_CMP_N_ENABLE or TIM_CAP_CMP_N_DISABLE. + */ +void TIM_EnableCapCmpChN(TIM_Module* TIMx, uint16_t Channel, uint32_t TIM_CCxN) +{ + uint16_t tmp = 0; + + /* Check the parameters */ + assert_param(IsTimList2Module(TIMx)); + assert_param(IsTimComplementaryCh(Channel)); + assert_param(IsTimCapCmpNState(TIM_CCxN)); + + tmp = CAPCMPEN_CCNE_SET << Channel; + + /* Reset the CCxNE Bit */ + TIMx->CCEN &= (uint32_t)~tmp; + + /* Set or reset the CCxNE Bit */ + TIMx->CCEN |= (uint32_t)(TIM_CCxN << Channel); +} + +/** + * @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_EnableCapCmpCh and TIM_EnableCapCmpChN functions. + * @param TIMx where x can be 1 to 8 except 6 and 7 to select the TIM peripheral. + * @param Channel specifies the TIM Channel + * This parameter can be one of the following values: + * @arg TIM_CH_1 TIM Channel 1 + * @arg TIM_CH_2 TIM Channel 2 + * @arg TIM_CH_3 TIM Channel 3 + * @arg TIM_CH_4 TIM Channel 4 + * @param OcMode specifies the TIM Output Compare Mode. + * This parameter can be one of the following values: + * @arg TIM_OCMODE_TIMING + * @arg TIM_OCMODE_ACTIVE + * @arg TIM_OCMODE_TOGGLE + * @arg TIM_OCMODE_PWM1 + * @arg TIM_OCMODE_PWM2 + * @arg TIM_FORCED_ACTION_ACTIVE + * @arg TIM_FORCED_ACTION_INACTIVE + */ +void TIM_SelectOcMode(TIM_Module* TIMx, uint16_t Channel, uint16_t OcMode) +{ + uint32_t tmp = 0; + uint16_t tmp1 = 0; + + /* Check the parameters */ + assert_param(IsTimList8Module(TIMx)); + assert_param(IsTimCh(Channel)); + assert_param(IsTimOc(OcMode)); + + tmp = (uint32_t)TIMx; + tmp += CAPCMPMOD_OFFSET; + + tmp1 = CAPCMPEN_CCE_SET << (uint16_t)Channel; + + /* Disable the Channel: Reset the CCxE Bit */ + TIMx->CCEN &= (uint16_t)~tmp1; + + if ((Channel == TIM_CH_1) || (Channel == TIM_CH_3)) + { + tmp += (Channel >> 1); + + /* Reset the OCxM bits in the CCMRx register */ + *(__IO uint32_t*)tmp &= (uint32_t) ~((uint32_t)TIM_CCMOD1_OC1M); + + /* Configure the OCxM bits in the CCMRx register */ + *(__IO uint32_t*)tmp |= OcMode; + } + else + { + tmp += (uint16_t)(Channel - (uint16_t)4) >> (uint16_t)1; + + /* Reset the OCxM bits in the CCMRx register */ + *(__IO uint32_t*)tmp &= (uint32_t) ~((uint32_t)TIM_CCMOD1_OC2M); + + /* Configure the OCxM bits in the CCMRx register */ + *(__IO uint32_t*)tmp |= (uint16_t)(OcMode << 8); + } +} + +/** + * @brief Enables or Disables the TIMx Update event. + * @param TIMx where x can be 1 to 8 to select the TIM peripheral. + * @param Cmd new state of the TIMx UDIS bit + * This parameter can be: ENABLE or DISABLE. + */ +void TIM_EnableUpdateEvt(TIM_Module* TIMx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Set the Update Disable Bit */ + TIMx->CTRL1 |= TIM_CTRL1_UPDIS; + } + else + { + /* Reset the Update Disable Bit */ + TIMx->CTRL1 &= (uint32_t) ~((uint32_t)TIM_CTRL1_UPDIS); + } +} + +/** + * @brief Configures the TIMx Update Request Interrupt source. + * @param TIMx where x can be 1 to 8 to select the TIM peripheral. + * @param TIM_UpdateSource specifies the Update source. + * This parameter can be one of the following values: + * @arg TIM_UPDATE_SRC_REGULAr 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_UPDATE_SRC_GLOBAL Source of update is counter overflow/underflow. + */ +void TIM_ConfigUpdateRequestIntSrc(TIM_Module* TIMx, uint16_t TIM_UpdateSource) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + assert_param(IsTimUpdateSrc(TIM_UpdateSource)); + if (TIM_UpdateSource != TIM_UPDATE_SRC_GLOBAL) + { + /* Set the URS Bit */ + TIMx->CTRL1 |= TIM_CTRL1_UPRS; + } + else + { + /* Reset the URS Bit */ + TIMx->CTRL1 &= (uint32_t) ~((uint32_t)TIM_CTRL1_UPRS); + } +} + +/** + * @brief Enables or disables the TIMx's Hall sensor interface. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param Cmd new state of the TIMx Hall sensor interface. + * This parameter can be: ENABLE or DISABLE. + */ +void TIM_SelectHallSensor(TIM_Module* TIMx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Set the TI1S Bit */ + TIMx->CTRL2 |= TIM_CTRL2_TI1SEL; + } + else + { + /* Reset the TI1S Bit */ + TIMx->CTRL2 &= (uint32_t) ~((uint32_t)TIM_CTRL2_TI1SEL); + } +} + +/** + * @brief Selects the TIMx's One Pulse Mode. + * @param TIMx where x can be 1 to 8 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 + * @arg TIM_OPMODE_REPET + */ +void TIM_SelectOnePulseMode(TIM_Module* TIMx, uint16_t TIM_OPMode) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + assert_param(IsTimOpMOde(TIM_OPMode)); + /* Reset the OPM Bit */ + TIMx->CTRL1 &= (uint32_t) ~((uint32_t)TIM_CTRL1_ONEPM); + /* Configure the OPM Mode */ + TIMx->CTRL1 |= TIM_OPMode; +} + +/** + * @brief Selects the TIMx Trigger Output Mode. + * @param TIMx where x can be 1, 2, 3, 4, 5, 6, 7, 8 to select the TIM peripheral. + * @param TIM_TRGOSource specifies the Trigger Output source. + * This paramter can be one of the following values: + * + * - For all TIMx + * @arg TIM_TRGO_SRC_RESET The UG bit in the TIM_EVTGEN register is used as the trigger output (TRGO). + * @arg TIM_TRGO_SRC_ENABLE The Counter Enable CEN is used as the trigger output (TRGO). + * @arg TIM_TRGO_SRC_UPDATE The update event is selected as the trigger output (TRGO). + * + * - For all TIMx except TIM6 and TIM7 + * @arg TIM_TRGO_SRC_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_TRGO_SRC_OC1REF OC1REF signal is used as the trigger output (TRGO). + * @arg TIM_TRGO_SRC_OC2REF OC2REF signal is used as the trigger output (TRGO). + * @arg TIM_TRGO_SRC_OC3REF OC3REF signal is used as the trigger output (TRGO). + * @arg TIM_TRGO_SRC_OC4REF OC4REF signal is used as the trigger output (TRGO). + * + */ +void TIM_SelectOutputTrig(TIM_Module* TIMx, uint16_t TIM_TRGOSource) +{ + /* Check the parameters */ + assert_param(IsTimList7Module(TIMx)); + assert_param(IsTimTrgoSrc(TIM_TRGOSource)); + /* Reset the MMS Bits */ + TIMx->CTRL2 &= (uint32_t) ~((uint32_t)TIM_CTRL2_MMSEL); + /* Select the TRGO source */ + TIMx->CTRL2 |= TIM_TRGOSource; +} + + +/** + * @brief Selects the TIMx Ext Source. + * @param Source: 0:selection external ETR(from IOM) signal.1:selection internal ETR(fromo TSC) signal. + * @retval None + */ +void TIM_SelectExtSignalSource(TIM_Module* TIMx, uint16_t ExtSigalSource) +{ + /* Select Ext Signal Source Bits */ + TIMx->CTRL2 &= (uint32_t)~((uint32_t)TIM_ETR_Seletct_innerTsc); + /* Select the TRGO source */ + TIMx->CTRL2 |= ExtSigalSource; +} + + +/** + * @brief Selects the TIMx Slave Mode. + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 to select the TIM peripheral. + * @param TIM_SlaveMode specifies the Timer Slave Mode. + * This parameter can be one of the following values: + * @arg TIM_SLAVE_MODE_RESET Rising edge of the selected trigger signal (TRGI) re-initializes + * the counter and triggers an update of the registers. + * @arg TIM_SLAVE_MODE_GATED The counter clock is enabled when the trigger signal (TRGI) is high. + * @arg TIM_SLAVE_MODE_TRIG The counter starts at a rising edge of the trigger TRGI. + * @arg TIM_SLAVE_MODE_EXT1 Rising edges of the selected trigger (TRGI) clock the counter. + */ +void TIM_SelectSlaveMode(TIM_Module* TIMx, uint16_t TIM_SlaveMode) +{ + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + assert_param(IsTimSlaveMode(TIM_SlaveMode)); + /* Reset the SMS Bits */ + TIMx->SMCTRL &= (uint16_t) ~((uint16_t)TIM_SMCTRL_SMSEL); + /* Select the Slave Mode */ + TIMx->SMCTRL |= TIM_SlaveMode; +} + +/** + * @brief Sets or Resets the TIMx Master/Slave Mode. + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 to select the TIM peripheral. + * @param TIM_MasterSlaveMode specifies the Timer Master Slave Mode. + * This parameter can be one of the following values: + * @arg TIM_MASTER_SLAVE_MODE_ENABLE synchronization between the current timer + * and its slaves (through TRGO). + * @arg TIM_MASTER_SLAVE_MODE_DISABLE No action + */ +void TIM_SelectMasterSlaveMode(TIM_Module* TIMx, uint16_t TIM_MasterSlaveMode) +{ + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + assert_param(IsTimMasterSlaveMode(TIM_MasterSlaveMode)); + /* Reset the MSM Bit */ + TIMx->SMCTRL &= (uint16_t) ~((uint16_t)TIM_SMCTRL_MSMD); + + /* Set or Reset the MSM Bit */ + TIMx->SMCTRL |= TIM_MasterSlaveMode; +} + +/** + * @brief Sets the TIMx Counter Register value + * @param TIMx where x can be 1 to 8 to select the TIM peripheral. + * @param Counter specifies the Counter register new value. + */ +void TIM_SetCnt(TIM_Module* TIMx, uint16_t Counter) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + /* Set the Counter Register value */ + TIMx->CNT = Counter; +} + +/** + * @brief Sets the TIMx Autoreload Register value + * @param TIMx where x can be 1 to 8 to select the TIM peripheral. + * @param Autoreload specifies the Autoreload register new value. + */ +void TIM_SetAutoReload(TIM_Module* TIMx, uint16_t Autoreload) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + /* Set the Autoreload Register value */ + TIMx->AR = Autoreload; +} + +/** + * @brief Sets the TIMx Capture Compare1 Register value + * @param TIMx where x can be 1 to 8 except 6 and 7 to select the TIM peripheral. + * @param Compare1 specifies the Capture Compare1 register new value. + */ +void TIM_SetCmp1(TIM_Module* TIMx, uint16_t Compare1) +{ + /* Check the parameters */ + assert_param(IsTimList8Module(TIMx)); + /* Set the Capture Compare1 Register value */ + TIMx->CCDAT1 = Compare1; +} + +/** + * @brief Sets the TIMx Capture Compare2 Register value + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 to select the TIM peripheral. + * @param Compare2 specifies the Capture Compare2 register new value. + */ +void TIM_SetCmp2(TIM_Module* TIMx, uint16_t Compare2) +{ + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + /* Set the Capture Compare2 Register value */ + TIMx->CCDAT2 = Compare2; +} + +/** + * @brief Sets the TIMx Capture Compare3 Register value + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param Compare3 specifies the Capture Compare3 register new value. + */ +void TIM_SetCmp3(TIM_Module* TIMx, uint16_t Compare3) +{ + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + /* Set the Capture Compare3 Register value */ + TIMx->CCDAT3 = Compare3; +} + +/** + * @brief Sets the TIMx Capture Compare4 Register value + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param Compare4 specifies the Capture Compare4 register new value. + */ +void TIM_SetCmp4(TIM_Module* TIMx, uint16_t Compare4) +{ + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + /* Set the Capture Compare4 Register value */ + TIMx->CCDAT4 = Compare4; +} + +/** + * @brief Sets the TIMx Capture Compare5 Register value + * @param TIMx where x can be 1 or 8 to select the TIM peripheral. + * @param Compare5 specifies the Capture Compare5 register new value. + */ +void TIM_SetCmp5(TIM_Module* TIMx, uint16_t Compare5) +{ + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + /* Set the Capture Compare4 Register value */ + TIMx->CCDAT5 = Compare5; +} + +/** + * @brief Sets the TIMx Capture Compare4 Register value + * @param TIMx where x can be 1 or 8 to select the TIM peripheral. + * @param Compare6 specifies the Capture Compare6 register new value. + */ +void TIM_SetCmp6(TIM_Module* TIMx, uint16_t Compare6) +{ + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + /* Set the Capture Compare4 Register value */ + TIMx->CCDAT6 = Compare6; +} + +/** + * @brief Sets the TIMx Input Capture 1 prescaler. + * @param TIMx where x can be 1 to 8 except 6 and 7 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_IC_PSC_DIV1 no prescaler + * @arg TIM_IC_PSC_DIV2 capture is done once every 2 events + * @arg TIM_IC_PSC_DIV4 capture is done once every 4 events + * @arg TIM_IC_PSC_DIV8 capture is done once every 8 events + */ +void TIM_SetInCap1Prescaler(TIM_Module* TIMx, uint16_t TIM_ICPSC) +{ + /* Check the parameters */ + assert_param(IsTimList8Module(TIMx)); + assert_param(IsTimIcPrescaler(TIM_ICPSC)); + /* Reset the IC1PSC Bits */ + TIMx->CCMOD1 &= (uint16_t) ~((uint16_t)TIM_CCMOD1_IC1PSC); + /* Set the IC1PSC value */ + TIMx->CCMOD1 |= TIM_ICPSC; +} + +/** + * @brief Sets the TIMx Input Capture 2 prescaler. + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 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_IC_PSC_DIV1 no prescaler + * @arg TIM_IC_PSC_DIV2 capture is done once every 2 events + * @arg TIM_IC_PSC_DIV4 capture is done once every 4 events + * @arg TIM_IC_PSC_DIV8 capture is done once every 8 events + */ +void TIM_SetInCap2Prescaler(TIM_Module* TIMx, uint16_t TIM_ICPSC) +{ + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + assert_param(IsTimIcPrescaler(TIM_ICPSC)); + /* Reset the IC2PSC Bits */ + TIMx->CCMOD1 &= (uint16_t) ~((uint16_t)TIM_CCMOD1_IC2PSC); + /* Set the IC2PSC value */ + TIMx->CCMOD1 |= (uint16_t)(TIM_ICPSC << 8); +} + +/** + * @brief Sets the TIMx Input Capture 3 prescaler. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 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_IC_PSC_DIV1 no prescaler + * @arg TIM_IC_PSC_DIV2 capture is done once every 2 events + * @arg TIM_IC_PSC_DIV4 capture is done once every 4 events + * @arg TIM_IC_PSC_DIV8 capture is done once every 8 events + */ +void TIM_SetInCap3Prescaler(TIM_Module* TIMx, uint16_t TIM_ICPSC) +{ + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimIcPrescaler(TIM_ICPSC)); + /* Reset the IC3PSC Bits */ + TIMx->CCMOD2 &= (uint16_t) ~((uint16_t)TIM_CCMOD2_IC3PSC); + /* Set the IC3PSC value */ + TIMx->CCMOD2 |= TIM_ICPSC; +} + +/** + * @brief Sets the TIMx Input Capture 4 prescaler. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 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_IC_PSC_DIV1 no prescaler + * @arg TIM_IC_PSC_DIV2 capture is done once every 2 events + * @arg TIM_IC_PSC_DIV4 capture is done once every 4 events + * @arg TIM_IC_PSC_DIV8 capture is done once every 8 events + */ +void TIM_SetInCap4Prescaler(TIM_Module* TIMx, uint16_t TIM_ICPSC) +{ + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + assert_param(IsTimIcPrescaler(TIM_ICPSC)); + /* Reset the IC4PSC Bits */ + TIMx->CCMOD2 &= (uint16_t) ~((uint16_t)TIM_CCMOD2_IC4PSC); + /* Set the IC4PSC value */ + TIMx->CCMOD2 |= (uint16_t)(TIM_ICPSC << 8); +} + +/** + * @brief Sets the TIMx Clock Division value. + * @param TIMx where x can be 1 to 8 except 6 and 7 to select + * the TIM peripheral. + * @param TIM_CKD specifies the clock division value. + * This parameter can be one of the following value: + * @arg TIM_CLK_DIV1 TDTS = Tck_tim + * @arg TIM_CLK_DIV2 TDTS = 2*Tck_tim + * @arg TIM_CLK_DIV4 TDTS = 4*Tck_tim + */ +void TIM_SetClkDiv(TIM_Module* TIMx, uint16_t TIM_CKD) +{ + /* Check the parameters */ + assert_param(IsTimList8Module(TIMx)); + assert_param(IsTimClkDiv(TIM_CKD)); + /* Reset the CKD Bits */ + TIMx->CTRL1 &= (uint32_t) ~((uint32_t)TIM_CTRL1_CLKD); + /* Set the CKD value */ + TIMx->CTRL1 |= TIM_CKD; +} + +/** + * @brief Gets the TIMx Input Capture 1 value. + * @param TIMx where x can be 1 to 8 except 6 and 7 to select the TIM peripheral. + * @return Capture Compare 1 Register value. + */ +uint16_t TIM_GetCap1(TIM_Module* TIMx) +{ + /* Check the parameters */ + assert_param(IsTimList8Module(TIMx)); + /* Get the Capture 1 Register value */ + return TIMx->CCDAT1; +} + +/** + * @brief Gets the TIMx Input Capture 2 value. + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 to select the TIM peripheral. + * @return Capture Compare 2 Register value. + */ +uint16_t TIM_GetCap2(TIM_Module* TIMx) +{ + /* Check the parameters */ + assert_param(IsTimList6Module(TIMx)); + /* Get the Capture 2 Register value */ + return TIMx->CCDAT2; +} + +/** + * @brief Gets the TIMx Input Capture 3 value. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @return Capture Compare 3 Register value. + */ +uint16_t TIM_GetCap3(TIM_Module* TIMx) +{ + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + /* Get the Capture 3 Register value */ + return TIMx->CCDAT3; +} + +/** + * @brief Gets the TIMx Input Capture 4 value. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @return Capture Compare 4 Register value. + */ +uint16_t TIM_GetCap4(TIM_Module* TIMx) +{ + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + /* Get the Capture 4 Register value */ + return TIMx->CCDAT4; +} + +/** + * @brief Gets the TIMx Input Capture 5 value. + * @param TIMx where x can be 1 8 to select the TIM peripheral. + * @return Capture Compare 5 Register value. + */ +uint16_t TIM_GetCap5(TIM_Module* TIMx) +{ + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + /* Get the Capture 5 Register value */ + return TIMx->CCDAT5; +} + +/** + * @brief Gets the TIMx Input Capture 6 value. + * @param TIMx where x can be 1 or 8 to select the TIM peripheral. + * @return Capture Compare 6 Register value. + */ +uint16_t TIM_GetCap6(TIM_Module* TIMx) +{ + /* Check the parameters */ + assert_param(IsTimList1Module(TIMx)); + /* Get the Capture 6 Register value */ + return TIMx->CCDAT6; +} + +/** + * @brief Gets the TIMx Counter value. + * @param TIMx where x can be 1 to 8 to select the TIM peripheral. + * @return Counter Register value. + */ +uint16_t TIM_GetCnt(TIM_Module* TIMx) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + /* Get the Counter Register value */ + return TIMx->CNT; +} + +/** + * @brief Gets the TIMx Prescaler value. + * @param TIMx where x can be 1 to 8 to select the TIM peripheral. + * @return Prescaler Register value. + */ +uint16_t TIM_GetPrescaler(TIM_Module* TIMx) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + /* Get the Prescaler Register value */ + return TIMx->PSC; +} + +/** + * @brief Gets the TIMx Prescaler value. + * @param TIMx where x can be 1 to 8 to select the TIM peripheral. + * @return Prescaler Register value. + */ +uint16_t TIM_GetAutoReload(TIM_Module* TIMx) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + /* Get the Prescaler Register value */ + return TIMx->AR; +} + +/** + * @brief Checks whether the specified TIM flag is set or not. + * @param TIMx where x can be 1 to 5 , 8 to select the TIM peripheral. + * @param TIM_CCEN specifies the Bit to check. + * This parameter can be one of the following values: + * @arg TIM_CC1EN CC1EN Bit + * @arg TIM_CC1NEN CC1NEN Bit + * @arg TIM_CC2EN CC2EN Bit + * @arg TIM_CC2NEN CC2NEN Bit + * @arg TIM_CC3EN CC3EN Bit + * @arg TIM_CC3NEN CC3NEN Bit + * @arg TIM_CC4EN CC4EN Bit + * @arg TIM_CC5EN CC5EN Bit + * @arg TIM_CC6EN CC6EN Bit + * @note + * - TIM_CC1NEN TIM_CC2NEN TIM_CC3NEN is used only with TIM1, TIM8. + * @return The new state of TIM_FLAG (SET or RESET). + */ +FlagStatus TIM_GetCCENStatus(TIM_Module* TIMx, uint32_t TIM_CCEN) +{ + INTStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IsTimList3Module(TIMx)); + + if(TIMx==TIM1 || TIMx==TIM8) + { + assert_param(IsAdvancedTimCCENFlag(TIM_CCEN)); + if ((TIMx->CCEN & TIM_CCEN) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + } + else if(TIMx==TIM2 || TIMx==TIM3 || TIMx==TIM4 || TIMx==TIM5 ) + { + assert_param(IsGeneralTimCCENFlag(TIM_CCEN)); + if ((TIMx->CCEN & TIM_CCEN) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + } + + return bitstatus; +} + +/** + * @brief Checks whether the specified TIM flag is set or not. + * @param TIMx where x can be 1 to 8 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_COM TIM Commutation Flag + * @arg TIM_FLAG_TRIG TIM Trigger Flag + * @arg TIM_FLAG_BREAK TIM Break 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 + * @arg TIM_FLAG_CC5 TIM Capture Compare 5 Flag + * @arg TIM_FLAG_CC6 TIM Capture Compare 6 Flag + * @note + * - TIM6 and TIM7 can have only one update flag. + * - TIM_FLAG_BREAK is used only with TIM1, TIM8. + * - TIM_FLAG_COM is used only with TIM1, TIM8. + * @return The new state of TIM_FLAG (SET or RESET). + */ +FlagStatus TIM_GetFlagStatus(TIM_Module* TIMx, uint32_t TIM_FLAG) +{ + INTStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + assert_param(IsTimGetFlag(TIM_FLAG)); + + if ((TIMx->STS & TIM_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the TIMx's pending flags. + * @param TIMx where x can be 1 to 8 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_COM TIM Commutation Flag + * @arg TIM_FLAG_TRIG TIM Trigger Flag + * @arg TIM_FLAG_BREAK TIM Break 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. + * - TIM_FLAG_BREAK is used only with TIM1, TIM8. + * - TIM_FLAG_COM is used only with TIM1, TIM8. + */ +void TIM_ClearFlag(TIM_Module* TIMx, uint32_t TIM_FLAG) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + assert_param(IsTimClrFlag(TIM_FLAG)); + + /* Clear the flags */ + TIMx->STS &= (uint32_t)~TIM_FLAG; +} + +/** + * @brief Checks whether the TIM interrupt has occurred or not. + * @param TIMx where x can be 1 to 8 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_INT_UPDATE TIM update Interrupt source + * @arg TIM_INT_CC1 TIM Capture Compare 1 Interrupt source + * @arg TIM_INT_CC2 TIM Capture Compare 2 Interrupt source + * @arg TIM_INT_CC3 TIM Capture Compare 3 Interrupt source + * @arg TIM_INT_CC4 TIM Capture Compare 4 Interrupt source + * @arg TIM_INT_COM TIM Commutation Interrupt source + * @arg TIM_INT_TRIG TIM Trigger Interrupt source + * @arg TIM_INT_BREAK TIM Break Interrupt source + * @note + * - TIM6 and TIM7 can generate only an update interrupt. + * - TIM_INT_BREAK is used only with TIM1, TIM8. + * - TIM_INT_COM is used only with TIM1, TIM8. + * @return The new state of the TIM_IT(SET or RESET). + */ +INTStatus TIM_GetIntStatus(TIM_Module* TIMx, uint32_t TIM_IT) +{ + INTStatus bitstatus = RESET; + uint32_t itstatus = 0x0, itenable = 0x0; + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + assert_param(IsTimGetInt(TIM_IT)); + + itstatus = TIMx->STS & TIM_IT; + + itenable = TIMx->DINTEN & TIM_IT; + if ((itstatus != (uint32_t)RESET) && (itenable != (uint32_t)RESET)) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the TIMx's interrupt pending bits. + * @param TIMx where x can be 1 to 8 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_INT_UPDATE TIM1 update Interrupt source + * @arg TIM_INT_CC1 TIM Capture Compare 1 Interrupt source + * @arg TIM_INT_CC2 TIM Capture Compare 2 Interrupt source + * @arg TIM_INT_CC3 TIM Capture Compare 3 Interrupt source + * @arg TIM_INT_CC4 TIM Capture Compare 4 Interrupt source + * @arg TIM_INT_COM TIM Commutation Interrupt source + * @arg TIM_INT_TRIG TIM Trigger Interrupt source + * @arg TIM_INT_BREAK TIM Break Interrupt source + * @note + * - TIM6 and TIM7 can generate only an update interrupt. + * - TIM_INT_BREAK is used only with TIM1, TIM8. + * - TIM_INT_COM is used only with TIM1, TIM8. + */ +void TIM_ClrIntPendingBit(TIM_Module* TIMx, uint32_t TIM_IT) +{ + /* Check the parameters */ + assert_param(IsTimAllModule(TIMx)); + assert_param(IsTimInt(TIM_IT)); + /* Clear the IT pending Bit */ + TIMx->STS &= (uint32_t)~TIM_IT; +} + +/** + * @brief Configure the TI1 as Input. + * @param TIMx where x can be 1 to 8 except 6 and 7 to select the TIM peripheral. + * @param IcPolarity The Input Polarity. + * This parameter can be one of the following values: + * @arg TIM_IC_POLARITY_RISING + * @arg TIM_IC_POLARITY_FALLING + * @param IcSelection specifies the input to be used. + * This parameter can be one of the following values: + * @arg TIM_IC_SELECTION_DIRECTTI TIM Input 1 is selected to be connected to IC1. + * @arg TIM_IC_SELECTION_INDIRECTTI TIM Input 1 is selected to be connected to IC2. + * @arg TIM_IC_SELECTION_TRC TIM Input 1 is selected to be connected to TRC. + * @param IcFilter Specifies the Input Capture Filter. + * This parameter must be a value between 0x00 and 0x0F. + */ +static void ConfigTI1(TIM_Module* TIMx, uint16_t IcPolarity, uint16_t IcSelection, uint16_t IcFilter) +{ + uint16_t tmpccmr1 = 0; + uint32_t tmpccer = 0; + /* Disable the Channel 1: Reset the CC1E Bit */ + TIMx->CCEN &= (uint32_t) ~((uint32_t)TIM_CCEN_CC1EN); + tmpccmr1 = TIMx->CCMOD1; + tmpccer = TIMx->CCEN; + /* Select the Input and set the filter */ + tmpccmr1 &= (uint16_t)(((uint16_t) ~((uint16_t)TIM_CCMOD1_CC1SEL)) & ((uint16_t) ~((uint16_t)TIM_CCMOD1_IC1F))); + tmpccmr1 |= (uint16_t)(IcSelection | (uint16_t)(IcFilter << (uint16_t)4)); + + if ((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM2) || (TIMx == TIM3) || (TIMx == TIM4) || (TIMx == TIM5)) + { + /* Select the Polarity and set the CC1E Bit */ + tmpccer &= (uint32_t) ~((uint32_t)(TIM_CCEN_CC1P)); + tmpccer |= (uint32_t)(IcPolarity | (uint32_t)TIM_CCEN_CC1EN); + } + else + { + /* Select the Polarity and set the CC1E Bit */ + tmpccer &= (uint32_t) ~((uint32_t)(TIM_CCEN_CC1P | TIM_CCEN_CC1NP)); + tmpccer |= (uint32_t)(IcPolarity | (uint32_t)TIM_CCEN_CC1EN); + } + + /* Write to TIMx CCMOD1 and CCEN registers */ + TIMx->CCMOD1 = tmpccmr1; + TIMx->CCEN = tmpccer; +} + +/** + * @brief Configure the TI2 as Input. + * @param TIMx where x can be 1, 2, 3, 4, 5, 8 to select the TIM peripheral. + * @param IcPolarity The Input Polarity. + * This parameter can be one of the following values: + * @arg TIM_IC_POLARITY_RISING + * @arg TIM_IC_POLARITY_FALLING + * @param IcSelection specifies the input to be used. + * This parameter can be one of the following values: + * @arg TIM_IC_SELECTION_DIRECTTI TIM Input 2 is selected to be connected to IC2. + * @arg TIM_IC_SELECTION_INDIRECTTI TIM Input 2 is selected to be connected to IC1. + * @arg TIM_IC_SELECTION_TRC TIM Input 2 is selected to be connected to TRC. + * @param IcFilter Specifies the Input Capture Filter. + * This parameter must be a value between 0x00 and 0x0F. + */ +static void ConfigTI2(TIM_Module* TIMx, uint16_t IcPolarity, uint16_t IcSelection, uint16_t IcFilter) +{ + uint16_t tmpccmr1 = 0; + uint32_t tmpccer = 0, tmp = 0; + /* Disable the Channel 2: Reset the CC2E Bit */ + TIMx->CCEN &= (uint32_t) ~((uint32_t)TIM_CCEN_CC2EN); + tmpccmr1 = TIMx->CCMOD1; + tmpccer = TIMx->CCEN; + tmp = (uint32_t)(IcPolarity << 4); + /* Select the Input and set the filter */ + tmpccmr1 &= (uint16_t)(((uint16_t) ~((uint16_t)TIM_CCMOD1_CC2SEL)) & ((uint16_t) ~((uint16_t)TIM_CCMOD1_IC2F))); + tmpccmr1 |= (uint16_t)(IcFilter << 12); + tmpccmr1 |= (uint16_t)(IcSelection << 8); + + if ((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM2) || (TIMx == TIM3) || (TIMx == TIM4) || (TIMx == TIM5)) + { + /* Select the Polarity and set the CC2E Bit */ + tmpccer &= (uint32_t) ~((uint32_t)(TIM_CCEN_CC2P)); + tmpccer |= (uint32_t)(tmp | (uint32_t)TIM_CCEN_CC2EN); + } + else + { + /* Select the Polarity and set the CC2E Bit */ + tmpccer &= (uint32_t) ~((uint32_t)(TIM_CCEN_CC2P | TIM_CCEN_CC2NP)); + tmpccer |= (uint32_t)(IcPolarity | (uint32_t)TIM_CCEN_CC2EN); + } + + /* Write to TIMx CCMOD1 and CCEN registers */ + TIMx->CCMOD1 = tmpccmr1; + TIMx->CCEN = tmpccer; +} + +/** + * @brief Configure the TI3 as Input. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param IcPolarity The Input Polarity. + * This parameter can be one of the following values: + * @arg TIM_IC_POLARITY_RISING + * @arg TIM_IC_POLARITY_FALLING + * @param IcSelection specifies the input to be used. + * This parameter can be one of the following values: + * @arg TIM_IC_SELECTION_DIRECTTI TIM Input 3 is selected to be connected to IC3. + * @arg TIM_IC_SELECTION_INDIRECTTI TIM Input 3 is selected to be connected to IC4. + * @arg TIM_IC_SELECTION_TRC TIM Input 3 is selected to be connected to TRC. + * @param IcFilter Specifies the Input Capture Filter. + * This parameter must be a value between 0x00 and 0x0F. + */ +static void ConfigTI3(TIM_Module* TIMx, uint16_t IcPolarity, uint16_t IcSelection, uint16_t IcFilter) +{ + uint16_t tmpccmr2 = 0; + uint32_t tmpccer = 0, tmp = 0; + /* Disable the Channel 3: Reset the CC3E Bit */ + TIMx->CCEN &= (uint32_t) ~((uint32_t)TIM_CCEN_CC3EN); + tmpccmr2 = TIMx->CCMOD2; + tmpccer = TIMx->CCEN; + tmp = (uint32_t)(IcPolarity << 8); + /* Select the Input and set the filter */ + tmpccmr2 &= (uint16_t)(((uint16_t) ~((uint16_t)TIM_CCMOD2_CC3SEL)) & ((uint16_t) ~((uint16_t)TIM_CCMOD2_IC3F))); + tmpccmr2 |= (uint16_t)(IcSelection | (uint16_t)(IcFilter << (uint16_t)4)); + + if ((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM2) || (TIMx == TIM3) || (TIMx == TIM4) || (TIMx == TIM5)) + { + /* Select the Polarity and set the CC3E Bit */ + tmpccer &= (uint32_t) ~((uint32_t)(TIM_CCEN_CC3P)); + tmpccer |= (uint32_t)(tmp | (uint32_t)TIM_CCEN_CC3EN); + } + else + { + /* Select the Polarity and set the CC3E Bit */ + tmpccer &= (uint32_t) ~((uint32_t)(TIM_CCEN_CC3P | TIM_CCEN_CC3NP)); + tmpccer |= (uint32_t)(IcPolarity | (uint32_t)TIM_CCEN_CC3EN); + } + + /* Write to TIMx CCMOD2 and CCEN registers */ + TIMx->CCMOD2 = tmpccmr2; + TIMx->CCEN = tmpccer; +} + +/** + * @brief Configure the TI4 as Input. + * @param TIMx where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral. + * @param IcPolarity The Input Polarity. + * This parameter can be one of the following values: + * @arg TIM_IC_POLARITY_RISING + * @arg TIM_IC_POLARITY_FALLING + * @param IcSelection specifies the input to be used. + * This parameter can be one of the following values: + * @arg TIM_IC_SELECTION_DIRECTTI TIM Input 4 is selected to be connected to IC4. + * @arg TIM_IC_SELECTION_INDIRECTTI TIM Input 4 is selected to be connected to IC3. + * @arg TIM_IC_SELECTION_TRC TIM Input 4 is selected to be connected to TRC. + * @param IcFilter Specifies the Input Capture Filter. + * This parameter must be a value between 0x00 and 0x0F. + */ +static void ConfigTI4(TIM_Module* TIMx, uint16_t IcPolarity, uint16_t IcSelection, uint16_t IcFilter) +{ + uint16_t tmpccmr2 = 0; + uint32_t tmpccer = 0, tmp = 0; + + /* Disable the Channel 4: Reset the CC4E Bit */ + TIMx->CCEN &= (uint32_t) ~((uint32_t)TIM_CCEN_CC4EN); + tmpccmr2 = TIMx->CCMOD2; + tmpccer = TIMx->CCEN; + tmp = (uint32_t)(IcPolarity << 12); + /* Select the Input and set the filter */ + tmpccmr2 &= (uint16_t)((uint16_t)(~(uint16_t)TIM_CCMOD2_CC4SEL) & ((uint16_t) ~((uint16_t)TIM_CCMOD2_IC4F))); + tmpccmr2 |= (uint16_t)(IcSelection << 8); + tmpccmr2 |= (uint16_t)(IcFilter << 12); + + if ((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM2) || (TIMx == TIM3) || (TIMx == TIM4) || (TIMx == TIM5)) + { + /* Select the Polarity and set the CC4E Bit */ + tmpccer &= (uint32_t) ~((uint32_t)(TIM_CCEN_CC4P)); + tmpccer |= (uint32_t)(tmp | (uint32_t)TIM_CCEN_CC4EN); + } + else + { + /* Select the Polarity and set the CC4E Bit */ + tmpccer &= (uint32_t) ~((uint32_t)(TIM_CCEN_CC4P)); + tmpccer |= (uint32_t)(IcPolarity | (uint32_t)TIM_CCEN_CC4EN); + } + /* Write to TIMx CCMOD2 and CCEN registers */ + TIMx->CCMOD2 = tmpccmr2; + TIMx->CCEN = tmpccer; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/src/n32g45x_tsc.c b/src/n32g45x_tsc.c new file mode 100644 index 0000000..dcdded3 --- /dev/null +++ b/src/n32g45x_tsc.c @@ -0,0 +1,500 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_tsc.c + * @author Nations + * @version v1.0.2 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x.h" +#include "n32g45x_tsc.h" + +/** + * @brief Init TSC config for hardware detect mode. + * @param TSC_Def Pointer of TSC register. + * @param CtrlCfg configurations. + */ +TSC_ErrorTypeDef TSC_Init(TSC_Module* TSC_Def, TSC_InitType* CtrlCfg) +{ + uint32_t tempreg,timeout; + + assert_param(IS_TSC_FILTER(CtrlCfg->TSC_FilterCount)); + assert_param(IS_TSC_DET_PERIOD(CtrlCfg->TSC_DetPeriod)); + + if(TSC_Def != TSC) + return TSC_ERROR_PARAMETER; + + /* waiting tsc hw for idle status.*/ + timeout = 0; + do + { + __TSC_HW_DISABLE(); + + if(++timeout > TSC_TIMEOUT) + return TSC_ERROR_HW_MODE; + }while (__TSC_GET_HW_MODE()); + + /*TSC_CTRL config*/ + tempreg = 0; + if(CtrlCfg->TSC_DetIntEnable) + tempreg |= TSC_IT_DET_ENABLE; + + if(CtrlCfg->TSC_GreatEnable) + tempreg |= TSC_DET_TYPE_GREAT; + + if(CtrlCfg->TSC_LessEnable) + tempreg |= TSC_DET_TYPE_LESS; + + tempreg |= CtrlCfg->TSC_FilterCount; + tempreg |= CtrlCfg->TSC_DetPeriod; + + TSC_Def->CTRL = tempreg; + + return TSC_ERROR_OK; +} + +/** + * @brief Config the clock source of TSC + * @param TSC_ClkSource specifies the clock source of TSC + * This parameter can be one of the following values: + * @arg TSC_CLK_SRC_LSI: TSC clock source is LSI(default) + * @arg TSC_CLK_SRC_LSE: TSC clock source is LSE,and LSE is oscillator + * @arg TSC_CLK_SRC_LSE_BYPASS: TSC clock source is LSE,and LSE is extennal clock + * @retval TSC error code + */ +TSC_ErrorTypeDef TSC_ClockConfig(uint32_t TSC_ClkSource) +{ + uint32_t timeout; + + /*Enable PWR peripheral Clock*/ + RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_PWR,ENABLE); + + if(TSC_CLK_SRC_LSI == TSC_ClkSource) + { + /*enable LSI clock*/ + RCC_EnableLsi(ENABLE); + + /*Wait LSI stable*/ + timeout = 0; + while(RCC_GetFlagStatus(RCC_FLAG_LSIRD) == RESET) + { + if(++timeout >TSC_TIMEOUT) + return TSC_ERROR_CLOCK; + } + } + else if((TSC_CLK_SRC_LSE_BYPASS==TSC_ClkSource)||(TSC_CLK_SRC_LSE==TSC_ClkSource)) + { + if(RCC_GetFlagStatus(RCC_FLAG_LSERD)==RESET) + { + // Set bit 8 of PWR_CTRL1.Open PWR DBP. + PWR_BackupAccessEnable(ENABLE); + RCC_ConfigLse(TSC_ClkSource); + timeout = 0; + while(RCC_GetFlagStatus(RCC_FLAG_LSERD) == RESET) + { + if(++timeout >TSC_TIMEOUT) + return TSC_ERROR_CLOCK; + } + } + } + else + return TSC_ERROR_PARAMETER; + + /*Enable TSC clk*/ + RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TSC,ENABLE); + + return TSC_ERROR_OK; +} + +/** + * @brief Configure internal charge resistor for some channels + * @param TSC_Def Pointer of TSC register. + * @param res: internal resistor selecte + * This parameter can be one of the following values: + * @arg TSC_RESR_CHN_RESIST_0: 1M OHM + * @arg TSC_RESR_CHN_RESIST_1: 882K OHM + * @arg TSC_RESR_CHN_RESIST_2: 756K OHM + * @arg TSC_RESR_CHN_RESIST_3: 630K OHM + * @arg TSC_RESR_CHN_RESIST_4: 504K OHM + * @arg TSC_RESR_CHN_RESIST_5: 378K OHM + * @arg TSC_RESR_CHN_RESIST_6: 252K OHM + * @arg TSC_RESR_CHN_RESIST_7: 126K OHM + * @param Channels: channels to be configed, as TSC_CHNEN defined + * This parameter:bit[0:23] used,bit[24:31] must be 0 + * bitx: TSC channel x + * @return: none + */ +TSC_ErrorTypeDef TSC_ConfigInternalResistor(TSC_Module* TSC_Def,uint32_t Channels, uint32_t res ) +{ + uint32_t i,chn,timeout,*pReg,nPos; + + assert_param(IS_TSC_CHN(Channels)); + assert_param(IS_TSC_RESISTOR_VALUE(res)); + + if(TSC_Def != TSC) + return TSC_ERROR_PARAMETER; + + /*Check charge resistor value */ + if(res > TSC_RESR_CHN_RESIST_125K) + return TSC_ERROR_PARAMETER; + + /* waiting tsc hw for idle status.*/ + timeout = 0; + do + { + __TSC_HW_DISABLE(); + + if(++timeout > TSC_TIMEOUT) + return TSC_ERROR_HW_MODE; + }while (__TSC_GET_HW_MODE()); + + /* Mask invalie bits*/ + chn = Channels & TSC_CHNEN_CHN_SEL_MASK; + + /* Set resistance for each channel one by one*/ + for (i = 0; iRESR0)); + pReg += (i/8); + nPos = (i & 0x7UL)*4; + MODIFY_REG(*pReg,TSC_RESR_CHN_RESIST_MASK<>= 1; + } + + return TSC_ERROR_OK; +} + +/** + * @brief Configure threshold value for some channels + * @param TSC_Def Pointer of TSC register. + * @param Channels: channels to be configed, as TSC_CHNEN defined + * This parameter:bit[0:23] used,bit[24:31] must be 0 + * bitx: TSC channel x + * @param base: base value of threshold, 0-MAX_TSC_THRESHOLD_BASE + * @param delta: delta value of threshold,0-MAX_TSC_THRESHOLD_DELRA + * @return: None + */ +TSC_ErrorTypeDef TSC_ConfigThreshold( TSC_Module* TSC_Def, uint32_t Channels, uint32_t base, uint32_t delta) +{ + uint32_t i, chn,timeout,*pReg; + + assert_param(IS_TSC_CHN(Channels)); + assert_param(IS_TSC_THRESHOLD_BASE(base)); + assert_param(IS_TSC_THRESHOLD_DELTA(delta)); + + if(TSC_Def != TSC) + return TSC_ERROR_PARAMETER; + + /*Check the base and delta value*/ + if( (base>MAX_TSC_THRESHOLD_BASE)||(delta>MAX_TSC_THRESHOLD_DELTA)) + return TSC_ERROR_PARAMETER; + + /* waiting tsc hw for idle status.*/ + timeout = 0; + do + { + __TSC_HW_DISABLE(); + + if(++timeout > TSC_TIMEOUT) + return TSC_ERROR_HW_MODE; + }while (__TSC_GET_HW_MODE()); + + pReg = (uint32_t *)(&(TSC_Def->THRHD0)); + + /*Mask invalie bits*/ + chn = Channels & TSC_CHNEN_CHN_SEL_MASK; + + /* Set the base and delta for each channnel one by one*/ + for (i = 0; i>= 1; + } + + return TSC_ERROR_OK; +} + + +/** + * @brief Get parameters of one channel. + * @param TSC_Def Pointer of TSC register. + * @param ChnCfg: Pointer of TSC_ChnCfg structure. + * @param Channels: channels to be configed, as TSC_CHNEN defined + * This parameter:bit[0:23] used,bit[24:31] must be 0 + * bitx: TSC channel x + * @return: None + */ +TSC_ErrorTypeDef TSC_GetChannelCfg( TSC_Module* TSC_Def, TSC_ChnCfg* ChnCfg, uint32_t Channels) +{ + uint32_t i,chn, *pReg; + + if(TSC_Def != TSC) + return TSC_ERROR_PARAMETER; + + /*Check channel number*/ + if(!(IS_TSC_CHN(Channels))) + return TSC_ERROR_PARAMETER; + + chn = Channels & TSC_CHNEN_CHN_SEL_MASK; + + for (i = 0; iTHRHD0)); + pReg += i; + ChnCfg->TSC_Base = (uint16_t)(((*pReg) & TSC_THRHD_BASE_MASK) >> TSC_THRHD_BASE_SHIFT); + ChnCfg->TSC_Delta = (uint8_t)(((*pReg) & TSC_THRHD_DELTA_MASK)>> TSC_THRHD_DELTA_SHIFT); + + pReg = (uint32_t *)(&(TSC->RESR0)); + pReg += (i/8); + ChnCfg->TSC_ResisValue = (uint8_t)(((*pReg) >> ((i & 0x7UL)*4)) & TSC_RESR_CHN_RESIST_MASK); + break; + } + + chn >>= 1; + } + + return TSC_ERROR_OK; +} + + +/** + * @brief Get TSC status value. + * @param TSC_Def Pointer of TSC register. + * @param type TSC status type. + */ +uint32_t TSC_GetStatus(TSC_Module* TSC_Def, uint32_t type) +{ + uint32_t value = 0; + + if(TSC_Def != TSC) + return 0; + + switch (type) + { + case TSC_GET_STS_CNTVALUE: + value = __TSC_GET_CHN_CNT(); + break; + + case TSC_GET_STS_LESS_DET: + value = __TSC_GET_HW_DET_TYPE(TSC_FLAG_LESS_DET); + break; + + case TSC_GET_STS_GREAT_DET: + value = __TSC_GET_HW_DET_TYPE(TSC_FLAG_GREAT_DET); + break; + + case TSC_GET_STS_CHN_NUM: + value = __TSC_GET_CHN_NUMBER(); + break; + + case TSC_GET_STS_DET_ST: + value = __TSC_GET_HW_MODE(); + break; + + default: + break; + } + + return value; +} + +/** + * @brief Enable/Disable hardware detection. + * @param TSC_Def Pointer of TSC register. + * @param Channels: channels to be configed, as TSC_CHNEN defined + * This parameter:bit[0:23] used,bit[24:31] must be 0 + * bitx: TSC channel x + * @param Cmd ENABLE:Enable hardware detection,DISALBE:Disable hardware detection. + * @note You can only output one channel at a time. + */ +TSC_ErrorTypeDef TSC_Cmd(TSC_Module* TSC_Def, uint32_t Channels, FunctionalState Cmd) +{ + uint32_t timeout; + + if(TSC_Def != TSC) + return TSC_ERROR_PARAMETER; + + if (Cmd != DISABLE) + { + // enable tsc channel + Channels &= TSC_CHNEN_CHN_SEL_MASK; + __TSC_CHN_CONFIG(Channels ); + + /* Enable the TSC */ + __TSC_HW_ENABLE(); + } + else + { + /* Disable the TSC */ + timeout = 0; + do + { + __TSC_HW_DISABLE(); + + if(++timeout > TSC_TIMEOUT) + return TSC_ERROR_HW_MODE; + }while (__TSC_GET_HW_MODE()); + + __TSC_CHN_CONFIG(0); + } + + return TSC_ERROR_OK; +} + +/** + * @brief Toggle channels to output to TIMER2/TIMER4 by software mode. + * @param TSC_Def Pointer of TSC register. + * @param Channels: channels to be configed, as TSC_CHNEN defined + * This parameter:bit[0:23] used,bit[24:31] must be 0 + * bitx: TSC channel x + * @param TIMx Select timer. + * @param Cmd ENABLE:Enable hardware detection,DISALBE:Disable hardware detection. + * @note It can only output to TIMER2/TIMER4 by software mode.Other channels are not valid. + */ +TSC_ErrorTypeDef TSC_SW_SwtichChn(TSC_Module* TSC_Def, uint32_t Channel, TIM_Module* TIMx, FunctionalState Cmd) +{ + uint32_t i, timeout; + + if(TSC_Def != TSC) + return TSC_ERROR_PARAMETER; + + if ((TIMx != TIM2) && (TIMx != TIM4)) + return TSC_ERROR_PARAMETER; + + + /* Disable the TSC HW MODE */ + timeout = 0; + do + { + __TSC_HW_DISABLE(); + + if(++timeout > TSC_TIMEOUT) + return TSC_ERROR_HW_MODE; + }while (__TSC_GET_HW_MODE()); + + if (Cmd == DISABLE) // Close output by software mode + { + __TSC_OUT_CONFIG(TSC_OUT_PIN); + __TSC_SW_DISABLE(); + } + else + { + for (i = 0; i < MAX_TSC_HW_CHN; i++) + { + if (Channel & 0x00000001) + { + __TSC_SW_CHN_NUM_CONFIG(i); + break; + } + + Channel >>= 1; + } + + // Select to output to specified TIMER. + if (TIMx == TIM4) + { + __TSC_OUT_CONFIG(TSC_OUT_TIM4_ETR); + } + else + { + __TSC_OUT_CONFIG(TSC_OUT_TIM2_ETR); + } + + __TSC_SW_ENABLE(); + } + + // delay time for tsc channel stabilize output + for (i = 0; i < 2000; i++) + { + } + + return TSC_ERROR_OK; +} + +/** + * @brief Configure analog signal parameters. + * @param TSC_Def Pointer of TSC register. + * @param AnaoCfg Pointer of analog parameter structure. + */ +TSC_ErrorTypeDef TSC_SetAnaoCfg(TSC_Module* TSC_Def, TSC_AnaoCfg* AnaoCfg) +{ + if(TSC_Def != TSC) + return TSC_ERROR_PARAMETER; + + if(AnaoCfg == 0) + return TSC_ERROR_PARAMETER; + + assert_param(IS_TSC_PAD_OPTION(AnaoCfg->TSC_AnaoptrResisOption)); + assert_param(IS_TSC_PAD_SPEED(AnaoCfg->TSC_AnaoptrSpeedOption)); + + __TSC_PAD_OPT_CONFIG(AnaoCfg->TSC_AnaoptrResisOption); + __TSC_PAD_SPEED_CONFIG(AnaoCfg->TSC_AnaoptrSpeedOption); + + return TSC_ERROR_OK; +} + +/** + * @brief Configure channel parameters by channel or operation.Support configure several channels at the same time. + * @param TSC_Def Pointer of TSC register. + * @param ChnCfg Channel parameters. + * @param Channels: channels to be configed, as TSC_CHNEN defined + * This parameter:bit[0:23] used,bit[24:31] must be 0 + * bitx: TSC channel x + */ +TSC_ErrorTypeDef TSC_SetChannelCfg(TSC_Module* TSC_Def, TSC_ChnCfg* ChnCfg, uint32_t Channels) +{ + TSC_ErrorTypeDef err; + + if(TSC_Def != TSC) + return TSC_ERROR_PARAMETER; + + if(0 == ChnCfg) + return TSC_ERROR_PARAMETER; + + // Set resistance + err = TSC_ConfigInternalResistor(TSC_Def, Channels, ChnCfg->TSC_ResisValue); + if(err != TSC_ERROR_OK) + return err; + + // Set the threshold of base and delta. + err = TSC_ConfigThreshold(TSC_Def, Channels, ChnCfg->TSC_Base, ChnCfg->TSC_Delta); + return err; +} + + diff --git a/src/n32g45x_usart.c b/src/n32g45x_usart.c new file mode 100644 index 0000000..74bb97e --- /dev/null +++ b/src/n32g45x_usart.c @@ -0,0 +1,970 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_usart.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_usart.h" +#include "n32g45x_rcc.h" +#include "SystemDelayInterface.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup USART + * @brief USART driver modules + * @{ + */ + +/** @addtogroup USART_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup USART_Private_Defines + * @{ + */ + +#define CTRL1_UEN_SET ((uint16_t)0x2000) /*!< USART Enable Mask */ +#define CTRL1_UEN_RESET ((uint16_t)0xDFFF) /*!< USART Disable Mask */ + +#define CTRL1_WUM_MASK ((uint16_t)0xF7FF) /*!< USART WakeUp Method Mask */ + +#define CTRL1_RCVWU_SET ((uint16_t)0x0002) /*!< USART mute mode Enable Mask */ +#define CTRL1_RCVWU_RESET ((uint16_t)0xFFFD) /*!< USART mute mode Enable Mask */ +#define CTRL1_SDBRK_SET ((uint16_t)0x0001) /*!< USART Break Character send Mask */ +#define CTRL1_CLR_MASK ((uint16_t)0xE9F3) /*!< USART CTRL1 Mask */ +#define CTRL2_ADDR_MASK ((uint16_t)0xFFF0) /*!< USART address Mask */ + +#define CTRL2_LINMEN_SET ((uint16_t)0x4000) /*!< USART LIN Enable Mask */ +#define CTRL2_LINMEN_RESET ((uint16_t)0xBFFF) /*!< USART LIN Disable Mask */ + +#define CTRL2_LINBDL_MASK ((uint16_t)0xFFDF) /*!< USART LIN Break detection Mask */ +#define CTRL2_STPB_CLR_MASK ((uint16_t)0xCFFF) /*!< USART CTRL2 STOP Bits Mask */ +#define CTRL2_CLOCK_CLR_MASK ((uint16_t)0xF0FF) /*!< USART CTRL2 Clock Mask */ + +#define CTRL3_SCMEN_SET ((uint16_t)0x0020) /*!< USART SC Enable Mask */ +#define CTRL3_SCMEN_RESET ((uint16_t)0xFFDF) /*!< USART SC Disable Mask */ + +#define CTRL3_SCNACK_SET ((uint16_t)0x0010) /*!< USART SC NACK Enable Mask */ +#define CTRL3_SCNACK_RESET ((uint16_t)0xFFEF) /*!< USART SC NACK Disable Mask */ + +#define CTRL3_HDMEN_SET ((uint16_t)0x0008) /*!< USART Half-Duplex Enable Mask */ +#define CTRL3_HDMEN_RESET ((uint16_t)0xFFF7) /*!< USART Half-Duplex Disable Mask */ + +#define CTRL3_IRDALP_MASK ((uint16_t)0xFFFB) /*!< USART IrDA LowPower mode Mask */ +#define CTRL3_CLR_MASK ((uint16_t)0xFCFF) /*!< USART CTRL3 Mask */ + +#define CTRL3_IRDAMEN_SET ((uint16_t)0x0002) /*!< USART IrDA Enable Mask */ +#define CTRL3_IRDAMEN_RESET ((uint16_t)0xFFFD) /*!< USART IrDA Disable Mask */ +#define GTP_LSB_MASK ((uint16_t)0x00FF) /*!< Guard Time Register LSB Mask */ +#define GTP_MSB_MASK ((uint16_t)0xFF00) /*!< Guard Time Register MSB Mask */ +#define INT_MASK ((uint16_t)0x001F) /*!< USART Interrupt Mask */ + +/** + * @} + */ + +/** @addtogroup USART_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup USART_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup USART_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup USART_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the USARTx peripheral registers to their default reset values. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4 or UART5. + */ +void USART_DeInit(USART_Module* USARTx) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + + if (USARTx == USART1) + { + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_USART1, ENABLE); + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_USART1, DISABLE); + } + else if (USARTx == USART2) + { + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_USART2, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_USART2, DISABLE); + } + else if (USARTx == USART3) + { + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_USART3, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_USART3, DISABLE); + } + else if (USARTx == UART4) + { + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_UART4, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_UART4, DISABLE); + } + else if (USARTx == UART5) + { + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_UART5, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_UART5, DISABLE); + } + else if (USARTx == UART6) + { + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_UART6, ENABLE); + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_UART6, DISABLE); + } + else + { + if (USARTx == UART7) + { + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_UART7, ENABLE); + RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_UART7, DISABLE); + } + } +} + +/** + * @brief Initializes the USARTx peripheral according to the specified + * parameters in the USART_InitStruct . + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4 or UART5. + * @param USART_InitStruct pointer to a USART_InitType structure + * that contains the configuration information for the specified USART + * peripheral. + */ +void USART_Init(USART_Module* USARTx, USART_InitType* USART_InitStruct) +{ + uint32_t tmpregister = 0x00, apbclock = 0x00; + uint32_t integerdivider = 0x00; + uint32_t fractionaldivider = 0x00; + uint32_t usartxbase = 0; + RCC_ClocksType RCC_ClocksStatus; + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_BAUDRATE(USART_InitStruct->BaudRate)); + assert_param(IS_USART_WORD_LENGTH(USART_InitStruct->WordLength)); + assert_param(IS_USART_STOPBITS(USART_InitStruct->StopBits)); + assert_param(IS_USART_PARITY(USART_InitStruct->Parity)); + assert_param(IS_USART_MODE(USART_InitStruct->Mode)); + assert_param(IS_USART_HARDWARE_FLOW_CONTROL(USART_InitStruct->HardwareFlowControl)); + /* The hardware flow control is available only for USART1, USART2 and USART3 */ + if (USART_InitStruct->HardwareFlowControl != USART_HFCTRL_NONE) + { + assert_param(IS_USART_123_PERIPH(USARTx)); + } + + usartxbase = (uint32_t)USARTx; + + /*---------------------------- USART CTRL2 Configuration -----------------------*/ + tmpregister = USARTx->CTRL2; + /* Clear STOP[13:12] bits */ + tmpregister &= CTRL2_STPB_CLR_MASK; + /* Configure the USART Stop Bits, Clock, CPOL, CPHA and LastBit ------------*/ + /* Set STOP[13:12] bits according to StopBits value */ + tmpregister |= (uint32_t)USART_InitStruct->StopBits; + + /* Write to USART CTRL2 */ + USARTx->CTRL2 = (uint16_t)tmpregister; + + /*---------------------------- USART CTRL1 Configuration -----------------------*/ + tmpregister = USARTx->CTRL1; + /* Clear M, PCE, PS, TE and RE bits */ + tmpregister &= CTRL1_CLR_MASK; + /* Configure the USART Word Length, Parity and mode ----------------------- */ + /* Set the M bits according to WordLength value */ + /* Set PCE and PS bits according to Parity value */ + /* Set TE and RE bits according to Mode value */ + tmpregister |= (uint32_t)USART_InitStruct->WordLength | USART_InitStruct->Parity | USART_InitStruct->Mode; + /* Write to USART CTRL1 */ + USARTx->CTRL1 = (uint16_t)tmpregister; + + /*---------------------------- USART CTRL3 Configuration -----------------------*/ + tmpregister = USARTx->CTRL3; + /* Clear CTSE and RTSE bits */ + tmpregister &= CTRL3_CLR_MASK; + /* Configure the USART HFC -------------------------------------------------*/ + /* Set CTSE and RTSE bits according to HardwareFlowControl value */ + tmpregister |= USART_InitStruct->HardwareFlowControl; + /* Write to USART CTRL3 */ + USARTx->CTRL3 = (uint16_t)tmpregister; + + /*---------------------------- USART PBC Configuration -----------------------*/ + /* Configure the USART Baud Rate -------------------------------------------*/ + RCC_GetClocksFreqValue(&RCC_ClocksStatus); + if ((usartxbase == USART1_BASE) || (usartxbase == UART6_BASE) || (usartxbase == UART7_BASE)) + { + apbclock = RCC_ClocksStatus.Pclk2Freq; + } + else + { + apbclock = RCC_ClocksStatus.Pclk1Freq; + } + + /* Determine the integer part */ + integerdivider = ((25 * apbclock) / (4 * (USART_InitStruct->BaudRate))); + tmpregister = (integerdivider / 100) << 4; + + /* Determine the fractional part */ + fractionaldivider = integerdivider - (100 * (tmpregister >> 4)); + + /* Implement the fractional part in the register */ + tmpregister |= ((((fractionaldivider * 16) + 50) / 100)) & ((uint8_t)0x0F); + + /* Write to USART PBC */ + USARTx->BRCF = (uint16_t)tmpregister; +} + +/** + * @brief Fills each USART_InitStruct member with its default value. + * @param USART_InitStruct pointer to a USART_InitType structure + * which will be initialized. + */ +void USART_StructInit(USART_InitType* USART_InitStruct) +{ + /* USART_InitStruct members default value */ + USART_InitStruct->BaudRate = 9600; + USART_InitStruct->WordLength = USART_WL_8B; + USART_InitStruct->StopBits = USART_STPB_1; + USART_InitStruct->Parity = USART_PE_NO; + USART_InitStruct->Mode = USART_MODE_RX | USART_MODE_TX; + USART_InitStruct->HardwareFlowControl = USART_HFCTRL_NONE; +} + +/** + * @brief Initializes the USARTx peripheral Clock according to the + * specified parameters in the USART_ClockInitStruct . + * @param USARTx where x can be 1, 2, 3 to select the USART peripheral. + * @param USART_ClockInitStruct pointer to a USART_ClockInitType + * structure that contains the configuration information for the specified + * USART peripheral. + * @note The Smart Card and Synchronous modes are not available for UART4/UART5/UART6/UART7. + */ +void USART_ClockInit(USART_Module* USARTx, USART_ClockInitType* USART_ClockInitStruct) +{ + uint32_t tmpregister = 0x00; + /* Check the parameters */ + assert_param(IS_USART_123_PERIPH(USARTx)); + assert_param(IS_USART_CLOCK(USART_ClockInitStruct->Clock)); + assert_param(IS_USART_CPOL(USART_ClockInitStruct->Polarity)); + assert_param(IS_USART_CPHA(USART_ClockInitStruct->Phase)); + assert_param(IS_USART_LASTBIT(USART_ClockInitStruct->LastBit)); + + /*---------------------------- USART CTRL2 Configuration -----------------------*/ + tmpregister = USARTx->CTRL2; + /* Clear CLKEN, CPOL, CPHA and LBCL bits */ + tmpregister &= CTRL2_CLOCK_CLR_MASK; + /* Configure the USART Clock, CPOL, CPHA and LastBit ------------*/ + /* Set CLKEN bit according to Clock value */ + /* Set CPOL bit according to Polarity value */ + /* Set CPHA bit according to Phase value */ + /* Set LBCL bit according to LastBit value */ + tmpregister |= (uint32_t)USART_ClockInitStruct->Clock | USART_ClockInitStruct->Polarity + | USART_ClockInitStruct->Phase | USART_ClockInitStruct->LastBit; + /* Write to USART CTRL2 */ + USARTx->CTRL2 = (uint16_t)tmpregister; +} + +/** + * @brief Fills each USART_ClockInitStruct member with its default value. + * @param USART_ClockInitStruct pointer to a USART_ClockInitType + * structure which will be initialized. + */ +void USART_ClockStructInit(USART_ClockInitType* USART_ClockInitStruct) +{ + /* USART_ClockInitStruct members default value */ + USART_ClockInitStruct->Clock = USART_CLK_DISABLE; + USART_ClockInitStruct->Polarity = USART_CLKPOL_LOW; + USART_ClockInitStruct->Phase = USART_CLKPHA_1EDGE; + USART_ClockInitStruct->LastBit = USART_CLKLB_DISABLE; +} + +/** + * @brief Enables or disables the specified USART peripheral. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param Cmd new state of the USARTx peripheral. + * This parameter can be: ENABLE or DISABLE. + */ +void USART_Enable(USART_Module* USARTx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the selected USART by setting the UE bit in the CTRL1 register */ + USARTx->CTRL1 |= CTRL1_UEN_SET; + } + else + { + /* Disable the selected USART by clearing the UE bit in the CTRL1 register */ + USARTx->CTRL1 &= CTRL1_UEN_RESET; + } +} + +/** + * @brief Enables or disables the specified USART interrupts. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param USART_INT specifies the USART interrupt sources to be enabled or disabled. + * This parameter can be one of the following values: + * @arg USART_INT_CTSF CTS change interrupt (not available for UART4 and UART5) + * @arg USART_INT_LINBD LIN Break detection interrupt + * @arg USART_INT_TXDE Transmit Data Register empty interrupt + * @arg USART_INT_TXC Transmission complete interrupt + * @arg USART_INT_RXDNE Receive Data register not empty interrupt + * @arg USART_INT_IDLEF Idle line detection interrupt + * @arg USART_INT_PEF Parity Error interrupt + * @arg USART_INT_ERRF Error interrupt(Frame error, noise error, overrun error) + * @param Cmd new state of the specified USARTx interrupts. + * This parameter can be: ENABLE or DISABLE. + */ +void USART_ConfigInt(USART_Module* USARTx, uint16_t USART_INT, FunctionalState Cmd) +{ + uint32_t usartreg = 0x00, itpos = 0x00, itmask = 0x00; + uint32_t usartxbase = 0x00; + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_CFG_INT(USART_INT)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + /* The CTS interrupt is not available for UART4/UART5/UART6/UART7 */ + if (USART_INT == USART_INT_CTSF) + { + assert_param(IS_USART_123_PERIPH(USARTx)); + } + + usartxbase = (uint32_t)USARTx; + + /* Get the USART register index */ + usartreg = (((uint8_t)USART_INT) >> 0x05); + + /* Get the interrupt position */ + itpos = USART_INT & INT_MASK; + itmask = (((uint32_t)0x01) << itpos); + + if (usartreg == 0x01) /* The IT is in CTRL1 register */ + { + usartxbase += 0x0C; + } + else if (usartreg == 0x02) /* The IT is in CTRL2 register */ + { + usartxbase += 0x10; + } + else /* The IT is in CTRL3 register */ + { + usartxbase += 0x14; + } + if (Cmd != DISABLE) + { + *(__IO uint32_t*)usartxbase |= itmask; + } + else + { + *(__IO uint32_t*)usartxbase &= ~itmask; + } +} + +/** + * @brief Enables or disables the USART's DMA interface. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param USART_DMAReq specifies the DMA request. + * This parameter can be any combination of the following values: + * @arg USART_DMAREQ_TX USART DMA transmit request + * @arg USART_DMAREQ_RX USART DMA receive request + * @param Cmd new state of the DMA Request sources. + * This parameter can be: ENABLE or DISABLE. + */ +void USART_EnableDMA(USART_Module* USARTx, uint16_t USART_DMAReq, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_DMAREQ(USART_DMAReq)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the DMA transfer for selected requests by setting the DMAT and/or + DADDR bits in the USART CTRL3 register */ + USARTx->CTRL3 |= USART_DMAReq; + } + else + { + /* Disable the DMA transfer for selected requests by clearing the DMAT and/or + DADDR bits in the USART CTRL3 register */ + USARTx->CTRL3 &= (uint16_t)~USART_DMAReq; + } +} + +/** + * @brief Sets the address of the USART node. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param USART_Addr Indicates the address of the USART node. + */ +void USART_SetAddr(USART_Module* USARTx, uint8_t USART_Addr) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_ADDRESS(USART_Addr)); + + /* Clear the USART address */ + USARTx->CTRL2 &= CTRL2_ADDR_MASK; + /* Set the USART address node */ + USARTx->CTRL2 |= USART_Addr; +} + +/** + * @brief Selects the USART WakeUp method. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param USART_WakeUpMode specifies the USART wakeup method. + * This parameter can be one of the following values: + * @arg USART_WUM_IDLELINE WakeUp by an idle line detection + * @arg USART_WUM_ADDRMASK WakeUp by an address mark + */ +void USART_ConfigWakeUpMode(USART_Module* USARTx, uint16_t USART_WakeUpMode) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_WAKEUP(USART_WakeUpMode)); + + USARTx->CTRL1 &= CTRL1_WUM_MASK; + USARTx->CTRL1 |= USART_WakeUpMode; +} + +/** + * @brief Determines if the USART is in mute mode or not. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param Cmd new state of the USART mute mode. + * This parameter can be: ENABLE or DISABLE. + */ +void USART_EnableRcvWakeUp(USART_Module* USARTx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the USART mute mode by setting the RWU bit in the CTRL1 register */ + USARTx->CTRL1 |= CTRL1_RCVWU_SET; + } + else + { + /* Disable the USART mute mode by clearing the RWU bit in the CTRL1 register */ + USARTx->CTRL1 &= CTRL1_RCVWU_RESET; + } +} + +/** + * @brief Sets the USART LIN Break detection length. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param USART_LINBreakDetectLength specifies the LIN break detection length. + * This parameter can be one of the following values: + * @arg USART_LINBDL_10B 10-bit break detection + * @arg USART_LINBDL_11B 11-bit break detection + */ +void USART_ConfigLINBreakDetectLength(USART_Module* USARTx, uint16_t USART_LINBreakDetectLength) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_LIN_BREAK_DETECT_LENGTH(USART_LINBreakDetectLength)); + + USARTx->CTRL2 &= CTRL2_LINBDL_MASK; + USARTx->CTRL2 |= USART_LINBreakDetectLength; +} + +/** + * @brief Enables or disables the USART's LIN mode. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param Cmd new state of the USART LIN mode. + * This parameter can be: ENABLE or DISABLE. + */ +void USART_EnableLIN(USART_Module* USARTx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the LIN mode by setting the LINEN bit in the CTRL2 register */ + USARTx->CTRL2 |= CTRL2_LINMEN_SET; + } + else + { + /* Disable the LIN mode by clearing the LINEN bit in the CTRL2 register */ + USARTx->CTRL2 &= CTRL2_LINMEN_RESET; + } +} + +/** + * @brief Transmits single data through the USARTx peripheral. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param Data the data to transmit. + */ +void USART_SendData(USART_Module* USARTx, uint16_t Data) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_DATA(Data)); + + /* Transmit Data */ + USARTx->DAT = (Data & (uint16_t)0x01FF); +} + +/** + * @brief Returns the most recent received data by the USARTx peripheral. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @return The received data. + */ +uint16_t USART_ReceiveData(USART_Module* USARTx) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + + /* Receive Data */ + return (uint16_t)(USARTx->DAT & (uint16_t)0x01FF); +} + +/** + * @brief Transmits break characters. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + */ +void USART_SendBreak(USART_Module* USARTx) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + + /* Send break characters */ + USARTx->CTRL1 |= CTRL1_SDBRK_SET; +} + +/** + * @brief Sets the specified USART guard time. + * @param USARTx where x can be 1, 2 or 3 to select the USART peripheral. + * @param USART_GuardTime specifies the guard time. + * @note The guard time bits are not available for UART4/UART5/UART6/UART7. + */ +void USART_SetGuardTime(USART_Module* USARTx, uint8_t USART_GuardTime) +{ + /* Check the parameters */ + assert_param(IS_USART_123_PERIPH(USARTx)); + + /* Clear the USART Guard time */ + USARTx->GTP &= GTP_LSB_MASK; + /* Set the USART guard time */ + USARTx->GTP |= (uint16_t)((uint16_t)USART_GuardTime << 0x08); +} + +/** + * @brief Sets the system clock prescaler. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param USART_Prescaler specifies the prescaler clock. + * @note The function is used for IrDA mode with UART4 and UART5. + */ +void USART_SetPrescaler(USART_Module* USARTx, uint8_t USART_Prescaler) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + + /* Clear the USART prescaler */ + USARTx->GTP &= GTP_MSB_MASK; + /* Set the USART prescaler */ + USARTx->GTP |= USART_Prescaler; +} + +/** + * @brief Enables or disables the USART's Smart Card mode. + * @param USARTx where x can be 1, 2 or 3 to select the USART peripheral. + * @param Cmd new state of the Smart Card mode. + * This parameter can be: ENABLE or DISABLE. + * @note The Smart Card mode is not available for UART4/UART5/UART6/UART7. + */ +void USART_EnableSmartCard(USART_Module* USARTx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_USART_123_PERIPH(USARTx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the SC mode by setting the SCEN bit in the CTRL3 register */ + USARTx->CTRL3 |= CTRL3_SCMEN_SET; + } + else + { + /* Disable the SC mode by clearing the SCEN bit in the CTRL3 register */ + USARTx->CTRL3 &= CTRL3_SCMEN_RESET; + } +} + +/** + * @brief Enables or disables NACK transmission. + * @param USARTx where x can be 1, 2 or 3 to select the USART peripheral. + * @param Cmd new state of the NACK transmission. + * This parameter can be: ENABLE or DISABLE. + * @note The Smart Card mode is not available for UART4/UART5/UART6/UART7. + */ +void USART_SetSmartCardNACK(USART_Module* USARTx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_USART_123_PERIPH(USARTx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + if (Cmd != DISABLE) + { + /* Enable the NACK transmission by setting the NACK bit in the CTRL3 register */ + USARTx->CTRL3 |= CTRL3_SCNACK_SET; + } + else + { + /* Disable the NACK transmission by clearing the NACK bit in the CTRL3 register */ + USARTx->CTRL3 &= CTRL3_SCNACK_RESET; + } +} + +/** + * @brief Enables or disables the USART's Half Duplex communication. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param Cmd new state of the USART Communication. + * This parameter can be: ENABLE or DISABLE. + */ +void USART_EnableHalfDuplex(USART_Module* USARTx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the Half-Duplex mode by setting the HDSEL bit in the CTRL3 register */ + USARTx->CTRL3 |= CTRL3_HDMEN_SET; + } + else + { + /* Disable the Half-Duplex mode by clearing the HDSEL bit in the CTRL3 register */ + USARTx->CTRL3 &= CTRL3_HDMEN_RESET; + } +} + +/** + * @brief Configures the USART's IrDA interface. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param USART_IrDAMode specifies the IrDA mode. + * This parameter can be one of the following values: + * @arg USART_IRDAMODE_LOWPPWER + * @arg USART_IRDAMODE_NORMAL + */ +void USART_ConfigIrDAMode(USART_Module* USARTx, uint16_t USART_IrDAMode) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_IRDA_MODE(USART_IrDAMode)); + + USARTx->CTRL3 &= CTRL3_IRDALP_MASK; + USARTx->CTRL3 |= USART_IrDAMode; +} + +/** + * @brief Enables or disables the USART's IrDA interface. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param Cmd new state of the IrDA mode. + * This parameter can be: ENABLE or DISABLE. + */ +void USART_EnableIrDA(USART_Module* USARTx, FunctionalState Cmd) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_FUNCTIONAL_STATE(Cmd)); + + if (Cmd != DISABLE) + { + /* Enable the IrDA mode by setting the IREN bit in the CTRL3 register */ + USARTx->CTRL3 |= CTRL3_IRDAMEN_SET; + } + else + { + /* Disable the IrDA mode by clearing the IREN bit in the CTRL3 register */ + USARTx->CTRL3 &= CTRL3_IRDAMEN_RESET; + } +} + +/** + * @brief Checks whether the specified USART flag is set or not. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param USART_FLAG specifies the flag to check. + * This parameter can be one of the following values: + * @arg USART_FLAG_CTSF CTS Change flag (not available for UART4 and UART5) + * @arg USART_FLAG_LINBD LIN Break detection flag + * @arg USART_FLAG_TXDE Transmit data register empty flag + * @arg USART_FLAG_TXC Transmission Complete flag + * @arg USART_FLAG_RXDNE Receive data register not empty flag + * @arg USART_FLAG_IDLEF Idle Line detection flag + * @arg USART_FLAG_OREF OverRun Error flag + * @arg USART_FLAG_NEF Noise Error flag + * @arg USART_FLAG_FEF Framing Error flag + * @arg USART_FLAG_PEF Parity Error flag + * @return The new state of USART_FLAG (SET or RESET). + */ +/// bag +FlagStatus USART_GetFlagStatus(USART_Module* USARTx, uint16_t USART_FLAG) +{ + FlagStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_FLAG(USART_FLAG)); + /* The CTS flag is not available for UART4/UART5/UART6/UART7 */ + if (USART_FLAG == USART_FLAG_CTSF) + { + assert_param(IS_USART_123_PERIPH(USARTx)); + } + if ((USARTx->STS & USART_FLAG) != (uint16_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/** + * @brief Clears the USARTx's pending flags. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param USART_FLAG specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg USART_FLAG_CTSF CTS Change flag (not available for UART4 and UART5). + * @arg USART_FLAG_LINBD LIN Break detection flag. + * @arg USART_FLAG_TXC Transmission Complete flag. + * @arg USART_FLAG_RXDNE Receive data register not empty flag. + * + * @note + * - PE (Parity error), FE (Framing error), NE (Noise error), ORE (OverRun + * error) and IDLE (Idle line detected) flags are cleared by software + * sequence: a read operation to USART_SR register (USART_GetFlagStatus()) + * followed by a read operation to USART_DR register (USART_ReceiveData()). + * - RXNE flag can be also cleared by a read to the USART_DR register + * (USART_ReceiveData()). + * - TC flag can be also cleared by software sequence: a read operation to + * USART_SR register (USART_GetFlagStatus()) followed by a write operation + * to USART_DR register (USART_SendData()). + * - TXE flag is cleared only by a write to the USART_DR register + * (USART_SendData()). + */ +void USART_ClrFlag(USART_Module* USARTx, uint16_t USART_FLAG) +{ + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_CLEAR_FLAG(USART_FLAG)); + /* The CTS flag is not available for UART4/UART5/UART6/UART7 */ + if ((USART_FLAG & USART_FLAG_CTSF) == USART_FLAG_CTSF) + { + assert_param(IS_USART_123_PERIPH(USARTx)); + } + + USARTx->STS = (uint16_t)~USART_FLAG; +} + +/** + * @brief Checks whether the specified USART interrupt has occurred or not. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param USART_INT specifies the USART interrupt source to check. + * This parameter can be one of the following values: + * @arg USART_INT_CTSF CTS change interrupt (not available for UART4 and UART5) + * @arg USART_INT_LINBD LIN Break detection interrupt + * @arg USART_INT_TXDE Tansmit Data Register empty interrupt + * @arg USART_INT_TXC Transmission complete interrupt + * @arg USART_INT_RXDNE Receive Data register not empty interrupt + * @arg USART_INT_IDLEF Idle line detection interrupt + * @arg USART_INT_OREF OverRun Error interrupt + * @arg USART_INT_NEF Noise Error interrupt + * @arg USART_INT_FEF Framing Error interrupt + * @arg USART_INT_PEF Parity Error interrupt + * @return The new state of USART_INT (SET or RESET). + */ +INTStatus USART_GetIntStatus(USART_Module* USARTx, uint16_t USART_INT) +{ + uint32_t bitpos = 0x00, itmask = 0x00, usartreg = 0x00; + INTStatus bitstatus = RESET; + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_GET_INT(USART_INT)); + /* The CTS interrupt is not available for UART4/UART5/UART6/UART7 */ + if (USART_INT == USART_INT_CTSF) + { + assert_param(IS_USART_123_PERIPH(USARTx)); + } + + /* Get the USART register index */ + usartreg = (((uint8_t)USART_INT) >> 0x05); + /* Get the interrupt position */ + itmask = USART_INT & INT_MASK; + itmask = (uint32_t)0x01 << itmask; + + if (usartreg == 0x01) /* The IT is in CTRL1 register */ + { + itmask &= USARTx->CTRL1; + } + else if (usartreg == 0x02) /* The IT is in CTRL2 register */ + { + itmask &= USARTx->CTRL2; + } + else /* The IT is in CTRL3 register */ + { + itmask &= USARTx->CTRL3; + } + + bitpos = USART_INT >> 0x08; + bitpos = (uint32_t)0x01 << bitpos; + bitpos &= USARTx->STS; + if ((itmask != (uint16_t)RESET) && (bitpos != (uint16_t)RESET)) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + return bitstatus; +} + +/** + * @brief Clears the USARTx's interrupt pending bits. + * @param USARTx Select the USART or the UART peripheral. + * This parameter can be one of the following values: + * USART1, USART2, USART3, UART4, UART5, UART6 or UART7. + * @param USART_INT specifies the interrupt pending bit to clear. + * This parameter can be one of the following values: + * @arg USART_INT_CTSF CTS change interrupt (not available for UART4 and UART5) + * @arg USART_INT_LINBD LIN Break detection interrupt + * @arg USART_INT_TXC Transmission complete interrupt. + * @arg USART_INT_RXDNE Receive Data register not empty interrupt. + * + * @note + * - PE (Parity error), FE (Framing error), NE (Noise error), ORE (OverRun + * error) and IDLE (Idle line detected) pending bits are cleared by + * software sequence: a read operation to USART_SR register + * (USART_GetIntStatus()) followed by a read operation to USART_DR register + * (USART_ReceiveData()). + * - RXNE pending bit can be also cleared by a read to the USART_DR register + * (USART_ReceiveData()). + * - TC pending bit can be also cleared by software sequence: a read + * operation to USART_SR register (USART_GetIntStatus()) followed by a write + * operation to USART_DR register (USART_SendData()). + * - TXE pending bit is cleared only by a write to the USART_DR register + * (USART_SendData()). + */ +void USART_ClrIntPendingBit(USART_Module* USARTx, uint16_t USART_INT) +{ + uint16_t bitpos = 0x00, itmask = 0x00; + /* Check the parameters */ + assert_param(IS_USART_ALL_PERIPH(USARTx)); + assert_param(IS_USART_CLR_INT(USART_INT)); + /* The CTS interrupt is not available for UART4/UART5/UART6/UART7 */ + if (USART_INT == USART_INT_CTSF) + { + assert_param(IS_USART_123_PERIPH(USARTx)); + } + + bitpos = USART_INT >> 0x08; + itmask = ((uint16_t)0x01 << (uint16_t)bitpos); + USARTx->STS = (uint16_t)~itmask; +} +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/src/n32g45x_wwdg.c b/src/n32g45x_wwdg.c new file mode 100644 index 0000000..6510972 --- /dev/null +++ b/src/n32g45x_wwdg.c @@ -0,0 +1,223 @@ +/***************************************************************************** + * Copyright (c) 2019, Nations Technologies Inc. + * + * All rights reserved. + * **************************************************************************** + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Nations' name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ****************************************************************************/ + +/** + * @file n32g45x_wwdg.c + * @author Nations + * @version v1.0.0 + * + * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. + */ +#include "n32g45x_wwdg.h" +#include "n32g45x_rcc.h" + +/** @addtogroup N32G45X_StdPeriph_Driver + * @{ + */ + +/** @addtogroup WWDG + * @brief WWDG driver modules + * @{ + */ + +/** @addtogroup WWDG_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup WWDG_Private_Defines + * @{ + */ + +/* ----------- WWDG registers bit address in the alias region ----------- */ +#define WWDG_OFFADDR (WWDG_BASE - PERIPH_BASE) + +/* Alias word address of EWI bit */ +#define CFG_OFFADDR (WWDG_OFFADDR + 0x04) +#define EWINT_BIT 0x09 +#define CFG_EWINT_BB (PERIPH_BB_BASE + (CFG_OFFADDR * 32) + (EWINT_BIT * 4)) + +/* --------------------- WWDG registers bit mask ------------------------ */ + +/* CTRL register bit mask */ +#define CTRL_ACTB_SET ((uint32_t)0x00000080) + +/* CFG register bit mask */ +#define CFG_TIMERB_MASK ((uint32_t)0xFFFFFE7F) +#define CFG_W_MASK ((uint32_t)0xFFFFFF80) +#define BIT_MASK ((uint8_t)0x7F) + +/** + * @} + */ + +/** @addtogroup WWDG_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup WWDG_Private_Variables + * @{ + */ + +/** + * @} + */ + +/** @addtogroup WWDG_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup WWDG_Private_Functions + * @{ + */ + +/** + * @brief Deinitializes the WWDG peripheral registers to their default reset values. + */ +void WWDG_DeInit(void) +{ + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_WWDG, ENABLE); + RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_WWDG, DISABLE); +} + +/** + * @brief Sets the WWDG Prescaler. + * @param WWDG_Prescaler specifies the WWDG Prescaler. + * This parameter can be one of the following values: + * @arg WWDG_PRESCALER_DIV1 WWDG counter clock = (PCLK1/4096)/1 + * @arg WWDG_PRESCALER_DIV2 WWDG counter clock = (PCLK1/4096)/2 + * @arg WWDG_PRESCALER_DIV4 WWDG counter clock = (PCLK1/4096)/4 + * @arg WWDG_PRESCALER_DIV8 WWDG counter clock = (PCLK1/4096)/8 + */ +void WWDG_SetPrescalerDiv(uint32_t WWDG_Prescaler) +{ + uint32_t tmpregister = 0; + /* Check the parameters */ + assert_param(IS_WWDG_PRESCALER_DIV(WWDG_Prescaler)); + /* Clear WDGTB[1:0] bits */ + tmpregister = WWDG->CFG & CFG_TIMERB_MASK; + /* Set WDGTB[1:0] bits according to WWDG_Prescaler value */ + tmpregister |= WWDG_Prescaler; + /* Store the new value */ + WWDG->CFG = tmpregister; +} + +/** + * @brief Sets the WWDG window value. + * @param WindowValue specifies the window value to be compared to the downcounter. + * This parameter value must be lower than 0x80. + */ +void WWDG_SetWValue(uint8_t WindowValue) +{ + __IO uint32_t tmpregister = 0; + + /* Check the parameters */ + assert_param(IS_WWDG_WVALUE(WindowValue)); + /* Clear W[6:0] bits */ + + tmpregister = WWDG->CFG & CFG_W_MASK; + + /* Set W[6:0] bits according to WindowValue value */ + tmpregister |= WindowValue & (uint32_t)BIT_MASK; + + /* Store the new value */ + WWDG->CFG = tmpregister; +} + +/** + * @brief Enables the WWDG Early Wakeup interrupt(EWI). + */ +void WWDG_EnableInt(void) +{ + *(__IO uint32_t*)CFG_EWINT_BB = (uint32_t)ENABLE; +} + +/** + * @brief Sets the WWDG counter value. + * @param Counter specifies the watchdog counter value. + * This parameter must be a number between 0x40 and 0x7F. + */ +void WWDG_SetCnt(uint8_t Counter) +{ + /* Check the parameters */ + assert_param(IS_WWDG_CNT(Counter)); + /* Write to T[6:0] bits to configure the counter value, no need to do + a read-modify-write; writing a 0 to WDGA bit does nothing */ + WWDG->CTRL = Counter & BIT_MASK; +} + +/** + * @brief Enables WWDG and load the counter value. + * @param Counter specifies the watchdog counter value. + * This parameter must be a number between 0x40 and 0x7F. + */ +void WWDG_Enable(uint8_t Counter) +{ + /* Check the parameters */ + assert_param(IS_WWDG_CNT(Counter)); + WWDG->CTRL = CTRL_ACTB_SET | Counter; +} + +/** + * @brief Checks whether the Early Wakeup interrupt flag is set or not. + * @return The new state of the Early Wakeup interrupt flag (SET or RESET) + */ +FlagStatus WWDG_GetEWINTF(void) +{ + return (FlagStatus)(WWDG->STS); +} + +/** + * @brief Clears Early Wakeup interrupt flag. + */ +void WWDG_ClrEWINTF(void) +{ + WWDG->STS = (uint32_t)RESET; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */