mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-20 01:08:15 +01:00
[ion] N0200: improve code spliting between internal/external flash
Part I: move peripherals initiation to be executed from the external flash to avoid many dependencies to limit the number of functions that are forced in internal flash.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#include <drivers/board.h>
|
||||
#include <drivers/cache.h>
|
||||
#include <drivers/config/clocks.h>
|
||||
#include <drivers/external_flash.h>
|
||||
#include <regs/regs.h>
|
||||
#include <ion.h>
|
||||
|
||||
@@ -85,7 +86,7 @@ void initMPU() {
|
||||
Cache::isb();
|
||||
}
|
||||
|
||||
void init(bool initBacklight) {
|
||||
void init() {
|
||||
initFPU();
|
||||
initMPU();
|
||||
initClocks();
|
||||
@@ -106,7 +107,7 @@ void init(bool initBacklight) {
|
||||
GPIO(g).PUPDR()->set(0x00000000); // All to "None"
|
||||
}
|
||||
|
||||
initPeripherals(initBacklight);
|
||||
ExternalFlash::init();
|
||||
// Initiate L1 cache after initiating the external flash
|
||||
Cache::enable();
|
||||
}
|
||||
|
||||
@@ -48,12 +48,12 @@ SECTIONS {
|
||||
|
||||
/* Internal flash memory */
|
||||
|
||||
/* We link 'non_inlined_ion_main' in a separate section from text.internal.
|
||||
/* We link 'jump_to_external_flash' in a separate section from text.internal.
|
||||
* Indeed, it is the only internal flash symbol that refers the external
|
||||
* flash. This way we can assert that there are no cross references from the
|
||||
* internal flash to the external flash. */
|
||||
.text.internal_to_external : {
|
||||
*(.text._ZL20non_inlined_ion_mainv)
|
||||
*(.text._ZL22jump_to_external_flashv)
|
||||
} >INTERNAL_FLASH
|
||||
|
||||
/* Use boot routine and required dependencies */
|
||||
@@ -61,38 +61,44 @@ SECTIONS {
|
||||
* done with -fdata-sections -ffunction-sections */
|
||||
.text.internal : {
|
||||
. = ALIGN(4);
|
||||
*(.text.__assert)
|
||||
*(.text.start)
|
||||
*(.text.abort)
|
||||
*(.text.isr_systick)
|
||||
*(.text.__assert)
|
||||
*(.text.memcpy)
|
||||
*(.text.memset)
|
||||
/*
|
||||
*(.text.strlen)
|
||||
*(.text.strncmp)
|
||||
*(.text.strlcpy)
|
||||
*(.text.strcmp)
|
||||
*(.text.memset)
|
||||
*(.text.memmove)
|
||||
*(.text._ZN3Ion*)
|
||||
*(.text._ZNV3Ion*)
|
||||
*(.text._ZNK3Ion*)
|
||||
*(.text.LZ4_*)
|
||||
*/
|
||||
/* 'start' dependecies */
|
||||
*(.text.start)
|
||||
*(.text._ZN3Ion6Device5Board4initEv)
|
||||
*(.text._ZN3Ion6Device5Board7initFPUEv)
|
||||
*(.text._ZN3Ion6Device5Board7initMPUEv)
|
||||
*(.text._ZN3Ion6Device5Board10initClocksEv)
|
||||
*(.text._ZNV3Ion6Device4Regs8Register*)
|
||||
*(.text._ZN3Ion6Device4Regs8Register*)
|
||||
*(.text._ZNK3Ion6Device4Regs9AFGPIOPin*)
|
||||
*(.text._ZN3Ion6Device13ExternalFlash*)
|
||||
*(.text._ZN3Ion6Device5Cache*)
|
||||
*(.text._ZN3Ion6Timing6usleepEj)
|
||||
|
||||
/* 'abort' dependcies */
|
||||
*(.text._ZN3Ion6Device5Reset4coreEv)
|
||||
|
||||
/**(.text._ZN3Ion5Power7suspendEb)*/
|
||||
|
||||
/* Optimization */
|
||||
*/libgcc.a:(.text)
|
||||
} >INTERNAL_FLASH
|
||||
|
||||
|
||||
.rodata.internal : {
|
||||
. = ALIGN(4);
|
||||
*(.rodata.dfu_bootloader)
|
||||
*(.rodata)
|
||||
*(.rodata.str1.1)
|
||||
*(.rodata._ZN3Ion*)
|
||||
*(.rodata._ZZN3Ion*)
|
||||
*(.rodata._ZNK3Ion*)
|
||||
*(.rodata._ZTVN3Ion6*)
|
||||
*(.rodata._ZN3KDColor*)
|
||||
*(.rodata._ZL11KDColor*)
|
||||
*(.rodata._ZL12KDColor*)
|
||||
*(.rodata._ZL13KDColor*)
|
||||
*(.rodata._ZN3Ion6Device13ExternalFlash*)
|
||||
} >INTERNAL_FLASH
|
||||
|
||||
/* External flash memory */
|
||||
@@ -103,6 +109,7 @@ SECTIONS {
|
||||
} >EXTERNAL_FLASH
|
||||
|
||||
.rodata.external : {
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
} >EXTERNAL_FLASH
|
||||
|
||||
|
||||
@@ -27,7 +27,23 @@ void abort() {
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This additional function call 'non_inlined_ion_main' serves two purposes:
|
||||
/* In order to ensure that this method is execute from the external flash, we
|
||||
* forbid inlining it.*/
|
||||
|
||||
static void __attribute__((noinline)) external_flash_start() {
|
||||
/* Init the peripherals. If there is the on boarding app, do not initialize the
|
||||
* backlight so that the user does not see the LCD tests. The backlight will
|
||||
* be initialized after the Power-On Self-Test.*/
|
||||
#if EPSILON_ONBOARDING_APP == 0
|
||||
Ion::Device::Board::initPeripherals(true);
|
||||
#else
|
||||
Ion::Device::Board::initPeripherals(false);
|
||||
#endif
|
||||
|
||||
return ion_main(0, nullptr);
|
||||
}
|
||||
|
||||
/* This additional function call 'jump_to_external_flash' serves two purposes:
|
||||
* - By default, the compiler is free to inline any function call he wants. If
|
||||
* the compiler decides to inline some functions that make use of VFP
|
||||
* registers, it will need to push VFP them onto the stack in calling
|
||||
@@ -40,16 +56,20 @@ void abort() {
|
||||
* start(), we isolate it in its very own non-inlined function call.
|
||||
* - To avoid jumping on the external flash when it is shut down, we ensure
|
||||
* there is no symbol references from the internal flash to the external
|
||||
* flash except the jump to ion_main. In order to do that, we isolate this
|
||||
* flash except this jump. In order to do that, we isolate this
|
||||
* jump in a symbol that we link in a special section separated from the
|
||||
* internal flash section. We can than forbid cross references from the
|
||||
* internal flash to the external flash. */
|
||||
|
||||
static void __attribute__((noinline)) non_inlined_ion_main() {
|
||||
return ion_main(0, nullptr);
|
||||
static void __attribute__((noinline)) jump_to_external_flash() {
|
||||
external_flash_start();
|
||||
}
|
||||
|
||||
void start() {
|
||||
/* When 'start' is executed, the external flash is supposed to be shutdown. We
|
||||
* thus forbid inlining to prevent executing this code from external flash
|
||||
* (just in case 'start' was to be called from the external flash). */
|
||||
|
||||
void __attribute__((noinline)) start() {
|
||||
/* This is where execution starts after reset.
|
||||
* Many things are not initialized yet so the code here has to pay attention. */
|
||||
|
||||
@@ -90,16 +110,12 @@ void start() {
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Init the board. If there is the on boarding app, do not initialize the
|
||||
* backlight so that the user does not see the LCD tests. The backlight will
|
||||
* be initialized after the Power-On Self-Test.*/
|
||||
#if EPSILON_ONBOARDING_APP == 0
|
||||
Ion::Device::Board::init(true);
|
||||
#else
|
||||
Ion::Device::Board::init(false);
|
||||
#endif
|
||||
Ion::Device::Board::init();
|
||||
|
||||
non_inlined_ion_main();
|
||||
/* At this point, we initialized clocks and the external flash but no other
|
||||
* peripherals. */
|
||||
|
||||
jump_to_external_flash();
|
||||
|
||||
abort();
|
||||
}
|
||||
|
||||
@@ -42,11 +42,9 @@ void initPeripherals(bool initBacklight) {
|
||||
Console::init();
|
||||
SWD::init();
|
||||
Timing::init();
|
||||
ExternalFlash::init();
|
||||
}
|
||||
|
||||
void shutdownPeripherals(bool keepLEDAwake) {
|
||||
ExternalFlash::shutdown();
|
||||
Timing::shutdown();
|
||||
SWD::shutdown();
|
||||
Console::shutdown();
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Ion {
|
||||
namespace Device {
|
||||
namespace Board {
|
||||
|
||||
void init(bool initBacklight = true);
|
||||
void init();
|
||||
void shutdown();
|
||||
|
||||
void initFPU();
|
||||
|
||||
Reference in New Issue
Block a user