From a001f5e85f46fcb2826bdac3a8c0e7e136b5ca1d Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Wed, 27 Mar 2019 07:57:09 -0700 Subject: [PATCH 1/4] Split IRAM into 2 linker sections to move std::fcn Callbacks need to be placed in IRAM when being called from an IRQ (like the SPISlave callbacks). This can be done by hacking the std::functional header and making every single specialization of the template into an IRAM section, which would take a lot of space for no benefit in the majority of cases. The alternate is to specify the single instantiation types/operators required, but the problem is the flash segment matcher would match them before the IRAM section was begun, and rules for them would just not be applied. Get around this by splitting the IRAM section definition into .text and .text1. This is linker syntactic sugar and does not actually change the on-chip layout. But it does allow us to put the exception vectors at the required absolute addresses and add single functions to IRAM. --- tools/sdk/ld/eagle.app.v6.common.ld.h | 71 ++++++++++++++++----------- 1 file changed, 41 insertions(+), 30 deletions(-) diff --git a/tools/sdk/ld/eagle.app.v6.common.ld.h b/tools/sdk/ld/eagle.app.v6.common.ld.h index aa4201221c..99c65f6c7e 100644 --- a/tools/sdk/ld/eagle.app.v6.common.ld.h +++ b/tools/sdk/ld/eagle.app.v6.common.ld.h @@ -93,6 +93,44 @@ SECTIONS #include "eagle.app.v6.common.ld.vtables.h" #endif + /* IRAM is split into .text and .text1 to allow for moving specific */ + /* functions into IRAM that would be matched by the irom0.text matcher */ + .text : ALIGN(4) + { + _stext = .; + _text_start = ABSOLUTE(.); + *(.UserEnter.text) + . = ALIGN(16); + *(.DebugExceptionVector.text) + . = ALIGN(16); + *(.NMIExceptionVector.text) + . = ALIGN(16); + *(.KernelExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN(16); + *(.UserExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN(16); + *(.DoubleExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN (16); + *(.entry.text) + *(.init.literal) + *(.init) + + /* Special functions/templates that need to be in IRAM (SPI/IRQ callbacks/etc. here */ + *(.text._ZNKSt8functionIFvvEEclEv) /* std::function::operator()() const */ + } >iram1_0_seg :iram1_0_phdr + .irom0.text : ALIGN(4) { _irom0_text_start = ABSOLUTE(.); @@ -163,37 +201,10 @@ SECTIONS _flash_code_end = ABSOLUTE(.); } >irom0_0_seg :irom0_0_phdr - .text : ALIGN(4) + + + .text1 : ALIGN(4) { - _stext = .; - _text_start = ABSOLUTE(.); - *(.UserEnter.text) - . = ALIGN(16); - *(.DebugExceptionVector.text) - . = ALIGN(16); - *(.NMIExceptionVector.text) - . = ALIGN(16); - *(.KernelExceptionVector.text) - LONG(0) - LONG(0) - LONG(0) - LONG(0) - . = ALIGN(16); - *(.UserExceptionVector.text) - LONG(0) - LONG(0) - LONG(0) - LONG(0) - . = ALIGN(16); - *(.DoubleExceptionVector.text) - LONG(0) - LONG(0) - LONG(0) - LONG(0) - . = ALIGN (16); - *(.entry.text) - *(.init.literal) - *(.init) *(.literal .text .iram.literal .iram.text .iram.text.* .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) #ifdef VTABLES_IN_IRAM *(.rodata._ZTV*) /* C++ vtables */ From 8d1ec76f3015ffa97af191f61a538aa11c74eecd Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Wed, 27 Mar 2019 19:10:06 -0700 Subject: [PATCH 2/4] Add .text1 segment to space used calculation in IDE --- platform.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform.txt b/platform.txt index b3c184ae60..2a62afde18 100644 --- a/platform.txt +++ b/platform.txt @@ -117,7 +117,7 @@ recipe.output.save_file={build.project_name}.{build.variant}.bin ## Compute size recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" -recipe.size.regex=^(?:\.irom0\.text|\.text|\.data|\.rodata|)\s+([0-9]+).* +recipe.size.regex=^(?:\.irom0\.text|\.text|\.text1|\.data|\.rodata|)\s+([0-9]+).* recipe.size.regex.data=^(?:\.data|\.rodata|\.bss)\s+([0-9]+).* #recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).* From 1c4f912039497566effd759c8fc3488c2813407b Mon Sep 17 00:00:00 2001 From: david gauchard Date: Sun, 7 Apr 2019 02:48:14 +0200 Subject: [PATCH 3/4] Update eagle.app.v6.common.ld.h all functional callers are placed in IRAM --- tools/sdk/ld/eagle.app.v6.common.ld.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/sdk/ld/eagle.app.v6.common.ld.h b/tools/sdk/ld/eagle.app.v6.common.ld.h index 99c65f6c7e..1aeb257c23 100644 --- a/tools/sdk/ld/eagle.app.v6.common.ld.h +++ b/tools/sdk/ld/eagle.app.v6.common.ld.h @@ -127,8 +127,8 @@ SECTIONS *(.init.literal) *(.init) - /* Special functions/templates that need to be in IRAM (SPI/IRQ callbacks/etc. here */ - *(.text._ZNKSt8functionIFvvEEclEv) /* std::function::operator()() const */ + /* all functional callers are placed in IRAM (including SPI/IRQ callbacks/etc) here */ + *(.text._ZNKSt8functionIF*EE*) /* std::function::operator()() const */ } >iram1_0_seg :iram1_0_phdr .irom0.text : ALIGN(4) From 13d7a4d55efee85084eea09b72a2e5a3671141f6 Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Tue, 9 Apr 2019 13:14:58 -0700 Subject: [PATCH 4/4] Write out the .text1 segment to the BIN The extra segment name needs to be placed into the output binary as well, or else only the init code gets stored and none of the real app is present. This leads to an infinite boot loop. This change adds in the segment to the generated image. --- tools/elf2bin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/elf2bin.py b/tools/elf2bin.py index 0d3c8b3bec..3e70caf14a 100755 --- a/tools/elf2bin.py +++ b/tools/elf2bin.py @@ -109,7 +109,7 @@ def main(): out = open(args.out, "wb") write_bin(out, args.eboot, ['.text'], 4096, args.flash_mode, args.flash_size, args.flash_freq, args.path) - write_bin(out, args.app, ['.irom0.text', '.text', '.data', '.rodata'], 0, args.flash_mode, args.flash_size, args.flash_freq, args.path) + write_bin(out, args.app, ['.irom0.text', '.text', '.text1', '.data', '.rodata'], 0, args.flash_mode, args.flash_size, args.flash_freq, args.path) out.close() return 0