/*
  ******************************************************************************
  * Copyright (c)  2008 - 2022, Shanghai AisinoChip Co.,Ltd .
  * @file    APP.c 
  * @version V1.0.0
  * @date    2022
  * @author  Aisinochip Firmware Team  
  * @brief   Stop Mode demo source code.
  ******************************************************************************        
*/
#include "APP.h"

GPIO_InitTypeDef GPIOD_Handle;

EXTI_HandleTypeDef EXTI_Line9_Handle;

GPIO_InitTypeDef GPIO_PB9_Handle;


/*********************************************************************************
* Function    : EXTI_IRQHandler
* Description : EXTI Interrupt Handler
* Input       : None
* Output      : None
**********************************************************************************/
void EXTI_IRQHandler(void)
{ 
    HAL_EXTI_IRQHandler(&EXTI_Line9_Handle);
}

void Exit_Config(void)
{
	System_Module_Enable(EN_EXTI);

    /* Initialization GPIO */
    GPIO_PB9_Handle.Pin       = GPIO_PIN_9;
    GPIO_PB9_Handle.Mode      = GPIO_MODE_INPUT;
    GPIO_PB9_Handle.Pull      = GPIO_PULLUP;
    GPIO_PB9_Handle.Alternate = GPIO_FUNCTION_0;

    HAL_GPIO_Init(GPIOB, &GPIO_PB9_Handle);
    
    /* Config EXTI */
    EXTI_Line9_Handle.u32_Line    = EXTI_LINE_9;
    EXTI_Line9_Handle.u32_Mode    = EXTI_MODE_INTERRUPT;
    EXTI_Line9_Handle.u32_Trigger = EXTI_TRIGGER_FALLING;
    EXTI_Line9_Handle.u32_GPIOSel = EXTI_GPIOB;

    HAL_EXTI_SetConfigLine(&EXTI_Line9_Handle);

}

void GPIO_Turn()  /* 翻转IO，起到延时作用 */
{
    uint32_t i;
    GPIOD_Handle.Pin       = GPIO_PIN_3 ;
    GPIOD_Handle.Mode      = GPIO_MODE_OUTPUT_PP;
    GPIOD_Handle.Pull      = GPIO_PULLUP;
    GPIOD_Handle.Alternate = GPIO_FUNCTION_0;

    HAL_GPIO_Init(GPIOD, &GPIOD_Handle);

    for(i = 0; i < 20 ; i++)
    {   
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_3 , GPIO_PIN_SET);
		System_Delay_MS(100);
        HAL_GPIO_WritePin(GPIOD, GPIO_PIN_3 , GPIO_PIN_CLEAR);
		System_Delay_MS(100);
    }
}


static void SimpleDelay(volatile uint32_t delay)  
{
    while(delay--)
    {
        ;
    }
}

/*********************************************************************************
* 函数名 :  Enter_LowPower_STOP
* 功  能 :  STOP & 模拟模块各IP 功耗
* 说  明 :  
* 入  参 :  无
* 返  回 :  无
**********************************************************************************/
void Enter_LowPower_STOP(void)
{
    /* 关闭中断 */
    __set_PRIMASK(1);
    /* 关闭Systick中断 */     
    SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;
    /* 清除Systick中断挂起标志 */    
    SCB->ICSR = BIT25;
    
    HAL_RTC_PCLK_ENABLE();
	/*----------------进stop模式前设置-------------*/
    /* 所有IO配置位模拟 */
    SCU->PABADS= 0xFFFFFFFF;
    SCU->PCDADS  = 0xFFFFFFFF;

	/*时钟切换到RCH*/
	SCU->CCR1 =SYS_CLK_SRC_RCH;
    /* 关闭XTH、XTL、RC4M、32K 时钟  */
    SCU->RCHCR&= ~(1 << 16);      // RC4M Disable
    SCU->XTHCR &= ~(1 <<  0);     // XTH  Disable
	SCU->PLLCR &= ~(1 << 0);      //PLL Disable

    SCU->STOPCFG   |=  (1 << 0);  // RTC域写使能
    PMU->ANACR &= ~(1 << 0);      // XTL   Disable
    PMU->ANACR &= ~(1 << 8);      // RC32K Disable

	/*唤醒源配置*/
	Exit_Config();	
	
    /* LVD Disable */
    SCU->LVDCFG &= ~(1 << 0);

    /* STOP 模式下关闭LDO12、RC64M */
    /* 进入STOP模式前，需要将MLDO12电压自动降低(MLDO12LV)为1.0V，以减小随后关闭MLDO12带来的电压波动 */
    SCU->STOPCFG &= ~(0x03 << 4);
    SCU->STOPCFG |= (0x01 << 4);//MLDO12调整为1.0V
    SCU->STOPCFG |= 1 << 9;//STOP 下自动进入 LPSTP 模式
    SCU->STOPCFG |= 1 << 3;//停止（STOP）模式下，RC64M 自动关闭

    /* All Clock Disable */
    SCU->CLKOCR &= ~(1ul << 31);    // Buzzer2 Disable
    SCU->CLKOCR &= ~(1ul << 23);    // Buzzer1 Disable

    /*RAM Retention 模式*/	
	SCU->STOPCFG |=(1<<28);
	
	/*关闭SRAM未用空间*/
	//SCU->MEMCFG  |= (14<<16);    //1110 关闭未用的后24K
	
    /*Eflash 进入sleep模式 */
    EFC->CTRL |= 1<<12;
	
    SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));   // Set SLEEPDEEP bit of Cortex System Control Register 
    
    SCU->STOPCFG &= (~BIT11);  // PDDS=0     
    

	/*---------------进入stop模式-----------*/
	/* Wait For Interrupt */   
    __WFI();
	
	/*---------------唤醒后设置-------------*/
	CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk)); 
    
    SCU->STOPCFG &= ~(0x03 << 4);//MLDO12调整为1.2V
	 	 
	/* 唤醒后，Eflash退出Sleep模式 */
	EFC->CTRL &= ~(1<<12);
    /* Elash退出Sleep最少延时10uS */
	SimpleDelay(5000); 

    /* 使能Systick中断 */
    SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; 
    /* 使能全部中断 */    
    __set_PRIMASK(0);
	
}


/*********************************************************************************
* Function    : APP_Power_Stop_Test
* Description : 
* Input       : None
* Output      : None
**********************************************************************************/
void APP_Power_Stop_Test(void)
{
    while(1)
    {
        GPIO_Turn();   //GPIO翻转，相当于延时
        printfS("MCU enter stop mode, MCU will wakeup by PB9 falling edge!\n");            
        Enter_LowPower_STOP();
        System_Init(); 
        
        extern void Uart_Init(uint32_t fu32_Baudrate);
        Uart_Init(115200);
        
        printfS("MCU exit stop mode, wakeup by PB9 falling edge!\n");
    }
}
