From ae079c1fc5d990ba55714d4b3a51b19f96edaec4 Mon Sep 17 00:00:00 2001
From: WXK <287788329@qq.com>
Date: 星期四, 24 四月 2025 16:01:43 +0800
Subject: [PATCH] 改为中断来低电平触发发送当前扫描数据,3s内扫描不到的会退出,串口来55 AA 75 70 64 61 74 65,进入升级模式

---
 01_SDK/modules/hal/panchip/panplat/pan1070/bsp/device/Source/pan_lp.c |  614 ++++++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 462 insertions(+), 152 deletions(-)

diff --git a/01_SDK/modules/hal/panchip/panplat/pan1070/bsp/device/Source/pan_lp.c b/01_SDK/modules/hal/panchip/panplat/pan1070/bsp/device/Source/pan_lp.c
index 688ead5..a1d92e1 100644
--- a/01_SDK/modules/hal/panchip/panplat/pan1070/bsp/device/Source/pan_lp.c
+++ b/01_SDK/modules/hal/panchip/panplat/pan1070/bsp/device/Source/pan_lp.c
@@ -1,11 +1,15 @@
 #include "PanSeries.h"
 #include "pan_lp.h"
 #include "pan_clk.h"
+#include "comm_prf.h"
+
+extern const uint32_t PanFlashLineMode;
+extern const bool PanFlashEnhanceEnable;
 
 /**
-* @brief  This function enable gpio p56 wake up 
+* @brief  This function enable gpio p56 wake up
 * @param[in]  ana: where ana is analog module
-* @param[in]  WkEdge: wake up edge select,0-->low,1-->high 
+* @param[in]  WkEdge: wake up edge select,0-->low,1-->high
 * @return   none
 */
 void LP_SetExternalWake(ANA_T *ana,uint8_t WkEdge)
@@ -21,7 +25,7 @@
 * @brief  This function set sleep time
 * @param[in]  ana: where ana is analog module
 * @param[in]  u32ClkCnt: where u32ClkCnt is 32k clock cnt num
-* @param[in]  idx: where idx is 0,1, 2
+* @param[in]  idx: channel index of sleeptimer, can be 0, 1, 2
 * @return   none
 */
 void LP_SetSleepTime(ANA_T *ana,uint32_t u32ClkCnt,uint8_t idx)
@@ -29,6 +33,15 @@
 	((__IO uint32_t *)(&(ana)->LP_SPACING_TIME0))[idx] = u32ClkCnt;
 }
 
+/**
+* @brief  This function get current 32K timer counter
+* @param[in]  ana: where ana is analog module
+* @return  Current 32K timer counter
+*/
+uint32_t LP_GetSlptmrCurrCount(ANA_T *ana)
+{
+    return ana->LP_SLPTMR;
+}
 
 /**
 * @brief  This function set delay time used for standby_m0 mode for wait LPLDOH ready
@@ -73,7 +86,6 @@
 *
 * @return   none
 */
-
 void LP_SetSleepMode(ANA_T *ana,uint8_t mode)
 {
 	uint32_t tmp_reg;
@@ -84,174 +96,472 @@
 	ana->LP_FL_CTRL_3V = tmp_reg;
 }
 
+__STATIC_FORCEINLINE void PHY_FifoFlush(void)
+{
+	PRI_RF_WRITE_REG_VALUE(PRI_RF, PHY1, PHY_DRV_CFG_BUF_FLUSH, 0x1);
+	PRI_RF_WRITE_REG_VALUE(PRI_RF, PHY1, PHY_DRV_CFG_BUF_FLUSH, 0x0);
 
- /**
+	PRI_RF_WRITE_REG_VALUE(PRI_RF, PHY1, PHY_DRV_RSP_BUF_FLUSH, 0x1);
+	PRI_RF_WRITE_REG_VALUE(PRI_RF, PHY1, PHY_DRV_RSP_BUF_FLUSH, 0x0);
+}
+
+uint32_t PHY_WriteCfgFifoBatchCopy(const uint32_t *command, const uint32_t cmd_len, uint32_t *ptr_rsp_value)
+{
+	volatile uint32_t reg = 0;
+	uint32_t time_out = 0, cmd_idx = 0;
+	uint32_t rsp_len = 0;
+
+	if (0 == cmd_len)
+	{
+		goto fun_ext;
+	}
+
+	/* Flush the PHY Driver FIFO */
+	PHY_FifoFlush();
+
+	/* Trigger the FIFO */
+	PRI_RF_WRITE_REG_VALUE(PRI_RF, PHY1, PHY_DRV_CFG_TRG, 0x1);
+
+	do
+	{
+		do
+		{
+			/* check that the FIFO is empty */
+			reg = PRI_RF_READ_REG_VALUE(PRI_RF, PHY1, PHY_DRV_CFG_BUF_FULL);
+		} while (reg == 1);
+
+		/* Write the commands to FIFO */
+		PRI_RF_WRITE_REG_VALUE(PRI_RF, PHY3, PHY_DRV_CFG_BUF_DIN, command[cmd_idx++]);
+
+		/* check that the Response buff is full */
+		reg = PRI_RF_READ_REG_VALUE(PRI_RF, PHY1, PHY_DRV_RSP_BUF_EMPTY);
+		if ((ptr_rsp_value != NULL) && (reg == 0))
+		{
+			/* read the response from FIFO */
+			ptr_rsp_value[rsp_len++] = PRI_RF_READ_REG_VALUE(PRI_RF, PHY4, PHY_DRV_RSP_BUF_DOUT);
+		}
+	} while (cmd_idx < cmd_len);
+
+	do
+	{
+			time_out++;
+			reg = PRI_RF_READ_REG_VALUE(PRI_RF, INTR1, IC_PHY_DRV_CFG_DONE);
+	} while (reg == 0);
+
+	/* check that the Response buff is full */
+	reg = PRI_RF_READ_REG_VALUE(PRI_RF, PHY1, PHY_DRV_RSP_BUF_EMPTY);
+
+	while ((ptr_rsp_value != NULL) && (reg == 0))
+	{
+		/* read the response from FIFO */
+		ptr_rsp_value[rsp_len++] = PRI_RF_READ_REG_VALUE(PRI_RF, PHY4, PHY_DRV_RSP_BUF_DOUT);
+		/* check that the Response buff is full */
+		reg = PRI_RF_READ_REG_VALUE(PRI_RF, PHY1,  PHY_DRV_RSP_BUF_EMPTY);
+	}
+
+	/* Clear the interrupt */
+	PRI_RF_WRITE_REG_VALUE(PRI_RF, INTCLR, IC_PHY_DRV_CFG_DONE_CLR, 1);
+	PRI_RF_WRITE_REG_VALUE(PRI_RF, INTCLR, IC_PHY_DRV_CFG_DONE_CLR, 0);
+	PRI_RF_WRITE_REG_VALUE(PRI_RF, PHY1, PHY_DRV_CFG_TRG, 0x0);
+
+fun_ext:
+
+	return rsp_len;
+}
+
+uint32_t PHY_SingleRegRead(uint32_t reg_addr)
+{
+    uint32_t reg;
+    uint32_t val;
+    uint32_t cmd[] = {
+        0x00000013 | (reg_addr << 8),
+    };
+
+    // Backup AHB Clock Register and enable LL Clock
+    reg = CLK->AHB_CLK_CTRL;
+    CLK->AHB_CLK_CTRL |= CLK_AHBCLK_BLE32M_EN_Msk | CLK_AHBCLK_BLE32K_EN_Msk;
+
+    // Enable LL module for later phy operation
+    LLHWC_WRITE_MASK32_REG(REG_FILE_OFST, CTRL_MEM_SOFT_RST_N, CTRL_MEM_SOFT_RST_N_MSK, CTRL_MEM_SOFT_RST_N_SHFT, 0);
+    LLHWC_WRITE_MASK32_REG(REG_FILE_OFST, CTRL_MEM_SOFT_RST_N, CTRL_MEM_SOFT_RST_N_MSK, CTRL_MEM_SOFT_RST_N_SHFT, 1);
+    LLHWC_WRITE_MASK32_REG(REG_FILE_OFST, CTRL_PWR_MOD, CTRL_PWR_MOD_MSK, CTRL_PWR_MOD_SHFT, 1);
+
+    // Start to read phy register
+    PHY_WriteCfgFifoBatchCopy(cmd, sizeof(cmd) >> 2, &val);
+
+    // Restore AHB Clock Register
+    CLK->AHB_CLK_CTRL = reg;
+
+    return val;
+}
+
+void PHY_SingleRegWrite(uint32_t reg_addr, uint32_t reg_val)
+{
+    uint32_t reg;
+    uint32_t cmd[] = {
+        0x00000012 | (reg_addr << 8) | (reg_val << 16),
+    };
+
+    // Backup AHB Clock Register and enable LL Clock
+    reg = CLK->AHB_CLK_CTRL;
+    CLK->AHB_CLK_CTRL |= CLK_AHBCLK_BLE32M_EN_Msk | CLK_AHBCLK_BLE32K_EN_Msk;
+
+    // Enable LL module for later phy operation
+    LLHWC_WRITE_MASK32_REG(REG_FILE_OFST, CTRL_MEM_SOFT_RST_N, CTRL_MEM_SOFT_RST_N_MSK, CTRL_MEM_SOFT_RST_N_SHFT, 0);
+    LLHWC_WRITE_MASK32_REG(REG_FILE_OFST, CTRL_MEM_SOFT_RST_N, CTRL_MEM_SOFT_RST_N_MSK, CTRL_MEM_SOFT_RST_N_SHFT, 1);
+    LLHWC_WRITE_MASK32_REG(REG_FILE_OFST, CTRL_PWR_MOD, CTRL_PWR_MOD_MSK, CTRL_PWR_MOD_SHFT, 1);
+
+    // Start to write phy register
+    PHY_WriteCfgFifoBatchCopy(cmd, sizeof(cmd) >> 2, NULL);
+
+    // Restore AHB Clock Register
+    CLK->AHB_CLK_CTRL = reg;
+}
+
+
+/**
 * @brief  This function set sleep mode config
-* @param[in]  ana: where ana is analog module
-* @param[in]  u8ExtWkDis: where u8ExtWkDis determine whether to wake up by GPIO
-*																									0:gpio can wake up
-*																									1:gpio can notwake up
+* @param[in]  ana: Select analog module
+* @param[in]  enterCyclically: Enable ARM Sleep-On-Exit Feature or not
 * @return   none
 */
-void LP_SetSleepModeConfig(ANA_T *ana,uint32_t wkMode,bool enterCyclically)
-{	
-	LP_EnableInt(ana,ENABLE);
-	LP_SetSleepMode(ana, LP_MODE_SEL_SLEEP_MODE);
-	if((LP_WKUP_MODE_SEL_EXT_GPIO != wkMode)&&(LP_WKUP_MODE_SEL_GPIO != wkMode)){
-		ana->LP_FL_CTRL_3V |= ANAC_FL_RC32K_EN_Msk_3v;
-		ana->LP_FL_CTRL_3V |= ANAC_FL_SLEEP_CNT_EN_Msk;
-	} else {
-        ana->LP_FL_CTRL_3V &= ~ANAC_FL_SLEEP_CNT_EN_Msk;
-		ana->LP_FL_CTRL_3V &= ~ANAC_FL_RC32K_EN_Msk_3v;
-    }
-#ifdef SYNC_3V_REG_MANUALLY
-    CLK_Wait3vSyncReady();
-#endif
-	SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
-	if(enterCyclically)
-		SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk;
-	else
-		SCB->SCR &= ~SCB_SCR_SLEEPONEXIT_Msk;
-	__WFI();
-#ifdef SYNC_3V_REG_MANUALLY
-    CLK_Wait3vSyncReady();
-#endif
-}
-
-void LP_SetDeepSleepConfig(ANA_T *ana,
-							uint32_t wkMode,
-							bool enterCyclically,
-							uint8_t PowerCtrl,
-							uint8_t dp_mode)
+void LP_EnterSleepMode(ANA_T *ana, bool enterCyclically)
 {
-	LP_EnableInt(ana,ENABLE);
-	if (dp_mode == LP_DEEPSLEEP_MODE1){
-		ana->LP_LP_LDO_3V |= ANAC_LPLDO_H_EN_Msk_3v;
-		ana->LP_LP_LDO_3V |= ANAC_LPLDO_L_EN_Msk;
-		ana->LP_FL_CTRL_3V |= ANAC_LDO_POWER_CTL_Msk | ANAC_FL_LDO_ISOLATE_EN_Msk;
-		ana->LP_FL_CTRL_3V &= ~ANAC_LDOL_POWER_CTL_Msk;
-	} else if (dp_mode == LP_DEEPSLEEP_MODE2){
-		ana->LP_LP_LDO_3V |= ANAC_LPLDO_H_EN_Msk_3v;
-		ana->LP_LP_LDO_3V &= ~ANAC_LPLDO_L_EN_Msk;
-		ana->LP_FL_CTRL_3V |= ANAC_LDOL_POWER_CTL_Msk | ANAC_LDO_POWER_CTL_Msk;
-		ana->LP_FL_CTRL_3V &= ~ANAC_FL_LDO_ISOLATE_EN_Msk;
-	} else if (dp_mode == LP_DEEPSLEEP_MODE3){
-		ana->LP_LP_LDO_3V &= ~ANAC_LPLDO_H_EN_Msk_3v;
-		ana->LP_LP_LDO_3V |= ANAC_LPLDO_L_EN_Msk;
-		ana->LP_FL_CTRL_3V |= ANAC_LDOL_POWER_CTL_Msk | ANAC_LDO_POWER_CTL_Msk;
-		ana->LP_FL_CTRL_3V &= ~ANAC_FL_LDO_ISOLATE_EN_Msk;
-	}
+    LP_EnableInt(ana, ENABLE);
 
-    // Enable flash power in lp mode (Also need to enable flash AutoDp to save power)
-//	ana->LP_FL_CTRL_3V |= ANAC_FL_FLASH_BP_EN_Msk;
-
-	LP_SetSleepMode(ana, LP_MODE_SEL_DEEPSLEEP_MODE);
-	if((LP_WKUP_MODE_SEL_EXT_GPIO != wkMode)&&(LP_WKUP_MODE_SEL_GPIO != wkMode)){
-		if (CLK->CLK_TOP_CTRL_3V & CLK_TOPCTL_32K_CLK_SEL_Msk_3v) {
-			ana->LP_FL_CTRL_3V |= ANAC_FL_XTAL32K_EN_Msk_3v;
-			ana->LP_FL_CTRL_3V &= ~ANAC_FL_RC32K_EN_Msk_3v;
-		} else {
-			ana->LP_FL_CTRL_3V &= ~ANAC_FL_XTAL32K_EN_Msk_3v;
-			ana->LP_FL_CTRL_3V |= ANAC_FL_RC32K_EN_Msk_3v;
-		}
-		ana->LP_INT_CTRL |= ANAC_INT_SLEEP_TMR_WK_EN_Msk;
-	} else {
-		ana->LP_FL_CTRL_3V &= ~ANAC_FL_RC32K_EN_Msk_3v;
+    /* Enable proper 32k clock in low power mode */
+    if (CLK->CLK_TOP_CTRL_3V & CLK_TOPCTL_32K_CLK_SEL_Msk_3v) {
+        ana->LP_FL_CTRL_3V |= ANAC_FL_XTAL32K_EN_Msk_3v;
+        ana->LP_FL_CTRL_3V &= ~ANAC_FL_RC32K_EN_Msk_3v;
+    } else {
+        ana->LP_FL_CTRL_3V &= ~ANAC_FL_XTAL32K_EN_Msk_3v;
+        ana->LP_FL_CTRL_3V |= ANAC_FL_RC32K_EN_Msk_3v;
     }
 
-	ana->LP_FL_CTRL_3V = ((PowerCtrl & 0x1f) << 24u) | (ana->LP_FL_CTRL_3V & 0xe0FFFFFF);
+    LP_SetSleepMode(ana, LP_MODE_SEL_SLEEP_MODE);
+    SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
 
-	// Wait 3v sync ready manually
-	ANA->LP_REG_SYNC |= ANAC_LP_REG_SYNC_3V_Msk | ANAC_LP_REG_SYNC_3V_TRG_Msk;
-	while(ANA->LP_REG_SYNC & (ANAC_LP_REG_SYNC_3V_TRG_Msk)) {}
+    if (enterCyclically) {
+        SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk;
+    } else {
+        SCB->SCR &= ~SCB_SCR_SLEEPONEXIT_Msk;
+    }
 
-	SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
-	if(enterCyclically)
-		SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk;
-	else
-		SCB->SCR &= ~SCB_SCR_SLEEPONEXIT_Msk;
-	ANA->LP_INT_CTRL |= ANAC_INT_SLEEP_TMR_INT_EN_Msk;
-	__WFI();
+    __WFI();
 }
 
-
-void LP_SetStandbyMode0Config(void)
+void LP_EnterDeepSleepMode(ANA_T *ana, bool enterCyclically, uint8_t powerCtrl, uint8_t dpMode)
 {
-	LP_SetSleepMode(ANA, LP_MODE_SEL_STANDBY_M0_MODE);
-	LP_EnableInt(ANA,ENABLE);
-	ANA->LP_FL_CTRL_3V &= ~ANAC_FL_XTAL32K_EN_Msk_3v;
-	ANA->LP_FL_CTRL_3V &= ~ANAC_FL_RC32K_EN_Msk_3v;
-	#ifdef SYNC_3V_REG_MANUALLY
-	CLK_Wait3vSyncReady();
-	#endif
+    uint32_t nvicInt;
 
-	SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
-	__WFI();
+    ana->LP_INT_CTRL |= ANAC_INT_LP_INT_EN_Msk | ANAC_INT_SLEEP_TMR_INT_EN_Msk | ANAC_INT_SLEEP_TMR_WK_EN_Msk;
+
+    if (dpMode == LP_DEEPSLEEP_MODE1) {
+        ana->LP_LP_LDO_3V |= ANAC_LPLDO_H_EN_Msk_3v;
+        ana->LP_LP_LDO_3V |= ANAC_LPLDO_L_EN_Msk;
+        ana->LP_FL_CTRL_3V |= ANAC_LDO_POWER_CTL_Msk | ANAC_FL_LDO_ISOLATE_EN_Msk;
+        ana->LP_FL_CTRL_3V &= ~ANAC_LDOL_POWER_CTL_Msk;
+    } else if (dpMode == LP_DEEPSLEEP_MODE2) {
+        ana->LP_LP_LDO_3V |= ANAC_LPLDO_H_EN_Msk_3v;
+        ana->LP_LP_LDO_3V &= ~ANAC_LPLDO_L_EN_Msk;
+        ana->LP_FL_CTRL_3V |= ANAC_LDOL_POWER_CTL_Msk | ANAC_LDO_POWER_CTL_Msk;
+        ana->LP_FL_CTRL_3V &= ~ANAC_FL_LDO_ISOLATE_EN_Msk;
+    } else if (dpMode == LP_DEEPSLEEP_MODE3) {
+        ana->LP_LP_LDO_3V &= ~ANAC_LPLDO_H_EN_Msk_3v;
+        ana->LP_LP_LDO_3V |= ANAC_LPLDO_L_EN_Msk;
+        ana->LP_FL_CTRL_3V |= ANAC_LDOL_POWER_CTL_Msk | ANAC_LDO_POWER_CTL_Msk;
+        ana->LP_FL_CTRL_3V &= ~ANAC_FL_LDO_ISOLATE_EN_Msk;
+    }
+
+    // Enable LPDOH mode 2 to save power
+    // NOTE: This option is now configured in SystemHwParamLoader() flow due to ft version.
+#if 0
+    ana->LP_LP_LDO_3V |= ANAC_LPLDO_H_MODE_SEL_Msk_3v;
+#endif
+
+#if CONFIG_KEEP_FLASH_POWER_IN_LP_MODE
+    // Keep flash power in Deepsleep mode
+#if CONFIG_FLASH_LDO_EN
+    ana->LP_FL_CTRL_3V |= ANAC_FL_FLASH_LP_EN_Msk;
+    ana->LP_FL_CTRL_3V &= ~ANAC_FL_FLASH_BP_EN_Msk;
+#else
+    ana->LP_FL_CTRL_3V &= ~ANAC_FL_FLASH_LP_EN_Msk;
+    ana->LP_FL_CTRL_3V |= ANAC_FL_FLASH_BP_EN_Msk;
+#endif /* CONFIG_FLASH_LDO_EN */
+    // Configure rdp wait cnt for auto dp use
+    FMC_SetRdpWaitCount(FLCTL, 0x400);
+#else
+    // Power down flash in Deepsleep mode
+    ana->LP_FL_CTRL_3V &= ~ANAC_FL_FLASH_LP_EN_Msk;
+    ana->LP_FL_CTRL_3V &= ~ANAC_FL_FLASH_BP_EN_Msk;
+#endif /* CONFIG_KEEP_FLASH_POWER_IN_LP_MODE */
+
+    /* Enable flash auto-dp no matter flash power-down or not in deepsleep mode */
+    FMC_EnableAutoDp(FLCTL);
+
+    /* Enable proper 32k clock in low power mode */
+    if (CLK->CLK_TOP_CTRL_3V & CLK_TOPCTL_32K_CLK_SEL_Msk_3v) {
+        ana->LP_FL_CTRL_3V |= ANAC_FL_XTAL32K_EN_Msk_3v;
+        ana->LP_FL_CTRL_3V &= ~ANAC_FL_RC32K_EN_Msk_3v;
+    } else {
+        ana->LP_FL_CTRL_3V &= ~ANAC_FL_XTAL32K_EN_Msk_3v;
+        ana->LP_FL_CTRL_3V |= ANAC_FL_RC32K_EN_Msk_3v;
+    }
+
+    // Configure power of SRAM
+    ana->LP_FL_CTRL_3V = ((powerCtrl & 0x1f) << 24u) | (ana->LP_FL_CTRL_3V & 0xe0FFFFFF);
+
+    // Configure LP delay
+    ana->LP_DLY_CTRL_3V &= ~0x3ff;
+    ana->LP_DLY_CTRL_3V |= 0x7;
+
+    // Mask all interrupts
+    __disable_irq();
+
+    // Set LP irq to lowest priority
+    NVIC_SetPriority(LP_IRQn, 3);
+
+    /* Store and Clear NVIC Interrupt Enable Register */
+    nvicInt = NVIC->ISER[0U];
+    NVIC->ICER[0U] = 0xFFFFFFFF;
+    /* Enable LP IRQ to make sure related ISR would trigger after wake up */
+    NVIC_EnableIRQ(LP_IRQn);
+
+    // Ensure next wfi enter deepsleep mode
+    LP_SetSleepMode(ana, LP_MODE_SEL_DEEPSLEEP_MODE);
+    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
+
+    // Wait 3v sync ready manually
+    ana->LP_REG_SYNC |= ANAC_LP_REG_SYNC_3V_Msk | ANAC_LP_REG_SYNC_3V_TRG_Msk;
+    while (ana->LP_REG_SYNC & (ANAC_LP_REG_SYNC_3V_TRG_Msk)) {}
+
+    if (enterCyclically) {
+        SCB->SCR |= SCB_SCR_SLEEPONEXIT_Msk;
+    } else {
+        SCB->SCR &= ~SCB_SCR_SLEEPONEXIT_Msk;
+    }
+
+    __WFI();
+
+    // Ensure next wfi enter sleep mode
+    SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
+    LP_SetSleepMode(ana, LP_MODE_SEL_SLEEP_MODE);
+
+    /* Disable flash auto-dp after deepsleep wakeup */
+    FMC_DisableAutoDp(FLCTL);
+
+#if ((!CONFIG_KEEP_FLASH_POWER_IN_LP_MODE) && (CONFIG_FLASH_LINE_MODE == FLASH_X4_MODE))
+    /* Set en_burst_wrap in FMC */
+    FLCTL->X_FL_X_MODE |= (0x1 << 16);
+    /* Re-issue burst_wrap command to flash if is X4 mode */
+    FLCTL->X_FL_CTL = (0 << 8) | (0x05 << 0);
+    FLCTL->X_FL_WD[0] = CMD_BURST_READ;
+    FLCTL->X_FL_WD[4] = BURST_READ_MODE_32 << 5;
+    FLCTL->X_FL_TRIG = CMD_TRIG;
+    while (FLCTL->X_FL_TRIG) {
+        __NOP();
+    }
+#endif
+
+    /* Restore NVIC Interrupt Enable Register [xxx:107 must]*/
+    NVIC->ISER[0U] = nvicInt;
 }
 
-void LP_SetStandbyMode0BodLvrConfig(void)
+__ASM static void LP_WfiWithCoreRegsBackupAndResume(void)
 {
-	LP_SetSleepMode(ANA, LP_MODE_SEL_STANDBY_M0_MODE);
-	LP_EnableInt(ANA,ENABLE);
-	//bod/lvr wakeup need
-	ANA->LP_FL_CTRL_3V |= ANAC_FL_XTAL32K_EN_Msk_3v;
-	ANA->LP_FL_CTRL_3V |= ANAC_FL_RC32K_EN_Msk_3v;
-	#ifdef SYNC_3V_REG_MANUALLY
-	CLK_Wait3vSyncReady();
-	#endif
-
-	SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
-	__WFI();
+    push {r0-r7}    /* Backup r0 ~ r7 */
+    mov r0, r8
+    mov r1, r9
+    mov r2, r10
+    mov r3, r11
+    mov r4, r12
+    mov r5, lr
+    push {r0-r5}    /* Backup r8 ~ r12 and lr */
+    wfi             /* Trigger hw to enter low power mode */
+    pop {r0-r5}     /* Restore r8 ~ r12 and lr */
+    mov r8, r0
+    mov r9, r1
+    mov r10, r2
+    mov r11, r3
+    mov r12, r4
+    mov lr, r5
+    pop {r0-r7}     /* Restore r0 ~ r7 */
+    bx lr           /* Function return */
 }
 
-void LP_SetStandbyMode1Config(ANA_T *ana,
-							uint32_t wkMode,
-							uint8_t PowerCtrl,
-							uint32_t slpTimer,
-							uint8_t spaceIdx,
-							uint8_t stdy_mode)
+void LP_EnterStandbyMode1(ANA_T *ana, uint8_t powerCtrl, bool wakeupWithoutReset)
 {
-	LP_SetSleepMode(ana, LP_MODE_SEL_STANDBY_M1_MODE);
-	LP_EnableInt(ana,ENABLE);
-	if (stdy_mode == LP_STANDBY_M1_MODE1){
-		ana->LP_LP_LDO_3V |= ANAC_LPLDO_H_EN_Msk_3v;
-		ana->LP_LP_LDO_3V |= ANAC_LPLDO_L_EN_Msk;
-		ana->LP_FL_CTRL_3V |=  ANAC_FL_LDO_ISOLATE_EN_Msk;
-		ana->LP_FL_CTRL_3V &= ~(ANAC_LDOL_POWER_CTL_Msk | ANAC_LDO_POWER_CTL_Msk);
-	} else if (stdy_mode == LP_STANDBY_M1_MODE2){
-		ana->LP_LP_LDO_3V |= ANAC_LPLDO_H_EN_Msk_3v;
-		ana->LP_LP_LDO_3V &= ~ANAC_LPLDO_L_EN_Msk;
-		ana->LP_FL_CTRL_3V |= ANAC_LDOL_POWER_CTL_Msk | ANAC_FL_LDO_ISOLATE_EN_Msk;
-		ana->LP_FL_CTRL_3V &= ~(ANAC_LDO_POWER_CTL_Msk);
-	} else if (stdy_mode == LP_STANDBY_M1_MODE3){
-		ana->LP_LP_LDO_3V &= ~ANAC_LPLDO_H_EN_Msk_3v;
-		ana->LP_LP_LDO_3V |= ANAC_LPLDO_L_EN_Msk;
-		ana->LP_FL_CTRL_3V |= ANAC_LDOL_POWER_CTL_Msk | ANAC_FL_LDO_ISOLATE_EN_Msk;
-		ana->LP_FL_CTRL_3V &= ~(ANAC_LDO_POWER_CTL_Msk);
-	}
-	
-	ana->LP_FL_CTRL_3V = ((PowerCtrl & 0x1f) << 24u) | (ana->LP_FL_CTRL_3V & 0xe0FFFFFF);
-	if((LP_WKUP_MODE_SEL_EXT_GPIO != wkMode)&&(LP_WKUP_MODE_SEL_GPIO != wkMode)){
-		if (CLK->CLK_TOP_CTRL_3V & CLK_TOPCTL_32K_CLK_SEL_Msk_3v) {
-			ana->LP_FL_CTRL_3V |= ANAC_FL_XTAL32K_EN_Msk_3v;
-			ana->LP_FL_CTRL_3V &= ~ANAC_FL_RC32K_EN_Msk_3v;
-		} else {
-			ana->LP_FL_CTRL_3V &= ~ANAC_FL_XTAL32K_EN_Msk_3v;
-			ana->LP_FL_CTRL_3V |= ANAC_FL_RC32K_EN_Msk_3v;
-		}
-		ana->LP_INT_CTRL |= ANAC_INT_SLEEP_TMR_WK_EN_Msk;
-	} else {
-		ana->LP_FL_CTRL_3V &= ~ANAC_FL_RC32K_EN_Msk_3v;
-		ana->LP_FL_CTRL_3V &= ~ANAC_FL_XTAL32K_EN_Msk_3v;
-	}
+    ana->LP_INT_CTRL |= ANAC_INT_LP_INT_EN_Msk | ANAC_INT_SLEEP_TMR_INT_EN_Msk | ANAC_INT_SLEEP_TMR_WK_EN_Msk;
 
-	// Wait 3v sync ready manually
-	ANA->LP_REG_SYNC |= ANAC_LP_REG_SYNC_3V_Msk | ANAC_LP_REG_SYNC_3V_TRG_Msk;
-	while(ANA->LP_REG_SYNC & (ANAC_LP_REG_SYNC_3V_TRG_Msk)) {}
+    /* StandbyM1 Power Mode 1, use both LPLDOH and LPLDOL */
+    ana->LP_LP_LDO_3V |= ANAC_LPLDO_H_EN_Msk_3v;
+    ana->LP_LP_LDO_3V |= ANAC_LPLDO_L_EN_Msk;
+    ana->LP_FL_CTRL_3V |= ANAC_FL_LDO_ISOLATE_EN_Msk;
+    ana->LP_FL_CTRL_3V &= ~(ANAC_LDOL_POWER_CTL_Msk | ANAC_LDO_POWER_CTL_Msk);
 
-	if((LP_WKUP_MODE_SEL_EXT_GPIO != wkMode)&&(LP_WKUP_MODE_SEL_GPIO != wkMode)){
-		LP_SetSleepTime(ana,slpTimer,spaceIdx);
-	}
-	SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
-	__WFI();
+    /* LPDOH switch to mode 2 for better power consumption performance */
+    ana->LP_LP_LDO_3V |= ANAC_LPLDO_H_MODE_SEL_Msk_3v;
+
+    /* Power down Flash in lp mode discard the dedicated Flash LDO enabled or not */
+    ana->LP_FL_CTRL_3V = (ana->LP_FL_CTRL_3V & ~(0x3 << 12u)) | (0x0 << 12u);
+
+    /* Enable proper 32k clock in low power mode */
+    if (CLK->CLK_TOP_CTRL_3V & CLK_TOPCTL_32K_CLK_SEL_Msk_3v) {
+        ana->LP_FL_CTRL_3V |= ANAC_FL_XTAL32K_EN_Msk_3v;
+        ana->LP_FL_CTRL_3V &= ~ANAC_FL_RC32K_EN_Msk_3v;
+    } else {
+        ana->LP_FL_CTRL_3V &= ~ANAC_FL_XTAL32K_EN_Msk_3v;
+        ana->LP_FL_CTRL_3V |= ANAC_FL_RC32K_EN_Msk_3v;
+    }
+
+    /* Configure retention SRAM modules in low power mode */
+    ana->LP_FL_CTRL_3V = ((powerCtrl & 0x1f) << 24u) | (ana->LP_FL_CTRL_3V & 0xe0FFFFFF);
+
+    /* Set digital delay with 32k tick unit */
+    ana->LP_DLY_CTRL_3V &= ~0x3ff;
+    ana->LP_DLY_CTRL_3V |= 7;
+
+    /* Insure we are going to enter hw standby mode 1 */
+    LP_SetSleepMode(ana, LP_MODE_SEL_STANDBY_M1_MODE);
+    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
+
+    // Mask all interrupts
+    __disable_irq();
+
+    /* Trigger 3v sync */
+    ana->LP_REG_SYNC |= ANAC_LP_REG_SYNC_3V_Msk | ANAC_LP_REG_SYNC_3V_TRG_Msk;
+
+    /* Clear all lowpower related int flags if any */
+    ana->LP_INT_CTRL = ana->LP_INT_CTRL;
+#if 0
+    /* Reset all hw peripheral modules except eFuse and GPIO */
+    CLK->IPRST0 = 0x1CC;
+    CLK->IPRST0 = 0x0;
+    CLK->IPRST1 = 0x17FFF;
+    CLK->IPRST1 = 0x0;
+#endif
+    /* Disable all IRQs and clear all pending IRQs on NVIC */
+    NVIC->ICER[0U] = 0xFFFFFFFF;
+    NVIC->ICPR[0U] = 0xFFFFFFFF;
+
+    /* Wait until 3v sync done */
+    while (ana->LP_REG_SYNC & (ANAC_LP_REG_SYNC_3V_TRG_Msk)) {
+        __NOP();
+    }
+
+    if (!wakeupWithoutReset) {
+
+        /* Reset CPU Vector Remap register to avoid issue after waking up */
+        ana->CPU_ADDR_REMAP_CTRL = 0;
+
+        /* Trigger hw to enter low power mode */
+        __WFI();
+
+        /*
+         * ======== (Now SoC is expected in HW Standby Mode 1 and would never return back here) =========
+         */
+    } else {
+        /*
+         * Enable CPU core regs retention in standby mode 1
+         * The CPU core registers PC, MSP, PSP and CONTROL would automatically
+         * be saved and restored by hardware in SoC standby mode 1.
+         */
+        ana->LP_FL_CTRL_3V |= ANAC_FL_CPU_RETENTION_EN_Msk;
+
+        /* Backup the FMC remap register in case we configure it in bootloader */
+        uint32_t fmc_remap_bkp = FLCTL->X_FL_REMAP_ADDR;
+
+        /*
+         * 1. Backup CPU core registers which are not auto-saved by hardware
+         * 2. Enter SoC Standby Mode 1 (WFI)
+         * 3. Restore previous backup CPU core registers
+         */
+        LP_WfiWithCoreRegsBackupAndResume();
+
+        /* Restore FMC remap register after waking up */
+        FLCTL->X_FL_REMAP_ADDR = fmc_remap_bkp;
+
+        // Disable CPU core regs retention after wakeup
+        ANA->LP_FL_CTRL_3V &= ~ANAC_FL_CPU_RETENTION_EN_Msk;
+
+        /* Reset SoC lp mode to sleep mode (1.2v area, do not need 3v sync) */
+        ana->LP_FL_CTRL_3V = (ana->LP_FL_CTRL_3V & ~ANAC_FL_SLEEP_MODE_SEL_Msk)
+            | (LP_MODE_SEL_SLEEP_MODE << ANAC_FL_SLEEP_MODE_SEL_Pos);
+
+        /* Restore fmc and flash status */
+        FMC_SetFlashMode(FLCTL, PanFlashEnhanceEnable, PanFlashEnhanceEnable);
+        /* Reinit I-Cache */
+        InitIcache(FLCTL, PanFlashEnhanceEnable);
+        /*
+         * Clear StandbyM1 int flag (write 1 to clear) in this register, but still
+         * retain all other ctrl/status flags.
+         */
+        ana->LP_INT_CTRL = (ana->LP_INT_CTRL | ANAC_INT_STANDBY_M1_FLAG_Msk)
+            & ~(ANAC_INT_SLEEP_TMR0_Msk | ANAC_INT_SLEEP_TMR1_Msk | ANAC_INT_SLEEP_TMR2_Msk
+            | ANAC_INT_DP_FLAG_Msk | ANAC_INT_STANDBY_M0_FLAG_Msk | ANAC_INT_SRAM_RET_FLAG_Msk);
+    }
+}
+
+void LP_EnterStandbyMode0(ANA_T *ana, bool enableClk32k)
+{
+    /* Mask all IRQs when we are on the way to enter standby mode */
+    __disable_irq();
+
+    if (enableClk32k) {
+        /* Enable proper 32k clock in low power mode */
+        if (CLK->CLK_TOP_CTRL_3V & CLK_TOPCTL_32K_CLK_SEL_Msk_3v) {
+            ANA->LP_FL_CTRL_3V |= ANAC_FL_XTAL32K_EN_Msk_3v;
+            ANA->LP_FL_CTRL_3V &= ~ANAC_FL_RC32K_EN_Msk_3v;
+        } else {
+            ANA->LP_FL_CTRL_3V &= ~ANAC_FL_XTAL32K_EN_Msk_3v;
+            ANA->LP_FL_CTRL_3V |= ANAC_FL_RC32K_EN_Msk_3v;
+        }
+    } else {
+        // Disable 32K Clock Source to save power
+        ANA->LP_FL_CTRL_3V &= ~ANAC_FL_RC32K_EN_Msk_3v;
+        ANA->LP_FL_CTRL_3V &= ~ANAC_FL_XTAL32K_EN_Msk_3v;
+    }
+
+    /* Set digital delay with 32k tick unit */
+    ANA->LP_DLY_CTRL_3V &= ~0x3ff;
+    ANA->LP_DLY_CTRL_3V |= 7;
+
+    /* Insure we are going to enter hw standby mode 1 */
+    LP_SetSleepMode(ANA, LP_MODE_SEL_STANDBY_M0_MODE);
+    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
+
+    /* Trigger 3v sync */
+    ANA->LP_REG_SYNC |= ANAC_LP_REG_SYNC_3V_Msk | ANAC_LP_REG_SYNC_3V_TRG_Msk;
+
+    /* Disable SLPTMR interrupt and wakeup in lp mode (Only enable LP interrupt) */
+    ANA->LP_INT_CTRL = ANAC_INT_LP_INT_EN_Msk;
+    // Clear configured time of sleep timers
+    ANA->LP_SPACING_TIME0 = 0;
+    ANA->LP_SPACING_TIME1 = 0;
+    ANA->LP_SPACING_TIME2 = 0;
+
+    /* Clear all lowpower related int flags if any */
+    ANA->LP_INT_CTRL = ANA->LP_INT_CTRL;
+#if 0
+    /* Reset all hw peripheral modules except eFuse and GPIO */
+    CLK->IPRST0 = 0x1CC;
+    CLK->IPRST0 = 0x0;
+    CLK->IPRST1 = 0x17FFF;
+    CLK->IPRST1 = 0x0;
+#endif
+    /* Disable all IRQs and clear all pending IRQs on NVIC */
+    NVIC->ICER[0U] = 0xFFFFFFFF;
+    NVIC->ICPR[0U] = 0xFFFFFFFF;
+
+    /* Wait until 3v sync done */
+    while (ANA->LP_REG_SYNC & (ANAC_LP_REG_SYNC_3V_TRG_Msk)) {
+        __NOP();
+    }
+
+    /* Trigger hw to enter low power mode */
+    __WFI();
+
+    /*
+     * ======== (Now SoC is expected in HW Standby Mode 0 and would never return back here) =========
+     */
 }

--
Gitblit v1.9.3