/* Copyright (c) 2009-2023 ARM Limited. All rights reserved. SPDX-License-Identifier: Apache-2.0 Licensed under the Apache License, Version 2.0 (the License); you may not use this file except in compliance with the License. You may obtain a copy of the License at www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. NOTICE: This file has been modified by Nordic Semiconductor ASA. */ #include #include #include /*--------------------------------------------------------------------------- Stack and heap definitions *---------------------------------------------------------------------------*/ #ifndef NRF_SKIP_STACK_DECLARATION extern uint8_t __STACK[] __STACK_ATTRIBUTES(__STACK_ALIGNMENT); uint8_t __STACK[__STACK_SIZE] __STACK_ATTRIBUTES(__STACK_ALIGNMENT); #define __STACK_BASE ((uint32_t)(__STACK + __STACK_SIZE)) #define __STACK_LIMIT ((uint32_t)(__STACK)) #endif #if !defined(NRF_SKIP_HEAP_DECLARATION) && __HEAP_SIZE > 0 extern uint8_t __HEAP[] __HEAP_ATTRIBUTES(__HEAP_ALIGNMENT); uint8_t __HEAP[__HEAP_SIZE] __HEAP_ATTRIBUTES(__HEAP_ALIGNMENT); #define __HEAP_LIMIT ((uint32_t)(__HEAP + __HEAP_SIZE)) #define __HEAP_BASE ((uint32_t)(__HEAP)) #endif /*--------------------------------------------------------------------------- Define __PROGRAM_START to avoid conflict with CMSIS *---------------------------------------------------------------------------*/ #define __PROGRAM_START /*--------------------------------------------------------------------------- Interrupt vector tables *---------------------------------------------------------------------------*/ #include __VECTOR_TABLE_ATTRIBUTE extern const VECTOR_TABLE_Type __VECTOR_TABLE[]; #include /*--------------------------------------------------------------------------- Memory initializer structs *---------------------------------------------------------------------------*/ #if ! defined (__ARMCC_VERSION) && (defined( __GNUC__ ) || defined( __clang__ )) #define DO_GNU_MEM_INIT /** Source: https://github.com/ARM-software/CMSIS_5/blob/develop/CMSIS/Core/Include/cmsis_gcc.h */ typedef struct __copy_table { uint32_t const * src; uint32_t * dest; uint32_t wlen; } __copy_table_t; typedef struct __zero_table { uint32_t * dest; uint32_t wlen; } __zero_table_t; __STATIC_FORCEINLINE void copy_region(const __copy_table_t * table) { for (uint32_t i = 0; i < table->wlen; ++i) { table->dest[i] = table->src[i]; } } __STATIC_FORCEINLINE void zero_region(const __zero_table_t * table) { for (uint32_t i = 0; i < table->wlen; ++i) { table->dest[i] = 0; } } __STATIC_FORCEINLINE void GNUInitializeMemories() { /* Perform C memory initialization */ #ifndef NRF_SKIP_VARIABLE_INIT extern const __copy_table_t __copy_table_start__; extern const __copy_table_t __copy_table_end__; for (__copy_table_t const* pTable = &__copy_table_start__; pTable < &__copy_table_end__; ++pTable) { copy_region(pTable); } #endif #ifndef NRF_SKIP_ZERO_INIT extern const __zero_table_t __zero_table_start__; extern const __zero_table_t __zero_table_end__; for (__zero_table_t const* pTable = &__zero_table_start__; pTable < &__zero_table_end__; ++pTable) { zero_region(pTable); } #endif #ifdef NRF_VECTORS_IN_RAM /* Copy vector table from code to data region */ extern const uint32_t __vectors_load_start; extern uint32_t __vectors_start; extern uint32_t __vectors_end; const __copy_table_t vector_copy = { &__vectors_load_start, &__vectors_start, (&__vectors_end - &__vectors_start) / 4 }; copy_region(&vector_copy); SCB->VTOR = &__vectors_start; #endif } #endif /*--------------------------------------------------------------------------- Implement newlib heap monitor *---------------------------------------------------------------------------*/ #ifdef NRF_ENABLE_HEAP_LIMIT #include #include void * _sbrk (ptrdiff_t incr) { extern char __heap_base; /* Defined by the linker. */ extern char __heap_limit; /* Defined by the linker. */ static char * heap_top = NULL; if (heap_top == NULL) heap_top = & __heap_base; char * prev_heap_top = heap_top; if ((heap_top + incr > (char *)GET_SP()) || (heap_top + incr > &__heap_limit)) { errno = ENOMEM; return (void *) -1; } heap_top += incr; return (void *) prev_heap_top; } #endif #if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) /* ArmClang stack / heap setup method. */ void __attribute__((naked)) __user_setup_stackheap() { __asm( " ldr r0, = %0\n" /* __STACK_BASE */ " mov sp, r0\n" #if __HEAP_SIZE != 0 " ldr r0, = %1 \n" /* __HEAP_BASE */ " ldr r2, = %2 \n" /* __HEAP_LIMIT */ #else " mov r0, #0\n" " mov r2, #0\n" #endif " bx lr\n" :: "i"(__STACK_BASE), "i"(__HEAP_BASE), "i"(__HEAP_LIMIT)); } #endif /*--------------------------------------------------------------------------- Reset Handler called on controller reset *---------------------------------------------------------------------------*/ extern __NO_RETURN void __START(void); __RESET_HANDLER_ATTRIBUTE void Reset_Handler(void) { #ifndef NRF_NO_STACK_INIT __set_PSP((uint32_t)(__STACK_BASE)); #if __ARM_ARCH >= 8 __set_MSPLIM((uint32_t)(__STACK_LIMIT)); __set_PSPLIM((uint32_t)(__STACK_LIMIT)); #endif #endif NRFPreInit(); SystemInit(); /* CMSIS System Initialization */ #ifdef DO_GNU_MEM_INIT GNUInitializeMemories(); #endif /* Configure vector table offset register */ #ifdef NRF_VTOR_CONFIG SCB->VTOR = NRF_VTOR_CONFIG; #endif __START(); } #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wmissing-noreturn" #endif /*--------------------------------------------------------------------------- Default Handler for Exceptions / Interrupts *---------------------------------------------------------------------------*/ void Default_Handler(void) { while (1) ; } #ifdef INITIALIZE_USER_SECTIONS void InitializeUserMemorySections() { extern const copy_region_t __start_nrf_sections; copy_memory_region(&__start_nrf_sections); } #endif #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) #pragma clang diagnostic pop #endif