diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/src/Makefile | 40 | ||||
-rw-r--r-- | arch/src/arm_main.c | 38 | ||||
-rw-r--r-- | arch/src/arm_mm.c | 57 | ||||
-rw-r--r-- | arch/src/armv6-m/arm_nvic.c | 322 | ||||
-rw-r--r-- | arch/src/armv6-m/armv6-crt0.S | 56 | ||||
-rw-r--r-- | arch/src/armv6-m/exception.S | 42 | ||||
-rw-r--r-- | arch/src/armv6-m/ld.S | 191 | ||||
-rw-r--r-- | arch/src/armv6-m/reset-v6.S | 20 | ||||
-rw-r--r-- | arch/src/armv7-m/arm_nvic.c | 352 | ||||
-rw-r--r-- | arch/src/armv7-m/armv7-crt0.S | 53 | ||||
-rw-r--r-- | arch/src/armv7-m/exception.S | 41 | ||||
-rw-r--r-- | arch/src/armv7-m/ld.S | 191 | ||||
-rw-r--r-- | arch/src/armv7-m/reset-v7.S | 39 | ||||
-rw-r--r-- | arch/src/section.h | 77 |
14 files changed, 1519 insertions, 0 deletions
diff --git a/arch/src/Makefile b/arch/src/Makefile new file mode 100644 index 0000000..d9a9205 --- /dev/null +++ b/arch/src/Makefile @@ -0,0 +1,40 @@ +# +# Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include $(BS_DIR)/cpu.mk + +BS_LIB_NAME = arch + +BS_LIB_SOURCES_armv6-m += armv6-m/exception.S +BS_LIB_SOURCES_armv6-m += armv6-m/reset-v6.S +BS_LIB_SOURCES_armv6-m += armv6-m/armv6-crt0.S +BS_LIB_SOURCES_armv6-m += armv6-m/arm_nvic.c +BS_LIB_SOURCES_armv6-m += arm_main.c +BS_LIB_SOURCES_armv6-m += arm_mm.c + +BS_LIB_INCLUDES_armv6-m += $(TOP_DIR)/cmsis/CMSIS/Core/Include/ + +BS_LIB_SOURCES_armv7-m += armv7-m/exception.S +BS_LIB_SOURCES_armv7-m += armv7-m/reset-v7.S +BS_LIB_SOURCES_armv7-m += armv7-m/armv7-crt0.S +BS_LIB_SOURCES_armv7-m += armv7-m/arm_nvic.c +BS_LIB_SOURCES_armv7-m += arm_main.c +BS_LIB_SOURCES_armv7-m += arm_mm.c + +BS_LIB_INCLUDES_armv7-m += $(TOP_DIR)/cmsis/CMSIS/Core/Include/ + +BS_LIB_INCLUDES += $(ARCH_DIR)/include +BS_LIB_INCLUDES += $(FWK_DIR)/include + +# +# Select arch-specific sources and includes +# +BS_LIB_SOURCES += $(BS_LIB_SOURCES_$(BS_ARCH_CPU)) +BS_LIB_SOURCES += $(BS_LIB_SOURCES_$(BS_ARCH_ARCH)) +BS_LIB_INCLUDES += $(BS_LIB_INCLUDES_$(BS_ARCH_CPU)) +BS_LIB_INCLUDES += $(BS_LIB_INCLUDES_$(BS_ARCH_ARCH)) + +include $(BS_DIR)/lib.mk diff --git a/arch/src/arm_main.c b/arch/src/arm_main.c new file mode 100644 index 0000000..eb116a7 --- /dev/null +++ b/arch/src/arm_main.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include <stdbool.h> +#include <stdnoreturn.h> +#include <fwk_arch.h> +#include <fwk_errno.h> +#include <cmsis_compiler.h> + +extern int arm_nvic_init(struct fwk_arch_interrupt_driver **driver); +extern int arm_mm_init(struct fwk_arch_mm_data *data); + +/* + * Error handler for failures that occur during early initialization. + */ +static noreturn void arm_panic(void) +{ + while (true) + __WFI(); +} + +static struct fwk_arch_init_driver arch_init_driver = { + .mm = arm_mm_init, + .interrupt = arm_nvic_init, +}; + +void arm_main(void) +{ + int status; + + status = fwk_arch_init(&arch_init_driver); + if (status != FWK_SUCCESS) + arm_panic(); +} diff --git a/arch/src/arm_mm.c b/arch/src/arm_mm.c new file mode 100644 index 0000000..a356150 --- /dev/null +++ b/arch/src/arm_mm.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Memory initialization. + */ + +#include <assert.h> +#include <stdint.h> +#include <fwk_arch.h> +#include <fwk_errno.h> +#include <fwk_macros.h> +#include <section.h> + +int arm_mm_init(struct fwk_arch_mm_data *data) +{ + const unsigned int ALIGNMENT = sizeof(uint64_t); + + uintptr_t start; + uintptr_t end; + + if (data == NULL) + return FWK_E_PARAM; + + if (ARCH_SECTION_HEAP_SIZE == 0) + return FWK_E_NOMEM; + + /* Check if the main stack section overlaps the .bss section */ + if (ARCH_SECTION_STACK_START <= ARCH_SECTION_BSS_END) { + assert(false); + return FWK_E_PANIC; + } + + /* Ensure the start address did not overflow following 64-bit alignment */ + start = FWK_ALIGN_NEXT(ARCH_SECTION_HEAP_START, ALIGNMENT); + if (start < ARCH_SECTION_HEAP_START) + return FWK_E_NOMEM; + + /* Ensure the end address did not underflow following 64-bit alignment */ + end = FWK_ALIGN_PREVIOUS(ARCH_SECTION_HEAP_END, ALIGNMENT); + if (end > ARCH_SECTION_HEAP_END) + return FWK_E_NOMEM; + + /* + * Ensure there is space left after performing 64-bit alignment on the start + * and end addresses. + */ + if (end <= start) + return FWK_E_NOMEM; + + data->start = start; + data->size = end - start; + + return FWK_SUCCESS; +} diff --git a/arch/src/armv6-m/arm_nvic.c b/arch/src/armv6-m/arm_nvic.c new file mode 100644 index 0000000..6c2eb33 --- /dev/null +++ b/arch/src/armv6-m/arm_nvic.c @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Interrupt management. + */ + +#include <limits.h> +#include <stdint.h> +#include <stdlib.h> +#include <stdnoreturn.h> +#include <fwk_arch.h> +#include <fwk_errno.h> +#include <fwk_interrupt.h> +#include <fwk_macros.h> +#include <fwk_mm.h> +#include <cmsis_compiler.h> + +#ifdef BUILD_HAS_MULTITHREADING + #include <rtx_os.h> +#endif + +extern noreturn void exception_invalid(void); + +struct nvic; + +#define SCB_VTOR ((FWK_RW uint32_t *)(0xE000ED08UL)) +#define SCS_NVIC ((struct nvic *)(0xE000E100UL)) + +enum exception_num { + EXCEPTION_NUM_INVALID = 0U, + EXCEPTION_NUM_RESET = 1U, + EXCEPTION_NUM_NMI = 2U, + EXCEPTION_NUM_HARDFAULT = 3U, + EXCEPTION_NUM_SVCALL = 11U, + EXCEPTION_NUM_PENDSV = 14U, + EXCEPTION_NUM_SYSTICK = 15U, + EXCEPTION_NUM_COUNT, +}; + +struct nvic { + FWK_RW uint32_t ISER; /* Interrupt Set Enabled Register */ + FWK_RW uint32_t ICER; /* Interrupt Clear Enabled Register */ + FWK_RW uint32_t ISPR; /* Interrupt Set Pending Register */ + FWK_RW uint32_t ICPR; /* Interrupt Clear Pending Register */ + FWK_W uint32_t IPR; /* Interrupt Priority Register */ +}; + +static uint32_t isr_count; +static uint32_t irq_count; + +/* + * For interrupts with parameters, their entry in the vector table points to a + * global handler that calls a registered function in the callback table with a + * corresponding parameter. Entries in the vector table for interrupts without + * parameters point directly to the handler functions. + */ +struct callback { + void (*func)(uintptr_t param); + uintptr_t param; +}; + +static void (**vector)(void); +static struct callback *callback; + +static void irq_global(void) +{ + struct callback *entry = &callback[__get_IPSR()]; + entry->func(entry->param); +} + +static int global_enable(void) +{ + __enable_irq(); + + return FWK_SUCCESS; +} + +static int global_disable(void) +{ + __disable_irq(); + + return FWK_SUCCESS; +} + +static int is_enabled(unsigned int interrupt, bool *enabled) +{ + if (interrupt >= irq_count) + return FWK_E_PARAM; + + *enabled = SCS_NVIC->ISER & (UINT32_C(1) << (interrupt & 0x1F)); + + return FWK_SUCCESS; +} + +static int enable(unsigned int interrupt) +{ + if (interrupt >= irq_count) + return FWK_E_PARAM; + + SCS_NVIC->ISER = UINT32_C(1) << (interrupt & 0x1F); + + return FWK_SUCCESS; +} + +static int disable(unsigned int interrupt) +{ + if (interrupt >= irq_count) + return FWK_E_PARAM; + + SCS_NVIC->ICER = UINT32_C(1) << (interrupt & 0x1F); + + return FWK_SUCCESS; +} + +static int is_pending(unsigned int interrupt, bool *pending) +{ + if (interrupt >= irq_count) + return FWK_E_PARAM; + + *pending = SCS_NVIC->ISPR & (UINT32_C(1) << (interrupt & 0x1F)); + + return FWK_SUCCESS; +} + +static int set_pending(unsigned int interrupt) +{ + if (interrupt >= irq_count) + return FWK_E_PARAM; + + + + return FWK_SUCCESS; +} + +static int clear_pending(unsigned int interrupt) +{ + if (interrupt >= irq_count) + return FWK_E_PARAM; + + SCS_NVIC->ICPR = UINT32_C(1) << (interrupt & 0x1F); + + return FWK_SUCCESS; +} + +static int set_isr_irq(unsigned int interrupt, void (*isr)(void)) +{ + if (interrupt >= irq_count) + return FWK_E_PARAM; + + vector[EXCEPTION_NUM_COUNT + interrupt] = isr; + + return FWK_SUCCESS; +} + +static int set_isr_irq_param(unsigned int interrupt, + void (*isr)(uintptr_t param), + uintptr_t parameter) +{ + struct callback *entry; + if (interrupt >= irq_count) + return FWK_E_PARAM; + + vector[EXCEPTION_NUM_COUNT + interrupt] = irq_global; + + entry = &callback[EXCEPTION_NUM_COUNT + interrupt]; + entry->func = isr; + entry->param = parameter; + + return FWK_SUCCESS; +} + +static int set_isr_nmi(void (*isr)(void)) +{ + vector[EXCEPTION_NUM_NMI] = isr; + + return FWK_SUCCESS; +} + +static int set_isr_nmi_param(void (*isr)(uintptr_t param), uintptr_t parameter) +{ + struct callback *entry; + + vector[EXCEPTION_NUM_NMI] = irq_global; + + entry = &callback[EXCEPTION_NUM_NMI]; + entry->func = isr; + entry->param = parameter; + + return FWK_SUCCESS; +} + +static int set_isr_fault(void (*isr)(void)) +{ + vector[EXCEPTION_NUM_HARDFAULT] = isr; + + return FWK_SUCCESS; +} + +static int get_current(unsigned int *interrupt) +{ + *interrupt = __get_IPSR(); + + /* Not an interrupt */ + if (*interrupt == 0) + return FWK_E_STATE; + + if (*interrupt == EXCEPTION_NUM_NMI) + *interrupt = FWK_INTERRUPT_NMI; + else if ((*interrupt) < EXCEPTION_NUM_COUNT) + *interrupt = FWK_INTERRUPT_EXCEPTION; + else + *interrupt -= EXCEPTION_NUM_COUNT; + + return FWK_SUCCESS; +} + +static const struct fwk_arch_interrupt_driver arm_nvic_driver = { + .global_enable = global_enable, + .global_disable = global_disable, + .is_enabled = is_enabled, + .enable = enable, + .disable = disable, + .is_pending = is_pending, + .set_pending = set_pending, + .clear_pending = clear_pending, + .set_isr_irq = set_isr_irq, + .set_isr_irq_param = set_isr_irq_param, + .set_isr_nmi = set_isr_nmi, + .set_isr_nmi_param = set_isr_nmi_param, + .set_isr_fault = set_isr_fault, + .get_current = get_current, +}; + +static void irq_invalid(void) +{ + static unsigned int spurious = 0; + + spurious++; + + disable(__get_IPSR()); +} + +int arm_nvic_init(const struct fwk_arch_interrupt_driver **driver) +{ + uint32_t align_entries; + uint32_t align_word; + unsigned int i; + + if (driver == NULL) + return FWK_E_PARAM; + + /* Find the number of interrupt lines implemented in hardware */ + irq_count = 32; + isr_count = irq_count + EXCEPTION_NUM_COUNT; + + /* + * Allocate and initialize a table for the callback functions and their + * corresponding parameters. + */ + callback = fwk_mm_calloc(isr_count, sizeof(callback[0])); + if (callback == NULL) + return FWK_E_NOMEM; + /* + * The base address for the vector table must align on the number of + * entries in the table, corresponding to a word boundary rounded up to the + * next power of two. + * + * For example, for a vector table with 48 entries, the base address must be + * on a 64-word boundary. + */ + + /* Calculate the next power of two */ + align_entries = UINT32_C(1) << (32 - __CLZ(isr_count - 1)); + + /* Calculate alignment on a word boundary */ + align_word = align_entries * sizeof(vector[0]); + + vector = fwk_mm_alloc_aligned(isr_count, sizeof(vector[0]), align_word); + + if (vector == NULL) + return FWK_E_NOMEM; + + /* + * Initialize all exception entries to point to the exception_invalid() + * handler. + * + * Note: Initialization starts from entry 1 since entry 0 is not an + * exception pointer but the default stack pointer. + */ + for (i = 1; i < EXCEPTION_NUM_COUNT; i++) + vector[i] = exception_invalid; + + /* Initialize IRQs */ + for (i = 0; i < irq_count; i++) { + /* Initialize all IRQ entries to point to the irq_invalid() handler */ + vector[EXCEPTION_NUM_COUNT + i] = irq_invalid; + + /* Ensure IRQs are disabled during boot sequence */ + disable(i); + clear_pending(i); + } + +#ifdef BUILD_HAS_MULTITHREADING + /* Set exception entries that are implemented and handled by RTX */ + vector[EXCEPTION_NUM_SVCALL] = SVC_Handler; + vector[EXCEPTION_NUM_PENDSV] = PendSV_Handler; + vector[EXCEPTION_NUM_SYSTICK] = SysTick_Handler; +#endif + + __DMB(); + + /* Switch to the new vector table */ + *SCB_VTOR = (uint32_t)vector; + __DMB(); + + *driver = &arm_nvic_driver; + + return FWK_SUCCESS; +} diff --git a/arch/src/armv6-m/armv6-crt0.S b/arch/src/armv6-m/armv6-crt0.S new file mode 100644 index 0000000..26632ad --- /dev/null +++ b/arch/src/armv6-m/armv6-crt0.S @@ -0,0 +1,56 @@ + /* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * startup file. + */ + + .syntax unified + + .text + + .global start + .thumb_func + .func start +start: + +/* Load .data, which is 4-byte aligned */ + ldr r1, =__DATA_SIZE__ + cmp r1, #0 + beq 6f + ldr r4, =4 + ldr r0, =__DATA_LMA_START__ + ldr r2, =__DATA_START__ + cmp r0, r2 + beq 6f +5: + ldr r3, [r0] + add r0, r0, r4 + str r3, [r2] + add r2, r2, r4 + subs r1, r4 + bne 5b +6: + /* Clear .bss, which is also 4-byte aligned */ + ldr r1, =__BSS_SIZE__ + cmp r1, #0 + beq 8f + ldr r0, =__BSS_START__ + ldr r2, =0 +7: + str r2, [r0] + add r0, r4 + subs r1, r4 + bne 7b + +8: + dsb + bl arm_main + +9: + wfi + b 9b + .pool + .endfunc diff --git a/arch/src/armv6-m/exception.S b/arch/src/armv6-m/exception.S new file mode 100644 index 0000000..9cdd907 --- /dev/null +++ b/arch/src/armv6-m/exception.S @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * exceptions. + */ + + + .syntax unified + + .section .exception + + .global exceptions +exceptions: + .word __STACK_END__ + .word exception_reset /* Reset */ + .word exception_invalid /* NMI */ + .word exception_invalid /* HardFault */ + .word exception_invalid /* MemManage */ + .word exception_invalid /* Bus Fault */ + .word exception_invalid /* UsageFault */ + .word exception_invalid /* Reserved */ + .word exception_invalid /* Reserved */ + .word exception_invalid /* Reserved */ + .word exception_invalid /* Reserved */ + .word exception_invalid /* SVCall */ + .word exception_invalid /* DebugMonitor */ + .word exception_invalid /* Reserved */ + .word exception_invalid /* PendSV */ + .word exception_invalid /* SysTick */ + + .section .text + + .global exception_invalid + .thumb_func + .func exception_invalid +exception_invalid: + wfi + b exception_invalid + .endfunc diff --git a/arch/src/armv6-m/ld.S b/arch/src/armv6-m/ld.S new file mode 100644 index 0000000..98c03e7 --- /dev/null +++ b/arch/src/armv6-m/ld.S @@ -0,0 +1,191 @@ + /* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * scatter file. + */ + + /* + * There are three supported memory layouts for the ARMv6-M architecture: + * + * Layout 1 - Single region: + * - All sections are placed in one contiguous region. + * - This layout uses only the mem0 memory region. + * - The memory is considered RXW by the linker, but the sections can be + * configured later on with different attributes using the MPU. + * - The main stack is placed at the end of mem0. + * - This layout is mainly used by second-stage firmware that is loaded directly + * into a single RAM. + * + * Layout 2 - Dual region with relocation: + * - One region is used for .text and .data (storage). + * - A second region is used for the remaining sections. + * - This layout uses memory regions mem0 and mem1 as the first and second + * regions, respectively. + * - The main stack is placed at the end of mem1. + * - This layout is mainly used by ROM firmware which uses part of the RAM for + * the data sections. + * + * Layout 3 - Dual region without relocation + * - One region is used only for the .text section. + * - A second region is used for all data sections. + * - This layout uses memory regions mem0 and mem1 as the first and second + * regions, respectively. + * - The main stack is placed at the end of mem1. + * - The main difference from layout 2 is that there is no relocation of the + * .data section. + * - This layout is mainly used by second-stage firmware loaded directly into + * two RAM regions. One of the RAM regions is attached to the instruction bus, + * which improves the performance as data and instruction accesses are + * independent. + * + */ + +#define FWK_MEM_MODE_INVALID 0 +#define FWK_MEM_MODE_SINGLE_REGION 1 +#define FWK_MEM_MODE_DUAL_REGION_RELOCATION 2 +#define FWK_MEM_MODE_DUAL_REGION_NO_RELOCATION 3 + +#include <fmw_memory.ld.S> + +#define STACK_ALIGNMENT 8 + +/* + * Input validation + */ + +#ifndef FIRMWARE_MEM_MODE + #error "FIRMWARE_MEM_MODE has not been configured" +#endif + +#ifndef FIRMWARE_STACK_SIZE + #error "FIRMWARE_STACK_SIZE has not been configured" +#endif + +#ifndef FIRMWARE_MEM0_BASE + #error "FIRMWARE_MEM0_BASE has not been configured" +#endif + +#ifndef FIRMWARE_MEM0_SIZE + #error "FIRMWARE_MEM0_SIZE has not been configured" +#endif + +#if ((FIRMWARE_MEM_MODE != FWK_MEM_MODE_SINGLE_REGION) && \ + (FIRMWARE_MEM_MODE != FWK_MEM_MODE_DUAL_REGION_RELOCATION) && \ + (FIRMWARE_MEM_MODE != FWK_MEM_MODE_DUAL_REGION_NO_RELOCATION)) + #error "FIRMWARE_MEM_MODE has been configured improperly" +#endif + +#if FIRMWARE_MEM_MODE != FWK_MEM_MODE_SINGLE_REGION + #ifndef FIRMWARE_MEM1_BASE + #error "FIRMWARE_MEM1_BASE has not been configured" + #endif + + #ifndef FIRMWARE_MEM1_SIZE + #error "FIRMWARE_MEM1_SIZE has not been configured" + #endif +#endif + +/* + * Calculate stack region in the data memory. + */ + +#if FIRMWARE_MEM_MODE == FWK_MEM_MODE_SINGLE_REGION + ASSERT(FIRMWARE_STACK_SIZE < FIRMWARE_MEM0_SIZE, + "FIRMWARE_STACK_SIZE does not fit in MEM0") + #define UNALIGNED_STACK_BASE \ + (FIRMWARE_MEM0_BASE + FIRMWARE_MEM0_SIZE - FIRMWARE_STACK_SIZE) +#else + ASSERT(FIRMWARE_STACK_SIZE < FIRMWARE_MEM1_SIZE, + "FIRMWARE_STACK_SIZE does not fit in MEM1") + #define UNALIGNED_STACK_BASE \ + (FIRMWARE_MEM1_BASE + FIRMWARE_MEM1_SIZE - FIRMWARE_STACK_SIZE) +#endif + +#define STACK_BASE \ + ( \ + ((UNALIGNED_STACK_BASE + STACK_ALIGNMENT - 1) / STACK_ALIGNMENT) \ + * STACK_ALIGNMENT \ + ) + +#define STACK_SIZE \ + (( \ + ((STACK_BASE + FIRMWARE_STACK_SIZE) / STACK_ALIGNMENT) \ + * STACK_ALIGNMENT \ + ) - STACK_BASE) + +ASSERT(STACK_SIZE > 0, "FIRMWARE_STACK_SIZE is too small") + +ENTRY(exception_reset) + +MEMORY { +#if FIRMWARE_MEM_MODE == FWK_MEM_MODE_SINGLE_REGION + /* Only one memory region with read, execute and write attributes */ + mem0 (rxw): ORIGIN = FIRMWARE_MEM0_BASE, LENGTH = FIRMWARE_MEM0_SIZE - \ + FIRMWARE_STACK_SIZE +#else + mem0 (rx): ORIGIN = FIRMWARE_MEM0_BASE, LENGTH = FIRMWARE_MEM0_SIZE + mem1 (rxw): ORIGIN = FIRMWARE_MEM1_BASE, LENGTH = FIRMWARE_MEM1_SIZE - \ + FIRMWARE_STACK_SIZE +#endif + + stack (rw): ORIGIN = STACK_BASE, LENGTH = STACK_SIZE +} + +SECTIONS { + .text : { + KEEP(*(.exception)) + *(.text*) + *(.rodata*) + } > mem0 + + .data : { + . = ALIGN(4); + *(.data*) + . = ALIGN(4); +#if FIRMWARE_MEM_MODE == FWK_MEM_MODE_SINGLE_REGION + } > mem0 /* .data follows .text in mem0 */ +#elif FIRMWARE_MEM_MODE == FWK_MEM_MODE_DUAL_REGION_NO_RELOCATION + } > mem1 /* .data is the first section in mem1 */ +#elif FIRMWARE_MEM_MODE == FWK_MEM_MODE_DUAL_REGION_RELOCATION + } > mem1 AT>mem0 /* Run-time image is at mem1, but loaded from mem0 */ +#else + ASSERT(0, "Unrecognized FIRMWARE_MEM_MODE") +#endif + + .bss : { + . = ALIGN(4); + *(.bss*) + . = ALIGN(4); +#if FIRMWARE_MEM_MODE == FWK_MEM_MODE_SINGLE_REGION + } > mem0 /* Run-time image is at mem1, but loaded from mem0 */ +#else + } > mem1 /* .bss follows .data in mem1 */ +#endif + + .stack : { + . = . + STACK_SIZE; + } > stack + + __TEXT_START__ = LOADADDR(.text); + __TEXT_SIZE__ = SIZEOF(.text); + __TEXT_END__ = __TEXT_START__ + __TEXT_SIZE__; + + __STACK_START__ = LOADADDR(.stack); + __STACK_SIZE__ = SIZEOF(.stack); + __STACK_END__ = __STACK_START__ + __STACK_SIZE__; + + __DATA_LMA_START__ = LOADADDR(.data); + __DATA_START__ = ADDR(.data); + __DATA_SIZE__ = SIZEOF(.data); + + __BSS_START__ = ADDR(.bss); + __BSS_SIZE__ = SIZEOF(.bss); + __BSS_END__ = __BSS_START__ + __BSS_SIZE__; + + __HEAP_START__ = __BSS_START__ + __BSS_SIZE__; + __HEAP_END__ = __STACK_START__; + __HEAP_SIZE__ = __HEAP_END__ - __HEAP_START__; +} diff --git a/arch/src/armv6-m/reset-v6.S b/arch/src/armv6-m/reset-v6.S new file mode 100644 index 0000000..4425081 --- /dev/null +++ b/arch/src/armv6-m/reset-v6.S @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * reset vector. + */ + + .syntax unified + + .text + + .global exception_reset + .thumb_func + .func exception_reset +exception_reset: + bl start + .pool + .endfunc diff --git a/arch/src/armv7-m/arm_nvic.c b/arch/src/armv7-m/arm_nvic.c new file mode 100644 index 0000000..c113ba4 --- /dev/null +++ b/arch/src/armv7-m/arm_nvic.c @@ -0,0 +1,352 @@ + /* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Interrupt management. + */ + +#include <limits.h> +#include <stdint.h> +#include <stdlib.h> +#include <stdnoreturn.h> +#include <fwk_arch.h> +#include <fwk_errno.h> +#include <fwk_interrupt.h> +#include <fwk_macros.h> +#include <fwk_mm.h> +#include <cmsis_compiler.h> + +#ifdef BUILD_HAS_MULTITHREADING + #include <rtx_os.h> +#endif + +extern noreturn void exception_invalid(void); + +struct nvic; + +#define SCB_SHCSR ((FWK_RW uint32_t *)(0xE000ED24UL)) +#define SCB_VTOR ((FWK_RW uint32_t *)(0xE000ED08UL)) +#define SCS_ICTR ((FWK_R uint32_t *)(0xE000E004UL)) +#define SCS_STIR ((FWK_W uint32_t *)(0xE000EF00UL)) +#define SCS_NVIC ((struct nvic *)(0xE000E100UL)) + +#define SCB_SHCSR_MEMFAULTENA_MASK (1 << 16) +#define SCB_SHCSR_BUSFAULTENA_MASK (1 << 17) +#define SCB_SHCSR_USGFAULTENA_MASK (1 << 18) + +enum exception_num { + EXCEPTION_NUM_INVALID = 0U, + EXCEPTION_NUM_RESET = 1U, + EXCEPTION_NUM_NMI = 2U, + EXCEPTION_NUM_HARDFAULT = 3U, + EXCEPTION_NUM_MEMMANAGE = 4U, + EXCEPTION_NUM_BUSFAULT = 5U, + EXCEPTION_NUM_USAGEFAULT = 6U, + EXCEPTION_NUM_SVCALL = 11U, + EXCEPTION_NUM_DEBUGMONITOR = 12U, + EXCEPTION_NUM_PENDSV = 14U, + EXCEPTION_NUM_SYSTICK = 15U, + EXCEPTION_NUM_COUNT, +}; + +struct nvic { + FWK_RW uint32_t ISER[16]; /* Interrupt Set Enabled Register */ + uint32_t RESERVED0[16]; + FWK_RW uint32_t ICER[16]; /* Interrupt Clear Enabled Register */ + uint32_t RESERVED1[16]; + FWK_RW uint32_t ISPR[16]; /* Interrupt Set Pending Register */ + uint32_t RESERVED2[16]; + FWK_RW uint32_t ICPR[16]; /* Interrupt Clear Pending Register */ + uint32_t RESERVED3[16]; + FWK_R uint32_t IABR[16]; /* Interrupt Active Bit Register */ + uint32_t RESERVED4[48]; + FWK_W uint32_t IPR[16]; /* Interrupt Priority Register */ + uint32_t RESERVED5[48]; +}; + +static uint32_t isr_count; +static uint32_t irq_count; + +/* + * For interrupts with parameters, their entry in the vector table points to a + * global handler that calls a registered function in the callback table with a + * corresponding parameter. Entries in the vector table for interrupts without + * parameters point directly to the handler functions. + */ +struct callback { + void (*func)(uintptr_t param); + uintptr_t param; +}; + +static void (**vector)(void); +static struct callback *callback; + +static void irq_global(void) +{ + struct callback *entry = &callback[__get_IPSR()]; + entry->func(entry->param); +} + +static int global_enable(void) +{ + __enable_irq(); + + return FWK_SUCCESS; +} + +static int global_disable(void) +{ + __disable_irq(); + + return FWK_SUCCESS; +} + +static int is_enabled(unsigned int interrupt, bool *enabled) +{ + if (interrupt >= irq_count) + return FWK_E_PARAM; + + *enabled = SCS_NVIC->ISER[interrupt / 32] & + (UINT32_C(1) << (interrupt & 0x1F)); + + return FWK_SUCCESS; +} + +static int enable(unsigned int interrupt) +{ + if (interrupt >= irq_count) + return FWK_E_PARAM; + + SCS_NVIC->ISER[interrupt / 32] = UINT32_C(1) << (interrupt & 0x1F); + + return FWK_SUCCESS; +} + +static int disable(unsigned int interrupt) +{ + if (interrupt >= irq_count) + return FWK_E_PARAM; + + SCS_NVIC->ICER[interrupt / 32] = UINT32_C(1) << (interrupt & 0x1F); + + return FWK_SUCCESS; +} + +static int is_pending(unsigned int interrupt, bool *pending) +{ + if (interrupt >= irq_count) + return FWK_E_PARAM; + + *pending = SCS_NVIC->ISPR[interrupt / 32] & + (UINT32_C(1) << (interrupt & 0x1F)); + + return FWK_SUCCESS; +} + +static int set_pending(unsigned int interrupt) +{ + if (interrupt >= irq_count) + return FWK_E_PARAM; + + *SCS_STIR = interrupt; + + return FWK_SUCCESS; +} + +static int clear_pending(unsigned int interrupt) +{ + if (interrupt >= irq_count) + return FWK_E_PARAM; + + SCS_NVIC->ICPR[interrupt / 32] = UINT32_C(1) << (interrupt & 0x1F); + + return FWK_SUCCESS; +} + +static int set_isr_irq(unsigned int interrupt, void (*isr)(void)) +{ + if (interrupt >= irq_count) + return FWK_E_PARAM; + + vector[EXCEPTION_NUM_COUNT + interrupt] = isr; + + return FWK_SUCCESS; +} + +static int set_isr_irq_param(unsigned int interrupt, + void (*isr)(uintptr_t param), + uintptr_t parameter) +{ + struct callback *entry; + if (interrupt >= irq_count) + return FWK_E_PARAM; + + vector[EXCEPTION_NUM_COUNT + interrupt] = irq_global; + + entry = &callback[EXCEPTION_NUM_COUNT + interrupt]; + entry->func = isr; + entry->param = parameter; + + return FWK_SUCCESS; +} + +static int set_isr_nmi(void (*isr)(void)) +{ + vector[EXCEPTION_NUM_NMI] = isr; + + return FWK_SUCCESS; +} + +static int set_isr_nmi_param(void (*isr)(uintptr_t param), uintptr_t parameter) +{ + struct callback *entry; + + vector[EXCEPTION_NUM_NMI] = irq_global; + + entry = &callback[EXCEPTION_NUM_NMI]; + entry->func = isr; + entry->param = parameter; + + return FWK_SUCCESS; +} + +static int set_isr_fault(void (*isr)(void)) +{ + vector[EXCEPTION_NUM_HARDFAULT] = isr; + vector[EXCEPTION_NUM_MEMMANAGE] = isr; + vector[EXCEPTION_NUM_BUSFAULT] = isr; + vector[EXCEPTION_NUM_USAGEFAULT] = isr; + + return FWK_SUCCESS; +} + +static int get_current(unsigned int *interrupt) +{ + *interrupt = __get_IPSR(); + + /* Not an interrupt */ + if (*interrupt == 0) + return FWK_E_STATE; + + if (*interrupt == EXCEPTION_NUM_NMI) + *interrupt = FWK_INTERRUPT_NMI; + else if ((*interrupt) < EXCEPTION_NUM_COUNT) + *interrupt = FWK_INTERRUPT_EXCEPTION; + else + *interrupt -= EXCEPTION_NUM_COUNT; + + return FWK_SUCCESS; +} + +static const struct fwk_arch_interrupt_driver arm_nvic_driver = { + .global_enable = global_enable, + .global_disable = global_disable, + .is_enabled = is_enabled, + .enable = enable, + .disable = disable, + .is_pending = is_pending, + .set_pending = set_pending, + .clear_pending = clear_pending, + .set_isr_irq = set_isr_irq, + .set_isr_irq_param = set_isr_irq_param, + .set_isr_nmi = set_isr_nmi, + .set_isr_nmi_param = set_isr_nmi_param, + .set_isr_fault = set_isr_fault, + .get_current = get_current, +}; + +static void irq_invalid(void) +{ + static unsigned int spurious = 0; + + spurious++; + + disable(__get_IPSR()); +} + +int arm_nvic_init(const struct fwk_arch_interrupt_driver **driver) +{ + uint32_t ictr_intlinesnum; + uint32_t align_entries; + uint32_t align_word; + unsigned int i; + + if (driver == NULL) + return FWK_E_PARAM; + + /* Find the number of interrupt lines implemented in hardware */ + ictr_intlinesnum = *SCS_ICTR & 0x0000000F; + irq_count = (ictr_intlinesnum + 1) * 32; + isr_count = irq_count + EXCEPTION_NUM_COUNT; + + /* + * Allocate and initialize a table for the callback functions and their + * corresponding parameters. + */ + callback = fwk_mm_calloc(isr_count, sizeof(callback[0])); + if (callback == NULL) + return FWK_E_NOMEM; + /* + * The base address for the vector table must align on the number of + * entries in the table, corresponding to a word boundary rounded up to the + * next power of two. + * + * For example, for a vector table with 48 entries, the base address must be + * on a 64-word boundary. + */ + + /* Calculate the next power of two */ + align_entries = UINT32_C(1) << (32 - __CLZ(isr_count - 1)); + + /* Calculate alignment on a word boundary */ + align_word = align_entries * sizeof(vector[0]); + + vector = fwk_mm_alloc_aligned(isr_count, sizeof(vector[0]), align_word); + + if (vector == NULL) + return FWK_E_NOMEM; + + /* + * Initialize all exception entries to point to the exception_invalid() + * handler. + * + * Note: Initialization starts from entry 1 since entry 0 is not an + * exception pointer but the default stack pointer. + */ + for (i = 1; i < EXCEPTION_NUM_COUNT; i++) + vector[i] = exception_invalid; + + /* Initialize IRQs */ + for (i = 0; i < irq_count; i++) { + /* Initialize all IRQ entries to point to the irq_invalid() handler */ + vector[EXCEPTION_NUM_COUNT + i] = irq_invalid; + + /* Ensure IRQs are disabled during boot sequence */ + disable(i); + clear_pending(i); + } + +#ifdef BUILD_HAS_MULTITHREADING + /* Set exception entries that are implemented and handled by RTX */ + vector[EXCEPTION_NUM_SVCALL] = SVC_Handler; + vector[EXCEPTION_NUM_PENDSV] = PendSV_Handler; + vector[EXCEPTION_NUM_SYSTICK] = SysTick_Handler; +#endif + + __DMB(); + + /* Switch to the new vector table */ + *SCB_VTOR = (uint32_t)vector; + __DMB(); + + /* Enable the Usage, Bus and Memory faults which are disabled by default */ + *SCB_SHCSR |= SCB_SHCSR_MEMFAULTENA_MASK | + SCB_SHCSR_BUSFAULTENA_MASK | + SCB_SHCSR_USGFAULTENA_MASK; + + *driver = &arm_nvic_driver; + + return FWK_SUCCESS; +} diff --git a/arch/src/armv7-m/armv7-crt0.S b/arch/src/armv7-m/armv7-crt0.S new file mode 100644 index 0000000..f01ef1a --- /dev/null +++ b/arch/src/armv7-m/armv7-crt0.S @@ -0,0 +1,53 @@ + /* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * startup file. + */ + + + .syntax unified + + .text + + .global start + .thumb_func + .func start +start: + /* Load .data, which is 4-byte aligned */ + ldr r1, =__DATA_SIZE__ + cmp r1, #0 + beq 6f + ldr r0, =__DATA_LMA_START__ + ldr r2, =__DATA_START__ + cmp r0, r2 + beq 6f +5: + ldr r3, [r0], #4 + str r3, [r2], #4 + subs r1, #4 + bne 5b + +6: + /* Clear .bss, which is also 4-byte aligned */ + ldr r1, =__BSS_SIZE__ + cmp r1, #0 + beq 8f + ldr r0, =__BSS_START__ + mov r2, #0 +7: + str r2, [r0], #4 + subs r1, #4 + bne 7b + +8: + dsb + bl arm_main + +9: + wfi + b 9b + .pool + .endfunc diff --git a/arch/src/armv7-m/exception.S b/arch/src/armv7-m/exception.S new file mode 100644 index 0000000..1f943f2 --- /dev/null +++ b/arch/src/armv7-m/exception.S @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * exceptions. + */ + + .syntax unified + + .section .exception + + .global exceptions +exceptions: + .word __STACK_END__ + .word exception_reset /* Reset */ + .word exception_invalid /* NMI */ + .word exception_invalid /* HardFault */ + .word exception_invalid /* MemManage */ + .word exception_invalid /* Bus Fault */ + .word exception_invalid /* UsageFault */ + .word exception_invalid /* Reserved */ + .word exception_invalid /* Reserved */ + .word exception_invalid /* Reserved */ + .word exception_invalid /* Reserved */ + .word exception_invalid /* SVCall */ + .word exception_invalid /* DebugMonitor */ + .word exception_invalid /* Reserved */ + .word exception_invalid /* PendSV */ + .word exception_invalid /* SysTick */ + + .section .text + + .global exception_invalid + .thumb_func + .func exception_invalid +exception_invalid: + wfi + b exception_invalid + .endfunc diff --git a/arch/src/armv7-m/ld.S b/arch/src/armv7-m/ld.S new file mode 100644 index 0000000..068fcca --- /dev/null +++ b/arch/src/armv7-m/ld.S @@ -0,0 +1,191 @@ + /* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * scatter file. + */ + +/* + * There are three supported memory layouts for the ARMv7-M architecture: + * + * Layout 1 - Single region: + * - All sections are placed in one contiguous region. + * - This layout uses only the mem0 memory region. + * - The memory is considered RXW by the linker, but the sections can be + * configured later on with different attributes using the MPU. + * - The main stack is placed at the end of mem0. + * - This layout is mainly used by second-stage firmware that is loaded directly + * into a single RAM. + * + * Layout 2 - Dual region with relocation: + * - One region is used for .text and .data (storage). + * - A second region is used for the remaining sections. + * - This layout uses memory regions mem0 and mem1 as the first and second + * regions, respectively. + * - The main stack is placed at the end of mem1. + * - This layout is mainly used by ROM firmware which uses part of the RAM for + * the data sections. + * + * Layout 3 - Dual region without relocation + * - One region is used only for the .text section. + * - A second region is used for all data sections. + * - This layout uses memory regions mem0 and mem1 as the first and second + * regions, respectively. + * - The main stack is placed at the end of mem1. + * - The main difference from layout 2 is that there is no relocation of the + * .data section. + * - This layout is mainly used by second-stage firmware loaded directly into + * two RAM regions. One of the RAM regions is attached to the instruction bus, + * which improves the performance as data and instruction accesses are + * independent. + * + */ + +#define FWK_MEM_MODE_INVALID 0 +#define FWK_MEM_MODE_SINGLE_REGION 1 +#define FWK_MEM_MODE_DUAL_REGION_RELOCATION 2 +#define FWK_MEM_MODE_DUAL_REGION_NO_RELOCATION 3 + +#include <fmw_memory.ld.S> + +#define STACK_ALIGNMENT 8 + +/* + * Input validation + */ + +#ifndef FIRMWARE_MEM_MODE + #error "FIRMWARE_MEM_MODE has not been configured" +#endif + +#ifndef FIRMWARE_STACK_SIZE + #error "FIRMWARE_STACK_SIZE has not been configured" +#endif + +#ifndef FIRMWARE_MEM0_BASE + #error "FIRMWARE_MEM0_BASE has not been configured" +#endif + +#ifndef FIRMWARE_MEM0_SIZE + #error "FIRMWARE_MEM0_SIZE has not been configured" +#endif + +#if ((FIRMWARE_MEM_MODE != FWK_MEM_MODE_SINGLE_REGION) && \ + (FIRMWARE_MEM_MODE != FWK_MEM_MODE_DUAL_REGION_RELOCATION) && \ + (FIRMWARE_MEM_MODE != FWK_MEM_MODE_DUAL_REGION_NO_RELOCATION)) + #error "FIRMWARE_MEM_MODE has been configured improperly" +#endif + +#if FIRMWARE_MEM_MODE != FWK_MEM_MODE_SINGLE_REGION + #ifndef FIRMWARE_MEM1_BASE + #error "FIRMWARE_MEM1_BASE has not been configured" + #endif + + #ifndef FIRMWARE_MEM1_SIZE + #error "FIRMWARE_MEM1_SIZE has not been configured" + #endif +#endif + +/* + * Calculate stack region in the data memory. + */ + +#if FIRMWARE_MEM_MODE == FWK_MEM_MODE_SINGLE_REGION + ASSERT(FIRMWARE_STACK_SIZE < FIRMWARE_MEM0_SIZE, + "FIRMWARE_STACK_SIZE does not fit in MEM0") + #define UNALIGNED_STACK_BASE \ + (FIRMWARE_MEM0_BASE + FIRMWARE_MEM0_SIZE - FIRMWARE_STACK_SIZE) +#else + ASSERT(FIRMWARE_STACK_SIZE < FIRMWARE_MEM1_SIZE, + "FIRMWARE_STACK_SIZE does not fit in MEM1") + #define UNALIGNED_STACK_BASE \ + (FIRMWARE_MEM1_BASE + FIRMWARE_MEM1_SIZE - FIRMWARE_STACK_SIZE) +#endif + +#define STACK_BASE \ + ( \ + ((UNALIGNED_STACK_BASE + STACK_ALIGNMENT - 1) / STACK_ALIGNMENT) \ + * STACK_ALIGNMENT \ + ) + +#define STACK_SIZE \ + (( \ + ((STACK_BASE + FIRMWARE_STACK_SIZE) / STACK_ALIGNMENT) \ + * STACK_ALIGNMENT \ + ) - STACK_BASE) + +ASSERT(STACK_SIZE > 0, "FIRMWARE_STACK_SIZE is too small") + +ENTRY(exception_reset) + +MEMORY { +#if FIRMWARE_MEM_MODE == FWK_MEM_MODE_SINGLE_REGION + /* Only one memory region with read, execute and write attributes */ + mem0 (rxw): ORIGIN = FIRMWARE_MEM0_BASE, LENGTH = FIRMWARE_MEM0_SIZE - \ + FIRMWARE_STACK_SIZE +#else + mem0 (rx): ORIGIN = FIRMWARE_MEM0_BASE, LENGTH = FIRMWARE_MEM0_SIZE + mem1 (rxw): ORIGIN = FIRMWARE_MEM1_BASE, LENGTH = FIRMWARE_MEM1_SIZE - \ + FIRMWARE_STACK_SIZE +#endif + + stack (rw): ORIGIN = STACK_BASE, LENGTH = STACK_SIZE +} + +SECTIONS { + .text : { + KEEP(*(.exception)) + *(.text*) + *(.rodata*) + } > mem0 + + .data : { + . = ALIGN(4); + *(.data*) + . = ALIGN(4); +#if FIRMWARE_MEM_MODE == FWK_MEM_MODE_SINGLE_REGION + } > mem0 /* .data follows .text in mem0 */ +#elif FIRMWARE_MEM_MODE == FWK_MEM_MODE_DUAL_REGION_NO_RELOCATION + } > mem1 /* .data is the first section in mem1 */ +#elif FIRMWARE_MEM_MODE == FWK_MEM_MODE_DUAL_REGION_RELOCATION + } > mem1 AT>mem0 /* Run-time image is at mem1, but loaded from mem0 */ +#else + ASSERT(0, "Unrecognized FIRMWARE_MEM_MODE") +#endif + + .bss : { + . = ALIGN(4); + *(.bss*) + . = ALIGN(4); +#if FIRMWARE_MEM_MODE == FWK_MEM_MODE_SINGLE_REGION + } > mem0 /* Run-time image is at mem1, but loaded from mem0 */ +#else + } > mem1 /* .bss follows .data in mem1 */ +#endif + + .stack : { + . = . + STACK_SIZE; + } > stack + + __TEXT_START__ = LOADADDR(.text); + __TEXT_SIZE__ = SIZEOF(.text); + __TEXT_END__ = __TEXT_START__ + __TEXT_SIZE__; + + __STACK_START__ = LOADADDR(.stack); + __STACK_SIZE__ = SIZEOF(.stack); + __STACK_END__ = __STACK_START__ + __STACK_SIZE__; + + __DATA_LMA_START__ = LOADADDR(.data); + __DATA_START__ = ADDR(.data); + __DATA_SIZE__ = SIZEOF(.data); + + __BSS_START__ = ADDR(.bss); + __BSS_SIZE__ = SIZEOF(.bss); + __BSS_END__ = __BSS_START__ + __BSS_SIZE__; + + __HEAP_START__ = __BSS_START__ + __BSS_SIZE__; + __HEAP_END__ = __STACK_START__; + __HEAP_SIZE__ = __HEAP_END__ - __HEAP_START__; +} diff --git a/arch/src/armv7-m/reset-v7.S b/arch/src/armv7-m/reset-v7.S new file mode 100644 index 0000000..4ba1898 --- /dev/null +++ b/arch/src/armv7-m/reset-v7.S @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * reset vector. + */ + + .syntax unified + + .text + + .global exception_reset + .thumb_func + .func exception_reset +exception_reset: + /* + * Set up the Configuration Control Register (CCR) in the System Control + * Block (1) by setting the following flag bits: + * + * UNALIGN_TRP [3]: Enable trapping on unaligned word or halfword accesses. + * DIV_0_TRP [4]: Enable trapping on division by zero. + * STKALIGN [9]: Enable automatic DWORD stack-alignment on exception + * entry (2). + * + * All other bits are left in their default state. + * + * (1) ARMĀ® v7-M Architecture Reference Manual, section B3.2.8. + * (2) ARMĀ® v7-M Architecture Reference Manual, section B1.5.7. + */ + ldr r0, =0xE000ED14 /* Load CCR address (architecture-defined) */ + ldr r1, [r0] /* Load existing CCR value */ + orr r1, #0x218 /* Set flag bits */ + str r1, [r0] /* Store modified value back to the CCR */ + + bl start + .pool + .endfunc diff --git a/arch/src/section.h b/arch/src/section.h new file mode 100644 index 0000000..96447dd --- /dev/null +++ b/arch/src/section.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Description: + * Section symbols. + */ + +#ifndef ARCH_SECTION_H +#define ARCH_SECTION_H + +#include <stddef.h> + +extern unsigned int __TEXT_START__; +extern unsigned int __TEXT_SIZE__; +extern unsigned int __TEXT_END__; + +extern unsigned int __DATA_START__; +extern unsigned int __DATA_SIZE__; +extern unsigned int __DATA_END__; + +extern unsigned int __BSS_START__; +extern unsigned int __BSS_SIZE__; +extern unsigned int __BSS_END__; + +extern unsigned int __STACK_START__; +extern unsigned int __STACK_SIZE__; +extern unsigned int __STACK_END__; + +/* Beginning of the .text section */ +#define ARCH_SECTION_TEXT_START ((uintptr_t)(&__TEXT_START__)) + +/* End of the .text section */ +#define ARCH_SECTION_TEXT_END ((uintptr_t)(&__TEXT_END__)) + +/* Size of the .text section */ +#define ARCH_SECTION_TEXT_SIZE ((size_t)(&__TEXT_SIZE__)) + +/* Start of the .data section */ +#define ARCH_SECTION_DATA_START ((uintptr_t)(&__DATA_START__)) + +/* End of the .data section */ +#define ARCH_SECTION_DATA_END ((uintptr_t)(&__DATA_END__)) + +/* Size of the .data section */ +#define ARCH_SECTION_DATA_SIZE ((size_t)(&__DATA_SIZE__)) + +/* Start of the .bss section */ +#define ARCH_SECTION_BSS_START ((uintptr_t)(&__BSS_START__)) + +/* End of the .bss section */ +#define ARCH_SECTION_BSS_END ((uintptr_t)(&__BSS_END__)) + +/* Size of the .bss section */ +#define ARCH_SECTION_BSS_SIZE ((size_t)(&__BSS_SIZE__)) + +/* Start of the .heap section */ +#define ARCH_SECTION_HEAP_START ARCH_SECTION_BSS_END + +/* End of the .heap section */ +#define ARCH_SECTION_HEAP_END ARCH_SECTION_STACK_START + +/* Size of the .heap section */ +#define ARCH_SECTION_HEAP_SIZE ((size_t)(ARCH_SECTION_HEAP_END - \ + ARCH_SECTION_HEAP_START)) + +/* Start of the .stack section */ +#define ARCH_SECTION_STACK_START ((uintptr_t)(&__STACK_START__)) + +/* End of the .stack section */ +#define ARCH_SECTION_STACK_END ((uintptr_t)(&__STACK_END__)) + +/* Size of the .stack section */ +#define ARCH_SECTION_STACK_SIZE ((size_t)(&__STACK_SIZE__)) + +#endif /* ARCH_SECTION_H */ |