/*********************************************************
*Copyright (C), 2018, Shanghai Eastsoft Microelectronics Co., Ltd
*文件名:  ES_STLmain.c
*作  者:  Eastsoft AE Team
*版  本:  V1.00
*日  期:  2018/06/21
*描  述:  CLASSB
*备  注:
          本软件仅供学习和演示使用，对用户直接引用代码所带来的风险或后果不承担任何法律责任。
**********************************************************/
/* Includes ------------------------------------------------------------------*/
#include "lib_config.h"
#include "ES_STL_param.h"
#include "ES_STLclassBvar.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
ClockStatus STL_MainClockTest(void);
ErrorStatus STL_CheckStack(void);
ClockStatus STL_ClockFreqTest(void);
/**
  * @brief Initializes the Class B variables and their inverted
  *   redundant counterparts. Init also the Systick and RTC timer
  *   for clock frequency monitoring.
  * @param :  None
  * @retval : None
  */
void STL_InitRunTimeChecks(void)
{
    /* Init Class B variables required in main routine and SysTick interrupt
    service routine for timing purposes */
    TickCounter = 0uL;
    TickCounterInv = 0xFFFFFFFFuL;

    TimeBaseFlag = 0uL;
    TimeBaseFlagInv = 0xFFFFFFFFuL;

    /* Initialize variables for SysTick interrupt routine control flow monitoring */
    ISRCtrlFlowCnt = 0uL;
    ISRCtrlFlowCntInv = 0xFFFFFFFFuL;

    /* Initialize variables for invariable memory check */
    STL_TranspMarchCInit();

    /* Initialize variables for run time invariable memory check */
    STL_FlashCrc16Init();

#if 0
    Init_system_wdogs();
#endif

    /* Initialize variables for main routine control flow monitoring */
    CtrlFlowCnt = 0uL;
    CtrlFlowCntInv = 0xFFFFFFFFuL;
    /* Initialize  variables for run time invariable clock check*/
    CurrentRTCPeriod = SYSTICK_1S_TB;
    CurrentRTCPeriodInv = ~SYSTICK_1S_TB;
    LastRTCPeriod = SYSTICK_1S_TB;
    LastRTCPeriodInv = ~SYSTICK_1S_TB;
    AbandonTimes = 2ul;
    AbandonTimesInv = ~2ul;
}

/* ---------------------------------------------------------------------------*/
/**
  * @brief  Provide a short description of the function
  * @param :  None
  * @retval : None
  */
void STL_DoRunTimeChecks(void)
{
    uint32_t FlashTest;
    uint32_t TmpFlag;

    /* Is the time base duration elapsed? */
    if (TimeBaseFlag == 0xAAAAAAAAuL)
    {
        TmpFlag = TimeBaseFlagInv;

        /* Verify its integrity (class B variable) */
        if ((TimeBaseFlag ^ TmpFlag) == 0xFFFFFFFFuL)
        {
            /* Reset Flag (no need to reset the redundant: it is not tested if
            TimeBaseFlag != 0xAAAAAAAA, it means that 100ms elapsed */
            TimeBaseFlag = 0uL;

            /*----------------------------------------------------------------------*/
            /*---------------------------- CPU registers ----------------------------*/
            /*----------------------------------------------------------------------*/
            CtrlFlowCnt += CPU_TEST_CALLER;

            if (STL_RunTimeCPUTest() != CPU_TEST_SUCCESSFUL)
            {
#ifdef STL_VERBOSE_PRINTF
                printf("Run-time CPU Test Failure\n\r");
#endif
                FailSafePOR();
            }
            else
            {
                CtrlFlowCntInv -= CPU_TEST_CALLER;
#ifdef STL_VERBOSE_PRINTF
                printf("Run-time CPU Test Successful\n\r");
#endif
            }

            /*----------------------------------------------------------------------*/
            /*------------------------- Stack overflow -----------------------------*/
            /*----------------------------------------------------------------------*/
            CtrlFlowCnt += STACK_OVERFLOW_TEST;

            if (STL_CheckStack() != SUCCESS)
            {
#ifdef STL_VERBOSE_PRINTF
                printf("Stack overflow\n\r");
#endif
                FailSafePOR();
            }
            else
            {
                CtrlFlowCntInv -= STACK_OVERFLOW_TEST;
#ifdef STL_VERBOSE_PRINTF
                printf("Stack overflow Test Successful\n\r");
#endif
            }

            /*----------------------------------------------------------------------*/
            /*------------------------- Clock monitoring ---------------------------*/
            /*----------------------------------------------------------------------*/
            CtrlFlowCnt += CLOCK_TEST_CALLER;

            if (STL_ClockFreqTest() != ClockStatus_TEST_SUCCESSFUL)
            {
#ifdef STL_VERBOSE_PRINTF
                printf("Clock error %d\n\r", LastRTCPeriod);
#endif
                FailSafePOR();
            }
            else
            {
                CtrlFlowCntInv -= CLOCK_TEST_CALLER;
#ifdef STL_VERBOSE_PRINTF
                printf("Clock Test Successful %d\n\r", LastRTCPeriod);
#endif
            }

            /*----------------------------------------------------------------------*/
            /*------------------ Invariable memory CRC check -----------------------*/
            /*----------------------------------------------------------------------*/
            CtrlFlowCnt += FLASH_TEST_CALLER;

            FlashTest = STL_crc16Run();

            switch (FlashTest)
            {
                case TEST_RUNNING:
                    CtrlFlowCntInv -= FLASH_TEST_CALLER;
                    break;

                case TEST_OK:
                    CtrlFlowCntInv -= FLASH_TEST_CALLER;
#ifdef STL_VERBOSE_PRINTF
                    printf("Flash Test Successful\n\r");
#endif
                    break;

                case TEST_FAILURE:
                case CLASS_B_DATA_FAIL:
                default:
#ifdef STL_VERBOSE_PRINTF
                    printf("\n\r Run-time FLASH CRC Error\n\r");
#endif
                    FailSafePOR();
                    break;
            }

            /*----------------------------------------------------------------------*/
            /*---------------- Check Safety routines Control flow  -----------------*/
            /*------------- Refresh Window and independent watchdogs ---------------*/
            /*----------------------------------------------------------------------*/
            IWDT_Clear();

            if ((CtrlFlowCnt ^ CtrlFlowCntInv) == 0xFFFFFFFFuL)
            {
                if (FlashTest == TEST_OK)                 //FLASH test finish
                {
                    CtrlFlowCnt = 0uL;
                    CtrlFlowCntInv = 0xFFFFFFFFuL;
                }
            }
            else
            {
#ifdef STL_VERBOSE_PRINTF
                printf("Control Flow Error (main loop)\n\r");
#endif
                FailSafePOR();
            }
        } /* End of periodic Self-test routine */
        else  /* Class B variable error (can be Systick interrupt lost) */
        {
#ifdef STL_VERBOSE_PRINTF
            printf("\n\r Class B variable error (clock test)\n\r");
#endif
            FailSafePOR();
        }
    } /* End of periodic Self-test routine */
}

/* ---------------------------------------------------------------------------*/
/**
  * @brief  This function verifies the frequency using the measurement
  *   done in Systick interrupt.
  * @param :  None
  * @retval : ClockStatus = (LSI_START_FAIL, HSE_START_FAIL,
  *   HSI_HSE_SWITCH_FAIL, TEST_ONGOING, EXT_SOURCE_FAIL,
  *   CLASS_B_VAR_FAIL, CTRL_FLOW_ERROR, FREQ_OK)
  */
ClockStatus STL_MainClockTest(void)
{
    ClockStatus Result = ClockStatus_TEST_FAIL;

    CtrlFlowCnt += CLOCK_TEST_CALLEE;

    if (SCU_GetSysClk() != SCU_SysClk_HRC)
    {
        Result = ClockStatus_TEST_FAIL;
    }
    else
    {
        Result = ClockStatus_TEST_SUCCESSFUL;
    }

    CtrlFlowCntInv -= CLOCK_TEST_CALLEE;

    return (Result);
}

/* ---------------------------------------------------------------------------*/
/**
  * @brief  This function verifies that Stack didn't overflow
  * @param :  None
  * @retval : ErrorStatus = (ERROR, SUCCESS)
  */
ErrorStatus STL_CheckStack(void)
{
    ErrorStatus Result = ERROR;

    CtrlFlowCnt += STACK_OVERFLOW_CALLEE;

    if (StackOverFlowPtrn[0] != 0xAAAAAAAAuL)
    {
        Result = ERROR;
    }
    else /* StackOverFlowPtrn[0] == 0xAAAAAAAA */
    {
        if (StackOverFlowPtrn[1] != 0xBBBBBBBBuL)
        {
            Result = ERROR;
        }
        else /* StackOverFlowPtrn[1] == 0xBBBBBBBB */
        {
            if (StackOverFlowPtrn[2] != 0xCCCCCCCCuL)
            {
                Result = ERROR;
            }
            else /* StackOverFlowPtrn[2] == 0xCCCCCCCC */
            {
                if (StackOverFlowPtrn[3] != 0xDDDDDDDDuL)
                {
                    Result = ERROR;
                }
                else
                {
                    Result = SUCCESS;
                }
            }
        }
    }

    CtrlFlowCntInv -= STACK_OVERFLOW_CALLEE;

    return (Result);
}

/* ---------------------------------------------------------------------------*/
/**
  * @brief  This function Init both independent & window system watch dogs
  * @param :  None
  * @retval None
  */
void Init_system_wdogs(void)
{
    IWDT_InitStruType x;

    //需要将配置字中WDT禁止！！！！！
    IWDT_RegUnLock();
    x.WDT_Tms = 2000;           //喂狗周期2s
    x.WDT_IE = DISABLE;
    x.WDT_Rst = ENABLE;
    x.WDT_Clock = WDT_CLOCK_WDT;
    IWDT_Init(&x);
    IWDT_Enable();               //WDT需在解锁里面Enable
    IWDT_RegLock();

    NVIC_Init(NVIC_IWDT_IRQn, NVIC_Priority_0, DISABLE);
}

/******************* (C) COPYRIGHT Eastsoft *****END OF FILE****/

