/*
 * Copyright 2020-2021 YTMicro
 * All rights reserved.
 *
 * YTMicro Confidential. This software is owned or controlled by YTMicro and may
 * only be used strictly in accordance with the applicable license terms. By expressly
 * accepting such terms or by downloading, installing, activating and/or otherwise
 * using the software, you are agreeing that you have read, and that you agree to
 * comply with and are bound by, such license terms. If you do not agree to be
 * bound by the applicable license terms, then you may not retain, install,
 * activate or otherwise use the software. The production use license in
 * Section 2.3 is expressly granted for this software.
 */

/**
 * @page misra_violations MISRA-C:2012 violations list
 *
 * PRQA S 3684 Rule-8.11: When an array with external linkage is declared, its size should be explicitly specified
 * PRQA S 2983 Rule-2.2: There shall be no dead code
 * PRQA S 0306 Rule-11.4: A conversion should not be performed between a pointer to object and an integer type
 * PRQA S 2871 Dir-4.1: Run-time failures shall be minimized
 * PRQA S 2990 Rule 14.3: Controlling expressions shall not be invariant
 */

#include "startup.h"
#include "Std_Types.h"

#if defined(CPU_YTM32B1ME0) || defined(CPU_YTM32B1MD1)
#include "core_CM33_scb.h"
#endif

#if defined(TESSY) || defined(TEST)
#include "inc/fakeCM33Scb.h"
#endif

#define PLATFORM_START_SEC_CODE
#include "Platform_MemMap.h"

/*******************************************************************************
 * Code
 ******************************************************************************/

/*FUNCTION**********************************************************************
 *
 * Function Name : init_data_bss
 * Description   : Make necessary initializations for RAM.
 * - Copy the vector table from ROM to RAM.
 * - Copy initialized data from ROM to RAM.
 * - Copy code that should reside in RAM from ROM
 * - Clear the zero-initialized data section.
 *
 * Tool Chains:
 *   __GNUC__           : GNU Compiler Collection
 *   __ghs__            : Green Hills ARM Compiler
 *   __ICCARM__         : IAR ARM Compiler
 *   __DCC__            : Wind River Diab Compiler
 *   __ARMCC_VERSION    : ARMC Compiler
 *
 * Implements    : init_data_bss_Activity
 *END**************************************************************************/
PLATFORM_FUNC void init_data_bss(void)
{
    uint32 n;
/* For ARMC we are using the library method of initializing DATA, Custom Section and
 * Code RAM sections so the below variables are not needed */
#if !defined(__ARMCC_VERSION)
    /* Declare pointers for various data sections. These pointers
     * are initialized using values pulled in from the linker file */
    uint32 * data_ram;
    uint32 * code_ram;
#if defined(__GNUC__)    
    uint32 * init_ram;
#endif    
    uint32 * bss_start;
    uint32 * custom_ram;
    const uint32 * data_rom, * data_rom_end;
    const uint32 * code_rom, * code_rom_end;
#if defined(__GNUC__)
    const uint32 * init_rom, * init_rom_end;
#endif    
    const uint32 * bss_end;
    const uint32 * custom_rom, * custom_rom_end;
#if defined(__ICCARM__)
    uint32 * mcal_bss_start;
    uint32 * mcal_data_ram;
    const uint32 * mcal_bss_end;
    const uint32 * mcal_data_rom, * mcal_data_rom_end;
#endif
#endif
    /* Addresses for VECTOR_TABLE and VECTOR_RAM come from the linker file */

#if defined(__ARMCC_VERSION)

/*  
*  MR12 Rule-8.11 VIOLATION: The array __RAM_VECTOR_TABLE_SIZE/__VECTOR_ROM/__VECTOR_RAM are symbols generated by linker file
*                            The usage is well-validated on the support toolchains and can work as expected.
*/
    extern uint32 __RAM_VECTOR_TABLE_SIZE;  /* PRQA S 3684 */
    extern uint32 __VECTOR_ROM;             /* PRQA S 3684 */
    extern uint32 __VECTOR_RAM;             /* PRQA S 3684 */
#else
    extern uint32 __RAM_VECTOR_TABLE_SIZE[]; /* PRQA S 3684 */
    extern uint32 __VECTOR_TABLE[];          /* PRQA S 3684 */
    extern uint32 __VECTOR_RAM[];            /* PRQA S 3684 */
#endif
    /* Get section information from linker files */
#if defined(__ICCARM__)
    /* Data */
    data_ram        = __section_begin(".data");
    data_rom        = __section_begin(".data_init");
    data_rom_end    = __section_end(".data_init");

    /* MCAL Data */
    #pragma section = "__MCAL_DATA_ROM"
    #pragma section = "__MCAL_DATA_RAM"
    mcal_data_ram        = __section_begin("__MCAL_DATA_RAM");
    mcal_data_rom        = __section_begin("__MCAL_DATA_ROM");
    mcal_data_rom_end    = __section_end("__MCAL_DATA_ROM");

    /* CODE RAM */
    #pragma section = "__CODE_ROM"
    #pragma section = "__CODE_RAM"
    code_ram        = __section_begin("__CODE_RAM");
    code_rom        = __section_begin("__CODE_ROM");
    code_rom_end    = __section_end("__CODE_ROM");

    /* BSS */
    bss_start       = __section_begin(".bss");
    bss_end         = __section_end(".bss");

    /* MCAL BSS */
    #pragma section = ".mcal_bss"
    mcal_bss_start  = __section_begin(".mcal_bss");
    mcal_bss_end    = __section_end(".mcal_bss");

    custom_ram      = __section_begin(".customSection");
    custom_rom      = __section_begin(".customSection_init");
    custom_rom_end  = __section_end(".customSection_init");
    
#elif defined (__ARMCC_VERSION)
    /* VECTOR TABLE*/
    uint8 * vector_table_size = (uint8 *)__RAM_VECTOR_TABLE_SIZE;
    uint32 * vector_rom    = (uint32 *)__VECTOR_ROM;
    uint32 * vector_ram    = (uint32 *)__VECTOR_RAM;
#else
/*  
*  MR12 Rule-8.11 VIOLATION: The array __DATA_ROM/__DATA_RAM/__DATA_END are symbols generated by linker file
*                            The usage is well-validated on the support toolchains and can work as expected.
*/
    extern uint32 __DATA_ROM[];  /* PRQA S 3684 */
    extern uint32 __DATA_RAM[];  /* PRQA S 3684 */
    extern uint32 __DATA_END[];  /* PRQA S 3684 */

/*  
*  MR12 Rule-8.11 VIOLATION: The array __CODE_RAM/__CODE_ROM/__CODE_END are symbols generated by linker file
*                            The usage is well-validated on the support toolchains and can work as expected.
*/
    extern uint32 __CODE_RAM[];  /* PRQA S 3684 */
    extern uint32 __CODE_ROM[];  /* PRQA S 3684 */
    extern uint32 __CODE_END[];  /* PRQA S 3684 */
  
/*  
*  MR12 Rule-8.11 VIOLATION: The array LIN_CONST/__PREINIT_END/__INIT_END are symbols generated by linker file
*                            The usage is well-validated on the support toolchains and can work as expected.
*/
    extern uint32 __init_array_start[]; /* PRQA S 3684 */
    extern uint32 __PREINIT_END[];      /* PRQA S 3684 */
    extern uint32 __INIT_END[];         /* PRQA S 3684 */

/*  
*  MR12 Rule-8.11 VIOLATION: The array __BSS_START/__BSS_END are symbols generated by linker file
*                            The usage is well-validated on the support toolchains and can work as expected.
*/
    extern uint32 __BSS_START[];        /* PRQA S 3684 */
    extern uint32 __BSS_END[];          /* PRQA S 3684 */

/*  
*  MR12 Rule-8.11 VIOLATION: The array __CUSTOM_ROM/__CUSTOM_END are symbols generated by linker file
*                            The usage is well-validated on the support toolchains and can work as expected.
*/
    extern uint32 __CUSTOM_ROM[];       /* PRQA S 3684 */
    extern uint32 __CUSTOM_END[];       /* PRQA S 3684 */

    /* Data */
    data_ram        = (uint32 *)__DATA_RAM;
    data_rom        = (uint32 *)__DATA_ROM;
    data_rom_end    = (uint32 *)__DATA_END;

/*  
*  MR12 Rule-2.2 VIOLATION:  The rom copy form code ram, init array and bss as well as custom section  are different for different toolchains
*                            The usage is well-validated on the support toolchains and can work as expected.
*/
    /* CODE RAM */
    code_ram        = (uint32 *)__CODE_RAM;    /* PRQA S 2983 */
    code_rom        = (uint32 *)__CODE_ROM;    /* PRQA S 2983 */
    code_rom_end    = (uint32 *)__CODE_END;    /* PRQA S 2983 */
    /* init array */
    init_ram        = (uint32 *)__init_array_start;  /* PRQA S 2983 */
    init_rom        = (uint32 *)__PREINIT_END;       /* PRQA S 2983 */
    init_rom_end    = (uint32 *)__INIT_END;          /* PRQA S 2983 */
    /* BSS */
    bss_start       = (uint32 *)__BSS_START;   /* PRQA S 2983 */
    bss_end         = (uint32 *)__BSS_END;     /* PRQA S 2983 */

	/* Custom section */
    custom_ram      = CUSTOMSECTION_SECTION_START;  /* PRQA S 2983 */
    custom_rom      = (uint32 *)__CUSTOM_ROM;       /* PRQA S 2983 */
    custom_rom_end  = (uint32 *)__CUSTOM_END;       /* PRQA S 2983 */

#endif

#if !defined(__ARMCC_VERSION)
    /* Copy initialized data from ROM to RAM */
/*  
*  MR12 Rule-14.3/Di-4.1 VIOLATION: The data_rom_end and data_rom are generated symbols during link accoring to the linker file
*                            The usage is well-validated on the support toolchains and can work as expected.
*/
    while (data_rom_end != data_rom)/* PRQA S 2990,2871 */
    {
        *data_ram = *data_rom;
        data_ram++;
        data_rom++;
    }

    /* Copy functions from ROM to RAM */
    while (code_rom_end != code_rom)
    {
        *code_ram = *code_rom;
        code_ram++;
        code_rom++;
    }

#if defined(__GNUC__)
    /* Init functions from ROM to RAM */
    while (init_rom_end != init_rom)
    {
        *init_ram = *init_rom;
        init_ram++;
        init_rom++;
    }
#endif

    /* Clear the zero-initialized data section */
    while(bss_end > bss_start)
    {
        *bss_start = 0;
        bss_start++;
    }

    /* Copy customsection rom to ram */
    while(custom_rom_end != custom_rom)
    {
        *custom_ram = *custom_rom;
        custom_rom++;
        custom_ram++;
    }
#if !defined(__GNUC__)
    /* Copy initialized MCAL data from ROM to RAM with 4-byte aligned. */
    while (mcal_data_rom_end != mcal_data_rom)
    {
        *mcal_data_ram = *mcal_data_rom;
        mcal_data_ram++;
        mcal_data_rom++;
    }
    
    /* Clear the MCAL zero-initialized data section */
    while(mcal_bss_end > mcal_bss_start)
    {
        *mcal_bss_start = 0;
        mcal_bss_start++;
    }
#endif
#endif /* __ARMCC_VERSION */

#if defined (__ARMCC_VERSION)
        /* Copy the vector table from ROM to RAM */
                /* Workaround */
        for (n = 0; n < (((uint32)(vector_table_size))/sizeof(uint32)); n++)
        {
            vector_ram[n] = vector_rom[n];
        }
        /* Point the VTOR to the position of vector table */
        CM33_SCB->VTOR = (uint32) __VECTOR_RAM;
#else
    /* Check if VECTOR_TABLE copy is needed */
    if (__VECTOR_RAM != __VECTOR_TABLE)
    {
        /* Copy the vector table from ROM to RAM */
/*  
*  MR12 Rule-11.4 VIOLATION: The__RAM_VECTOR_TABLE_SIZE is a generated 32bit symbols during link, it has no risk to cast it to an integral type
*                            The usage is well-validated on the support toolchains and can work as expected.
*/
        for (n = 0; n < (((uint32)__RAM_VECTOR_TABLE_SIZE)/sizeof(uint32)); n++)  /* PRQA S 0306 */
        {
            __VECTOR_RAM[n] = __VECTOR_TABLE[n];
        }
        /* Point the VTOR to the position of vector table */
/*  
*  MR12 Rule-11.4 VIOLATION: __VECTOR_RAM is a generated 32bit symbols during link, it has no risk to cast it to an integral type
*                            The usage is well-validated on the support toolchains and can work as expected.
*/
        CM33_SCB->VTOR = (uint32) __VECTOR_RAM; /* PRQA S 0306 */
    }
    else
    {
        /* Point the VTOR to the position of vector table */
/*  
*  MR12 Rule-11.4 VIOLATION: __VECTOR_RAM is a generated 32bit symbols during link, it has no risk to cast it to an integral type
*                            The usage is well-validated on the support toolchains and can work as expected.
*/
        CM33_SCB->VTOR = (uint32) __VECTOR_RAM; /* PRQA S 0306 */
    }
#endif /* __ARMCC_VERSION */
    /* Enable CP10 and CP11 coprocessors */
    CM33_SCB->CPACR |= (CM33_SCB_CPACR_CP10_MASK | CM33_SCB_CPACR_CP11_MASK);
}

#define PLATFORM_STOP_SEC_CODE
#include "Platform_MemMap.h"

/*******************************************************************************
 * EOF
 ******************************************************************************/

