755 lines
29 KiB
C
755 lines
29 KiB
C
/**********************************************************************************************************************
|
|
* COPYRIGHT
|
|
* -------------------------------------------------------------------------------------------------------------------
|
|
* \verbatim
|
|
* Copyright (c) 2025 by Vector Informatik GmbH. All rights reserved.
|
|
*
|
|
* This software is copyright protected and proprietary to Vector Informatik GmbH.
|
|
* Vector Informatik GmbH grants to you only those rights as set out in the license conditions.
|
|
* All other rights remain with Vector Informatik GmbH.
|
|
* \endverbatim
|
|
* -------------------------------------------------------------------------------------------------------------------
|
|
* FILE DESCRIPTION
|
|
* -----------------------------------------------------------------------------------------------------------------*/
|
|
/** \file File: ARMStartup_CortexR.c
|
|
* Project: Vector Basic Runtime System
|
|
* Module: BrsHw for all platforms with ARM core Cortex-R
|
|
* Template: This file is reviewed according to Brs_Template@Implementation[1.03.12]
|
|
*
|
|
* \brief Description: This file contains the assembler part of the BRS StartUpCode.
|
|
*
|
|
* \attention Please note:
|
|
* The demo and example programs only show special aspects of the software. With regard to the fact
|
|
* that these programs are meant for demonstration purposes only, Vector Informatik liability shall be
|
|
* expressly excluded in cases of ordinary negligence, to the extent admissible by law or statute.
|
|
*********************************************************************************************************************/
|
|
|
|
/**********************************************************************************************************************
|
|
* REVISION HISTORY
|
|
* -------------------------------------------------------------------------------------------------------------------
|
|
* Refer to ARMBrsHw_CortexR.h.
|
|
*********************************************************************************************************************/
|
|
|
|
/**********************************************************************************************************************
|
|
* EXAMPLE CODE ONLY
|
|
* -------------------------------------------------------------------------------------------------------------------
|
|
* This Example Code is only intended for illustrating an example of a possible BSW integration and BSW configuration.
|
|
* The Example Code has not passed any quality control measures and may be incomplete. The Example Code is neither
|
|
* intended nor qualified for use in series production. The Example Code as well as any of its modifications and/or
|
|
* implementations must be tested with diligent care and must comply with all quality requirements which are necessary
|
|
* according to the state of the art before their use.
|
|
*********************************************************************************************************************/
|
|
|
|
#define ARMSTARTUP_CORTEXR_SOURCE
|
|
|
|
/**********************************************************************************************************************
|
|
* INCLUDES
|
|
*********************************************************************************************************************/
|
|
#include "BrsHw.h"
|
|
|
|
#if defined (BRS_FIRST_EXECUTION_INSTANCE)
|
|
/* This code is only needed for the first instance/executable in the system */
|
|
|
|
#include "vBrs_Lcfg.h"
|
|
#include "vLinkGen_Lcfg.h"
|
|
|
|
/**********************************************************************************************************************
|
|
* CONFIGURATION CHECK
|
|
*********************************************************************************************************************/
|
|
#if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
|
|
#else
|
|
#error "Unknown compiler specified!"
|
|
#endif
|
|
|
|
#if (VLINKGEN_CFG_MAJOR_VERSION != 2u)
|
|
#error "This StartUpCode is dependent to the vLinkGen version! vLinkGen major version does not fit!"
|
|
#else
|
|
# if (VLINKGEN_CFG_MINOR_VERSION < 5u)
|
|
#error "This StartUpCode is dependent to the vLinkGen version! Your vLinkGen minor version is too old!"
|
|
# endif
|
|
#endif
|
|
|
|
/**********************************************************************************************************************
|
|
* DEFINITION + MACROS
|
|
*********************************************************************************************************************/
|
|
#if defined (BRS_FIRST_EXECUTION_INSTANCE)
|
|
extern void intvect_CoreExceptions(void);
|
|
#endif
|
|
|
|
#if defined (BRS_ENABLE_OS_MULTICORESUPPORT)
|
|
extern ARMBrsHw_PhysicalCoreId_CoreExceptions_MappingType BrsHw_intvect_CoreExceptions_list[BRS_CPU_CORE_AMOUNT-1];
|
|
#endif
|
|
|
|
/**********************************************************************************************************************
|
|
* GLOBAL VARIABLES
|
|
*********************************************************************************************************************/
|
|
#if defined (BRS_ENABLE_OS_MULTICORESUPPORT)
|
|
/* used 32bit values for less assembler differences in accessing code */
|
|
const uint32 BrsHw_InitCoreID = (uint32) BRSHW_INIT_CORE_ID;
|
|
const uint32 BrsHw_CpuCoreAmountMinus1 = (uint32) (BRS_CPU_CORE_AMOUNT-1);
|
|
#endif
|
|
|
|
/**********************************************************************************************************************
|
|
* PROTOTYPES OF LOCAL FUNCTIONS
|
|
*********************************************************************************************************************/
|
|
BRS_LOCAL_PROTOTYPE(_start)
|
|
BRS_LOCAL_PROTOTYPE(brsStartupEntry)
|
|
BRS_LOCAL_PROTOTYPE(brsStartupInvalidateCache)
|
|
BRS_LOCAL_PROTOTYPE(brsStartupZeroInitLoop)
|
|
BRS_LOCAL_PROTOTYPE(brsStartupStackSearch)
|
|
BRS_LOCAL_PROTOTYPE(coreRegisterInit)
|
|
BRS_LOCAL_PROTOTYPE(coreRegisterInit2)
|
|
BRS_LOCAL_PROTOTYPE(coreRegisterInit3)
|
|
BRS_LOCAL_PROTOTYPE(stackPointerInit)
|
|
BRS_LOCAL_PROTOTYPE(brsPreAsmStartupHook)
|
|
|
|
|
|
/* =========================================================================== */
|
|
/* */
|
|
/* Description: Entry point for all cores */
|
|
/* */
|
|
/* =========================================================================== */
|
|
|
|
BRS_SECTION_CODE(brsStartup)
|
|
|
|
/* Alternativ entry point from OS default config */
|
|
BRS_GLOBAL(_start)
|
|
BRS_MULTILINE_ASM_BEGIN()
|
|
BRS_LABEL(_start)
|
|
BRS_MULTILINE_ASM_END()
|
|
BRS_GLOBAL_END()
|
|
|
|
BRS_GLOBAL(brsStartupEntry)
|
|
BRS_MULTILINE_ASM_BEGIN()
|
|
BRS_LABEL(brsStartupEntry)
|
|
#if defined (BRSHW_PRE_ASM_STARTUP_HOOK_AVAILABLE)
|
|
#endif
|
|
|
|
BRS_BRANCH(brsPreAsmStartupHook)
|
|
BRS_MULTILINE_ASM_END()
|
|
BRS_GLOBAL_END()
|
|
|
|
/* =========================================================================== */
|
|
/* */
|
|
/* Description: Optional hook for platform specific tasks */
|
|
/* */
|
|
/* =========================================================================== */
|
|
#if !defined (BRSHW_PRE_ASM_STARTUP_HOOK_AVAILABLE)
|
|
BRS_GLOBAL(brsPreAsmStartupHook)
|
|
BRS_MULTILINE_ASM_BEGIN()
|
|
BRS_LABEL(brsPreAsmStartupHook)
|
|
/* Nothing to do here */
|
|
|
|
BRS_BRANCH(coreRegisterInit)
|
|
BRS_MULTILINE_ASM_END()
|
|
BRS_GLOBAL_END()
|
|
#endif /*!BRSHW_PRE_ASM_STARTUP_HOOK_AVAILABLE*/
|
|
|
|
/* =========================================================================== */
|
|
/* */
|
|
/* Description: Initialize core ID independent core registers */
|
|
/* */
|
|
/* =========================================================================== */
|
|
BRS_GLOBAL(coreRegisterInit)
|
|
BRS_MULTILINE_ASM_BEGIN()
|
|
BRS_LABEL(coreRegisterInit)
|
|
|
|
/* Note: ARMStartup_CortexR.c must be compiled in ARM mode, since
|
|
* the exception table is implemented in ARM mode only
|
|
*/
|
|
__as1(LDR r0, =BrsStartupInstSetInit)
|
|
|
|
#if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
__as2(ORR r0 ,r0, 0)
|
|
#else
|
|
__as2(ORR r0 ,r0, #0)
|
|
#endif
|
|
___asm(BX r0)
|
|
|
|
|
|
BRS_LABEL(BrsStartupInstSetInit)
|
|
|
|
#if defined (BRS_FPU_USED)
|
|
/* Allow full access to coprocessors 10,11 */
|
|
/* r0 gets the content of the Coprocessor Access Control Register */
|
|
# if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
__as5(MRC p15, 0, r0, c1, c0, 2)
|
|
# else
|
|
__as5(MRC p15, #0x00, r0, c1, c0, #0x02)
|
|
# endif
|
|
|
|
__as2(ORR r0, r0, #0x00F00000)
|
|
/* Write Coprocessor Access Control Register to set access rights for coprocessor cp10, cp11 to full access
|
|
Note: Coprocessors cp10 and cp11 support floating-point and vector operations, and the control and configuration of
|
|
the Floating-point and Advanced SIMD architecture extensions. */
|
|
# if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
__as5(MCR p15, 0, r0, c1, c0, 2)
|
|
# else
|
|
__as5(MCR p15, #0x00, r0, c1, c0, #0x02)
|
|
# endif
|
|
|
|
/* Enable Advanced SIMD and Floating-point Extensions */
|
|
__as1(VMRS r0, FPEXC)
|
|
__as1(MOV r1, #0x40000000)
|
|
__as2(ORR r0, r0, r1)
|
|
__as1(VMSR FPEXC, r0)
|
|
#endif /*BRS_FPU_USED*/
|
|
|
|
/* Switch to System Mode */
|
|
__as1(MRS r0, CPSR)
|
|
#if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
__as2(ORR r0, r0, 0x1f)
|
|
__as1(MSR CPSR, r0)
|
|
#else
|
|
__as2(ORR r0, r0, #0x1f)
|
|
__as1(MSR cpsr_cxsf, r0)
|
|
#endif
|
|
|
|
BRS_BRANCH(coreRegisterInit2)
|
|
BRS_MULTILINE_ASM_END()
|
|
BRS_GLOBAL_END()
|
|
|
|
/* =========================================================================== */
|
|
/* */
|
|
/* Description: Initialize all core ID dependent core registers */
|
|
/* Setup exception table */
|
|
/* */
|
|
/* =========================================================================== */
|
|
BRS_GLOBAL(coreRegisterInit2)
|
|
BRS_MULTILINE_ASM_BEGIN()
|
|
BRS_LABEL(coreRegisterInit2)
|
|
|
|
#if defined (BRSHW_ARMCOMMON_COREEXCEPTIONS_AT_ADDRESS_0)
|
|
# if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
__as1(MOV R2, 0)
|
|
# else
|
|
__as1(MOV R2, #0)
|
|
# endif
|
|
|
|
#else /*(BRSHW_ARMCOMMON_COREEXCEPTIONS_AT_ADDRESS_0)*/
|
|
# if defined (BRS_ENABLE_OS_MULTICORESUPPORT)
|
|
__as1(LDR R1, =BrsHw_InitCoreID)
|
|
__as1(LDR R3, [R1])
|
|
/* ==> R3 = BrsHw_InitCoreID */
|
|
|
|
BRS_READ_COREID(R0)
|
|
/* ==> R0 = BRS_READ_COREID */
|
|
|
|
/* If actual running core is init core, directly jump to implemantation for init core.
|
|
(ExceptionTable of init core is not part of BrsHw_intvect_CoreExceptions_list[]) */
|
|
BRS_BRANCH_EQUAL(R0, R3, set_exception_table_location_on_init_core)
|
|
|
|
__as1(LDR R1, =BrsHw_CpuCoreAmountMinus1)
|
|
__as1(LDR R5, [R1])
|
|
/* ==> R5 = BrsHw_CpuCoreAmountMinus1 */
|
|
|
|
__as1(LDR R4, =BrsHw_intvect_CoreExceptions_list)
|
|
/* ==> R4 = BrsHw_intvect_CoreExceptions_list */
|
|
|
|
/* Use R6 as count register in the loop. Initialize with zero. */
|
|
# if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
__as1(MOV R6, 0)
|
|
# else
|
|
__as1(MOV R6, #0)
|
|
# endif
|
|
|
|
BRS_LABEL(get_exception_table_location_for_this_core_loop)
|
|
|
|
__as1(LDR R7, [R4])
|
|
/* ==> R7 = BrsHw_intvect_CoreExceptions_list[R6].PhysicalCoreId */
|
|
|
|
BRS_READ_COREID(R0)
|
|
/* ==> R0 = BRS_READ_COREID */
|
|
|
|
/* Check, if BrsHw_intvect_CoreExceptions_list entry of actual running core is reached */
|
|
BRS_BRANCH_EQUAL(R0, R7, get_exception_table_location_for_this_core)
|
|
|
|
/* Increase count register by one. */
|
|
# if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
__as2(ADD R6, R6, 1)
|
|
# else
|
|
__as2(ADD R6, R6, #1)
|
|
# endif
|
|
|
|
/* Set R4 to point to next entry of BrsHw_intvect_CoreExceptions_list. */
|
|
# if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
__as2(ADD R4, R4, 8)
|
|
# else
|
|
__as2(ADD R4, R4, #8)
|
|
# endif
|
|
|
|
/* Check if end of BrsHw_intvect_CoreExceptions_list has been reached. */
|
|
BRS_BRANCH_NOT_EQUAL(R6, R5, get_exception_table_location_for_this_core_loop)
|
|
/* If no Exception Table address for running core has been found -> BrsMainExceptionStartup. */
|
|
BRS_BRANCH(get_exception_table_location_error)
|
|
|
|
BRS_LABEL(get_exception_table_location_for_this_core)
|
|
|
|
/* Set R4 to point to next attribute of the current (R6)
|
|
struct ARMBrsHw_PhysicalCoreId_CoreExceptions_MappingType: CoreExceptions
|
|
*/
|
|
# if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
__as2(ADD R4, R4, 4)
|
|
# else
|
|
__as2(ADD R4, R4, #4)
|
|
# endif
|
|
|
|
__as1(LDR R2, [R4])
|
|
/* ==> R2 = BrsHw_intvect_CoreExceptions_list[R6].CoreExceptions */
|
|
|
|
BRS_BRANCH(get_exception_table_location_end)
|
|
|
|
BRS_LABEL(set_exception_table_location_on_init_core)
|
|
# endif /*BRS_ENABLE_OS_MULTICORESUPPORT*/
|
|
|
|
# if defined (BRS_FIRST_EXECUTION_INSTANCE)
|
|
__as1(LDR R2, =intvect_CoreExceptions)
|
|
|
|
# else
|
|
/* init core should be configured, but no 1st execution instance! -> BrsMainExceptionStartup. */
|
|
BRS_BRANCH(get_exception_table_location_error)
|
|
# endif /*BRS_FIRST_EXECUTION_INSTANCE*/
|
|
|
|
BRS_LABEL(get_exception_table_location_end)
|
|
#endif /*else BRSHW_ARMCOMMON_COREEXCEPTIONS_AT_ADDRESS_0*/
|
|
|
|
/* Copy backup exception vectors over exception vectors at address "intvect_CoreExceptions"
|
|
See ARMv7_Cortex-R_BRS_Exception_Handling.pdf for details of the mechanism!
|
|
R2 = destination address / R3 = source address / R6 = index / R4,R5 = data buffer
|
|
*/
|
|
__as1(MOV R3, R2)
|
|
__as1(MOV R7, R2) /* save Exception Table address in R7 */
|
|
|
|
/* Use R6 as count register in the loop. Initialize with zero. */
|
|
#if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
__as1(MOV R6, 0)
|
|
__as2(ADD R2, R2, 32)
|
|
__as2(ADD R3, R3, 64)
|
|
#else
|
|
__as1(MOV R6, #0)
|
|
__as2(ADD R2, R2, #32)
|
|
__as2(ADD R3, R3, #64)
|
|
#endif
|
|
|
|
BRS_LABEL(copy_exception_vectors_backup_to_active_start)
|
|
|
|
__as3(LDRD R4, R5, [R3], #+8)
|
|
__as3(STRD R4, R5, [R2], #+8)
|
|
|
|
/* Increase count register by one. */
|
|
#if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
__as2(ADD R6, R6, 1)
|
|
#else
|
|
__as2(ADD R6, R6, #1)
|
|
#endif
|
|
|
|
#if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
BRS_BRANCH_EQUAL(R6, 4, copy_exception_vectors_backup_to_active_end)
|
|
#else
|
|
BRS_BRANCH_EQUAL(R6, #4, copy_exception_vectors_backup_to_active_end)
|
|
#endif
|
|
|
|
BRS_BRANCH(copy_exception_vectors_backup_to_active_start)
|
|
|
|
BRS_LABEL(copy_exception_vectors_backup_to_active_end)
|
|
|
|
/* Set Exception Table code for all 8 Exceptions to the default "LDR PC, [PC,0x18]"
|
|
using R7 = Exception Table address.
|
|
Use R6 as count register in the loop. Initialize with zero.
|
|
*/
|
|
#if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
__as1(MOV R6, 0)
|
|
__as1(MOVW R2, 0xF018)
|
|
__as1(MOVT R2, 0xE59F)
|
|
#else
|
|
__as1(MOV R6, #0)
|
|
__as1(MOVW R2, #0xF018)
|
|
__as1(MOVT R2, #0xE59F)
|
|
#endif
|
|
|
|
BRS_LABEL(restore_exception_table_start)
|
|
|
|
__as2(STR R2, [R7], #+4)
|
|
|
|
/* Increase count register by one. */
|
|
#if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
__as2(ADD R6, R6, 1)
|
|
#else
|
|
__as2(ADD R6, R6, #1)
|
|
#endif
|
|
|
|
#if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
BRS_BRANCH_EQUAL(R6, 8, restore_exception_table_end)
|
|
#else
|
|
BRS_BRANCH_EQUAL(R6, #8, restore_exception_table_end)
|
|
#endif
|
|
|
|
BRS_BRANCH(restore_exception_table_start)
|
|
|
|
BRS_LABEL(restore_exception_table_end)
|
|
|
|
/* The exception table is implemented for ARM instrcutions -> The exception must be entered in ARM state
|
|
* -> Set SCTLR.TE bit for ARM state
|
|
*/
|
|
__as5(MRC p15, #0, r0, c1, c0, #0) /* read SCTLR register */
|
|
__as2(BIC r0, r0, #(1 << 30)) /* clear the TE bit to enter Exc in ARM mode */
|
|
__as5(MCR p15, #0, r0, c1, c0, #0) /* write SCTLR register */
|
|
|
|
/* Assure V-Bit is cleard and low exception vectors at 0x00000000 were set
|
|
* -> Set SCTLR.V bit for low exception base
|
|
*/
|
|
__as5(MRC p15, #0x00, r0, c1, c0, #0x0) /* Read SCTLR (System Control Register)*/
|
|
__as2(BIC r0, r0, #(1 << 13)) /* clear the V-bit */
|
|
__as5(MCR p15, #0x00, r0, c1, c0, #0x0) /* Write SCTLR (System Control Register) */
|
|
|
|
BRS_BRANCH(brsStartupInvalidateCache)
|
|
|
|
BRS_LABEL(get_exception_table_location_error)
|
|
|
|
BRS_MULTILINE_ASM_END()
|
|
|
|
/* Branch to BrsMainExceptionStartup if no Exception Table address can be found. */
|
|
BRS_EXTERN_BRANCH(BrsMainExceptionStartup)
|
|
BRS_GLOBAL_END()
|
|
|
|
/* =========================================================================== */
|
|
/* */
|
|
/* Description: Invalidate cache memory */
|
|
/* */
|
|
/* =========================================================================== */
|
|
BRS_GLOBAL(brsStartupInvalidateCache)
|
|
BRS_MULTILINE_ASM_BEGIN()
|
|
BRS_LABEL(brsStartupInvalidateCache)
|
|
|
|
#if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
__as5(MRC p15, 1, r0, c0, c0, 0) /* read cache size id */
|
|
__as1(MOVW r3, 0x01ff)
|
|
__as1(MOVT r3, 0x0000)
|
|
__as3(AND r0, r3, r0, lsr #13)
|
|
__as1(MOV r1, 0)
|
|
BRS_LABEL(way_loop)
|
|
__as1(MOV r3, 0)
|
|
BRS_LABEL(set_loop)
|
|
__as2(MOV r2, r1, lsl #30)
|
|
__as3(ORR r2, r2, r3, lsl #5)
|
|
BRS_LABEL(format)
|
|
__as5(MCR p15, 0, r2, c7, c6, 2) /* invalidate */
|
|
___asm(DSB)
|
|
___asm(ISB)
|
|
__as2(ADD r3, r3, 1)
|
|
BRS_BRANCH_GREATER_THAN(r0, r3, set_loop)
|
|
__as2(ADD r1, r1, 1)
|
|
BRS_BRANCH_NOT_EQUAL(r1, 4, way_loop)
|
|
|
|
#else
|
|
__as5(MRC p15, #1, r0, c0, c0, #0) /* read cache size id */
|
|
__as1(MOVW r3, #0x01ff)
|
|
__as1(MOVT r3, #0x0000)
|
|
__as3(AND r0, r3, r0, lsr #13)
|
|
__as1(MOV r1, #0)
|
|
BRS_LABEL(way_loop)
|
|
__as1(MOV r3, #0)
|
|
BRS_LABEL(set_loop)
|
|
__as2(MOV r2, r1, lsl #30)
|
|
__as3(ORR r2, r2, r3, lsl #5)
|
|
BRS_LABEL(format)
|
|
__as5(MCR p15, #0, r2, c7, c6, #2) /* invalidate */
|
|
___asm(DSB)
|
|
___asm(ISB)
|
|
__as2(ADD r3, r3, #1)
|
|
BRS_BRANCH_GREATER_THAN(r0, r3, set_loop)
|
|
__as2(ADD r1, r1, #1)
|
|
BRS_BRANCH_NOT_EQUAL(r1, #4, way_loop)
|
|
#endif /*BRS_COMP_x*/
|
|
|
|
BRS_BRANCH(brsStartupZeroInitLoop)
|
|
|
|
BRS_MULTILINE_ASM_END()
|
|
BRS_GLOBAL_END()
|
|
|
|
/* =========================================================================== */
|
|
/* */
|
|
/* Description: Initialize memory blocks and groups with zero */
|
|
/* */
|
|
/* =========================================================================== */
|
|
BRS_GLOBAL(brsStartupZeroInitLoop)
|
|
BRS_MULTILINE_ASM_BEGIN()
|
|
BRS_LABEL(brsStartupZeroInitLoop)
|
|
|
|
/* Initialize memory sections blocks with zeros */
|
|
#if defined (VLINKGEN_CFG_NUM_ZERO_INIT_EARLY_BLOCKS)
|
|
# if (VLINKGEN_CFG_NUM_ZERO_INIT_EARLY_BLOCKS>1uL)
|
|
__as1(LDR R1, =vLinkGen_ZeroInit_Early_Blocks)
|
|
|
|
BRS_READ_COREID(R0)
|
|
|
|
BRS_LABEL(startup_block_zero_init_start)
|
|
__as1(MOV R2, R1)
|
|
|
|
# if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
__as2(ADD R1, R1, 16)
|
|
# else
|
|
__as2(ADD R1, R1, #16)
|
|
# endif
|
|
|
|
__as1(LDR R3, [R2]) /* vLinkGen_ZeroInit_Early_Blocks->start */
|
|
__as2(LDR R4, [R2, #4]) /* vLinkGen_ZeroInit_Early_Blocks->end */
|
|
__as2(LDR R5, [R2, #8]) /* vLinkGen_ZeroInit_Early_Blocks->core */
|
|
__as2(LDR R6, [R2, #12]) /* vLinkGen_ZeroInit_Early_Blocks->alignment */
|
|
|
|
/* Verify if the end of struct vLinkGen_ZeroInit_Early_Blocks is reached, by checking if start == 0, end == 0 and core == 0 */
|
|
# if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
__as1(MOV R7, 0)
|
|
# else
|
|
__as1(MOV R7, #0)
|
|
# endif
|
|
|
|
__as2(ORR R7, R7, R3) /* Or with vLinkGen_ZeroInit_Early_Blocks->start */
|
|
__as2(ORR R7, R7, R4) /* Or with vLinkGen_ZeroInit_Early_Blocks->end */
|
|
__as2(ORR R7, R7, R5) /* Or with vLinkGen_ZeroInit_Early_Blocks->core */
|
|
|
|
# if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
BRS_BRANCH_EQUAL(R7, 0, startup_block_zero_init_end) /* If start address, end address and core are equal to zero -> Finished */
|
|
# else
|
|
BRS_BRANCH_EQUAL(R7, #0, startup_block_zero_init_end) /* If start address, end address and core are equal to zero -> Finished */
|
|
# endif
|
|
|
|
BRS_BRANCH_NOT_EQUAL(R0, R5, startup_block_zero_init_start) /* If InitCore is not running -> go to the next array entry */
|
|
|
|
# if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
__as1(MOV R7, 0) /* set R7 to '0', as value to write in memory later */
|
|
__as1(MOV R8, 0) /* set R8 to '0', as value to write in memory later */
|
|
# else
|
|
__as1(MOV R7, #0) /* set R7 to '0', as value to write in memory later */
|
|
__as1(MOV R8, #0) /* set R8 to '0', as value to write in memory later */
|
|
# endif
|
|
|
|
BRS_BRANCH_EQUAL(R6, #8, startup_block_zero_init_8byte_loop_start) /* if block is 8-Byte aligned, use specific init loop */
|
|
|
|
BRS_LABEL(startup_block_zero_init_loop_start)
|
|
BRS_BRANCH_GREATER_THAN_OR_EQUAL(R3, R4, startup_block_zero_init_start) /* if start address is same with or higher than end address-> Finished. */
|
|
|
|
__as1(STR R7, [R3]) /* write value of R7 ('0') to address of R3 (4-byte access); must be an aligned memory access! */
|
|
|
|
# if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
__as2(ADD R3, R3, 4) /* increase address value of R3 by '4' */
|
|
# else
|
|
__as2(ADD R3, R3, #4) /* increase address value of R3 by '4' */
|
|
# endif
|
|
|
|
/* End address of this block was not yet reached. Run through the loop again */
|
|
BRS_BRANCH(startup_block_zero_init_loop_start)
|
|
|
|
/* ================================================================ */
|
|
/* 8-Byte aligned initialization, to support 8-Byte aligned ECC RAM */
|
|
/* ================================================================ */
|
|
BRS_LABEL(startup_block_zero_init_8byte_loop_start)
|
|
BRS_BRANCH_GREATER_THAN_OR_EQUAL(R3, R4, startup_block_zero_init_start) /* if start address is same with or higher than end address-> Finished. */
|
|
|
|
/* Address stored in R3 must be 8 Byte aligned at this point! */
|
|
__as2(STMIA R3!, {R7, R8}) /* 8 Byte alignment store for ECC, R3 would be automatically updated after the write */
|
|
|
|
/* End address of this block was not yet reached. Run through the loop again */
|
|
BRS_BRANCH(startup_block_zero_init_8byte_loop_start)
|
|
|
|
/* Zero-Init loop of blocks end label */
|
|
BRS_LABEL(startup_block_zero_init_end)
|
|
# endif /*VLINKGEN_CFG_NUM_ZERO_INIT_EARLY_BLOCKS>1uL*/
|
|
|
|
#else
|
|
#error "Mandatory define VLINKGEN_CFG_NUM_ZERO_INIT_EARLY_BLOCKS missing within vLinkGen configuration!"
|
|
#endif /*VLINKGEN_CFG_NUM_ZERO_INIT_EARLY_BLOCKS*/
|
|
|
|
/* Initialize memory sections groups with zeros */
|
|
#if defined (VLINKGEN_CFG_NUM_ZERO_INIT_EARLY_GROUPS)
|
|
# if (VLINKGEN_CFG_NUM_ZERO_INIT_EARLY_GROUPS>1uL)
|
|
__as1(LDR R1, =vLinkGen_ZeroInit_Early_Groups)
|
|
|
|
BRS_LABEL(startup_group_zero_init_start)
|
|
__as1(MOV R2, R1)
|
|
|
|
# if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
__as2(ADD R1, R1, 16)
|
|
# else
|
|
__as2(ADD R1, R1, #16)
|
|
# endif
|
|
|
|
__as1(LDR R3, [R2]) /* vLinkGen_ZeroInit_Early_Groups->start */
|
|
__as2(LDR R4, [R2, #4]) /* vLinkGen_ZeroInit_Early_Groups->end */
|
|
__as2(LDR R5, [R2, #8]) /* vLinkGen_ZeroInit_Early_Groups->core */
|
|
__as2(LDR R6, [R2, #12]) /* vLinkGen_ZeroInit_Early_Groups->alignment */
|
|
|
|
/* Verify if the end of struct vLinkGen_ZeroInit_Early_Groups is reached, by checking if start == 0, end == 0 and core == 0 */
|
|
# if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
__as1(MOV R7, 0)
|
|
# else
|
|
__as1(MOV R7, #0)
|
|
# endif
|
|
|
|
__as2(ORR R7, R7, R3) /* Or with vLinkGen_ZeroInit_Early_Groups->start */
|
|
__as2(ORR R7, R7, R4) /* Or with vLinkGen_ZeroInit_Early_Groups->end */
|
|
__as2(ORR R7, R7, R5) /* Or with vLinkGen_ZeroInit_Early_Groups->core */
|
|
|
|
# if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
BRS_BRANCH_EQUAL(R7, 0, startup_group_zero_init_end) /* If start address, end address and core are equal to zero -> Finished */
|
|
# else
|
|
BRS_BRANCH_EQUAL(R7, #0, startup_group_zero_init_end) /* If start address, end address and core are equal to zero -> Finished */
|
|
# endif
|
|
|
|
BRS_BRANCH_NOT_EQUAL(R0, R5, startup_group_zero_init_start) /* If InitCore is not running -> go to the next array entry */
|
|
|
|
# if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
__as1(MOV R7, 0) /* set R7 to '0', as value to write in memory later */
|
|
__as1(MOV R8, 0) /* set R8 to '0', as value to write in memory later */
|
|
# else
|
|
__as1(MOV R7, #0) /* set R7 to '0', as value to write in memory later */
|
|
__as1(MOV R8, #0) /* set R8 to '0', as value to write in memory later */
|
|
# endif
|
|
|
|
BRS_BRANCH_EQUAL(R6, #8, startup_group_zero_init_8byte_loop_start) /* if group is 8-Byte aligned, use specific init loop */
|
|
|
|
BRS_LABEL(startup_group_zero_init_loop_start)
|
|
BRS_BRANCH_GREATER_THAN_OR_EQUAL(R3, R4, startup_group_zero_init_start) /* if start address is same with or higher than end address-> Finished. */
|
|
|
|
__as1(STR R7, [R3]) /* write value of R7 ('0') to address of R3 (4-byte access); must be an aligned memory access! */
|
|
|
|
# if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
__as2(ADD R3, R3, 4) /* increase address value of R3 by '4' */
|
|
# else
|
|
__as2(ADD R3, R3, #4) /* increase address value of R3 by '4' */
|
|
# endif
|
|
|
|
/* End address of this group was not yet reached. Run through the loop again */
|
|
BRS_BRANCH(startup_group_zero_init_loop_start)
|
|
|
|
/* ================================================================ */
|
|
/* 8-Byte aligned initialization, to support 8-Byte aligned ECC RAM */
|
|
/* ================================================================ */
|
|
BRS_LABEL(startup_group_zero_init_8byte_loop_start)
|
|
BRS_BRANCH_GREATER_THAN_OR_EQUAL(R3, R4, startup_group_zero_init_start) /* if start address is same with or higher than end address-> Finished. */
|
|
|
|
/* Address stored in R3 must be 8 Byte aligned at this point! */
|
|
__as2(STMIA R3!, {R7, R8}) /* 8 Byte alignment store for ECC, R3 would be automatically updated after the write */
|
|
|
|
/* End address of this group was not yet reached. Run through the loop again */
|
|
BRS_BRANCH(startup_group_zero_init_8byte_loop_start)
|
|
|
|
/* Zero-Init loop of groups end label */
|
|
BRS_LABEL(startup_group_zero_init_end)
|
|
# endif /*VLINKGEN_CFG_NUM_ZERO_INIT_EARLY_GROUPS>1uL*/
|
|
|
|
#else
|
|
#error "Mandatory define VLINKGEN_CFG_NUM_ZERO_INIT_EARLY_GROUPS missing within vLinkGen configuration!"
|
|
#endif /*VLINKGEN_CFG_NUM_ZERO_INIT_EARLY_GROUPS*/
|
|
|
|
/* Jump to routine to search for valid startup stack pointer of actual running core */
|
|
BRS_BRANCH(brsStartupStackSearch)
|
|
BRS_MULTILINE_ASM_END()
|
|
BRS_GLOBAL_END()
|
|
|
|
/* =========================================================================== */
|
|
/* */
|
|
/* Description: Search for valid startup stack pointer of actual running core */
|
|
/* (vBRS is genearing the core specific configuration into the */
|
|
/* struct BrsMain_CoreConfig in vBrs_Lcfg.c) */
|
|
/* */
|
|
/* =========================================================================== */
|
|
BRS_GLOBAL(brsStartupStackSearch)
|
|
BRS_MULTILINE_ASM_BEGIN()
|
|
BRS_LABEL(brsStartupStackSearch)
|
|
|
|
__as1(LDR R1, =BrsMain_CoreConfig_Size)
|
|
|
|
BRS_LABEL(core_config_size_init)
|
|
__as1(LDR R5, [R1]) /* R5 = BrsMain_CoreConfig_Size */
|
|
|
|
__as1(LDR R1, =BrsMain_CoreConfig)
|
|
|
|
BRS_READ_COREID(R0)
|
|
|
|
BRS_LABEL(core_config_init_start)
|
|
|
|
/* Use R2 as count register in the loop. Initialize with zero. */
|
|
#if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
__as1(MOV R2, 0)
|
|
#else
|
|
__as1(MOV R2, #0)
|
|
#endif
|
|
|
|
BRS_LABEL(brs_coreconfig_loop)
|
|
|
|
__as2(LDR R4, [R1,#4]) /* BrsMain_CoreConfig->PhysicalCoreId */
|
|
/* Check if core id (R0) matches to physical core id of BrsMain_CoreConfig entry (R4). */
|
|
BRS_BRANCH_EQUAL(R0, R4, stackPointerInit)
|
|
|
|
/* Increase count register by one. */
|
|
#if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
__as2(ADD R2, R2, 1)
|
|
#else
|
|
__as2(ADD R2, R2, #1)
|
|
#endif
|
|
|
|
/* Set R1 to point to next entry of BrsMain_CoreConfig. */
|
|
#if defined (BRS_COMP_LLVMTEXASINSTRUMENTS)
|
|
__as2(ADD R1, R1, 28)
|
|
#else
|
|
__as2(ADD R1, R1, #28)
|
|
#endif
|
|
|
|
/* Check if end of BrsMain_CoreConfig has been reached. */
|
|
BRS_BRANCH_NOT_EQUAL(R2, R5, brs_coreconfig_loop)
|
|
|
|
BRS_MULTILINE_ASM_END()
|
|
|
|
/* Branch to BrsMainExceptionStartup if there are no more entries in the array. */
|
|
BRS_EXTERN_BRANCH(BrsMainExceptionStartup)
|
|
BRS_GLOBAL_END()
|
|
|
|
/* =========================================================================== */
|
|
/* */
|
|
/* Description: Initialize all core registers of actual running core with */
|
|
/* specific init values */
|
|
/* */
|
|
/* =========================================================================== */
|
|
BRS_GLOBAL(stackPointerInit)
|
|
BRS_MULTILINE_ASM_BEGIN()
|
|
BRS_LABEL(stackPointerInit)
|
|
__as2(LDR R4, [R1,#8]) /* BrsMain_CoreConfig->StartupStackEndLabel */
|
|
__as1(MOV SP, R4)
|
|
|
|
BRS_BRANCH(coreRegisterInit3)
|
|
|
|
BRS_MULTILINE_ASM_END()
|
|
BRS_GLOBAL_END()
|
|
|
|
/* =========================================================================== */
|
|
/* */
|
|
/* Description: Initialize additional core registers */
|
|
/* */
|
|
/* =========================================================================== */
|
|
BRS_GLOBAL(coreRegisterInit3)
|
|
BRS_MULTILINE_ASM_BEGIN()
|
|
BRS_LABEL(coreRegisterInit3)
|
|
BRS_MULTILINE_ASM_END()
|
|
|
|
/* =========================================================================== */
|
|
/* */
|
|
/* Description: Jump to Brs_PreMainStartup() (BrsMainStartup.c) */
|
|
/* */
|
|
/* =========================================================================== */
|
|
BRS_EXTERN_BRANCH(Brs_PreMainStartup)
|
|
|
|
/* =========================================================================== */
|
|
/* */
|
|
/* Description: Jump to BrsMainExceptionStartup() in case of an unexpected */
|
|
/* return from PreMain/main */
|
|
/* */
|
|
/* =========================================================================== */
|
|
BRS_EXTERN_BRANCH(BrsMainExceptionStartup)
|
|
|
|
BRS_GLOBAL_END()
|
|
|
|
|
|
#endif /*BRS_FIRST_EXECUTION_INSTANCE*/
|