/******************************************************************************
*@file  : app.c
*@brief : application
******************************************************************************/
#include "app.h"

extern volatile uint32_t gu32_SystemCount;
volatile uint32_t g_iwdtIRQFlag = 0;

/******************************************************************************
*@brief : IWDT reset test 
*@param : none
*@return: none
******************************************************************************/
void IWDT_Reset_Test(void)
{
    uint8_t cnt;
    printfS("IWDT reset test\r\n");
    if((SCU->RSR & BIT2) == BIT2)
    {
        SCU->RSR = BIT16;
        printfS("Last Reset Reason: IWDT\r\n");         
    }

    /* 使能IWDT复位导致系统复位 */
    IWDT_ResetCmd(IWDT_STATE_ENABLE);
    /* 开启看门狗 */
    IWDT_Cmd(IWDT_STATE_ENABLE);
    /* 允许PR、RLR、WINR寄存器写操作 */
    IWDT_WriteAccessCmd(IWDT_STATE_ENABLE);
    /* 设置预分频 */
    IWDT_SetPrescaler(IWDT_CLOCK_PRESCALER_32);
    while(IWDT_GetFlagStatus(IWDT_FLAG_PVU));
    /* 设置重装载值 */
    IWDT_SetReload(4000);
    while(IWDT_GetFlagStatus(IWDT_FLAG_RVU));
    /* 喂狗 */
    IWDT_FeedDog();
    while(IWDT_GetFlagStatus(IWDT_FLAG_RLF));
    
    cnt = 0;    
    while(1)
    {
        /* 在复位时间到达前150ms，刷新IWDT； */
        System_Delay_MS(850);
        if(cnt++ < 10)
        {
            IWDT_FeedDog();
            while(IWDT_GetFlagStatus(IWDT_FLAG_RLF));            
            printfS("[%d]feed wachdog time : %u\r\n", cnt, gu32_SystemCount);    
        }
        else
        {
            printfS("[%d]: %u\r\n", cnt, gu32_SystemCount);
        }            
    }   
}



/******************************************************************************
*@brief : IWDT wakeup test 
*@param : none
*@return: none
******************************************************************************/
void IWDT_Wakeup_Test(void)
{
    EXTI_InitTypeDef EXTI_InitStruct = {0};        
    printfS("IWDT wakeup test\r\n");
    
    System_Delay_MS(1500);
    
    /* 使能IWDT复位导致系统复位 */
    IWDT_ResetCmd(IWDT_STATE_ENABLE);
    /* 开启看门狗 */
    IWDT_Cmd(IWDT_STATE_ENABLE);
    /* 允许PR、RLR、WINR寄存器写操作 */
    IWDT_WriteAccessCmd(IWDT_STATE_ENABLE);
    /* 设置预分频 */
    IWDT_SetPrescaler(IWDT_CLOCK_PRESCALER_32);
    while(IWDT_GetFlagStatus(IWDT_FLAG_PVU));
    /* 设置重装载值 */
    IWDT_SetReload(4000);
    while(IWDT_GetFlagStatus(IWDT_FLAG_RVU));
    /* 设置唤醒值 */
    IWDT_SetWakeup(2000);
    while(IWDT_GetFlagStatus(IWDT_FLAG_WTU));
    /* 使能唤醒功能 */
    IWDT_WakeupCmd(IWDT_STATE_ENABLE);
    /* 喂狗 */
    IWDT_FeedDog();
    while(IWDT_GetFlagStatus(IWDT_FLAG_RLF));
    
    /* 配置EXTI */
    System_Module_Enable(EN_EXTI);
    /* Select EXTI_Line  */
    EXTI_InitStruct.EXTI_Line = IWDT_EXTI_LINE;
    /* EXTI MODE   EXTI_MODE_INTERRUPT */
    EXTI_InitStruct.EXTI_Mode = EXTI_MODE_INTERRUPT;
    /* EXTI_Trigger   EXTI_TRIGGER_FALLING*/
    EXTI_InitStruct.EXTI_Trigger = EXTI_TRIGGER_FALLING;
    EXTI_InitStruct.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStruct);    
    
    NVIC_ClearPendingIRQ(EXTI_IRQn);
    NVIC_SetPriority(EXTI_IRQn, 0x00);
    NVIC_EnableIRQ(EXTI_IRQn);
    while(1)
    {
        printfS("mcu enter stop mode!\r\n"); 
        
        EXTI->PDR = 0xffffff;
        
        __set_PRIMASK(1);    // disable interrupt
        SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;    // disable systick interrupt
        SCB->ICSR = BIT25;   // clear systick pending bit  
        
        System_Enter_Stop_Mode(STOPENTRY_WFI);        
        
        SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;//enable systick interrupt            
        __set_PRIMASK(0);    // enable interrupt   
        
        printfS("exti stop, wakeup by EXTI_Line%d \r\n", g_iwdtIRQFlag);
        System_Delay_MS(1000);
        IWDT_FeedDog();
        while(IWDT_GetFlagStatus(IWDT_FLAG_RLF));
        
    } 
}

/******************************************************************************
*@brief : IWDT window test 
*@param : none
*@return: none
******************************************************************************/
void IWDT_Window_Test(void)
{
    uint8_t cnt;
    printfS("IWDT windows test\r\n");
    if((SCU->RSR & BIT2) == BIT2)
    {
        SCU->RSR = BIT16;
        printfS("Last Reset Reason: IWDT\r\n");         
    }

    /* 使能IWDT复位导致系统复位 */
    IWDT_ResetCmd(IWDT_STATE_ENABLE);
    /* 开启看门狗 */
    IWDT_Cmd(IWDT_STATE_ENABLE);
    /* 允许PR、RLR、WINR寄存器写操作 */
    IWDT_WriteAccessCmd(IWDT_STATE_ENABLE);
    /* 设置预分频 */
    IWDT_SetPrescaler(IWDT_CLOCK_PRESCALER_32);
    while(IWDT_GetFlagStatus(IWDT_FLAG_PVU));
    /* 设置重装载值 */
    IWDT_SetReload(4000);
    while(IWDT_GetFlagStatus(IWDT_FLAG_RVU));
    /* 设置窗口值 */
    IWDT_SetWindow(2000);
    while(IWDT_GetFlagStatus(IWDT_FLAG_WVU));
    /* 喂狗 */
    IWDT_FeedDog();
    while(IWDT_GetFlagStatus(IWDT_FLAG_RLF));
    
    cnt = 0;    
    while(1)
    {
        if(cnt++ < 10)
        {
            /* 在窗口内，刷新IWDT； */
            System_Delay_MS(3000);
        }
        else
        {
            /* 在窗口外，刷新IWDT； */
            System_Delay_MS(1000);
        }            
        IWDT_FeedDog();
        while(IWDT_GetFlagStatus(IWDT_FLAG_RLF));            
        printfS("[%d]feed wachdog time : %u\r\n", cnt, gu32_SystemCount);            
    }   
}

/******************************************************************************
*@brief : IWDT test
*@param : test_mode: Test mode selection
*@return: none
******************************************************************************/
void IWDT_Test(Test_mode_t test_mode)
{
    switch(test_mode)
    {
        case Test_IWDT_Reset:
        {
            IWDT_Reset_Test();
        }break;
        case Test_IWDT_Wakeup:
        {
            IWDT_Wakeup_Test();
        }break;
        case Test_IWDT_Window:
        {
            IWDT_Window_Test();
        }break;
        default:
        {
            printfS("This application does not support\r\n");
        }break;
    }
}

/******************************************************************************
* @brief : app test.
* @param : None
* @return: None
******************************************************************************/
void APP_Test(void)
{  
    /*
	Test_IWDT_Reset,
	Test_IWDT_Wakeup,
    Test_IWDT_Window,
    */
    
    IWDT_Test(Test_IWDT_Reset);

}








