1/* 2 * Arm SCP/MCP Software 3 * Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved. 4 * Copyright (c) 2019-2021, Renesas Electronics Corporation. All rights 5 * reserved. 6 * 7 * SPDX-License-Identifier: BSD-3-Clause 8 * 9 * There are three supported memory layouts for the ARMv7-M architecture: 10 * 11 * Layout 1 - Single region: 12 * - All sections are placed in one contiguous region. 13 * - This layout uses only the mem0 memory region. 14 * - The memory is considered RXW by the linker, but the sections can be 15 * configured later on with different attributes using the MPU. 16 * - The main stack is placed at the end of mem0. 17 * - This layout is mainly used by second-stage firmware that is loaded directly 18 * into a single RAM. 19 * 20 * Layout 2 - Dual region with relocation: 21 * - One region is used for .text and .data (storage). 22 * - A second region is used for the remaining sections. 23 * - This layout uses memory regions mem0 and mem1 as the first and second 24 * regions, respectively. 25 * - The main stack is placed at the end of mem1. 26 * - This layout is mainly used by ROM firmware which uses part of the RAM for 27 * the data sections. 28 * 29 * Layout 3 - Dual region without relocation 30 * - One region is used only for the .text section. 31 * - A second region is used for all data sections. 32 * - This layout uses memory regions mem0 and mem1 as the first and second 33 * regions, respectively. 34 * - The main stack is placed at the end of mem1. 35 * - The main difference from layout 2 is that there is no relocation of the 36 * .data section. 37 * - This layout is mainly used by second-stage firmware loaded directly into 38 * two RAM regions. One of the RAM regions is attached to the instruction bus, 39 * which improves the performance as data and instruction accesses are 40 * independent. 41 * 42 */ 43 44#define ARCH_MEM_MODE_SINGLE_REGION 0 45#define ARCH_MEM_MODE_DUAL_REGION_RELOCATION 1 46#define ARCH_MEM_MODE_DUAL_REGION_NO_RELOCATION 2 47 48#include <fmw_memory.h> 49 50#define STACK_ALIGNMENT 8 51 52/* 53 * Input validation 54 */ 55 56#ifndef FMW_MEM_MODE 57 #error "FMW_MEM_MODE has not been configured" 58#endif 59 60#ifndef FMW_STACK_SIZE 61 #error "FMW_STACK_SIZE has not been configured" 62#endif 63 64#ifndef FMW_MEM0_BASE 65 #error "FMW_MEM0_BASE has not been configured" 66#endif 67 68#ifndef FMW_MEM0_SIZE 69 #error "FMW_MEM0_SIZE has not been configured" 70#endif 71 72#if ((FMW_MEM_MODE != ARCH_MEM_MODE_SINGLE_REGION) && \ 73 (FMW_MEM_MODE != ARCH_MEM_MODE_DUAL_REGION_RELOCATION) && \ 74 (FMW_MEM_MODE != ARCH_MEM_MODE_DUAL_REGION_NO_RELOCATION)) 75 #error "FMW_MEM_MODE has been configured improperly" 76#endif 77 78#if FMW_MEM_MODE != ARCH_MEM_MODE_SINGLE_REGION 79 #ifndef FIRMWARE_MEM1_BASE 80 #error "FIRMWARE_MEM1_BASE has not been configured" 81 #endif 82 83 #ifndef FIRMWARE_MEM1_SIZE 84 #error "FIRMWARE_MEM1_SIZE has not been configured" 85 #endif 86#endif 87 88/* 89 * Calculate stack region in the data memory. 90 */ 91 92#if FMW_MEM_MODE == ARCH_MEM_MODE_SINGLE_REGION 93 ASSERT(FMW_STACK_SIZE < FMW_MEM0_SIZE, 94 "FMW_STACK_SIZE does not fit in MEM0") 95 #define UNALIGNED_STACK_BASE \ 96 (FMW_MEM0_BASE + FMW_MEM0_SIZE - FMW_STACK_SIZE) 97#else 98 ASSERT(FMW_STACK_SIZE < FIRMWARE_MEM1_SIZE, 99 "FMW_STACK_SIZE does not fit in MEM1") 100 #define UNALIGNED_STACK_BASE \ 101 (FIRMWARE_MEM1_BASE + FIRMWARE_MEM1_SIZE - FMW_STACK_SIZE) 102#endif 103 104#define STACK_BASE \ 105 ( \ 106 ((UNALIGNED_STACK_BASE + STACK_ALIGNMENT - 1) / STACK_ALIGNMENT) \ 107 * STACK_ALIGNMENT \ 108 ) 109 110#define STACK_SIZE \ 111 (( \ 112 ((STACK_BASE + FMW_STACK_SIZE) / STACK_ALIGNMENT) \ 113 * STACK_ALIGNMENT \ 114 ) - STACK_BASE) 115 116ASSERT(STACK_SIZE > 0, "FMW_STACK_SIZE is too small") 117 118ENTRY(_entrypoint) 119 120MEMORY { 121#if FMW_MEM_MODE == ARCH_MEM_MODE_SINGLE_REGION 122 /* Only one memory region with read, execute and write attributes */ 123 mem0 (rxw): ORIGIN = FMW_MEM0_BASE, LENGTH = FMW_MEM0_SIZE - \ 124 FMW_STACK_SIZE 125#else 126 mem0 (rx): ORIGIN = FMW_MEM0_BASE, LENGTH = FMW_MEM0_SIZE 127 mem1 (rxw): ORIGIN = FIRMWARE_MEM1_BASE, LENGTH = FIRMWARE_MEM1_SIZE - \ 128 FMW_STACK_SIZE 129#endif 130 stack (rw): ORIGIN = STACK_BASE, LENGTH = STACK_SIZE 131 sram (rxw): ORIGIN = ((0xE6302000)), LENGTH = (0x00001000) 132} 133 134SECTIONS { 135 .text : { 136 *(.vectors) 137 *(.entrypoint) 138 *(.text*) 139 *(.rodata*) 140 *(.note.gnu.build-id) 141 } > mem0 142 143 __text__ = .; 144 145 __sram_copy_start__ = .; 146 .system_ram : { 147 __system_ram_start__ = .; 148 *(.system_ram*) 149 *iic_dvfs.o(.rodata) 150 __system_ram_end__ = .; 151 } > sram AT> mem0 152 153 . = __text__ + SIZEOF(.system_ram); 154 155 /* 156 * Define a linker symbol to mark start of the RW memory area for this 157 * image. 158 */ 159 __RW_START__ = . ; 160 161 .data : { 162 . = ALIGN(4); 163 *(.data*) 164 . = ALIGN(4); 165#if FMW_MEM_MODE == ARCH_MEM_MODE_SINGLE_REGION 166 } > mem0 /* .data follows .text in mem0 */ 167#elif FMW_MEM_MODE == ARCH_MEM_MODE_DUAL_REGION_NO_RELOCATION 168 } > mem1 /* .data is the first section in mem1 */ 169#elif FMW_MEM_MODE == ARCH_MEM_MODE_DUAL_REGION_RELOCATION 170 } > mem1 AT>mem0 /* Run-time image is at mem1, but loaded from mem0 */ 171#else 172 ASSERT(0, "Unrecognized FMW_MEM_MODE") 173#endif 174 175 .bss : { 176 . = ALIGN(4); 177 *(.bss*) 178 . = ALIGN(4); 179#if FMW_MEM_MODE == ARCH_MEM_MODE_SINGLE_REGION 180 } > mem0 /* Run-time image is at mem1, but loaded from mem0 */ 181#else 182 } > mem1 /* .bss follows .data in mem1 */ 183#endif 184 185 .stack (NOLOAD) : { 186 . = . + STACK_SIZE; 187 } > stack 188 __RW_END__ = .; 189 190 /* 191 * Define a linker symbol to mark end of the RW memory area for this 192 * image. 193 */ 194 195 __TEXT_START__ = LOADADDR(.text); 196 __TEXT_SIZE__ = SIZEOF(.text); 197 __TEXT_END__ = __TEXT_START__ + __TEXT_SIZE__; 198 199 __STACK_START__ = LOADADDR(.stack); 200 __STACK_SIZE__ = SIZEOF(.stack); 201 __STACK_END__ = __STACK_START__ + __STACK_SIZE__; 202 __STACK_TOP__ = __STACK_END__; 203 __STACK_SP3_SIZE__ = 0x400; 204 __STACK_SP0_TOP__ = __STACK_END__ - __STACK_SP3_SIZE__; 205 206 __DATA_LMA_START__ = LOADADDR(.data); 207 __DATA_START__ = ADDR(.data); 208 __DATA_SIZE__ = SIZEOF(.data); 209 210 __BSS_START__ = ADDR(.bss); 211 __BSS_SIZE__ = SIZEOF(.bss); 212 __BSS_END__ = __BSS_START__ + __BSS_SIZE__; 213 214 __HEAP_START__ = __BSS_START__ + __BSS_SIZE__; 215 __HEAP_END__ = __STACK_START__; 216 __HEAP_SIZE__ = __HEAP_END__ - __HEAP_START__; 217} 218