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

#define ALLOC_GLOBALS
#include "ES_STLclassBvar.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
void STL_SystemInit(void);
void STL_UARTInit(void);

/*--------------------------------------------------------------------------*/
/*----------------------- Fail safe startup routine ------------------------*/
/*--------------------------------------------------------------------------*/
/**
  * @brief  Contains the Fail Safe routine executed in case of
  *   failure detected during one of the POR self-test routines
  * @param : None
  * @retval : None
  */
void FailSafePOR(void)
{
    SysTick_Disable();

#ifdef STL_VERBOSE_PRINTF
    printf(" >>>>>>>>>> POR FailSafe Mode <<<<<<<<<<\n\r");
#endif

    while (1)
    {
#if 1
        NVIC_SystemReset();
#else
        IWDT_Clear();
#endif
    }
}

#ifdef __CC_ARM
/**
  * @brief  Switch between startup and main code
  * @param  None
  * @retval  None
  */
void $Sub$$main(void)
{
    /* default execute STL_StartUp()*/
    if (T32N0->CON0.EN == 0)
    {
        /* trick to call StartUp before main entry */
        STL_StartUp();
    }

    /* Reset startup flag */
    T32N0_Disable();
    T32Nx_SetCNT(T32N0, 0);

    $Super$$main();
}
#endif /* __CC_ARM */

#ifdef __IAR_SYSTEMS_ICC__
extern int main(void);
extern void __iar_data_init3(void);

/**
  * @brief  Switch between startup and main code
  * @param  None
  * @retval  None
  */
int __low_level_init(void)
{
    __iar_data_init3();

    /* default execute STL_StartUp()*/
    if (T32N0->CON0.EN == 0)
    {
        /* trick to call StartUp before main entry */
        STL_StartUp();
    }

    /* Reset startup flag */
    T32N0_Disable();;
    T32Nx_SetCNT(T32N0, 0);

    main();

    return 0;
}
#endif /* __IAR_SYSTEMS_ICC__ */

/**
  * @brief  Contains the very first test routines executed right after
  *   the reset
  * @param :  None
  *   Flash interface initialized, Systick timer ON (2ms timebase)
  * @retval : None
  */
void STL_StartUp(void)
{
    STL_SystemInit();

#ifdef STL_VERBOSE_PRINTF
    STL_UARTInit();         //打印信息接口初始化（硬件串口IO一定上拉！！！）
#endif

#ifdef STL_VERBOSE_PRINTF
    printf("\n\n\r *******STL_StartUp: Self Test Library Init*******\n\r");
#endif

    /*------------------- CPU registers and Flags Self Test --------------------*/
    /* WARNING: all registers destroyed when exiting this function (including
    preserved registers R4 to R11) and excluding stack point R13) */

    /* Initializes counter for control flow monitoring */
    CtrlFlowCnt = CPU_TEST_CALLER;
    CtrlFlowCntInv = 0xFFFFFFFFuL;

    if (STL_StartUpCPUTest() != CPU_TEST_SUCCESSFUL)
    {
#ifdef STL_VERBOSE_PRINTF
        printf("\n\n\r STL_StartUp: CPU Test Failure\n\r");
#endif
        FailSafePOR();
    }
    else  /* Test OK */
    {
        /* If else statement is not executed, it will be detected by control flow monitoring */
        CtrlFlowCntInv -= CPU_TEST_CALLER;
#ifdef STL_VERBOSE_PRINTF
        printf("\n\n\r STL_StartUp: CPU Test OK\n\r");
#endif
    }

    /*------------------------- Watch dogs Self Test ---------------------------*/
    CtrlFlowCnt += WDG_TEST_CALLER;
    STL_WDGSelfTest();
    CtrlFlowCntInv -= WDG_TEST_CALLER;
#ifdef STL_VERBOSE_PRINTF
    printf("\n\n\r STL_StartUp: WDT Test OK\n\r");
#endif

    /*-------------------- Clock Start Up operation --------------------*/
    CtrlFlowCnt += CLOCK_TEST_CALLER;

    if (STL_ClockStartUpTest() != ClockStatus_TEST_SUCCESSFUL)
    {
#ifdef STL_VERBOSE_PRINTF
        printf("\n\n\r STL_StartUp: Clock StartUp Failure!\n\r");
#endif
        FailSafePOR();
    }
    else
    {
        CtrlFlowCntInv -= CLOCK_TEST_CALLER;
#ifdef STL_VERBOSE_PRINTF
        printf("\n\n\r STL_StartUp: Clock StartUp test OK!\n\r");
#endif
    }

    /*---------------------- CRC16 operation ----------------------*/
    if (STL_crc16(CRC_INIT, (uint8_t *)FLASH_START, FLASH_SIZE) != __checksum)
    {
#ifdef STL_VERBOSE_PRINTF
        printf("\n\n\r FLASH 16-bit CRC Error at Start-up\n\r");
#endif
        FailSafePOR();
    }
    else
    {
#ifdef STL_VERBOSE_PRINTF
        printf("\n\n\r FLASH 16-bit CRC OK at Start-up\n\r");
#endif
    }

    /* ----- Verify Control flow before Starting main program execution ------ */
    if (((CtrlFlowCnt ^ CtrlFlowCntInv) != 0xFFFFFFFFuL))
    {
#ifdef STL_VERBOSE_PRINTF
        printf("\n\n\r Control Flow Checkpoint1 Failure \n\r");
#endif
        FailSafePOR();
    }
    else
    {
#ifdef STL_VERBOSE_PRINTF
        printf("\n\n\r Control Flow Checkpoint1 OK \n\r");
#endif
    }


    /* --------------------- Variable memory functional test -------------------*/
    /* WARNING: Stack is zero-initialized when exiting from this routine */
    if (STL_FullRamMarchC() != SUCCESS)
    {
#ifdef STL_VERBOSE_PRINTF
        printf("\n\n\r RAM Test Failure\n\r");
#endif
        FailSafePOR();
    }
    else
    {
#ifdef STL_VERBOSE_PRINTF
        printf("\n\n\r Full RAM Test OK\n\r");
#endif
    }

    /* ----- Store verify pattern to stack bottom for its later testing  ----- */
    CtrlFlowCnt += STACK_OVERFLOW_TEST;
    StackOverFlowPtrn[0] = 0xAAAAAAAAuL;
    StackOverFlowPtrn[1] = 0xBBBBBBBBuL;
    StackOverFlowPtrn[2] = 0xCCCCCCCCuL;
    StackOverFlowPtrn[3] = 0xDDDDDDDDuL;
    CtrlFlowCntInv -= STACK_OVERFLOW_TEST;

    /* ----- Verify Control flow before Starting main program execution ------ */
    if (((CtrlFlowCnt ^ CtrlFlowCntInv) != 0xFFFFFFFFuL))
    {
#ifdef STL_VERBOSE_PRINTF
        printf("\n\n\r Control Flow Checkpoint2 Failure \n\r");
#endif
        FailSafePOR();
    }
    else
    {
#ifdef STL_VERBOSE_PRINTF
        printf("\n\n\r Control Flow Checkpoint2 OK \n\r");
#endif
    }

#ifdef STL_VERBOSE_PRINTF
    printf("\n\n\r *******STL_StartUp: GotoCompilerStartUp *******\n\r");
#endif

    GotoCompilerStartUp()
}
/*********************************************************
函数名: void STL_UARTInit(void)
描  述: STL_UARTInit初始化子程序
输入值: 无
输出值: 无
返回值: 无
**********************************************************/
void STL_UARTInit(void)
{
    GPIO_InitStruType x;
    UART_InitStruType y;

    x.GPIO_Signal = GPIO_Pin_Signal_Digital;
    x.GPIO_Func = GPIO_Func_2;
    x.GPIO_Direction = GPIO_Dir_Out;
    x.GPIO_PUEN = GPIO_PUE_Input_Disable;
    x.GPIO_PDEN = GPIO_PDE_Input_Disable;
    x.GPIO_OD = GPIO_ODE_Output_Disable;
    x.GPIO_DS = GPIO_DS_Output_Normal;
    GPIO_Init(GPIOA, GPIO_Pin_15, &x);               //PA15---TxD

    x.GPIO_Signal = GPIO_Pin_Signal_Digital;
    x.GPIO_Func = GPIO_Func_2;
    x.GPIO_Direction = GPIO_Dir_In;
    x.GPIO_PUEN = GPIO_PUE_Input_Disable;
    x.GPIO_PDEN = GPIO_PDE_Input_Disable;
    x.GPIO_OD = GPIO_ODE_Output_Disable;
    x.GPIO_DS = GPIO_DS_Output_Normal;
    GPIO_Init(GPIOA, GPIO_Pin_16, &x);               //PA16---RxD

    y.UART_StopBits = UART_StopBits_1;          //停止位：1
    y.UART_TxMode = UART_DataMode_8;            //发送数据格式：8位数据
    y.UART_TxPolar = UART_Polar_Normal;         //发送端口极性：正常
    y.UART_RxMode = UART_DataMode_8;            //接收数据格式：8位数据
    y.UART_RxPolar = UART_Polar_Normal;         //接收端口极性：正常
    y.UART_BaudRate = 9600;                     //波特率
    y.UART_ClockSet = UART_Clock_4;             //时钟选择：Pclk/4
    UART_Init(UART2, &y);

    UART_TBIMConfig(UART2, UART_TRBIM_Byte);
    UART_RBIMConfig(UART2, UART_TRBIM_Byte);
    UART_ITConfig(UART2, UART_IT_RB, ENABLE);
    //NVIC_Init(NVIC_UART2_IRQn, NVIC_Priority_1, ENABLE);
    UART2_TxEnable();                               //UART2发送使能
    UART2_RxEnable();
}

/* ============================================================================ */
/**
  * @brief  Verifies the watchdog by forcing watchdog resets
  * @param :  None
  * @retval : None
  */
void STL_WDGSelfTest(void)
{
    IWDT_InitStruType x;

    if (SCU->PWRC.IWDTRSTF == 1)//已经发生过WDT复位
    {
        /* do nothing */
    }
    else                       //没有发生过WDT复位，则需要测试是否可以正常WDT复位
    {
        SCU_RegUnLock();
        SCU->PWRC.PORRSTF = 0;
        SCU_RegUnLock();
        //需要将配置字中WDT禁止！！！！！
        IWDT_RegUnLock();
        x.WDT_Tms = 10;           //喂狗周期10ms
        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);
#ifdef STL_VERBOSE_PRINTF
        printf("\n\n\r Waiting  for WDT reset\n\r");
#endif

        while (1);
    }

    IWDT_Clear();

    IWDT_RegUnLock();
    IWDT_Disable();
    IWDT_RegLock();
}

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