targets/emcraft_sf2_som: Add linker script for debugging
* Allows building ELF file for use with MSS Softconsole SDK debugger.
Change-Id: I5a44c101dece59f9e7b63c644895fcdc8c0fd783
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/91421
Reviewed-by: Armando Montanez <amontanez@google.com>
Commit-Queue: Sean Keys <skeys@google.com>
diff --git a/pw_package/py/pw_package/packages/smartfusion_mss.py b/pw_package/py/pw_package/packages/smartfusion_mss.py
index b9dbe49..ff37298 100644
--- a/pw_package/py/pw_package/packages/smartfusion_mss.py
+++ b/pw_package/py/pw_package/packages/smartfusion_mss.py
@@ -26,7 +26,7 @@
super().__init__(*args,
name='smartfusion_mss',
url='https://github.com/seank/smartfusion_mss',
- commit='9f47db73d3df786eab04d082645da5e735e63d28',
+ commit='bb22f26cc3a54df15bb901dc6c95662727158fed',
**kwargs)
def info(self, path: pathlib.Path) -> Sequence[str]:
diff --git a/targets/emcraft_sf2_som/BUILD.gn b/targets/emcraft_sf2_som/BUILD.gn
index 9d77869..b375ebe 100644
--- a/targets/emcraft_sf2_som/BUILD.gn
+++ b/targets/emcraft_sf2_som/BUILD.gn
@@ -14,6 +14,7 @@
import("//build_overrides/pigweed.gni")
+import("$dir_pw_build/linker_script.gni")
import("$dir_pw_build/target_types.gni")
import("$dir_pw_docgen/docs.gni")
import("$dir_pw_malloc/backend.gni")
@@ -28,7 +29,73 @@
}
}
+config("emcraft_ddr_init") {
+ # Emcraft's DDR config must be manually set by a custom init function. This
+ # conflicts with the built-in MSS init function. I have not looked into this
+ # myself to see if it's absoutely needed or not.
+ defines = [ "MSS_SYS_MDDR_CONFIG_BY_CORTEX=0" ]
+}
+
if (current_toolchain != default_toolchain) {
+ pw_linker_script("mddr_debug_linker_script") {
+ defines = [
+ "PW_BOOT_CODE_BEGIN=0x00000200", # After vector table.
+
+ # TODO(skeys) Bootloader is capable of loading 16M of uncompressed code
+ # from SPI flash to external RAM. For now use the allocated eNVM flash
+ # (256K - Bootloader - InSystemProgrammer = 192K)
+ "PW_BOOT_CODE_SIZE=0x30000",
+
+ # TODO(pwbug/219): Currently "pw_tokenizer/detokenize_test" requires at
+ # least 6K bytes in heap when using pw_malloc_freelist. The heap size
+ # required for tests should be investigated.
+ "PW_BOOT_HEAP_SIZE=4M",
+
+ # With external RAM remapped, we use the entire internal ram for the
+ # stack (64K).
+ "PW_BOOT_MIN_STACK_SIZE=64K",
+
+ # Using external DDR RAM, we just need to make sure we go past our ROM
+ # sections.
+ "PW_BOOT_RAM_BEGIN=0xA1000000",
+
+ # We assume that the bootloader loaded all 16M of text.
+ "PW_BOOT_RAM_SIZE=48M",
+ "PW_BOOT_VECTOR_TABLE_BEGIN=0x00000000",
+ "PW_BOOT_VECTOR_TABLE_SIZE=512",
+ ]
+ linker_script = "emcraft_sf2_som_mddr_debug.ld"
+ }
+ pw_linker_script("mddr_production_linker_script") {
+ defines = [
+ "PW_BOOT_FLASH_BEGIN=0x00000200", # After vector table.
+
+ # TODO(skeys) Bootloader is capable of loading 16M of uncompressed code
+ # from SPI flash to external RAM. For now use the allocated eNVM flash
+ # (256K - Bootloader - InSystemProgrammer = 192K)
+ "PW_BOOT_FLASH_SIZE=0x30000",
+
+ # TODO(pwbug/219): Currently "pw_tokenizer/detokenize_test" requires at
+ # least 6K bytes in heap when using pw_malloc_freelist. The heap size
+ # required for tests should be investigated.
+ "PW_BOOT_HEAP_SIZE=4M",
+
+ # With external RAM remapped, we use the entire internal ram for the
+ # stack (64K).
+ "PW_BOOT_MIN_STACK_SIZE=1024K",
+
+ # Using external DDR RAM, we just need to make sure we go past our ROM
+ # sections.
+ "PW_BOOT_RAM_BEGIN=0xA1000000",
+
+ # We assume that the bootloader loaded all 16M of text.
+ "PW_BOOT_RAM_SIZE=48M",
+ "PW_BOOT_VECTOR_TABLE_BEGIN=0x00000000",
+ "PW_BOOT_VECTOR_TABLE_SIZE=512",
+ ]
+ linker_script = "$dir_pw_boot_cortex_m/basic_cortex_m.ld"
+ }
+
pw_source_set("pre_init") {
configs = [ ":pw_malloc_active" ]
deps = [
@@ -49,6 +116,7 @@
config("config_includes") {
include_dirs = [ "config" ]
+ configs = [ ":emcraft_ddr_init" ]
}
pw_source_set("sf2_mss_hal_config") {
@@ -81,33 +149,8 @@
pw_third_party_freertos_PORT = "$dir_pw_third_party/freertos:arm_cm3"
pw_sys_io_BACKEND = dir_pw_sys_io_emcraft_sf2
- # Non-debug build for use with the boot loader.
- pw_boot_cortex_m_LINK_CONFIG_DEFINES = [
- "PW_BOOT_FLASH_BEGIN=0x00000200", # After vector table.
-
- # TODO(skeys) Bootloader is capable of loading 16M of uncompressed code
- # from SPI flash to external RAM. For now use the allocated eNVM flash
- # (256K - Bootloader - InSystemProgrammer = 192K)
- "PW_BOOT_FLASH_SIZE=0x30000",
-
- # TODO(pwbug/219): Currently "pw_tokenizer/detokenize_test" requires at
- # least 6K bytes in heap when using pw_malloc_freelist. The heap size
- # required for tests should be investigated.
- "PW_BOOT_HEAP_SIZE=4M",
-
- # With external RAM remapped, we use the entire internal ram for the
- # stack (64K).
- "PW_BOOT_MIN_STACK_SIZE=1024K",
-
- # Using external DDR RAM, we just need to make sure we go past our ROM
- # sections.
- "PW_BOOT_RAM_BEGIN=0xA1000000",
-
- # We assume that the bootloader loaded all 16M of text.
- "PW_BOOT_RAM_SIZE=48M",
- "PW_BOOT_VECTOR_TABLE_BEGIN=0x00000000",
- "PW_BOOT_VECTOR_TABLE_SIZE=512",
- ]
+ pw_boot_cortex_m_LINKER_SCRIPT =
+ "//targets/emcraft_sf2_som:mddr_production_linker_script"
}
}
@@ -127,20 +170,11 @@
pw_third_party_freertos_PORT = "$dir_pw_third_party/freertos:arm_cm3"
pw_sys_io_BACKEND = dir_pw_sys_io_emcraft_sf2
- pw_boot_cortex_m_LINK_CONFIG_DEFINES = [
- "PW_BOOT_FLASH_BEGIN=0x00000200",
- "PW_BOOT_FLASH_SIZE=200K",
-
- # TODO(pwbug/219): Currently "pw_tokenizer/detokenize_test" requires at
- # least 6K bytes in heap when using pw_malloc_freelist. The heap size
- # required for tests should be investigated.
- "PW_BOOT_HEAP_SIZE=7K",
- "PW_BOOT_MIN_STACK_SIZE=1K",
- "PW_BOOT_RAM_BEGIN=0x20000000",
- "PW_BOOT_RAM_SIZE=64K",
- "PW_BOOT_VECTOR_TABLE_BEGIN=0x00000000",
- "PW_BOOT_VECTOR_TABLE_SIZE=512",
- ]
+ # Override the default pw_boot_cortex_m linker script and set the memory
+ # regions for the target.
+ pw_boot_cortex_m_LINKER_SCRIPT =
+ "//targets/emcraft_sf2_som:mddr_debug_linker_script"
+ pw_third_party_smartfusion_mss_CONFIG = "debug"
}
}
diff --git a/targets/emcraft_sf2_som/boot.cc b/targets/emcraft_sf2_som/boot.cc
index bb786c8..ecb2eae 100644
--- a/targets/emcraft_sf2_som/boot.cc
+++ b/targets/emcraft_sf2_som/boot.cc
@@ -42,6 +42,8 @@
} // namespace
+extern "C" void Reset_Handler(void);
+
// Functions needed when configGENERATE_RUN_TIME_STATS is on.
extern "C" void configureTimerForRunTimeStats(void) {}
extern "C" unsigned long getRunTimeCounterValue(void) { return 10 /* FIXME */; }
@@ -183,6 +185,13 @@
PW_UNREACHABLE;
}
+extern "C" void sf2_SocInit() {
+#if SF2_MSS_NO_BOOTLOADER
+ Reset_Handler();
+#endif
+ pw_boot_Entry();
+}
+
// This `main()` stub prevents another main function from being linked since
// this target deliberately doesn't run `main()`.
extern "C" int main() {}
diff --git a/targets/emcraft_sf2_som/config/sf2_mss_hal_conf.h b/targets/emcraft_sf2_som/config/sf2_mss_hal_conf.h
index 0e82d68..4deb476 100644
--- a/targets/emcraft_sf2_som/config/sf2_mss_hal_conf.h
+++ b/targets/emcraft_sf2_som/config/sf2_mss_hal_conf.h
@@ -14,8 +14,10 @@
#pragma once
+#include "../drivers_config/sys_config/sys_config.h"
+
#if (MSS_SYS_MDDR_CONFIG_BY_CORTEX == 1)
-#error "Please turn off DDR initialization! See the comment in this file above."
+#error "Please turn off DDR initialization! See the comment in BUILD.gn file."
#endif
#define HAL_GPIO_MODULE_ENABLED
diff --git a/targets/emcraft_sf2_som/emcraft_sf2_som_mddr_debug.ld b/targets/emcraft_sf2_som/emcraft_sf2_som_mddr_debug.ld
new file mode 100644
index 0000000..05e8615
--- /dev/null
+++ b/targets/emcraft_sf2_som/emcraft_sf2_som_mddr_debug.ld
@@ -0,0 +1,257 @@
+/*
+ * Copyright 2022 The Pigweed Authors
+ *
+ * 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
+ *
+ * https://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.
+ */
+
+/* This relatively simplified linker script will work with many ARMv7-M and
+ * ARMv8-M cores that have on-board memory-mapped RAM and FLASH. For more
+ * complex projects and devices, it's possible this linker script will not be
+ * sufficient as-is.
+ *
+ * This linker script is likely not suitable for a project with a bootloader.
+ */
+
+/* Provide useful error messages when required configurations are not set. */
+#ifndef PW_BOOT_VECTOR_TABLE_BEGIN
+#error "PW_BOOT_VECTOR_TABLE_BEGIN is not defined, and is required to use pw_boot_cortex_m"
+#endif // PW_BOOT_VECTOR_TABLE_BEGIN
+
+#ifndef PW_BOOT_VECTOR_TABLE_SIZE
+#error "PW_BOOT_VECTOR_TABLE_SIZE is not defined, and is required to use pw_boot_cortex_m"
+#endif // PW_BOOT_VECTOR_TABLE_SIZE
+
+#ifndef PW_BOOT_CODE_BEGIN
+#error "PW_BOOT_CODE_BEGIN is not defined, and is required to use pw_boot_cortex_m"
+#endif // PW_BOOT_CODE_BEGIN
+
+#ifndef PW_BOOT_CODE_SIZE
+#error "PW_BOOT_CODE_SIZE is not defined, and is required to use pw_boot_cortex_m"
+#endif // PW_BOOT_CODE_SIZE
+
+#ifndef PW_BOOT_RAM_BEGIN
+#error "PW_BOOT_RAM_BEGIN is not defined, and is required to use pw_boot_cortex_m"
+#endif // PW_BOOT_RAM_BEGIN
+
+#ifndef PW_BOOT_RAM_SIZE
+#error "PW_BOOT_RAM_SIZE is not defined, and is required to use pw_boot_cortex_m"
+#endif // PW_BOOT_RAM_SIZE
+
+#ifndef PW_BOOT_HEAP_SIZE
+#error "PW_BOOT_HEAP_SIZE is not defined, and is required to use pw_boot_cortex_m"
+#endif // PW_BOOT_HEAP_SIZE
+
+#ifndef PW_BOOT_MIN_STACK_SIZE
+#error "PW_BOOT_MIN_STACK_SIZE is not defined, and is required to use pw_boot_cortex_m"
+#endif // PW_BOOT_MIN_STACK_SIZE
+
+
+/* Note: This technically doesn't set the firmware's entry point. Setting the
+ * firmware entry point is done by setting vector_table[1]
+ * (Reset_Handler). However, this DOES tell the compiler how to optimize
+ * when --gc-sections is enabled.
+ */
+ENTRY(pw_boot_Entry)
+
+MEMORY
+{
+ /* TODO(pwbug/57): Make it possible for projects to freely customize
+ * memory regions.
+ */
+
+ /* Vector Table */
+ VECTOR_TABLE(rx) : \
+ ORIGIN = PW_BOOT_VECTOR_TABLE_BEGIN, \
+ LENGTH = PW_BOOT_VECTOR_TABLE_SIZE
+ /* External RAM being used for code. */
+ TEXT_EXTERNAL_RAM(rx) : \
+ ORIGIN = PW_BOOT_CODE_BEGIN, \
+ LENGTH = PW_BOOT_CODE_SIZE
+ /* External DDR RAM */
+ EXTERNAL_RAM(rwx) : \
+ ORIGIN = PW_BOOT_RAM_BEGIN, \
+ LENGTH = PW_BOOT_RAM_SIZE
+}
+
+SECTIONS
+{
+ /* This is the link-time vector table. If used, the VTOR (Vector Table Offset
+ * Register) MUST point to this memory location in order to be used. This can
+ * be done by ensuring this section exists at the default location of the VTOR
+ * so it's used on reset, or by explicitly setting the VTOR in a bootloader
+ * manually to point to &pw_boot_vector_table_addr before interrupts are enabled.
+ */
+ .vector_table : ALIGN(512)
+ {
+ pw_boot_vector_table_addr = .;
+ KEEP(*(.vector_table))
+ } >VECTOR_TABLE
+
+ /* Main executable code. */
+ .code : ALIGN(0x10)
+ {
+ CREATE_OBJECT_SYMBOLS
+ __text_load = LOADADDR(.code);
+ /* Application code. */
+ *(.text)
+ *(.text*)
+ KEEP(*(.init))
+ KEEP(*(.fini))
+
+ . = ALIGN(0x10);
+ /* Constants.*/
+ *(.rodata)
+ *(.rodata*)
+
+ /* .preinit_array, .init_array, .fini_array are used by libc.
+ * Each section is a list of function pointers that are called pre-main and
+ * post-exit for object initialization and tear-down.
+ * Since the region isn't explicitly referenced, specify KEEP to prevent
+ * link-time garbage collection. SORT is used for sections that have strict
+ * init/de-init ordering requirements. */
+ . = ALIGN(0x10);
+ PROVIDE_HIDDEN(__preinit_array_start = .);
+ KEEP(*(.preinit_array*))
+ PROVIDE_HIDDEN(__preinit_array_end = .);
+
+ PROVIDE_HIDDEN(__init_array_start = .);
+ KEEP(*(SORT(.init_array.*)))
+ KEEP(*(.init_array*))
+ PROVIDE_HIDDEN(__init_array_end = .);
+
+ PROVIDE_HIDDEN(__fini_array_start = .);
+ KEEP(*(SORT(.fini_array.*)))
+ KEEP(*(.fini_array*))
+ PROVIDE_HIDDEN(__fini_array_end = .);
+ } >TEXT_EXTERNAL_RAM
+
+ /* Used by unwind-arm/ */
+ .ARM : ALIGN(0x10) {
+ __exidx_start = .;
+ *(.ARM.exidx*)
+ __exidx_end = .;
+ } >TEXT_EXTERNAL_RAM
+
+ /* Explicitly initialized global and static data. (.data)*/
+ .static_init_ram : ALIGN(0x10)
+ {
+ *(.data)
+ *(.data*)
+ . = ALIGN(0x10);
+ } >EXTERNAL_RAM AT> TEXT_EXTERNAL_RAM
+
+ /* Zero initialized global/static data. (.bss)
+ * This section is zero initialized in pw_boot_Entry(). */
+ .zero_init_ram : ALIGN(0x10)
+ {
+ *(.bss)
+ *(.bss*)
+ *(COMMON)
+ . = ALIGN(0x10);
+ } >EXTERNAL_RAM
+
+ .heap : ALIGN(8)
+ {
+ pw_boot_heap_low_addr = .;
+ . = . + PW_BOOT_HEAP_SIZE;
+ . = ALIGN(8);
+ pw_boot_heap_high_addr = .;
+ } >EXTERNAL_RAM
+
+ /* Link-time check for stack overlaps. */
+ .stack (NOLOAD) : ALIGN(8)
+ {
+ /* Set the address that the main stack pointer should be initialized to. */
+ pw_boot_stack_low_addr = .;
+ HIDDEN(_stack_size = ORIGIN(EXTERNAL_RAM) + LENGTH(EXTERNAL_RAM) - .);
+ /* Align the stack to a lower address to ensure it isn't out of range. */
+ HIDDEN(_stack_high = (. + _stack_size) & ~0x7);
+ ASSERT(_stack_high - . >= PW_BOOT_MIN_STACK_SIZE,
+ "Error: Not enough RAM for desired minimum stack size.");
+ . = _stack_high;
+ pw_boot_stack_high_addr = .;
+ } >EXTERNAL_RAM
+
+ /* Discard unwind info. */
+ .ARM.extab 0x0 (INFO) :
+ {
+ KEEP(*(.ARM.extab*))
+ }
+
+ /*
+ * Do not declare any output sections after this comment. This area is
+ * reserved only for declaring unused sections of memory. These sections are
+ * used by pw_bloat.bloaty_config to create the utilization data source for
+ * bloaty.
+ */
+ .VECTOR_TABLE.unused_space (NOLOAD) : ALIGN(8)
+ {
+ . = ABSOLUTE(ORIGIN(VECTOR_TABLE) + LENGTH(VECTOR_TABLE));
+ } >VECTOR_TABLE
+
+ .TEXT_EXTERNAL_RAM.unused_space (NOLOAD) : ALIGN(8)
+ {
+ . = ABSOLUTE(ORIGIN(TEXT_EXTERNAL_RAM) + LENGTH(TEXT_EXTERNAL_RAM));
+ } >TEXT_EXTERNAL_RAM
+
+ .EXTERNAL_RAM.unused_space (NOLOAD) : ALIGN(8)
+ {
+ . = ABSOLUTE(ORIGIN(EXTERNAL_RAM) + LENGTH(EXTERNAL_RAM));
+ } >EXTERNAL_RAM
+}
+
+/* Symbols used by core_init.c: */
+/* Start of .static_init_ram in TEXT_EXTERNAL_RAM. */
+_pw_static_init_flash_start = LOADADDR(.static_init_ram);
+
+/* Region of .static_init_ram in RAM. */
+_pw_static_init_ram_start = ADDR(.static_init_ram);
+_pw_static_init_ram_end = _pw_static_init_ram_start + SIZEOF(.static_init_ram);
+
+/* Region of .zero_init_ram. */
+_pw_zero_init_ram_start = ADDR(.zero_init_ram);
+_pw_zero_init_ram_end = _pw_zero_init_ram_start + SIZEOF(.zero_init_ram);
+
+/* arm-none-eabi expects `end` symbol to point to start of heap for sbrk. */
+PROVIDE(end = _pw_zero_init_ram_end);
+
+/* These symbols are used by pw_bloat.bloaty_config to create the memoryregions
+ * data source for bloaty in this format (where the optional _N defaults to 0):
+ * pw_bloat_config_memory_region_NAME_{start,end}{_N,} */
+pw_bloat_config_memory_region_VECTOR_TABLE_start = ORIGIN(VECTOR_TABLE);
+pw_bloat_config_memory_region_VECTOR_TABLE_end =
+ ORIGIN(VECTOR_TABLE) + LENGTH(VECTOR_TABLE);
+pw_bloat_config_memory_region_FLASH_start = ORIGIN(TEXT_EXTERNAL_RAM);
+pw_bloat_config_memory_region_FLASH_end = ORIGIN(TEXT_EXTERNAL_RAM) + LENGTH(TEXT_EXTERNAL_RAM);
+pw_bloat_config_memory_region_RAM_start = ORIGIN(EXTERNAL_RAM);
+pw_bloat_config_memory_region_RAM_end = ORIGIN(EXTERNAL_RAM) + LENGTH(EXTERNAL_RAM);
+
+/* Symbol mapping used by MSS Startup and Debugger. */
+PROVIDE (__smartfusion2_memory_remap = 2); /* Remap according to LMA (this script) */
+PROVIDE (__mirrored_nvm = 1); /* GDB will load to LMA directly no need to load again. */
+PROVIDE (_estack = pw_boot_stack_high_addr);
+PROVIDE (__stack_start__ = pw_boot_stack_low_addr);
+PROVIDE (__vector_table_load = LOADADDR(.vector_table));
+PROVIDE (__vector_table_start = pw_boot_vector_table_addr);
+PROVIDE (__vector_table_vma_base_address = __vector_table_start); /* required by debugger for start address */
+PROVIDE (__text_end = __exidx_end);
+PROVIDE (__heap_start__ = pw_boot_heap_low_addr);
+PROVIDE (_eheap = pw_boot_heap_high_addr);
+PROVIDE (_etext = __exidx_end);
+PROVIDE (_evector_table = pw_boot_vector_table_addr);
+PROVIDE (__data_start = _pw_static_init_ram_start);
+PROVIDE (_edata = _pw_static_init_ram_end);
+PROVIDE (__text_start = __text_load);
+PROVIDE (__bss_start__ = _pw_zero_init_ram_start);
+PROVIDE (__bss_end__ = _pw_static_init_ram_end);
+PROVIDE (__data_load = _pw_static_init_flash_start);
diff --git a/targets/emcraft_sf2_som/vector_table.c b/targets/emcraft_sf2_som/vector_table.c
index a4f5f7f..5205404 100644
--- a/targets/emcraft_sf2_som/vector_table.c
+++ b/targets/emcraft_sf2_som/vector_table.c
@@ -44,6 +44,7 @@
void SVC_Handler(void);
void PendSV_Handler(void);
void SysTick_Handler(void);
+void sf2_SocInit(void);
PW_KEEP_IN_SECTION(".vector_table")
const InterruptHandler vector_table[] = {
@@ -55,7 +56,7 @@
// Reset handler, dictates how to handle reset interrupt. This is the
// address that the Program Counter (PC) is initialized to at boot.
- [1] = pw_boot_Entry,
+ [1] = sf2_SocInit,
// NMI handler.
[2] = DefaultFaultHandler,
diff --git a/third_party/smartfusion_mss/README.md b/third_party/smartfusion_mss/README.md
index 7532545..90cfc61 100644
--- a/third_party/smartfusion_mss/README.md
+++ b/third_party/smartfusion_mss/README.md
@@ -2,5 +2,5 @@
The folder provides build scripts and configuration recipes for building
the SmartFusion2 Microcontroller Subsystem library. The source code needs to be downloaded by the user, or
-via the support in pw_package "pw package install sf2mss". For gn build,
+via the support in pw_package "pw package install smartfusion_mss". For gn build,
set `dir_pw_third_party_smartfusion_mss` to point to the path of the source code.