
/******************************************************************************
*@file  : app.c
*@brief : application
******************************************************************************/

#include "app.h" 

void EnterStopMode(void);

/******************************************************************************
*@brief : app test
*@param : none
*@return: none
******************************************************************************/
void APP_Test(void)
{
    uint32_t curr_tick;
    uint32_t end_tick;
    uint32_t period;
    uint32_t wakeup;
    EXTI_InitTypeDef EXTI_InitStruct = {0};
    
	printfS("SPL IWDT Demo : Wakeup from STOP mode.\r\n");
	printfS("\r\n");
    
    BSP_LED_Init();
    BSP_LED_On();
    DelayMs(500);
    BSP_LED_Off();
    DelayMs(500);
    BSP_LED_On();
    DelayMs(500);
    BSP_LED_Off();
    DelayMs(500);
    
    // Enable exti interrupt
    EXTI_InitStruct.Line      = EXTI_LINE_IWDT;
    EXTI_InitStruct.Mode      = EXTI_MODE_IT;
    EXTI_InitStruct.Trigger   = EXTI_TRIGGER_RISING;
    EXTI_InitStruct.Cmd       = ENABLE;
    
    EXTI_Init(&EXTI_InitStruct);
    
    // Enable NVIC IRQ
    NVIC_ClearPendingIRQ(IWDT_WAKEUP_IRQn);
    NVIC_SetPriority(IWDT_WAKEUP_IRQn, 0x00);
    NVIC_EnableIRQ(IWDT_WAKEUP_IRQn);
    
    period = (uint32_t)4000 * 1000 / (RCC_GetRC32KFreq() / 32);
    wakeup = (uint32_t)(4000 - 200) * 1000 / (RCC_GetRC32KFreq() / 32);
    
    printfS("IWDT refresh period : %u ms.\r\n", period);
    printfS("IWDT wakeup period : %u ms.\r\n", wakeup);
    printfS("If the IWDT wakeup fails, the system will be reset.\r\n");
    printfS("\r\n");
    
    // RC32K
    RCC_RC32KCmd(ENABLE);
    if (RCC_WaitForRC32KStartUp() == ERROR)
    {
        printfS("RC32K stabilization timeout.\r\n");
        while (1);
    }
    
    __RCC_IWDTRSTTOSYSRST_ENABLE();
    
    IWDT_Enable();
    IWDT_WriteAccessCmd(ENABLE);
    
    while (IWDT_GetFlagStatus(IWDT_FLAG_PVU));
    IWDT_SetPrescaler(IWDT_CLOCK_PRESCALER_32);
    
    while (IWDT_GetFlagStatus(IWDT_FLAG_RVU));
    IWDG_SetReload(4000);
    
    while (IWDT_GetFlagStatus(IWDT_FLAG_WTU));
    IWDG_SetWakeup(200);
    
    while (IWDT_GetFlagStatus(IWDT_FLAG_WVU));
    IWDG_SetWindow(4000);
    
    IWDT_WakeupCmd(ENABLE);
    IWDT_ReloadCounter();
    
    while(1)
    {
        printfS("mcu enter stop mode.\r\n"); 
        printfS("MCU will wake up automatically from STOP mode after %u ms.\r\n", wakeup); 
        
        EnterStopMode();
        
        IWDT_ReloadCounter();
        
		printfS("mcu has exited stop mode.\r\n");
		printfS("\r\n");
        
        BSP_LED_Toggle();
        DelayMs(1000);
    };
}


void EnterStopMode(void)
{
	volatile uint32_t i;
    uint32_t save_irq;

    save_irq = EnterCritical();
    SysTick_Suspend();
    
    RCC_RC32KCmd(ENABLE);
    RCC_SYSCLKConfig(RCC_SYSCLKSOURCE_RC32K);
    
    PMU_EnterSTOPMode(PMU_STOP_2, PMU_LOWPOWRENTRY_WFI);
    
    SysTick_Resume();   
    
    ExitCritical(save_irq);
    
    SystemClock_Config();    
    
    SystemCoreClockUpdate();
    
    BSP_UART_Init();  
	
}

void iwdt_wakeup_irq_handle(void)
{
    IWDT_ReloadCounter();
    EXTI_ClearFlag(EXTI_LINE_IWDT);
}

