/*********************************************************
*Copyright (C), 2018, Shanghai Eastsoft Microelectronics Co., Ltd
*文件名:  ES_STL_fullRamMC.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 ------------------------------------------------------------*/
#define RAM_BLOCKSIZE         ((uint32_t)16)
static const uint8_t RAM_SCRMBL[RAM_BLOCKSIZE] = {0u, 1u, 3u, 2u, 4u, 5u, 7u, 6u, 8u, 9u, 11u, 10u, 12u, 13u, 15u, 14u};
static const uint8_t RAM_REVSCRMBL[RAM_BLOCKSIZE] = {1u, 0u, 2u, 3u, 5u, 4u, 6u, 7u, 9u, 8u, 10u, 11u, 13u, 12u, 14u, 15u};

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/**
  * @brief  This function verifies that RAM is functional,
  *   using the March C- algorithm.
  * @param :  None
  *   at the exception of CtrlFlowCntInv, set to 0xFFFFFFFF.
  * @retval : ErrorStatus = (ERROR, SUCCESS)
  */
ErrorStatus STL_FullRamMarchC(void)
{
    ErrorStatus Result = SUCCESS;
    uint32_t *p;       /* RAM pointer */
    uint32_t j;        /* Index for RAM physical addressing */

#ifdef __IAR_SYSTEMS_ICC__  /* IAR Compiler */
    uint32_t ra = __get_LR(); /* save return address (as it will be destryed) */
#endif /* IAR Compiler */
#ifdef __CC_ARM   /* KEIL Compiler */
    uint32_t ra = __return_address(); /* save return address (as it will be destryed) */
#endif /* KEIL Compiler */
    /* CtrlFlowCnt not used at function entry, since it will be cleared by the
      routine. CtrlFlowCntInv is written at the function exit */

    /* ---------------------------- STEP 1 ----------------------------------- */
    /* Write background with addresses increasing */
    for (p = RAM_START; p <= RAM_END; p++)
    {
        /* Scrambling not important when there's no consecutive verify and write */
        *p = UINT32_ALL_00;
    }

    /* ---------------------------- STEP 2 ----------------------------------- */
    /* Verify background and write inverted background with addresses increasing */
    for (p = RAM_START; p <= RAM_END; p += RAM_BLOCKSIZE)
    {
        for (j = 0u; j < RAM_BLOCKSIZE; j++)
        {
            if (*(p + (uint32_t)RAM_SCRMBL[j]) != UINT32_ALL_00)
            {
                Result = ERROR;
            }

            *(p + (uint32_t)RAM_SCRMBL[j]) = UINT32_ALL_FF;
        }
    }

    /* ---------------------------- STEP 3 ----------------------------------- */
    /* Verify inverted background and write background with addresses increasing */
    for (p = RAM_START; p <= RAM_END; p += RAM_BLOCKSIZE)
    {
        for (j = 0u; j < RAM_BLOCKSIZE; j++)
        {
            if (*(p + (uint32_t)RAM_SCRMBL[j]) != UINT32_ALL_FF)
            {
                Result = ERROR;
            }

            *(p + (uint32_t)RAM_SCRMBL[j]) = UINT32_ALL_00;
        }
    }

    /* ---------------------------- STEP 4 ----------------------------------- */
    /* Verify background and write inverted background with addresses decreasing */
    for (p = RAM_END; p > RAM_START; p -= RAM_BLOCKSIZE)
    {
        for (j = 0u; j < RAM_BLOCKSIZE; j++)
        {
            if (*(p - (uint32_t)RAM_REVSCRMBL[j]) != UINT32_ALL_00)
            {
                Result = ERROR;
            }

            *(p - (uint32_t)RAM_REVSCRMBL[j]) = UINT32_ALL_FF;
        }
    }

    /* ---------------------------- STEP 5 ----------------------------------- */
    /* Verify inverted background and write background with addresses decreasing */
    for (p = RAM_END; p > RAM_START; p -= RAM_BLOCKSIZE)
    {
        for (j = 0u; j < RAM_BLOCKSIZE; j++)
        {
            if (*(p - (uint32_t)RAM_REVSCRMBL[j]) != UINT32_ALL_FF)
            {
                Result = ERROR;
            }

            *(p - (uint32_t)RAM_REVSCRMBL[j]) = UINT32_ALL_00;
        }
    }

    /* ---------------------------- STEP 6 ----------------------------------- */
    /* Verify background with addresses increasing */
    for (p = RAM_START; p <= RAM_END; p++)
    {
        if (*p != UINT32_ALL_00)
        {
            Result = ERROR;    /* No need to take into account scrambling here */
        }
    }

    /* As all SRAM is zeroed CtrlFlowCntInv is re-initialized here to be inverse */
    CtrlFlowCntInv = 0xFFFFFFFFuL;

    /* Restore destroyed return address back into the stack (all the content is destroyed).
      Next line of code supposes the {r4-r7,pc} for Keil and {r4-r5,pc} for IAR registers
      only was saved into stack by this test so their restored values are not valid:
      => optiomizations at caller must be switched off as caller cannot relay on r4-r7 values!!! */

#ifdef __IAR_SYSTEMS_ICC__  /* IAR Compiler */
    *((uint32_t *)(__get_SP()) + 3u) = ra;
#endif /* IAR Compiler */
#ifdef __CC_ARM   /* KEIL Compiler */
    *((uint32_t *)(__current_sp()) + 2u) = ra;
#endif /* KEIL Compiler */
    return (Result);
}

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