summaryrefslogtreecommitdiff
path: root/FreeRTOS/Demo/CORTEX_MPU_M33F_NXP_LPC55S69_MCUXpresso/NXP_Code/drivers/fsl_power.c
diff options
context:
space:
mode:
Diffstat (limited to 'FreeRTOS/Demo/CORTEX_MPU_M33F_NXP_LPC55S69_MCUXpresso/NXP_Code/drivers/fsl_power.c')
-rw-r--r--FreeRTOS/Demo/CORTEX_MPU_M33F_NXP_LPC55S69_MCUXpresso/NXP_Code/drivers/fsl_power.c1816
1 files changed, 1814 insertions, 2 deletions
diff --git a/FreeRTOS/Demo/CORTEX_MPU_M33F_NXP_LPC55S69_MCUXpresso/NXP_Code/drivers/fsl_power.c b/FreeRTOS/Demo/CORTEX_MPU_M33F_NXP_LPC55S69_MCUXpresso/NXP_Code/drivers/fsl_power.c
index ccc1ad471..41561f4d6 100644
--- a/FreeRTOS/Demo/CORTEX_MPU_M33F_NXP_LPC55S69_MCUXpresso/NXP_Code/drivers/fsl_power.c
+++ b/FreeRTOS/Demo/CORTEX_MPU_M33F_NXP_LPC55S69_MCUXpresso/NXP_Code/drivers/fsl_power.c
@@ -13,7 +13,1819 @@
#endif
/*******************************************************************************
- * Code
+ * Variables
******************************************************************************/
-/* Empty file since implementation is in header file and power library */
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+/** @brief Low Power main structure */
+typedef enum
+{
+ VD_AON = 0x0, /*!< Digital Always On power domain */
+ VD_MEM = 0x1, /*!< Memories (SRAM) power domain */
+ VD_DCDC = 0x2, /*!< Core logic power domain */
+ VD_DEEPSLEEP = 0x3 /*!< Core logic power domain */
+} LPC_POWER_DOMAIN_T;
+
+/**
+ * @brief LDO_FLASH_NV & LDO_USB voltage settings
+ */
+typedef enum _v_flashnv
+{
+ V_LDOFLASHNV_1P650 = 0, /*!< 0.95 V */
+ V_LDOFLASHNV_1P700 = 1, /*!< 0.975 V */
+ V_LDOFLASHNV_1P750 = 2, /*!< 1 V */
+ V_LDOFLASHNV_0P800 = 3, /*!< 1.025 V */
+ V_LDOFLASHNV_1P850 = 4, /*!< 1.050 V */
+ V_LDOFLASHNV_1P900 = 5, /*!< 1.075 V */
+ V_LDOFLASHNV_1P950 = 6, /*!< 1.1 V */
+ V_LDOFLASHNV_2P000 = 7 /*!< 1.125 V */
+} v_flashnv_t;
+
+/** @brief Low Power main structure */
+typedef struct
+{ /* */
+ __IO uint32_t CFG; /*!< Low Power Mode Configuration, and miscallenous options */
+ __IO uint32_t PDCTRL0; /*!< Power Down control : controls power of various modules
+ in the different Low power modes, including ROM */
+ __IO uint32_t SRAMRETCTRL; /*!< Power Down control : controls power SRAM instances
+ in the different Low power modes */
+ __IO uint32_t CPURETCTRL; /*!< CPU0 retention control : controls CPU retention parameters in POWER DOWN modes */
+ __IO uint64_t VOLTAGE; /*!< Voltage control in Low Power Modes */
+ __IO uint64_t WAKEUPSRC; /*!< Wake up sources control for sleepcon */
+ __IO uint64_t WAKEUPINT; /*!< Wake up sources control for ARM */
+ __IO uint32_t HWWAKE; /*!< Interrupt that can postpone power down modes
+ in case an interrupt is pending when the processor request deepsleep */
+ __IO uint32_t WAKEUPIOSRC; /*!< Wake up I/O sources in DEEP POWER DOWN mode */
+ __IO uint32_t TIMERCFG; /*!< Wake up timers configuration */
+ __IO uint32_t TIMERCOUNT; /*!< Wake up Timer count*/
+ __IO uint32_t POWERCYCLE; /*!< Cancels entry in Low Power mode if set with 0xDEADABBA (might be used by some
+ interrupt handlers)*/
+} LPC_LOWPOWER_T;
+
+/* */
+#define LOWPOWER_POWERCYCLE_CANCELLED 0xDEADABBAUL /*!< */
+
+/**
+ * @brief SRAM Low Power Modes
+ */
+#define LOWPOWER_SRAM_LPMODE_MASK (0xFUL)
+#define LOWPOWER_SRAM_LPMODE_ACTIVE (0x6UL) /*!< SRAM functional mode */
+#define LOWPOWER_SRAM_LPMODE_SLEEP (0xFUL) /*!< SRAM Sleep mode (Data retention, fast wake up) */
+#define LOWPOWER_SRAM_LPMODE_DEEPSLEEP (0x8UL) /*!< SRAM Deep Sleep mode (Data retention, slow wake up) */
+#define LOWPOWER_SRAM_LPMODE_SHUTDOWN (0x9UL) /*!< SRAM Shut Down mode (no data retention) */
+#define LOWPOWER_SRAM_LPMODE_POWERUP (0xAUL) /*!< SRAM is powering up */
+
+/**
+ * @brief Wake up timers configuration in Low Power Modes
+ */
+#define LOWPOWER_TIMERCFG_CTRL_INDEX 0
+#define LOWPOWER_TIMERCFG_CTRL_MASK (0x1UL << LOWPOWER_TIMERCFG_CTRL_INDEX)
+#define LOWPOWER_TIMERCFG_TIMER_INDEX 1
+#define LOWPOWER_TIMERCFG_TIMER_MASK (0x7UL << LOWPOWER_TIMERCFG_TIMER_INDEX)
+#define LOWPOWER_TIMERCFG_OSC32K_INDEX 4
+#define LOWPOWER_TIMERCFG_OSC32K_MASK (0x1UL << LOWPOWER_TIMERCFG_OSC32K_INDEX)
+
+#define LOWPOWER_TIMERCFG_CTRL_DISABLE 0 /*!< Wake Timer Disable */
+#define LOWPOWER_TIMERCFG_CTRL_ENABLE 1 /*!< Wake Timer Enable */
+
+/**
+ * @brief Primary Wake up timers configuration in Low Power Modes
+ */
+#define LOWPOWER_TIMERCFG_TIMER_RTC1KHZ 0 /*!< 1 KHz Real Time Counter (RTC) used as wake up source */
+#define LOWPOWER_TIMERCFG_TIMER_RTC1HZ 1 /*!< 1 Hz Real Time Counter (RTC) used as wake up source */
+#define LOWPOWER_TIMERCFG_TIMER_OSTIMER 2 /*!< OS Event Timer used as wake up source */
+
+#define LOWPOWER_TIMERCFG_OSC32K_FRO32KHZ 0 /*!< Wake up Timers uses FRO 32 KHz as clock source */
+#define LOWPOWER_TIMERCFG_OSC32K_XTAL32KHZ 1 /*!< Wake up Timers uses Chrystal 32 KHz as clock source */
+
+//! @brief Interface for lowpower functions
+typedef struct LowpowerDriverInterface
+{
+ void (*power_cycle_cpu_and_flash)(void);
+ void (*set_lowpower_mode)(LPC_LOWPOWER_T *p_lowpower_cfg);
+} lowpower_driver_interface_t;
+
+/**< DCDC Power Profiles */
+typedef enum
+{
+ DCDC_POWER_PROFILE_LOW, /**< LOW (for CPU frequencies below DCDC_POWER_PROFILE_LOW_MAX_FREQ_HZ) */
+ DCDC_POWER_PROFILE_MEDIUM, /**< MEDIUM (for CPU frequencies between DCDC_POWER_PROFILE_LOW_MAX_FREQ_HZ and
+ DCDC_POWER_PROFILE_MEDIUM_MAX_FREQ_HZ) */
+ DCDC_POWER_PROFILE_HIGH, /**< HIGH (for CPU frequencies between DCDC_POWER_PROFILE_MEDIUM_MAX_FREQ_HZ and
+ DCDC_POWER_PROFILE_HIGH_MAX_FREQ_HZ) */
+} lowpower_dcdc_power_profile_enum;
+
+/**< Manufacturing Process Corners */
+typedef enum
+{
+ PROCESS_CORNER_SSS, /**< Slow Corner Process */
+ PROCESS_CORNER_NNN, /**< Nominal Corner Process */
+ PROCESS_CORNER_FFF, /**< Fast Corner Process */
+ PROCESS_CORNER_OTHERS, /**< SFN, SNF, NFS, Poly Res ... Corner Process */
+} lowpower_process_corner_enum;
+
+/**
+ * @brief DCDC voltage settings
+ */
+typedef enum _v_dcdc
+{
+ V_DCDC_0P950 = 0, /*!< 0.95 V */
+ V_DCDC_0P975 = 1, /*!< 0.975 V */
+ V_DCDC_1P000 = 2, /*!< 1 V */
+ V_DCDC_1P025 = 3, /*!< 1.025 V */
+ V_DCDC_1P050 = 4, /*!< 1.050 V */
+ V_DCDC_1P075 = 5, /*!< 1.075 V */
+ V_DCDC_1P100 = 6, /*!< 1.1 V */
+ V_DCDC_1P125 = 7, /*!< 1.125 V */
+ V_DCDC_1P150 = 8, /*!< 1.150 V */
+ V_DCDC_1P175 = 9, /*!< 1.175 V */
+ V_DCDC_1P200 = 10 /*!< 1.2 V */
+} v_dcdc_t;
+
+/**
+ * @brief Deep Sleep LDO voltage settings
+ */
+typedef enum _v_deepsleep
+{
+ V_DEEPSLEEP_0P900 = 0, /*!< 0.9 V */
+ V_DEEPSLEEP_0P925 = 1, /*!< 0.925 V */
+ V_DEEPSLEEP_0P950 = 2, /*!< 0.95 V */
+ V_DEEPSLEEP_0P975 = 3, /*!< 0.975 V */
+ V_DEEPSLEEP_1P000 = 4, /*!< 1.000 V */
+ V_DEEPSLEEP_1P025 = 5, /*!< 1.025 V */
+ V_DEEPSLEEP_1P050 = 6, /*!< 1.050 V */
+ V_DEEPSLEEP_1P075 = 7 /*!< 1.075 V */
+} v_deepsleep_t;
+
+/**
+ * @brief Always On and Memories LDO voltage settings
+ */
+typedef enum _v_ao
+{
+ V_AO_0P700 = 1, /*!< 0.7 V */
+ V_AO_0P725 = 2, /*!< 0.725 V */
+ V_AO_0P750 = 3, /*!< 0.75 V */
+ V_AO_0P775 = 4, /*!< 0.775 V */
+ V_AO_0P800 = 5, /*!< 0.8 V */
+ V_AO_0P825 = 6, /*!< 0.825 V */
+ V_AO_0P850 = 7, /*!< 0.85 V */
+ V_AO_0P875 = 8, /*!< 0.875 V */
+ V_AO_0P900 = 9, /*!< 0.9 V */
+ V_AO_0P960 = 10, /*!< 0.96 V */
+ V_AO_0P970 = 11, /*!< 0.97 V */
+ V_AO_0P980 = 12, /*!< 0.98 V */
+ V_AO_0P990 = 13, /*!< 0.99 V */
+ V_AO_1P000 = 14, /*!< 1 V */
+ V_AO_1P010 = 15, /*!< 1.01 V */
+ V_AO_1P020 = 16, /*!< 1.02 V */
+ V_AO_1P030 = 17, /*!< 1.03 V */
+ V_AO_1P040 = 18, /*!< 1.04 V */
+ V_AO_1P050 = 19, /*!< 1.05 V */
+ V_AO_1P060 = 20, /*!< 1.06 V */
+ V_AO_1P070 = 21, /*!< 1.07 V */
+ V_AO_1P080 = 22, /*!< 1.08 V */
+ V_AO_1P090 = 23, /*!< 1.09 V */
+ V_AO_1P100 = 24, /*!< 1.1 V */
+ V_AO_1P110 = 25, /*!< 1.11 V */
+ V_AO_1P120 = 26, /*!< 1.12 V */
+ V_AO_1P130 = 27, /*!< 1.13 V */
+ V_AO_1P140 = 28, /*!< 1.14 V */
+ V_AO_1P150 = 29, /*!< 1.15 V */
+ V_AO_1P160 = 30, /*!< 1.16 V */
+ V_AO_1P220 = 31 /*!< 1.22 V */
+} v_ao_t;
+
+/* Low Power modes */
+#define LOWPOWER_CFG_LPMODE_INDEX 0
+#define LOWPOWER_CFG_LPMODE_MASK (0x3UL << LOWPOWER_CFG_LPMODE_INDEX)
+#define LOWPOWER_CFG_SELCLOCK_INDEX 2
+#define LOWPOWER_CFG_SELCLOCK_MASK (0x1UL << LOWPOWER_CFG_SELCLOCK_INDEX)
+#define LOWPOWER_CFG_SELMEMSUPPLY_INDEX 3
+#define LOWPOWER_CFG_SELMEMSUPPLY_MASK (0x1UL << LOWPOWER_CFG_SELMEMSUPPLY_INDEX)
+#define LOWPOWER_CFG_MEMLOWPOWERMODE_INDEX 4
+#define LOWPOWER_CFG_MEMLOWPOWERMODE_MASK (0x1UL << LOWPOWER_CFG_MEMLOWPOWERMODE_INDEX)
+#define LOWPOWER_CFG_LDODEEPSLEEPREF_INDEX 5
+#define LOWPOWER_CFG_LDODEEPSLEEPREF_MASK (0x1UL << LOWPOWER_CFG_LDODEEPSLEEPREF_INDEX)
+
+#define LOWPOWER_CFG_LPMODE_ACTIVE 0 /*!< ACTIVE mode */
+#define LOWPOWER_CFG_LPMODE_DEEPSLEEP 1 /*!< DEEP SLEEP mode */
+#define LOWPOWER_CFG_LPMODE_POWERDOWN 2 /*!< POWER DOWN mode */
+#define LOWPOWER_CFG_LPMODE_DEEPPOWERDOWN 3 /*!< DEEP POWER DOWN mode */
+#define LOWPOWER_CFG_LPMODE_SLEEP 4 /*!< SLEEP mode */
+
+#define LOWPOWER_CFG_SELCLOCK_1MHZ 0 /*!< The 1 MHz clock is used during the configuration of the PMC */
+#define LOWPOWER_CFG_SELCLOCK_12MHZ \
+ 1 /*!< The 12 MHz clock is used during the configuration of the PMC (to speed up PMC configuration process)*/
+
+#define LOWPOWER_CFG_SELMEMSUPPLY_LDOMEM 0 /*!< In DEEP SLEEP power mode, the Memories are supplied by the LDO_MEM */
+#define LOWPOWER_CFG_SELMEMSUPPLY_LDODEEPSLEEP \
+ 1 /*!< In DEEP SLEEP power mode, the Memories are supplied by the LDO_DEEP_SLEEP (or DCDC) */
+
+#define LOWPOWER_CFG_MEMLOWPOWERMODE_SOURCEBIASING \
+ 0 /*!< All SRAM instances use "Source Biasing" as low power mode technic (it is recommended to set LDO_MEM as high \
+ as possible -- 1.1V typical -- during low power mode) */
+#define LOWPOWER_CFG_MEMLOWPOWERMODE_VOLTAGESCALING \
+ 1 /*!< All SRAM instances use "Voltage Scaling" as low power mode technic (it is recommended to set LDO_MEM as low \
+ as possible -- down to 0.7V -- during low power mode) */
+
+#define LOWPOWER_CFG_LDODEEPSLEEPREF_FLASHBUFFER 0 /*!< LDO DEEP SLEEP uses Flash Buffer as reference */
+#define LOWPOWER_CFG_LDODEEPSLEEPREF_BANDGAG0P8V 1 /*!< LDO DEEP SLEEP uses Band Gap 0.8V as reference */
+
+/* CPU Retention Control*/
+#define LOWPOWER_CPURETCTRL_ENA_INDEX 0
+#define LOWPOWER_CPURETCTRL_ENA_MASK (0x1UL << LOWPOWER_CPURETCTRL_ENA_INDEX)
+#define LOWPOWER_CPURETCTRL_MEMBASE_INDEX 1
+#define LOWPOWER_CPURETCTRL_MEMBASE_MASK (0x1FFFUL << LOWPOWER_CPURETCTRL_MEMBASE_INDEX)
+#define LOWPOWER_CPURETCTRL_RETDATALENGTH_INDEX 14
+#define LOWPOWER_CPURETCTRL_RETDATALENGTH_MASK (0x3FFUL << LOWPOWER_CPURETCTRL_RETDATALENGTH_INDEX)
+
+/* Voltgae setting*/
+#define DCDC_POWER_PROFILE_LOW_MAX_FREQ_HZ \
+ (100000000U) /* Maximum System Frequency allowed with DCDC Power Profile LOW */
+#define DCDC_POWER_PROFILE_MEDIUM_MAX_FREQ_HZ \
+ (130000000U) /* Maximum System Frequency allowed with DCDC Power Profile MEDIUM */
+#define DCDC_POWER_PROFILE_HIGH_MAX_FREQ_HZ \
+ (150000000U) /* Maximum System Frequency allowed with DCDC Power Profile HIGH */
+#define PROCESS_NNN_AVG_HZ (19300000U) /* Average Ring OScillator value for Nominal (NNN) Manufacturing Process */
+#define PROCESS_NNN_STD_HZ \
+ (400000U) /* Standard Deviation Ring OScillator value for Nominal (NNN) Manufacturing Process */
+#define PROCESS_NNN_LIMITS \
+ (6U) /* Nominal (NNN) Manufacturing Process Ring Oscillator values limit (with respect to the Average value) */
+#define PROCESS_NNN_MIN_HZ \
+ (PROCESS_NNN_AVG_HZ - \
+ (PROCESS_NNN_LIMITS * \
+ PROCESS_NNN_STD_HZ)) /* Minimum Ring OScillator value for Nominal (NNN) Manufacturing Process */
+#define PROCESS_NNN_MAX_HZ \
+ (PROCESS_NNN_AVG_HZ + \
+ (PROCESS_NNN_LIMITS * \
+ PROCESS_NNN_STD_HZ)) /* Maximum Ring OScillator value for Nominal (NNN) Manufacturing Process */
+#define VOLTAGE_SSS_LOW_MV (1075U) /* Voltage Settings for : Process=SSS, DCDC Power Profile=LOW */
+#define VOLTAGE_SSS_MED_MV (1150U) /* Voltage Settings for : Process=SSS, DCDC Power Profile=MEDIUM */
+#define VOLTAGE_SSS_HIG_MV (1200U) /* Voltage Settings for : Process=SSS, DCDC Power Profile=HIGH */
+#define VOLTAGE_NNN_LOW_MV (1000U) /* Voltage Settings for : Process=NNN, DCDC Power Profile=LOW */
+#define VOLTAGE_NNN_MED_MV (1100U) /* Voltage Settings for : Process=NNN, DCDC Power Profile=MEDIUM */
+#define VOLTAGE_NNN_HIG_MV (1150U) /* Voltage Settings for : Process=NNN, DCDC Power Profile=HIGH */
+#define VOLTAGE_FFF_LOW_MV (1000U) /* Voltage Settings for : Process=FFF, DCDC Power Profile=LOW */
+#define VOLTAGE_FFF_MED_MV (1025U) /* Voltage Settings for : Process=FFF, DCDC Power Profile=MEDIUM */
+#define VOLTAGE_FFF_HIG_MV (1050U) /* Voltage Settings for : Process=FFF, DCDC Power Profile=HIGH */
+
+/**
+ * @brief LDO Voltage control in Low Power Modes
+ */
+#define LOWPOWER_VOLTAGE_LDO_PMU_INDEX 0
+#define LOWPOWER_VOLTAGE_LDO_PMU_MASK (0x1FULL << LOWPOWER_VOLTAGE_LDO_PMU_INDEX)
+#define LOWPOWER_VOLTAGE_LDO_MEM_INDEX 5
+#define LOWPOWER_VOLTAGE_LDO_MEM_MASK (0x1FULL << LOWPOWER_VOLTAGE_LDO_MEM_INDEX)
+#define LOWPOWER_VOLTAGE_LDO_DEEP_SLEEP_INDEX 10
+#define LOWPOWER_VOLTAGE_LDO_DEEP_SLEEP_MASK (0x7ULL << LOWPOWER_VOLTAGE_LDO_DEEP_SLEEP_INDEX)
+#define LOWPOWER_VOLTAGE_LDO_PMU_BOOST_INDEX 19
+#define LOWPOWER_VOLTAGE_LDO_PMU_BOOST_MASK (0x1FULL << LOWPOWER_VOLTAGE_LDO_PMU_BOOST_INDEX)
+#define LOWPOWER_VOLTAGE_LDO_MEM_BOOST_INDEX 24
+#define LOWPOWER_VOLTAGE_LDO_MEM_BOOST_MASK (0x1FULL << LOWPOWER_VOLTAGE_LDO_MEM_BOOST_INDEX)
+#define LOWPOWER_VOLTAGE_DCDC_INDEX 29
+#define LOWPOWER_VOLTAGE_DCDC_MASK (0xFULL << LOWPOWER_VOLTAGE_DCDC_INDEX)
+
+/*! @brief set and clear bit MACRO's. */
+#define U32_SET_BITS(P, B) ((*(uint32_t *)P) |= (B))
+#define U32_CLR_BITS(P, B) ((*(uint32_t *)P) &= ~(B))
+/* Return values from Config (N-2) page of flash */
+#define GET_16MXO_TRIM() (*(uint32_t *)0x9FCC8)
+#define GET_32KXO_TRIM() (*(uint32_t *)0x9FCCC)
+
+#define CPU_RETENTION_RAMX_STORAGE_START_ADDR (0x04006000)
+
+#define XO_SLAVE_EN (1)
+/*******************************************************************************
+ * Codes
+ ******************************************************************************/
+
+/*******************************************************************************
+ * LOCAL FUNCTIONS PROTOTYPES
+ ******************************************************************************/
+static void lf_get_deepsleep_core_supply_cfg(uint32_t exclude_from_pd, uint32_t *dcdc_voltage);
+static uint32_t lf_set_ldo_ao_ldo_mem_voltage(uint32_t p_lp_mode, uint32_t p_dcdc_voltage);
+static uint32_t lf_wakeup_io_ctrl(uint32_t p_wakeup_io_ctrl);
+static uint8_t CLOCK_u8OscCapConvert(uint8_t u8OscCap, uint8_t u8CapBankDiscontinuity);
+
+static void lowpower_set_dcdc_power_profile(lowpower_dcdc_power_profile_enum dcdc_power_profile);
+static lowpower_process_corner_enum lowpower_get_part_process_corner(void);
+static void lowpower_set_voltage_for_process(lowpower_dcdc_power_profile_enum dcdc_power_profile);
+
+/**
+ * @brief Configures and enters in low power mode
+ * @param p_lowpower_cfg: pointer to a structure that contains all low power mode parameters
+ * @return Nothing
+ *
+ * !!! IMPORTANT NOTES :
+ * 1 - CPU Interrupt Enable registers are updated with p_lowpower_cfg->WAKEUPINT. They are NOT restored by the
+ * API.
+ * 2 - The Non Maskable Interrupt (NMI) should be disable before calling this API (otherwise, there is a risk
+ * of Dead Lock).
+ * 3 - The HARD FAULT handler should execute from SRAM. (The Hard fault handler should initiate a full chip
+ * reset)
+ */
+static void POWER_EnterLowPower(LPC_LOWPOWER_T *p_lowpower_cfg);
+
+/**
+ * @brief
+ * @param
+ * @return
+ */
+static void lf_set_dcdc_power_profile_low(void)
+{
+#define DCDC_POWER_PROFILE_LOW_0_ADDRS (0x9FCE0U)
+#define DCDC_POWER_PROFILE_LOW_1_ADDRS (0x9FCE4U)
+
+ uint32_t dcdcTrimValue0 = (*((volatile unsigned int *)(DCDC_POWER_PROFILE_LOW_0_ADDRS)));
+ uint32_t dcdcTrimValue1 = (*((volatile unsigned int *)(DCDC_POWER_PROFILE_LOW_1_ADDRS)));
+
+ if (0UL != (dcdcTrimValue0 & 0x1UL))
+ {
+ PMC->DCDC0 = dcdcTrimValue0 >> 1;
+ PMC->DCDC1 = dcdcTrimValue1;
+ }
+}
+
+/**
+ * @brief Configures and enters in low power mode
+ * @param : p_lowpower_cfg
+ * @return Nothing
+ */
+static void POWER_EnterLowPower(LPC_LOWPOWER_T *p_lowpower_cfg)
+{
+ lowpower_driver_interface_t *s_lowpowerDriver;
+ /* Judging the core and call the corresponding API base address*/
+ if (0UL == Chip_GetVersion())
+ {
+ s_lowpowerDriver = (lowpower_driver_interface_t *)(0x130010d4UL);
+ }
+ else
+ {
+ s_lowpowerDriver = (lowpower_driver_interface_t *)(0x13001204UL);
+ }
+ /* PMC clk set to 12 MHZ */
+ p_lowpower_cfg->CFG |= (uint32_t)LOWPOWER_CFG_SELCLOCK_12MHZ << LOWPOWER_CFG_SELCLOCK_INDEX;
+
+ /* Enable Analog References fast wake-up in case of wake-up from a low power mode (DEEP SLEEP, POWER DOWN and DEEP
+ * POWER DOWN) and Hardware Pin reset */
+ PMC->REFFASTWKUP = (PMC->REFFASTWKUP & (~PMC_REFFASTWKUP_LPWKUP_MASK) & (~PMC_REFFASTWKUP_HWWKUP_MASK)) |
+ PMC_REFFASTWKUP_LPWKUP(1) | PMC_REFFASTWKUP_HWWKUP(1);
+
+ /* SRAM uses Voltage Scaling in all Low Power modes */
+ PMC->SRAMCTRL = (PMC->SRAMCTRL & (~PMC_SRAMCTRL_SMB_MASK)) | PMC_SRAMCTRL_SMB(3);
+
+ /* CPU Retention configuration : preserve the value of FUNCRETENTIONCTRL.RET_LENTH which is a Hardware defined
+ * parameter. */
+ p_lowpower_cfg->CPURETCTRL = (SYSCON->FUNCRETENTIONCTRL & SYSCON_FUNCRETENTIONCTRL_RET_LENTH_MASK) |
+ (p_lowpower_cfg->CPURETCTRL & (~SYSCON_FUNCRETENTIONCTRL_RET_LENTH_MASK));
+
+ /* Switch System Clock to FRO12Mhz (the configuration before calling this function will not be restored back) */
+ CLOCK_AttachClk(kFRO12M_to_MAIN_CLK); /* Switch main clock to FRO12MHz */
+ CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 1U, false); /* Main clock divided by 1 */
+ SYSCON->FMCCR = (SYSCON->FMCCR & 0xFFFF0000UL) | 0x201AUL; /* Adjust FMC waiting time cycles */
+ lf_set_dcdc_power_profile_low(); /* Align DCDC Power profile with the 12 MHz clock (DCDC Power Profile LOW) */
+
+ (*(s_lowpowerDriver->set_lowpower_mode))(p_lowpower_cfg);
+
+ /* Restore the configuration of the MISCCTRL Register : LOWPWR_FLASH_BUF = 0, LDOMEMBLEEDDSLP = 0, LDOMEMHIGHZMODE =
+ * 0 */
+ PMC->MISCCTRL &= (~PMC_MISCCTRL_LOWPWR_FLASH_BUF_MASK) & (~PMC_MISCCTRL_DISABLE_BLEED_MASK) &
+ (~PMC_MISCCTRL_LDOMEMHIGHZMODE_MASK);
+}
+
+/**
+ * @brief Shut off the Flash and execute the _WFI(), then power up the Flash after wake-up event
+ * @param None
+ * @return Nothing
+ */
+void POWER_CycleCpuAndFlash(void)
+{
+ /* Judging the core and call the corresponding API base address*/
+ lowpower_driver_interface_t *s_lowpowerDriver;
+ if (0UL == Chip_GetVersion())
+ {
+ s_lowpowerDriver = (lowpower_driver_interface_t *)(0x130010d4UL);
+ }
+ else
+ {
+ s_lowpowerDriver = (lowpower_driver_interface_t *)(0x13001204UL);
+ }
+ (*(s_lowpowerDriver->power_cycle_cpu_and_flash))();
+};
+
+/**
+ * brief PMC Deep Sleep function call
+ * return nothing
+ */
+void POWER_EnterDeepSleep(uint32_t exclude_from_pd,
+ uint32_t sram_retention_ctrl,
+ uint64_t wakeup_interrupts,
+ uint32_t hardware_wake_ctrl)
+{
+ LPC_LOWPOWER_T lv_low_power_mode_cfg; /* Low Power Mode configuration structure */
+ uint32_t cpu0_nmi_enable;
+ uint32_t cpu0_int_enable_0;
+ uint32_t cpu0_int_enable_1;
+ uint32_t dcdc_voltage;
+ uint32_t pmc_reset_ctrl;
+ /* Clear Low Power Mode configuration variable */
+ (void)memset(&lv_low_power_mode_cfg, 0x0, sizeof(LPC_LOWPOWER_T));
+
+ /* Configure Low Power Mode configuration variable */
+ lv_low_power_mode_cfg.CFG |= (uint32_t)LOWPOWER_CFG_LPMODE_DEEPSLEEP
+ << LOWPOWER_CFG_LPMODE_INDEX; /* DEEPSLEEP mode */
+
+ lf_get_deepsleep_core_supply_cfg(exclude_from_pd, &dcdc_voltage);
+
+ if (((exclude_from_pd & (uint32_t)kPDRUNCFG_PD_USB1_PHY) != 0UL) &&
+ ((exclude_from_pd & (uint32_t)kPDRUNCFG_PD_LDOUSBHS) != 0UL))
+ {
+ /* USB High Speed is required as wake-up source in Deep Sleep mode: make sure LDO FLASH NV stays powered during
+ * deep-sleep */
+ exclude_from_pd = exclude_from_pd | (uint32_t)kPDRUNCFG_PD_LDOFLASHNV;
+ }
+
+ /* DCDC will be always used during Deep Sleep (instead of LDO Deep Sleep); Make sure LDO MEM & Analog references
+ * will stay powered, Shut down ROM */
+ lv_low_power_mode_cfg.PDCTRL0 = (~exclude_from_pd & ~(uint32_t)kPDRUNCFG_PD_DCDC & ~(uint32_t)kPDRUNCFG_PD_LDOMEM &
+ ~(uint32_t)kPDRUNCFG_PD_BIAS) |
+ (uint32_t)kPDRUNCFG_PD_LDODEEPSLEEP | (uint32_t)kPDRUNCFG_PD_ROM;
+
+ /* Voltage control in DeepSleep Low Power Modes */
+ /* The Memories Voltage settings below are for voltage scaling */
+ lv_low_power_mode_cfg.VOLTAGE = lf_set_ldo_ao_ldo_mem_voltage(LOWPOWER_CFG_LPMODE_POWERDOWN, dcdc_voltage);
+
+ /* SRAM retention control during POWERDOWN */
+ lv_low_power_mode_cfg.SRAMRETCTRL = sram_retention_ctrl;
+
+ /* CPU Wake up & Interrupt sources control */
+ lv_low_power_mode_cfg.WAKEUPINT = wakeup_interrupts;
+ lv_low_power_mode_cfg.WAKEUPSRC = wakeup_interrupts;
+
+ /* Interrupts that allow DMA transfers with Flexcomm without waking up the Processor */
+ if (0UL != (hardware_wake_ctrl & (LOWPOWER_HWWAKE_PERIPHERALS | LOWPOWER_HWWAKE_SDMA0 | LOWPOWER_HWWAKE_SDMA1)))
+ {
+ lv_low_power_mode_cfg.HWWAKE = (hardware_wake_ctrl & ~LOWPOWER_HWWAKE_FORCED) | LOWPOWER_HWWAKE_ENABLE_FRO192M;
+ }
+
+ cpu0_nmi_enable = SYSCON->NMISRC & SYSCON_NMISRC_NMIENCPU0_MASK; /* Save the configuration of the NMI Register */
+ SYSCON->NMISRC &= ~SYSCON_NMISRC_NMIENCPU0_MASK; /* Disable NMI of CPU0 */
+
+ /* Save the configuration of the CPU interrupt enable Registers (because they are overwritten inside the low power
+ * API */
+ cpu0_int_enable_0 = NVIC->ISER[0];
+ cpu0_int_enable_1 = NVIC->ISER[1];
+
+ pmc_reset_ctrl = PMC->RESETCTRL;
+ if (0UL != (pmc_reset_ctrl & PMC_RESETCTRL_BODCORERESETENABLE_MASK))
+ {
+ /* BoD CORE reset is activated, so make sure BoD Core won't be shutdown */
+ lv_low_power_mode_cfg.PDCTRL0 &= ~(uint32_t)kPDRUNCFG_PD_BODCORE;
+ }
+ if (0UL != (pmc_reset_ctrl & PMC_RESETCTRL_BODVBATRESETENABLE_MASK))
+ {
+ /* BoD VBAT reset is activated, so make sure BoD VBAT won't be shutdown */
+ lv_low_power_mode_cfg.PDCTRL0 &= ~(uint32_t)kPDRUNCFG_PD_BODVBAT;
+ }
+
+ /* Enter low power mode */
+ POWER_EnterLowPower(&lv_low_power_mode_cfg);
+
+ /* Restore the configuration of the NMI Register */
+ SYSCON->NMISRC |= cpu0_nmi_enable;
+
+ /* Restore the configuration of the CPU interrupt enable Registers (because they have been overwritten inside the
+ * low power API */
+ NVIC->ISER[0] = cpu0_int_enable_0;
+ NVIC->ISER[1] = cpu0_int_enable_1;
+}
+
+/**
+ * brief PMC power Down function call
+ * return nothing
+ */
+void POWER_EnterPowerDown(uint32_t exclude_from_pd,
+ uint32_t sram_retention_ctrl,
+ uint64_t wakeup_interrupts,
+ uint32_t cpu_retention_ctrl)
+{
+ LPC_LOWPOWER_T lv_low_power_mode_cfg; /* Low Power Mode configuration structure */
+ uint32_t cpu0_nmi_enable;
+ uint32_t cpu0_int_enable_0;
+ uint32_t cpu0_int_enable_1;
+ uint64_t wakeup_src_int;
+ uint32_t pmc_reset_ctrl;
+
+ uint32_t analog_ctrl_regs[12]; /* To store Analog Controller Regristers */
+
+ /* Clear Low Power Mode configuration variable */
+ (void)memset(&lv_low_power_mode_cfg, 0x0, sizeof(LPC_LOWPOWER_T));
+
+ /* Configure Low Power Mode configuration variable */
+ lv_low_power_mode_cfg.CFG |= (uint32_t)LOWPOWER_CFG_LPMODE_POWERDOWN
+ << LOWPOWER_CFG_LPMODE_INDEX; /* POWER DOWN mode */
+
+ /* Only FRO32K, XTAL32K, COMP, BIAS and LDO_MEM can be stay powered during POWERDOWN (valid from application point
+ * of view; Hardware allows BODVBAT, LDODEEPSLEEP and FRO1M to stay powered, that's why they are excluded below) */
+ lv_low_power_mode_cfg.PDCTRL0 = (~exclude_from_pd) | (uint32_t)kPDRUNCFG_PD_BODVBAT | (uint32_t)kPDRUNCFG_PD_FRO1M |
+ (uint32_t)kPDRUNCFG_PD_LDODEEPSLEEP;
+
+ /* SRAM retention control during POWERDOWN */
+ lv_low_power_mode_cfg.SRAMRETCTRL = sram_retention_ctrl;
+
+ /* Sanity check: If retention is required for any of SRAM instances, make sure LDO MEM will stay powered */
+ if ((sram_retention_ctrl & 0x7FFFUL) != 0UL)
+ {
+ lv_low_power_mode_cfg.PDCTRL0 &= ~(uint32_t)kPDRUNCFG_PD_LDOMEM;
+ }
+
+ /* Voltage control in Low Power Modes */
+ /* The Memories Voltage settings below are for voltage scaling */
+ lv_low_power_mode_cfg.VOLTAGE = lf_set_ldo_ao_ldo_mem_voltage(LOWPOWER_CFG_LPMODE_POWERDOWN, 0);
+
+ /* CPU0 retention Ctrl.
+ * For the time being, we do not allow customer to relocate the CPU retention area in SRAMX, meaning that the
+ * retention area range is [0x0400_6000 - 0x0400_6600] (beginning of RAMX2) If required by customer,
+ * cpu_retention_ctrl[13:1] will be used for that to modify the default retention area
+ */
+ lv_low_power_mode_cfg.CPURETCTRL =
+ (cpu_retention_ctrl & LOWPOWER_CPURETCTRL_ENA_MASK) |
+ ((((uint32_t)CPU_RETENTION_RAMX_STORAGE_START_ADDR >> 2UL) << LOWPOWER_CPURETCTRL_MEMBASE_INDEX) &
+ LOWPOWER_CPURETCTRL_MEMBASE_MASK);
+ if (0UL != (cpu_retention_ctrl & 0x1UL))
+ {
+ /* CPU retention is required: store Analog Controller Registers */
+ analog_ctrl_regs[0] = ANACTRL->FRO192M_CTRL;
+ analog_ctrl_regs[1] = ANACTRL->ANALOG_CTRL_CFG;
+ analog_ctrl_regs[2] = ANACTRL->ADC_CTRL;
+ analog_ctrl_regs[3] = ANACTRL->XO32M_CTRL;
+ analog_ctrl_regs[4] = ANACTRL->BOD_DCDC_INT_CTRL;
+ analog_ctrl_regs[5] = ANACTRL->RINGO0_CTRL;
+ analog_ctrl_regs[6] = ANACTRL->RINGO1_CTRL;
+ analog_ctrl_regs[7] = ANACTRL->RINGO2_CTRL;
+ analog_ctrl_regs[8] = ANACTRL->LDO_XO32M;
+ analog_ctrl_regs[9] = ANACTRL->AUX_BIAS;
+ analog_ctrl_regs[10] = ANACTRL->USBHS_PHY_CTRL;
+ analog_ctrl_regs[11] = ANACTRL->USBHS_PHY_TRIM;
+ }
+
+ /* CPU Wake up & Interrupt sources control : only WAKEUP_GPIO_GLOBALINT0, WAKEUP_GPIO_GLOBALINT1, WAKEUP_FLEXCOMM3,
+ * WAKEUP_ACMP_CAPT, WAKEUP_RTC_LITE_ALARM_WAKEUP, WAKEUP_OS_EVENT_TIMER, WAKEUP_ALLWAKEUPIOS */
+ wakeup_src_int = (uint64_t)(WAKEUP_GPIO_GLOBALINT0 | WAKEUP_GPIO_GLOBALINT1 | WAKEUP_FLEXCOMM3 | WAKEUP_ACMP_CAPT |
+ WAKEUP_RTC_LITE_ALARM_WAKEUP | WAKEUP_OS_EVENT_TIMER | WAKEUP_ALLWAKEUPIOS);
+ lv_low_power_mode_cfg.WAKEUPINT = wakeup_interrupts & wakeup_src_int;
+ lv_low_power_mode_cfg.WAKEUPSRC = wakeup_interrupts & wakeup_src_int;
+
+ cpu0_nmi_enable = SYSCON->NMISRC & SYSCON_NMISRC_NMIENCPU0_MASK; /* Save the configuration of the NMI Register */
+ SYSCON->NMISRC &= ~SYSCON_NMISRC_NMIENCPU0_MASK; /* Disable NMI of CPU0 */
+
+ /* Save the configuration of the CPU interrupt enable Registers (because they are overwritten inside the low power
+ * API */
+ cpu0_int_enable_0 = NVIC->ISER[0];
+ cpu0_int_enable_1 = NVIC->ISER[1];
+
+ pmc_reset_ctrl = PMC->RESETCTRL;
+ /* Disable BoD VBAT and BoD Core resets */
+ PMC->RESETCTRL =
+ pmc_reset_ctrl & (~(PMC_RESETCTRL_BODVBATRESETENABLE_MASK | PMC_RESETCTRL_BODCORERESETENABLE_MASK));
+
+ /* Enter low power mode */
+ POWER_EnterLowPower(&lv_low_power_mode_cfg);
+
+ /*** We'll reach this point in case of POWERDOWN with CPU retention or if the POWERDOWN has not been taken (for
+ instance because an interrupt is pending). In case of CPU retention, assumption is that the SRAM containing the
+ stack used to call this function shall be preserved during low power ***/
+
+ /* Restore the configuration of the NMI Register */
+ SYSCON->NMISRC |= cpu0_nmi_enable;
+
+ /* Restore PMC RESETCTRL register */
+ PMC->RESETCTRL = pmc_reset_ctrl;
+
+ /* Restore the configuration of the CPU interrupt enable Registers (because they have been overwritten inside the
+ * low power API */
+ NVIC->ISER[0] = cpu0_int_enable_0;
+ NVIC->ISER[1] = cpu0_int_enable_1;
+
+ if (0UL != (cpu_retention_ctrl & 0x1UL))
+ {
+ /* Restore Analog Controller Registers */
+ ANACTRL->FRO192M_CTRL = analog_ctrl_regs[0] | ANACTRL_FRO192M_CTRL_WRTRIM_MASK;
+ ANACTRL->ANALOG_CTRL_CFG = analog_ctrl_regs[1];
+ ANACTRL->ADC_CTRL = analog_ctrl_regs[2];
+ ANACTRL->XO32M_CTRL = analog_ctrl_regs[3];
+ ANACTRL->BOD_DCDC_INT_CTRL = analog_ctrl_regs[4];
+ ANACTRL->RINGO0_CTRL = analog_ctrl_regs[5];
+ ANACTRL->RINGO1_CTRL = analog_ctrl_regs[6];
+ ANACTRL->RINGO2_CTRL = analog_ctrl_regs[7];
+ ANACTRL->LDO_XO32M = analog_ctrl_regs[8];
+ ANACTRL->AUX_BIAS = analog_ctrl_regs[9];
+ ANACTRL->USBHS_PHY_CTRL = analog_ctrl_regs[10];
+ ANACTRL->USBHS_PHY_TRIM = analog_ctrl_regs[11];
+ }
+}
+
+/**
+ * brief PMC Deep Sleep Power Down function call
+ * return nothing
+ */
+void POWER_EnterDeepPowerDown(uint32_t exclude_from_pd,
+ uint32_t sram_retention_ctrl,
+ uint64_t wakeup_interrupts,
+ uint32_t wakeup_io_ctrl)
+{
+ LPC_LOWPOWER_T lv_low_power_mode_cfg; /* Low Power Mode configuration structure */
+ uint32_t cpu0_nmi_enable;
+ uint32_t cpu0_int_enable_0;
+ uint32_t cpu0_int_enable_1;
+ uint32_t pmc_reset_ctrl;
+
+ /* Clear Low Power Mode configuration variable */
+ (void)memset(&lv_low_power_mode_cfg, 0x0, sizeof(LPC_LOWPOWER_T));
+
+ /* Configure Low Power Mode configuration variable */
+ lv_low_power_mode_cfg.CFG |= (uint32_t)LOWPOWER_CFG_LPMODE_DEEPPOWERDOWN
+ << LOWPOWER_CFG_LPMODE_INDEX; /* DEEP POWER DOWN mode */
+
+ /* Only FRO32K, XTAL32K and LDO_MEM can be stay powered during DEEPPOWERDOWN (valid from application point of view;
+ * Hardware allows BODVBAT, BIAS FRO1M and COMP to stay powered, that's why they are excluded below) */
+ lv_low_power_mode_cfg.PDCTRL0 = (~exclude_from_pd) | (uint32_t)kPDRUNCFG_PD_BIAS | (uint32_t)kPDRUNCFG_PD_BODVBAT |
+ (uint32_t)kPDRUNCFG_PD_FRO1M | (uint32_t)kPDRUNCFG_PD_COMP;
+
+ /* SRAM retention control during DEEPPOWERDOWN */
+ sram_retention_ctrl =
+ sram_retention_ctrl &
+ (~(LOWPOWER_SRAMRETCTRL_RETEN_RAMX0 | LOWPOWER_SRAMRETCTRL_RETEN_RAMX1 | LOWPOWER_SRAMRETCTRL_RETEN_RAM00));
+
+ /* SRAM retention control during DEEPPOWERDOWN */
+ lv_low_power_mode_cfg.SRAMRETCTRL = sram_retention_ctrl;
+
+ /* Sanity check: If retention is required for any of SRAM instances, make sure LDO MEM will stay powered */
+ if ((sram_retention_ctrl & 0x7FFFUL) != 0UL)
+ {
+ lv_low_power_mode_cfg.PDCTRL0 &= ~(uint32_t)kPDRUNCFG_PD_LDOMEM;
+ }
+
+ /* Voltage control in Low Power Modes */
+ /* The Memories Voltage settings below are for voltage scaling */
+ lv_low_power_mode_cfg.VOLTAGE = lf_set_ldo_ao_ldo_mem_voltage(LOWPOWER_CFG_LPMODE_DEEPPOWERDOWN, 0);
+
+ lv_low_power_mode_cfg.WAKEUPINT =
+ wakeup_interrupts & (WAKEUP_RTC_LITE_ALARM_WAKEUP |
+ WAKEUP_OS_EVENT_TIMER); /* CPU Wake up sources control : only WAKEUP_RTC_LITE_ALARM_WAKEUP,
+ WAKEUP_OS_EVENT_TIMER */
+ lv_low_power_mode_cfg.WAKEUPSRC =
+ wakeup_interrupts &
+ (WAKEUP_RTC_LITE_ALARM_WAKEUP | WAKEUP_OS_EVENT_TIMER |
+ WAKEUP_ALLWAKEUPIOS); /*!< Hardware Wake up sources control: : only WAKEUP_RTC_LITE_ALARM_WAKEUP,
+ WAKEUP_OS_EVENT_TIMER and WAKEUP_ALLWAKEUPIOS */
+
+ /* Wake up I/O sources */
+ lv_low_power_mode_cfg.WAKEUPIOSRC = lf_wakeup_io_ctrl(wakeup_io_ctrl);
+
+ cpu0_nmi_enable = SYSCON->NMISRC & SYSCON_NMISRC_NMIENCPU0_MASK; /* Save the configuration of the NMI Register */
+ SYSCON->NMISRC &= ~SYSCON_NMISRC_NMIENCPU0_MASK; /* Disable NMI of CPU0 */
+
+ /* Save the configuration of the CPU interrupt enable Registers */
+ cpu0_int_enable_0 = NVIC->ISER[0];
+ cpu0_int_enable_1 = NVIC->ISER[1];
+
+ /* Save the configuration of the PMC RESETCTRL register */
+ pmc_reset_ctrl = PMC->RESETCTRL;
+ /* Disable BoD VBAT and BoD Core resets */
+ PMC->RESETCTRL =
+ pmc_reset_ctrl & (~(PMC_RESETCTRL_BODVBATRESETENABLE_MASK | PMC_RESETCTRL_BODCORERESETENABLE_MASK));
+
+ /* Disable LDO MEM bleed current */
+ // PMC->MISCCTRL |= PMC_MISCCTRL_DISABLE_BLEED_MASK;
+
+ /* Enter low power mode */
+ POWER_EnterLowPower(&lv_low_power_mode_cfg);
+
+ /* Restore the configuration of the NMI Register */
+ SYSCON->NMISRC |= cpu0_nmi_enable;
+
+ /* Restore PMC RESETCTRL register */
+ PMC->RESETCTRL = pmc_reset_ctrl;
+
+ /* Restore the configuration of the CPU interrupt enable Registers */
+ NVIC->ISER[0] = cpu0_int_enable_0;
+ NVIC->ISER[1] = cpu0_int_enable_1;
+}
+
+/**
+ * brief PMC Sleep function call
+ * return nothing
+ */
+void POWER_EnterSleep(void)
+{
+ uint32_t pmsk;
+ pmsk = __get_PRIMASK();
+ __disable_irq();
+ SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
+ __WFI();
+ __set_PRIMASK(pmsk);
+}
+
+/**
+ * @brief Get Digital Core logic supply source to be used during Deep Sleep.
+ * @param [in] exclude_from_pd: COmpoenents NOT to be powered down during Deep Sleep
+ * @param [out] core_supply: 0 = LDO DEEPSLEEP will be used / 1 = DCDC will be used
+ * @param [out] dcdc_voltage: as defined by V_DCDC_* in fsl_power.h
+
+ * @return Nothing
+ */
+static void lf_get_deepsleep_core_supply_cfg(uint32_t exclude_from_pd, uint32_t *dcdc_voltage)
+{
+ *dcdc_voltage = (uint32_t)V_DCDC_0P950; /* Default value */
+
+ if (((exclude_from_pd & (uint32_t)kPDRUNCFG_PD_USB1_PHY) != 0UL) &&
+ ((exclude_from_pd & (uint32_t)kPDRUNCFG_PD_LDOUSBHS) != 0UL))
+ {
+ /* USB High Speed is required as wake-up source in Deep Sleep mode */
+ PMC->MISCCTRL |= PMC_MISCCTRL_LOWPWR_FLASH_BUF_MASK; /* Force flash buffer in low power mode */
+ *dcdc_voltage =
+ (uint32_t)V_DCDC_1P000; /* Set DCDC voltage to be 1.000 V (USB HS IP cannot work below 0.990 V) */
+ }
+}
+
+/**
+ * @brief
+ * @param
+ * @return
+ */
+static uint32_t lf_set_ldo_ao_ldo_mem_voltage(uint32_t p_lp_mode, uint32_t p_dcdc_voltage)
+{
+#define FLASH_NMPA_LDO_AO_ADDRS (0x9FCF4U)
+#define FLASH_NMPA_LDO_AO_DSLP_TRIM_VALID_MASK (0x100U)
+#define FLASH_NMPA_LDO_AO_DSLP_TRIM_MASK (0x3E00U)
+#define FLASH_NMPA_LDO_AO_DSLP_TRIM_SHIFT (9U)
+#define FLASH_NMPA_LDO_AO_PDWN_TRIM_VALID_MASK (0x10000U)
+#define FLASH_NMPA_LDO_AO_PDWN_TRIM_MASK (0x3E0000U)
+#define FLASH_NMPA_LDO_AO_PDWN_TRIM_SHIFT (17U)
+#define FLASH_NMPA_LDO_AO_DPDW_TRIM_VALID_MASK (0x1000000U)
+#define FLASH_NMPA_LDO_AO_DPDW_TRIM_MASK (0x3E000000U)
+#define FLASH_NMPA_LDO_AO_DPDW_TRIM_SHIFT (25U)
+
+ uint32_t ldo_ao_trim, voltage;
+ uint32_t lv_v_ldo_pmu, lv_v_ldo_pmu_boost;
+
+ ldo_ao_trim = (*((volatile unsigned int *)(FLASH_NMPA_LDO_AO_ADDRS)));
+
+ switch (p_lp_mode)
+ {
+ case LOWPOWER_CFG_LPMODE_DEEPSLEEP:
+ {
+ if ((ldo_ao_trim & FLASH_NMPA_LDO_AO_DSLP_TRIM_VALID_MASK) != 0UL)
+ {
+ /* Apply settings coming from Flash */
+ lv_v_ldo_pmu = (ldo_ao_trim & FLASH_NMPA_LDO_AO_DSLP_TRIM_MASK) >> FLASH_NMPA_LDO_AO_DSLP_TRIM_SHIFT;
+ lv_v_ldo_pmu_boost = lv_v_ldo_pmu - 2UL; /* - 50 mV */
+ }
+ else
+ {
+ /* Apply default settings */
+ lv_v_ldo_pmu = (uint32_t)V_AO_0P900;
+ lv_v_ldo_pmu_boost = (uint32_t)V_AO_0P850;
+ }
+ }
+ break;
+
+ case LOWPOWER_CFG_LPMODE_POWERDOWN:
+ {
+ if ((ldo_ao_trim & FLASH_NMPA_LDO_AO_PDWN_TRIM_VALID_MASK) != 0UL)
+ {
+ /* Apply settings coming from Flash */
+ lv_v_ldo_pmu = (ldo_ao_trim & FLASH_NMPA_LDO_AO_PDWN_TRIM_MASK) >> FLASH_NMPA_LDO_AO_PDWN_TRIM_SHIFT;
+ lv_v_ldo_pmu_boost = lv_v_ldo_pmu - 2UL; /* - 50 mV */
+ }
+ else
+ {
+ /* Apply default settings */
+ lv_v_ldo_pmu = (uint32_t)V_AO_0P800;
+ lv_v_ldo_pmu_boost = (uint32_t)V_AO_0P750;
+ }
+ }
+ break;
+
+ case LOWPOWER_CFG_LPMODE_DEEPPOWERDOWN:
+ {
+ if ((ldo_ao_trim & FLASH_NMPA_LDO_AO_DPDW_TRIM_VALID_MASK) != 0UL)
+ {
+ /* Apply settings coming from Flash */
+ lv_v_ldo_pmu = (ldo_ao_trim & FLASH_NMPA_LDO_AO_DPDW_TRIM_MASK) >> FLASH_NMPA_LDO_AO_DPDW_TRIM_SHIFT;
+ lv_v_ldo_pmu_boost = lv_v_ldo_pmu - 2UL; /* - 50 mV */
+ }
+ else
+ {
+ /* Apply default settings */
+ lv_v_ldo_pmu = (uint32_t)V_AO_0P800;
+ lv_v_ldo_pmu_boost = (uint32_t)V_AO_0P750;
+ }
+ }
+ break;
+
+ default:
+ /* Should never reach this point */
+ lv_v_ldo_pmu = (uint32_t)V_AO_1P100;
+ lv_v_ldo_pmu_boost = (uint32_t)V_AO_1P050;
+ break;
+ }
+
+ /* The Memories Voltage settings below are for voltage scaling */
+ voltage =
+ (lv_v_ldo_pmu << LOWPOWER_VOLTAGE_LDO_PMU_INDEX) | /* */
+ (lv_v_ldo_pmu_boost << LOWPOWER_VOLTAGE_LDO_PMU_BOOST_INDEX) | /* */
+ ((uint32_t)V_AO_0P750 << LOWPOWER_VOLTAGE_LDO_MEM_INDEX) | /* Set to 0.75V (voltage Scaling) */
+ ((uint32_t)V_AO_0P700 << LOWPOWER_VOLTAGE_LDO_MEM_BOOST_INDEX) | /* Set to 0.7V (voltage Scaling) */
+ ((uint32_t)V_DEEPSLEEP_0P900
+ << LOWPOWER_VOLTAGE_LDO_DEEP_SLEEP_INDEX) | /* Set to 0.90 V (Not used because LDO_DEEP_SLEEP is disabled)*/
+ (p_dcdc_voltage << LOWPOWER_VOLTAGE_DCDC_INDEX) /* */
+ ;
+
+ return (voltage);
+}
+
+/**
+ * @brief
+ * @param
+ * @return
+ */
+static uint32_t lf_wakeup_io_ctrl(uint32_t p_wakeup_io_ctrl)
+{
+ uint32_t wake_up_type;
+ uint32_t misc_ctrl_reg;
+ uint8_t use_external_pullupdown = 0;
+
+ /* Configure Pull up & Pull down based on the required wake-up edge */
+ CLOCK_EnableClock(kCLOCK_Iocon);
+
+ misc_ctrl_reg = 0UL;
+
+ /* Wake-up I/O 0 */
+ wake_up_type = (p_wakeup_io_ctrl & 0x3UL) >> LOWPOWER_WAKEUPIOSRC_PIO0_INDEX;
+ use_external_pullupdown = (uint8_t)((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO0_USEEXTERNALPULLUPDOWN_MASK) >>
+ LOWPOWER_WAKEUPIO_PIO0_USEEXTERNALPULLUPDOWN_INDEX);
+
+ if (use_external_pullupdown == 0UL)
+ {
+ if ((wake_up_type == 1UL) || (wake_up_type == 3UL))
+ {
+ /* Rising edge and both rising and falling edges */
+ IOCON->PIO[1][1] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(1); /* Pull down */
+ misc_ctrl_reg |= LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_MASK;
+ p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_MASK;
+ }
+ else
+ {
+ if (wake_up_type == 2UL)
+ {
+ /* Falling edge only */
+ IOCON->PIO[1][1] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(2); /* Pull up */
+ misc_ctrl_reg &= ~LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_MASK;
+ p_wakeup_io_ctrl |= LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_MASK;
+ }
+ else
+ {
+ /* Wake-up I/O is disabled : set it as required by the user */
+ if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO0_DISABLEPULLUPDOWN_MASK) != 0UL)
+ {
+ /* Wake-up I/O is configured as Plain Input */
+ p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_MASK;
+ }
+ else
+ {
+ /* Wake-up I/O is configured as pull-up or pull-down */
+ misc_ctrl_reg |= (~p_wakeup_io_ctrl) & LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_MASK;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* MISCCTRL[8]:WAKEUPIOCTRL[8]:00 -no pullup,pulldown, 10 - pulldown, 01 - pullup, 11 - reserved */
+ p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_MASK;
+ misc_ctrl_reg &= ~LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_MASK;
+ }
+
+ /* Wake-up I/O 1 */
+ wake_up_type = (p_wakeup_io_ctrl & 0xCUL) >> LOWPOWER_WAKEUPIOSRC_PIO1_INDEX;
+ use_external_pullupdown = (uint8_t)((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO1_USEEXTERNALPULLUPDOWN_MASK) >>
+ LOWPOWER_WAKEUPIO_PIO1_USEEXTERNALPULLUPDOWN_INDEX);
+
+ if (use_external_pullupdown == 0UL)
+ {
+ if ((wake_up_type == 1UL) || (wake_up_type == 3UL))
+ {
+ /* Rising edge and both rising and falling edges */
+ IOCON->PIO[0][28] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(1); /* Pull down */
+ misc_ctrl_reg |= LOWPOWER_WAKEUPIO_PIO1_PULLUPDOWN_MASK;
+ p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO1_PULLUPDOWN_MASK;
+ }
+ else
+ {
+ if (wake_up_type == 2UL)
+ {
+ /* Falling edge only */
+ IOCON->PIO[0][28] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(2); /* Pull up */
+ misc_ctrl_reg &= ~LOWPOWER_WAKEUPIO_PIO1_PULLUPDOWN_MASK;
+ p_wakeup_io_ctrl |= LOWPOWER_WAKEUPIO_PIO1_PULLUPDOWN_MASK;
+ }
+ else
+ {
+ /* Wake-up I/O is disabled : set it as required by the user */
+ if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO1_DISABLEPULLUPDOWN_MASK) != 0UL)
+ {
+ /* Wake-up I/O is configured as Plain Input */
+ p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO1_PULLUPDOWN_MASK;
+ }
+ else
+ {
+ /* Wake-up I/O is configured as pull-up or pull-down */
+ misc_ctrl_reg |= (~p_wakeup_io_ctrl) & LOWPOWER_WAKEUPIO_PIO1_PULLUPDOWN_MASK;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* MISCCTRL[9]:WAKEUPIOCTRL[9]:00 -no pullup,pulldown, 10 - pulldown, 01 - pullup, 11 - reserved */
+ p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO1_PULLUPDOWN_MASK;
+ misc_ctrl_reg &= ~LOWPOWER_WAKEUPIO_PIO1_PULLUPDOWN_MASK;
+ }
+
+ /* Wake-up I/O 2 */
+ wake_up_type = (p_wakeup_io_ctrl & 0x30UL) >> LOWPOWER_WAKEUPIOSRC_PIO2_INDEX;
+ use_external_pullupdown = (uint8_t)((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO2_USEEXTERNALPULLUPDOWN_MASK) >>
+ LOWPOWER_WAKEUPIO_PIO2_USEEXTERNALPULLUPDOWN_INDEX);
+
+ if (use_external_pullupdown == 0UL)
+ {
+ if ((wake_up_type == 1UL) || (wake_up_type == 3UL))
+ {
+ /* Rising edge and both rising and falling edges */
+ IOCON->PIO[1][18] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(1); /* Pull down */
+ misc_ctrl_reg |= LOWPOWER_WAKEUPIO_PIO2_PULLUPDOWN_MASK;
+ p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO2_PULLUPDOWN_MASK;
+ }
+ else
+ {
+ if (wake_up_type == 2UL)
+ {
+ /* Falling edge only */
+ IOCON->PIO[1][18] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(2); /* Pull up */
+ misc_ctrl_reg &= ~LOWPOWER_WAKEUPIO_PIO2_PULLUPDOWN_MASK;
+ p_wakeup_io_ctrl |= LOWPOWER_WAKEUPIO_PIO2_PULLUPDOWN_MASK;
+ }
+ else
+ {
+ /* Wake-up I/O is disabled : set it as required by the user */
+ if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO2_DISABLEPULLUPDOWN_MASK) != 0UL)
+ {
+ /* Wake-up I/O is configured as Plain Input */
+ p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO2_PULLUPDOWN_MASK;
+ }
+ else
+ {
+ /* Wake-up I/O is configured as pull-up or pull-down */
+ misc_ctrl_reg |= (~p_wakeup_io_ctrl) & LOWPOWER_WAKEUPIO_PIO2_PULLUPDOWN_MASK;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* MISCCTRL[10]:WAKEUPIOCTRL[10]:00 -no pullup,pulldown, 10 - pulldown, 01 - pullup, 11 - reserved */
+ p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO2_PULLUPDOWN_MASK;
+ misc_ctrl_reg &= ~LOWPOWER_WAKEUPIO_PIO2_PULLUPDOWN_MASK;
+ }
+
+ /* Wake-up I/O 3 */
+ wake_up_type = (p_wakeup_io_ctrl & 0xC0UL) >> LOWPOWER_WAKEUPIOSRC_PIO3_INDEX;
+ use_external_pullupdown = (uint8_t)((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO3_USEEXTERNALPULLUPDOWN_MASK) >>
+ LOWPOWER_WAKEUPIO_PIO3_USEEXTERNALPULLUPDOWN_INDEX);
+
+ if (use_external_pullupdown == 0UL)
+ {
+ if ((wake_up_type == 1UL) || (wake_up_type == 3UL))
+ {
+ /* Rising edge and both rising and falling edges */
+ IOCON->PIO[1][30] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(1); /* Pull down */
+ misc_ctrl_reg |= LOWPOWER_WAKEUPIO_PIO3_PULLUPDOWN_MASK;
+ p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO3_PULLUPDOWN_MASK;
+ }
+ else
+ {
+ if (wake_up_type == 2UL)
+ {
+ /* Falling edge only */
+ IOCON->PIO[1][30] = IOCON_PIO_DIGIMODE(1) | IOCON_PIO_MODE(2); /* Pull up */
+ misc_ctrl_reg &= ~LOWPOWER_WAKEUPIO_PIO3_PULLUPDOWN_MASK;
+ p_wakeup_io_ctrl |= LOWPOWER_WAKEUPIO_PIO3_PULLUPDOWN_MASK;
+ }
+ else
+ {
+ /* Wake-up I/O is disabled : set it as required by the user */
+ if ((p_wakeup_io_ctrl & LOWPOWER_WAKEUPIO_PIO3_DISABLEPULLUPDOWN_MASK) != 0UL)
+ {
+ /* Wake-up I/O is configured as Plain Input */
+ p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO3_PULLUPDOWN_MASK;
+ }
+ else
+ {
+ /* Wake-up I/O is configured as pull-up or pull-down */
+ misc_ctrl_reg |= (~p_wakeup_io_ctrl) & LOWPOWER_WAKEUPIO_PIO3_PULLUPDOWN_MASK;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* MISCCTRL[11]:WAKEUPIOCTRL[11]:00 -no pullup,pulldown, 10 - pulldown, 01 - pullup, 11 - reserved */
+ p_wakeup_io_ctrl &= ~LOWPOWER_WAKEUPIO_PIO3_PULLUPDOWN_MASK;
+ misc_ctrl_reg &= ~LOWPOWER_WAKEUPIO_PIO3_PULLUPDOWN_MASK;
+ }
+
+ PMC->MISCCTRL = (PMC->MISCCTRL & 0xFFFFF0FFUL) | misc_ctrl_reg;
+ PMC->WAKEUPIOCTRL = p_wakeup_io_ctrl & 0xFFFUL;
+
+ /*
+ * Defined according to :
+ * - LOWPOWER_WAKEUPIOSRC_<DISABLE,RISING,FALLING,RISING_FALLING> in fsl_power.h
+ * - LOWPOWER_WAKEUPIO_PIO0_PULLUPDOWN_<...> in fsl_power.h
+ */
+ return (p_wakeup_io_ctrl & 0xFFFUL);
+}
+
+/**
+ * @brief
+ * @param
+ * @return
+ */
+static uint8_t CLOCK_u8OscCapConvert(uint8_t u8OscCap, uint8_t u8CapBankDiscontinuity)
+{
+ /* Compensate for discontinuity in the capacitor banks */
+ if (u8OscCap < 64U)
+ {
+ if (u8OscCap >= u8CapBankDiscontinuity)
+ {
+ u8OscCap -= u8CapBankDiscontinuity;
+ }
+ else
+ {
+ u8OscCap = 0U;
+ }
+ }
+ else
+ {
+ if (u8OscCap <= (127U - u8CapBankDiscontinuity))
+ {
+ u8OscCap += u8CapBankDiscontinuity;
+ }
+ else
+ {
+ u8OscCap = 127U;
+ }
+ }
+ return u8OscCap;
+}
+
+/**
+ * @brief Described in fsl_common.h
+ * @param
+ * @return
+ */
+static void lowpower_set_system_voltage(uint32_t system_voltage_mv)
+{
+ /*
+ * Set system voltage
+ */
+ uint32_t lv_ldo_ao = (uint32_t)V_AO_1P100; /* <ldo_ao> */
+ uint32_t lv_ldo_ao_boost = (uint32_t)V_AO_1P150; /* <ldo_ao_boost> */
+ uint32_t lv_dcdc = (uint32_t)V_DCDC_1P100; /* <dcdc> */
+
+ if (system_voltage_mv <= 950UL)
+ {
+ lv_dcdc = (uint32_t)V_DCDC_0P950;
+ lv_ldo_ao = (uint32_t)V_AO_0P960;
+ lv_ldo_ao_boost = (uint32_t)V_AO_1P010;
+ }
+ else if (system_voltage_mv <= 975UL)
+ {
+ lv_dcdc = (uint32_t)V_DCDC_0P975;
+ lv_ldo_ao = (uint32_t)V_AO_0P980;
+ lv_ldo_ao_boost = (uint32_t)V_AO_1P030;
+ }
+ else if (system_voltage_mv <= 1000UL)
+ {
+ lv_dcdc = (uint32_t)V_DCDC_1P000;
+ lv_ldo_ao = (uint32_t)V_AO_1P000;
+ lv_ldo_ao_boost = (uint32_t)V_AO_1P050;
+ }
+ else if (system_voltage_mv <= 1025UL)
+ {
+ lv_dcdc = (uint32_t)V_DCDC_1P025;
+ lv_ldo_ao = (uint32_t)V_AO_1P030;
+ lv_ldo_ao_boost = (uint32_t)V_AO_1P080;
+ }
+ else if (system_voltage_mv <= 1050UL)
+ {
+ lv_dcdc = (uint32_t)V_DCDC_1P050;
+ lv_ldo_ao = (uint32_t)V_AO_1P060;
+ lv_ldo_ao_boost = (uint32_t)V_AO_1P110;
+ }
+ else if (system_voltage_mv <= 1075UL)
+ {
+ lv_dcdc = (uint32_t)V_DCDC_1P075;
+ lv_ldo_ao = (uint32_t)V_AO_1P080;
+ lv_ldo_ao_boost = (uint32_t)V_AO_1P130;
+ }
+ else if (system_voltage_mv <= 1100UL)
+ {
+ lv_dcdc = (uint32_t)V_DCDC_1P100;
+ lv_ldo_ao = (uint32_t)V_AO_1P100;
+ lv_ldo_ao_boost = (uint32_t)V_AO_1P150;
+ }
+ else if (system_voltage_mv <= 1125UL)
+ {
+ lv_dcdc = (uint32_t)V_DCDC_1P125;
+ lv_ldo_ao = (uint32_t)V_AO_1P130;
+ lv_ldo_ao_boost = (uint32_t)V_AO_1P160;
+ }
+ else if (system_voltage_mv <= 1150UL)
+ {
+ lv_dcdc = (uint32_t)V_DCDC_1P150;
+ lv_ldo_ao = (uint32_t)V_AO_1P160;
+ lv_ldo_ao_boost = (uint32_t)V_AO_1P220;
+ }
+ else if (system_voltage_mv <= 1175UL)
+ {
+ lv_dcdc = (uint32_t)V_DCDC_1P175;
+ lv_ldo_ao = (uint32_t)V_AO_1P160;
+ lv_ldo_ao_boost = (uint32_t)V_AO_1P220;
+ }
+ else
+ {
+ lv_dcdc = (uint32_t)V_DCDC_1P200;
+ lv_ldo_ao = (uint32_t)V_AO_1P160;
+ lv_ldo_ao_boost = (uint32_t)V_AO_1P220;
+ }
+
+ /* Set up LDO Always-On voltages */
+ PMC->LDOPMU = (PMC->LDOPMU & (~PMC_LDOPMU_VADJ_MASK) & (~PMC_LDOPMU_VADJ_BOOST_MASK)) | PMC_LDOPMU_VADJ(lv_ldo_ao) |
+ PMC_LDOPMU_VADJ_BOOST(lv_ldo_ao_boost);
+
+ /* Set up DCDC voltage */
+ PMC->DCDC0 = (PMC->DCDC0 & (~PMC_DCDC0_VOUT_MASK)) | PMC_DCDC0_VOUT(lv_dcdc);
+}
+
+/**
+ * @brief Described in fsl_common.h
+ * @param
+ * @return
+ */
+static void lowpower_set_dcdc_power_profile(lowpower_dcdc_power_profile_enum dcdc_power_profile)
+{
+#define FLASH_NMPA_BASE (0x9FC00u)
+#define FLASH_NMPA_DCDC_POWER_PROFILE_LOW_0_ADDRS (FLASH_NMPA_BASE + 0xE0U) // (0x9FCE0U)
+#define FLASH_NMPA_DCDC_POWER_PROFILE_LOW_1_ADDRS (FLASH_NMPA_BASE + 0xE4U) // (0x9FCE4U)
+#define FLASH_NMPA_DCDC_POWER_PROFILE_MEDIUM_0_ADDRS (FLASH_NMPA_BASE + 0xE8U) // (0x9FCE8U)
+#define FLASH_NMPA_DCDC_POWER_PROFILE_MEDIUM_1_ADDRS (FLASH_NMPA_BASE + 0xECU) // (0x9FCECU)
+#define FLASH_NMPA_DCDC_POWER_PROFILE_HIGH_0_ADDRS (FLASH_NMPA_BASE + 0xD8U) // (0x9FCD8U)
+#define FLASH_NMPA_DCDC_POWER_PROFILE_HIGH_1_ADDRS (FLASH_NMPA_BASE + 0xDCU) // (0x9FCDCU)
+
+ const uint32_t PMC_DCDC0_DEFAULT = 0x010C4E68;
+ const uint32_t PMC_DCDC1_DEFAULT = 0x01803A98;
+
+ uint32_t dcdcTrimValue0;
+ uint32_t dcdcTrimValue1;
+
+ switch (dcdc_power_profile)
+ {
+ case DCDC_POWER_PROFILE_LOW:
+ /* Low */
+ dcdcTrimValue0 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_LOW_0_ADDRS)));
+ dcdcTrimValue1 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_LOW_1_ADDRS)));
+
+ if (0UL != (dcdcTrimValue0 & 0x1UL))
+ {
+ dcdcTrimValue0 = dcdcTrimValue0 >> 1;
+
+ PMC->DCDC0 = dcdcTrimValue0;
+ PMC->DCDC1 = dcdcTrimValue1;
+#if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
+ PRINTF(
+ "\nINFO : DCDC Power Profile set to "
+ "LOW"
+ "\n");
+#endif
+ }
+ break;
+
+ case DCDC_POWER_PROFILE_MEDIUM:
+ /* Medium */
+ dcdcTrimValue0 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_MEDIUM_0_ADDRS)));
+ dcdcTrimValue1 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_MEDIUM_1_ADDRS)));
+
+ if (0UL != (dcdcTrimValue0 & 0x1UL))
+ {
+ dcdcTrimValue0 = dcdcTrimValue0 >> 1;
+
+ PMC->DCDC0 = dcdcTrimValue0;
+ PMC->DCDC1 = dcdcTrimValue1;
+#if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
+ PRINTF(
+ "\nINFO : DCDC Power Profile set to "
+ "MEDIUM"
+ "\n");
+#endif
+ }
+ break;
+
+ case DCDC_POWER_PROFILE_HIGH:
+ /* High */
+ dcdcTrimValue0 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_HIGH_0_ADDRS)));
+ dcdcTrimValue1 = (*((volatile unsigned int *)(FLASH_NMPA_DCDC_POWER_PROFILE_HIGH_1_ADDRS)));
+
+ if (0UL != (dcdcTrimValue0 & 0x1UL))
+ {
+ dcdcTrimValue0 = dcdcTrimValue0 >> 1;
+
+ PMC->DCDC0 = dcdcTrimValue0;
+ PMC->DCDC1 = dcdcTrimValue1;
+#if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
+ PRINTF(
+ "\nINFO : DCDC Power Profile set to "
+ "HIGH"
+ "\n");
+#endif
+ }
+ break;
+
+ default:
+ /* Low */
+ PMC->DCDC0 = PMC_DCDC0_DEFAULT;
+ PMC->DCDC1 = PMC_DCDC1_DEFAULT;
+#if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
+ PRINTF(
+ "\nINFO : DCDC Power Profile set to "
+ "LOW"
+ "\n");
+#endif
+ break;
+ }
+}
+
+/**
+ * @brief
+ * @param
+ * @return
+ */
+static lowpower_process_corner_enum lowpower_get_part_process_corner(void)
+{
+#define FLASH_NMPA_PVT_MONITOR_0_RINGO_ADDRS (FLASH_NMPA_BASE + 0x130U)
+#define FLASH_NMPA_PVT_MONITOR_1_RINGO_ADDRS (FLASH_NMPA_BASE + 0x140U)
+
+ lowpower_process_corner_enum part_process_corner;
+ uint32_t pvt_ringo_hz;
+ uint32_t pvt_ringo_0 = (*((volatile unsigned int *)(FLASH_NMPA_PVT_MONITOR_0_RINGO_ADDRS)));
+ uint32_t pvt_ringo_1 = (*((volatile unsigned int *)(FLASH_NMPA_PVT_MONITOR_1_RINGO_ADDRS)));
+
+ /*
+ * Check that the PVT Monitors Trimmings in flash are valid.
+ */
+ if (0UL != (pvt_ringo_0 & 0x1UL))
+ {
+ /* PVT Trimmings in Flash are valid */
+ pvt_ringo_0 = pvt_ringo_0 >> 1;
+ }
+ else
+ {
+ /* PVT Trimmings in Flash are NOT valid (average value assumed) */
+ pvt_ringo_0 = PROCESS_NNN_AVG_HZ;
+ }
+
+ if (0UL != (pvt_ringo_1 & 0x1UL))
+ {
+ /* PVT Trimmings in Flash are valid */
+ pvt_ringo_1 = pvt_ringo_1 >> 1;
+ }
+ else
+ {
+ /* PVT Trimmings in Flash are NOT valid (average value assumed) */
+ pvt_ringo_1 = PROCESS_NNN_AVG_HZ;
+ }
+
+ if (pvt_ringo_1 <= pvt_ringo_0)
+ {
+ pvt_ringo_hz = pvt_ringo_1;
+ }
+ else
+ {
+ pvt_ringo_hz = pvt_ringo_0;
+ }
+
+ /*
+ * Determine the process corner based on the value of the Ring Oscillator frequency
+ */
+ if (pvt_ringo_hz <= PROCESS_NNN_MIN_HZ)
+ {
+ /* SSS Process Corner */
+ part_process_corner = PROCESS_CORNER_SSS;
+#if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
+ PRINTF(
+ "\nINFO : Process Corner : "
+ "SSS"
+ "\n");
+#endif
+ }
+ else
+ {
+ if (pvt_ringo_hz <= PROCESS_NNN_MAX_HZ)
+ {
+ /* NNN Process Corner */
+ part_process_corner = PROCESS_CORNER_NNN;
+#if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
+ PRINTF(
+ "\nINFO : Process Corner : "
+ "NNN"
+ "\n");
+#endif
+ }
+ else
+ {
+ /* FFF Process Corner */
+ part_process_corner = PROCESS_CORNER_FFF;
+#if (defined(NIOBE_DEBUG_LEVEL) && (NIOBE_DEBUG_LEVEL >= 1))
+ PRINTF(
+ "\nINFO : Process Corner : "
+ "FFF"
+ "\n");
+#endif
+ }
+ }
+
+ return (part_process_corner);
+}
+
+/**
+ * @brief Described in fsl_common.h
+ * @param
+ * @return
+ */
+static void lowpower_set_voltage_for_process(lowpower_dcdc_power_profile_enum dcdc_power_profile)
+{
+ /* Get Sample Process Corner */
+ lowpower_process_corner_enum part_process_corner = lowpower_get_part_process_corner();
+
+ switch (part_process_corner)
+ {
+ case PROCESS_CORNER_SSS:
+ /* Slow Corner */
+ {
+ switch (dcdc_power_profile)
+ {
+ case DCDC_POWER_PROFILE_MEDIUM:
+ /* Medium */
+ lowpower_set_system_voltage(VOLTAGE_SSS_MED_MV);
+ break;
+
+ case DCDC_POWER_PROFILE_HIGH:
+ /* High */
+ lowpower_set_system_voltage(VOLTAGE_SSS_HIG_MV);
+ break;
+
+ default:
+ /* DCDC_POWER_PROFILE_LOW */
+ lowpower_set_system_voltage(VOLTAGE_SSS_LOW_MV);
+ break;
+ } // switch(dcdc_power_profile)
+ }
+ break;
+
+ case PROCESS_CORNER_FFF:
+ /* Fast Corner */
+ {
+ switch (dcdc_power_profile)
+ {
+ case DCDC_POWER_PROFILE_MEDIUM:
+ /* Medium */
+ lowpower_set_system_voltage(VOLTAGE_FFF_MED_MV);
+ break;
+
+ case DCDC_POWER_PROFILE_HIGH:
+ /* High */
+ lowpower_set_system_voltage(VOLTAGE_FFF_HIG_MV);
+ break;
+
+ default:
+ /* DCDC_POWER_PROFILE_LOW */
+ lowpower_set_system_voltage(VOLTAGE_FFF_LOW_MV);
+ break;
+ } // switch(dcdc_power_profile)
+ }
+ break;
+
+ default:
+ /* Nominal (NNN) and all others Process Corners : assume Nominal Corner */
+ {
+ switch (dcdc_power_profile)
+ {
+ case DCDC_POWER_PROFILE_MEDIUM:
+ /* Medium */
+ lowpower_set_system_voltage(VOLTAGE_NNN_MED_MV);
+ break;
+
+ case DCDC_POWER_PROFILE_HIGH:
+ /* High */
+ lowpower_set_system_voltage(VOLTAGE_NNN_HIG_MV);
+ break;
+
+ default:
+ /* DCDC_POWER_PROFILE_LOW */
+ lowpower_set_system_voltage(VOLTAGE_NNN_LOW_MV);
+ break;
+ } // switch(dcdc_power_profile)
+ break;
+ }
+ } // switch(part_process_corner)
+}
+
+/**
+ * @brief Described in fsl_common.h
+ * @param
+ * @return
+ */
+void POWER_SetVoltageForFreq(uint32_t system_freq_hz)
+{
+ if (system_freq_hz <= DCDC_POWER_PROFILE_LOW_MAX_FREQ_HZ)
+ {
+ /* [0 Hz - DCDC_POWER_PROFILE_LOW_MAX_FREQ_HZ Hz] */
+ lowpower_set_dcdc_power_profile(DCDC_POWER_PROFILE_LOW); /* DCDC VOUT = 1.05 V by default */
+ lowpower_set_voltage_for_process(DCDC_POWER_PROFILE_LOW);
+ }
+ else
+ {
+ if (system_freq_hz <= DCDC_POWER_PROFILE_MEDIUM_MAX_FREQ_HZ)
+ {
+ /* ]DCDC_POWER_PROFILE_LOW_MAX_FREQ_HZ Hz - DCDC_POWER_PROFILE_MEDIUM_MAX_FREQ_HZ Hz] */
+ lowpower_set_dcdc_power_profile(DCDC_POWER_PROFILE_MEDIUM); /* DCDC VOUT = 1.15 V by default */
+ lowpower_set_voltage_for_process(DCDC_POWER_PROFILE_MEDIUM);
+ }
+ else
+ {
+ /* > DCDC_POWER_PROFILE_MEDIUM_MAX_FREQ_HZ Hz */
+ lowpower_set_dcdc_power_profile(DCDC_POWER_PROFILE_HIGH); /* DCDC VOUT = 1.2 V by default */
+ lowpower_set_voltage_for_process(DCDC_POWER_PROFILE_HIGH);
+ }
+ }
+}
+
+void POWER_Xtal16mhzCapabankTrim(int32_t pi32_16MfXtalIecLoadpF_x100,
+ int32_t pi32_16MfXtalPPcbParCappF_x100,
+ int32_t pi32_16MfXtalNPcbParCappF_x100)
+{
+ uint32_t u32XOTrimValue;
+ uint8_t u8IECXinCapCal6pF, u8IECXinCapCal8pF, u8IECXoutCapCal6pF, u8IECXoutCapCal8pF, u8XOSlave;
+ int32_t iaXin_x4, ibXin, iaXout_x4, ibXout;
+ int32_t iXOCapInpF_x100, iXOCapOutpF_x100;
+ uint8_t u8XOCapInCtrl, u8XOCapOutCtrl;
+ uint32_t u32RegVal;
+ int32_t i32Tmp;
+
+ /* Enable and set LDO, if not already done */
+ POWER_SetXtal16mhzLdo();
+ /* Get Cal values from Flash */
+ u32XOTrimValue = GET_16MXO_TRIM();
+ /* Check validity and apply */
+ if ((0UL != (u32XOTrimValue & 1UL)) && (0UL != ((u32XOTrimValue >> 15UL) & 1UL)))
+ {
+ /* These fields are 7 bits, unsigned */
+ u8IECXinCapCal6pF = (uint8_t)((u32XOTrimValue >> 1UL) & 0x7fUL);
+ u8IECXinCapCal8pF = (uint8_t)((u32XOTrimValue >> 8UL) & 0x7fUL);
+ u8IECXoutCapCal6pF = (uint8_t)((u32XOTrimValue >> 16UL) & 0x7fUL);
+ u8IECXoutCapCal8pF = (uint8_t)((u32XOTrimValue >> 23UL) & 0x7fUL);
+ /* This field is 1 bit */
+ u8XOSlave = (uint8_t)((u32XOTrimValue >> 30UL) & 0x1UL);
+ /* Linear fit coefficients calculation */
+ iaXin_x4 = (int)u8IECXinCapCal8pF - (int)u8IECXinCapCal6pF;
+ ibXin = (int)u8IECXinCapCal6pF - iaXin_x4 * 3;
+ iaXout_x4 = (int)u8IECXoutCapCal8pF - (int)u8IECXoutCapCal6pF;
+ ibXout = (int)u8IECXoutCapCal6pF - iaXout_x4 * 3;
+ }
+ else
+ {
+ iaXin_x4 = 20; // gain in LSB/pF
+ ibXin = -9; // offset in LSB
+ iaXout_x4 = 20; // gain in LSB/pF
+ ibXout = -13; // offset in LSB
+ u8XOSlave = 0;
+ }
+ /* In & out load cap calculation with derating */
+ iXOCapInpF_x100 = 2 * pi32_16MfXtalIecLoadpF_x100 - pi32_16MfXtalNPcbParCappF_x100 +
+ 39 * ((int32_t)XO_SLAVE_EN - (int32_t)u8XOSlave) - 15;
+ iXOCapOutpF_x100 = 2 * pi32_16MfXtalIecLoadpF_x100 - pi32_16MfXtalPPcbParCappF_x100 - 21;
+ /* In & out XO_OSC_CAP_Code_CTRL calculation, with rounding */
+ i32Tmp = ((iXOCapInpF_x100 * iaXin_x4 + ibXin * 400) + 200) / 400;
+ u8XOCapInCtrl = (uint8_t)i32Tmp;
+ i32Tmp = ((iXOCapOutpF_x100 * iaXout_x4 + ibXout * 400) + 200) / 400;
+ u8XOCapOutCtrl = (uint8_t)i32Tmp;
+ /* Read register and clear fields to be written */
+ u32RegVal = ANACTRL->XO32M_CTRL;
+ u32RegVal &= ~(ANACTRL_XO32M_CTRL_OSC_CAP_IN_MASK | ANACTRL_XO32M_CTRL_OSC_CAP_OUT_MASK);
+ /* Configuration of 32 MHz XO output buffers */
+#if (XO_SLAVE_EN == 0)
+ u32RegVal &= ~(ANACTRL_XO32M_CTRL_SLAVE_MASK | ANACTRL_XO32M_CTRL_ACBUF_PASS_ENABLE_MASK);
+#else
+ u32RegVal |= ANACTRL_XO32M_CTRL_SLAVE_MASK | ANACTRL_XO32M_CTRL_ACBUF_PASS_ENABLE_MASK;
+#endif
+ /* XO_OSC_CAP_Code_CTRL to XO_OSC_CAP_Code conversion */
+ u32RegVal |= (uint32_t)CLOCK_u8OscCapConvert(u8XOCapInCtrl, 13) << ANACTRL_XO32M_CTRL_OSC_CAP_IN_SHIFT;
+ u32RegVal |= (uint32_t)CLOCK_u8OscCapConvert(u8XOCapOutCtrl, 13) << ANACTRL_XO32M_CTRL_OSC_CAP_OUT_SHIFT;
+ /* Write back to register */
+ ANACTRL->XO32M_CTRL = u32RegVal;
+}
+
+void POWER_Xtal32khzCapabankTrim(int32_t pi32_32kfXtalIecLoadpF_x100,
+ int32_t pi32_32kfXtalPPcbParCappF_x100,
+ int32_t pi32_32kfXtalNPcbParCappF_x100)
+{
+ uint32_t u32XOTrimValue;
+ uint8_t u8IECXinCapCal6pF, u8IECXinCapCal8pF, u8IECXoutCapCal6pF, u8IECXoutCapCal8pF;
+ int32_t iaXin_x4, ibXin, iaXout_x4, ibXout;
+ int32_t iXOCapInpF_x100, iXOCapOutpF_x100;
+ uint8_t u8XOCapInCtrl, u8XOCapOutCtrl;
+ uint32_t u32RegVal;
+ int32_t i32Tmp;
+ /* Get Cal values from Flash */
+ u32XOTrimValue = GET_32KXO_TRIM();
+ /* check validity and apply */
+ if ((0UL != (u32XOTrimValue & 1UL)) && (0UL != ((u32XOTrimValue >> 15UL) & 1UL)))
+ {
+ /* These fields are 7 bits, unsigned */
+ u8IECXinCapCal6pF = (uint8_t)((u32XOTrimValue >> 1UL) & 0x7fUL);
+ u8IECXinCapCal8pF = (uint8_t)((u32XOTrimValue >> 8UL) & 0x7fUL);
+ u8IECXoutCapCal6pF = (uint8_t)((u32XOTrimValue >> 16UL) & 0x7fUL);
+ u8IECXoutCapCal8pF = (uint8_t)((u32XOTrimValue >> 23UL) & 0x7fUL);
+ /* Linear fit coefficients calculation */
+ iaXin_x4 = (int)u8IECXinCapCal8pF - (int)u8IECXinCapCal6pF;
+ ibXin = (int)u8IECXinCapCal6pF - iaXin_x4 * 3;
+ iaXout_x4 = (int)u8IECXoutCapCal8pF - (int)u8IECXoutCapCal6pF;
+ ibXout = (int)u8IECXoutCapCal6pF - iaXout_x4 * 3;
+ }
+ else
+ {
+ iaXin_x4 = 16; // gain in LSB/pF
+ ibXin = 12; // offset in LSB
+ iaXout_x4 = 16; // gain in LSB/pF
+ ibXout = 11; // offset in LSB
+ }
+
+ /* In & out load cap calculation with derating */
+ iXOCapInpF_x100 = 2 * pi32_32kfXtalIecLoadpF_x100 - pi32_32kfXtalNPcbParCappF_x100 - 130;
+ iXOCapOutpF_x100 = 2 * pi32_32kfXtalIecLoadpF_x100 - pi32_32kfXtalPPcbParCappF_x100 - 41;
+
+ /* In & out XO_OSC_CAP_Code_CTRL calculation, with rounding */
+ i32Tmp = ((iXOCapInpF_x100 * iaXin_x4 + ibXin * 400) + 200) / 400;
+ u8XOCapInCtrl = (uint8_t)i32Tmp;
+ i32Tmp = ((iXOCapOutpF_x100 * iaXout_x4 + ibXout * 400) + 200) / 400;
+ u8XOCapOutCtrl = (uint8_t)i32Tmp;
+
+ /* Read register and clear fields to be written */
+ u32RegVal = PMC->XTAL32K;
+ u32RegVal &= ~(PMC_XTAL32K_CAPBANKIN_MASK | PMC_XTAL32K_CAPBANKOUT_MASK);
+
+ /* XO_OSC_CAP_Code_CTRL to XO_OSC_CAP_Code conversion */
+ u32RegVal |= (uint32_t)CLOCK_u8OscCapConvert(u8XOCapInCtrl, 23) << PMC_XTAL32K_CAPBANKIN_SHIFT;
+ u32RegVal |= (uint32_t)CLOCK_u8OscCapConvert(u8XOCapOutCtrl, 23) << PMC_XTAL32K_CAPBANKOUT_SHIFT;
+
+ /* Write back to register */
+ PMC->XTAL32K = u32RegVal;
+}
+
+void POWER_SetXtal16mhzLdo(void)
+{
+ uint32_t temp;
+ const uint32_t u32Mask =
+ (ANACTRL_LDO_XO32M_VOUT_MASK | ANACTRL_LDO_XO32M_IBIAS_MASK | ANACTRL_LDO_XO32M_STABMODE_MASK);
+
+ const uint32_t u32Value =
+ (ANACTRL_LDO_XO32M_VOUT(0x5) | ANACTRL_LDO_XO32M_IBIAS(0x2) | ANACTRL_LDO_XO32M_STABMODE(0x1));
+
+ /* Enable & set-up XTAL 32 MHz clock LDO */
+ temp = ANACTRL->LDO_XO32M;
+
+ if ((temp & u32Mask) != u32Value)
+ {
+ temp &= ~u32Mask;
+
+ /*
+ * Enable the XTAL32M LDO
+ * Adjust the output voltage level, 0x5 for 1.1V
+ * Adjust the biasing current, 0x2 value
+ * Stability configuration, 0x1 default mode
+ */
+ temp |= u32Value;
+
+ ANACTRL->LDO_XO32M = temp;
+
+ /* Delay for LDO to be up */
+ // CLOCK_uDelay(20);
+ }
+
+ /* Enable LDO XO32M */
+ PMC->PDRUNCFGCLR0 = PMC_PDRUNCFG0_PDEN_LDOXO32M_MASK;
+}
+
+/**
+ * @brief Return some key information related to the device reset causes / wake-up sources, for all power modes.
+ * @param p_reset_cause : the device reset cause, according to the definition of power_device_reset_cause_t type.
+ * @param p_boot_mode : the device boot mode, according to the definition of power_device_boot_mode_t type.
+ * @param p_wakeupio_cause: the wake-up pin sources, according to the definition of register PMC->WAKEIOCAUSE[3:0].
+
+ * @return Nothing
+ *
+ * !!! IMPORTANT ERRATA - IMPORTANT ERRATA - IMPORTANT ERRATA !!!
+ * !!! valid ONLY for LPC55S69 (not for LPC55S16 and LPC55S06) !!!
+ * !!! when FALLING EDGE DETECTION is enabled on wake-up pins: !!!
+ * - 1. p_wakeupio_cause is NOT ACCURATE
+ * - 2. Spurious kRESET_CAUSE_DPDRESET_WAKEUPIO* event is reported when
+ * several wake-up sources are enabled during DEEP-POWER-DOWN
+ * (like enabling wake-up on RTC and Falling edge wake-up pins)
+ *
+ */
+void POWER_GetWakeUpCause(power_device_reset_cause_t *p_reset_cause,
+ power_device_boot_mode_t *p_boot_mode,
+ uint32_t *p_wakeupio_cause)
+{
+ uint32_t reset_cause_reg;
+ uint32_t boot_mode_reg;
+
+#if (defined(LPC55S06_SERIES) || defined(LPC55S04_SERIES) || defined(LPC5506_SERIES) || defined(LPC5504_SERIES) || \
+ defined(LPC5502_SERIES) || defined(LPC55S16_SERIES) || defined(LPC55S14_SERIES) || defined(LPC5516_SERIES) || \
+ defined(LPC5514_SERIES) || defined(LPC5512_SERIES))
+ reset_cause_reg = (PMC->AOREG1) & 0x3FF0UL;
+#else /* LPC55S69/28 */
+ reset_cause_reg = (PMC->AOREG1) & 0x1FF0UL;
+#endif
+
+ /*
+ * Prioritize interrupts source with respect to their critical level
+ */
+#if (defined(LPC55S06_SERIES) || defined(LPC55S04_SERIES) || defined(LPC5506_SERIES) || defined(LPC5504_SERIES) || \
+ defined(LPC5502_SERIES) || defined(LPC55S16_SERIES) || defined(LPC55S14_SERIES) || defined(LPC5516_SERIES) || \
+ defined(LPC5514_SERIES) || defined(LPC5512_SERIES))
+ if (0UL != (reset_cause_reg & PMC_AOREG1_CDOGRESET_MASK))
+ { /* Code Watchdog Reset */
+ *p_reset_cause = kRESET_CAUSE_CDOGRESET;
+ *p_boot_mode = kBOOT_MODE_POWER_UP;
+ *p_wakeupio_cause = 0; /* Device has not been waked-up by any wake-up pins */
+ }
+ else
+#endif
+ {
+ if (0UL != (reset_cause_reg & PMC_AOREG1_WDTRESET_MASK))
+ { /* Watchdog Timer Reset */
+ *p_reset_cause = kRESET_CAUSE_WDTRESET;
+ *p_boot_mode = kBOOT_MODE_POWER_UP;
+ *p_wakeupio_cause = 0; /* Device has not been waked-up by any wake-up pins */
+ }
+ else
+ {
+ if (0UL != (reset_cause_reg & PMC_AOREG1_SYSTEMRESET_MASK))
+ { /* ARM System Reset */
+ *p_reset_cause = kRESET_CAUSE_ARMSYSTEMRESET;
+ *p_boot_mode = kBOOT_MODE_POWER_UP;
+ *p_wakeupio_cause = 0; /* Device has not been waked-up by any wake-up pins */
+ }
+ else
+ {
+ boot_mode_reg = (PMC->STATUS & PMC_STATUS_BOOTMODE_MASK) >> PMC_STATUS_BOOTMODE_SHIFT;
+
+ if (boot_mode_reg == 0UL) /* POWER-UP: Power On Reset, Pin reset, Brown Out Detectors, Software Reset */
+ {
+ *p_boot_mode = kBOOT_MODE_POWER_UP; /* All non wake-up from a Low Power mode */
+ *p_wakeupio_cause = 0; /* Device has not been waked-up by any wake-up pins */
+
+ /*
+ * Prioritise Reset causes, starting from the strongest (Power On Reset)
+ */
+ if (0UL != (reset_cause_reg & PMC_AOREG1_POR_MASK))
+ { /* Power On Reset */
+ *p_reset_cause = kRESET_CAUSE_POR;
+ }
+ else
+ {
+ if (0UL != (reset_cause_reg & PMC_AOREG1_BODRESET_MASK))
+ { /* Brown-out Detector reset (either BODVBAT or BODCORE) */
+ *p_reset_cause = kRESET_CAUSE_BODRESET;
+ }
+ else
+ {
+ if (0UL != (reset_cause_reg & PMC_AOREG1_PADRESET_MASK))
+ { /* Hardware Pin Reset */
+ *p_reset_cause = kRESET_CAUSE_PADRESET;
+ }
+ else
+ {
+ if (0UL != (reset_cause_reg & PMC_AOREG1_SWRRESET_MASK))
+ { /* Software triggered Reset */
+ *p_reset_cause = kRESET_CAUSE_SWRRESET;
+ }
+ else
+ { /* Unknown Reset Cause */
+ *p_reset_cause = kRESET_CAUSE_NOT_DETERMINISTIC;
+ }
+ }
+ }
+ }
+
+#if (defined(LPC55S06_SERIES) || defined(LPC55S04_SERIES) || defined(LPC5506_SERIES) || defined(LPC5504_SERIES) || \
+ defined(LPC5502_SERIES) || defined(LPC55S16_SERIES) || defined(LPC55S14_SERIES) || defined(LPC5516_SERIES) || \
+ defined(LPC5514_SERIES) || defined(LPC5512_SERIES))
+ /* Transfer the control of the 4 wake-up pins to IOCON (instead of the Power Management Controller
+ */
+ PMC->WAKEUPIOCTRL = PMC->WAKEUPIOCTRL & (~PMC_WAKEUPIOCTRL_WAKEUPIO_ENABLE_CTRL_MASK);
+#endif
+ }
+ else /* DEEP-SLEEP, POWER-DOWN and DEEP-POWER-DOWN */
+ {
+ /*
+ * 1- First, save wakeup_io_cause register ...
+ */
+ *p_wakeupio_cause = PMC->WAKEIOCAUSE;
+
+ if (boot_mode_reg == 3UL) /* DEEP-POWER-DOWN */
+ {
+ *p_boot_mode = kBOOT_MODE_LP_DEEP_POWER_DOWN;
+
+ switch (((reset_cause_reg >> PMC_AOREG1_DPDRESET_WAKEUPIO_SHIFT) & 0x7UL))
+ {
+ case 1:
+ *p_reset_cause = kRESET_CAUSE_DPDRESET_WAKEUPIO;
+ break;
+ case 2:
+ *p_reset_cause = kRESET_CAUSE_DPDRESET_RTC;
+ break;
+ case 3:
+ *p_reset_cause = kRESET_CAUSE_DPDRESET_WAKEUPIO_RTC;
+ break;
+ case 4:
+ *p_reset_cause = kRESET_CAUSE_DPDRESET_OSTIMER;
+ break;
+ case 5:
+ *p_reset_cause = kRESET_CAUSE_DPDRESET_WAKEUPIO_OSTIMER;
+ break;
+ case 6:
+ *p_reset_cause = kRESET_CAUSE_DPDRESET_RTC_OSTIMER;
+ break;
+ case 7:
+ *p_reset_cause = kRESET_CAUSE_DPDRESET_WAKEUPIO_RTC_OSTIMER;
+ break;
+ default:
+ /* Unknown Reset Cause */
+ *p_reset_cause = kRESET_CAUSE_NOT_DETERMINISTIC;
+ break;
+ }
+
+#if (defined(LPC55S06_SERIES) || defined(LPC55S04_SERIES) || defined(LPC5506_SERIES) || defined(LPC5504_SERIES) || \
+ defined(LPC5502_SERIES) || defined(LPC55S16_SERIES) || defined(LPC55S14_SERIES) || defined(LPC5516_SERIES) || \
+ defined(LPC5514_SERIES) || defined(LPC5512_SERIES))
+ /*
+ * 2- Next, transfer the control of the 4 wake-up pins
+ * to IOCON (instead of the Power Management Controller)
+ */
+ PMC->WAKEUPIOCTRL = PMC->WAKEUPIOCTRL & (~PMC_WAKEUPIOCTRL_WAKEUPIO_ENABLE_CTRL_MASK);
+#endif
+ }
+ else /* DEEP-SLEEP and POWER-DOWN */
+ {
+ *p_reset_cause = kRESET_CAUSE_NOT_RELEVANT;
+
+ /*
+ * The control of the 4 wake-up pins is already in IOCON,
+ * so there is nothing special to do.
+ */
+
+ if (boot_mode_reg == 1UL) /* DEEP-SLEEP */
+ {
+ *p_boot_mode = kBOOT_MODE_LP_DEEP_SLEEP;
+ }
+ else /* POWER-DOWN */
+ {
+ *p_boot_mode = kBOOT_MODE_LP_POWER_DOWN;
+
+ } /* if ( boot_mode_reg == 1 ) DEEP-SLEEP */
+
+ } /* if ( boot_mode == 3 ) DEEP-POWER-DOWN */
+
+ } /* if ( boot_mode == 0 ) POWER-UP */
+
+ } /* if ( reset_cause_reg & PMC_AOREG1_CDOGRESET_MASK ) */
+
+ } /* if ( reset_cause_reg & PMC_AOREG1_WDTRESET_MASK ) */
+
+ } /* if ( reset_cause_reg & PMC_AOREG1_SYSTEMRESET_MASK ) */
+}