linker: correct linker script _flash_used calculation

Linker scripts contains a `.last_section` section that is placed in rom
region as NOLOAD for the purpose of retrieve the actual number of bytes
contained in the image. See d85efe0b10

However, a previous section may cause the location counter to be
incremented for alignment purposes. This can result in the size of the
image to be 0x10FA but location counter to be 0x1100 because it has been
aligned for next section placement.

Therefore, two new Kconfig settings are introduced.
Those settings request the linker to will write a pattern in
`.last_section`. Together with removing NOLOAD and writing a patten to
the section then we ensure that data is written after alignment of
location counter, and thereby forces the image size to be in sync with
the location counter.

The default pattern used will be 0xE015 (end of last section).

Some systems may fill up the flash completely, or simply write data at
the end of the flash, which in both cases can result in overflow.
Therefore, the new settings can be disabled.

Signed-off-by: Torsten Rasmussen <Torsten.Rasmussen@nordicsemi.no>
This commit is contained in:
Torsten Rasmussen 2022-09-27 12:34:36 +02:00 committed by Fabio Baltieri
parent 11e3344909
commit c107827bb7
6 changed files with 61 additions and 10 deletions

View File

@ -266,6 +266,32 @@ config LINKER_GENERIC_SECTIONS_PRESENT_AT_BOOT
If unsure, say Y.
config LINKER_LAST_SECTION_ID
bool "Last section identifier"
default y
depends on ARM || ARM64 || RISCV
help
If enabled, the last section will contain an identifier.
This ensures that the '_flash_used' linker symbol will always be
correctly calculated, even in cases where the location counter may
have been incremented for alignment purposes but no data is placed
after alignment.
Note: in cases where the flash is fully used, for example application
specific data is written at the end of the flash area, then writing a
last section identifier may cause rom region overflow.
In such cases this setting should be disabled.
config LINKER_LAST_SECTION_ID_PATTERN
hex "Last section identifier pattern"
default "0xE015E015"
depends on LINKER_LAST_SECTION_ID
help
Pattern to fill into last section as identifier.
Default pattern is 0xE015 (end of last section), but any pattern can
be used.
The size of the pattern must not exceed 4 bytes.
endmenu # "Linker Sections"
endmenu

View File

@ -385,12 +385,17 @@ GROUP_END(OCM)
LINKER_DT_SECTIONS()
/* Must be last in romable region */
SECTION_PROLOGUE(.last_section,(NOLOAD),)
SECTION_PROLOGUE(.last_section,,)
{
#ifdef CONFIG_LINKER_LAST_SECTION_ID
/* Fill last section with a word to ensure location counter and actual rom
* region data usage match. */
LONG(CONFIG_LINKER_LAST_SECTION_ID_PATTERN)
#endif
} GROUP_LINK_IN(ROMABLE_REGION)
/* To provide the image size as a const expression,
* calculate this value here. */
_flash_used = LOADADDR(.last_section) - __rom_region_start;
_flash_used = LOADADDR(.last_section) + SIZEOF(.last_section) - __rom_region_start;
}

View File

@ -440,12 +440,17 @@ GROUP_END(DTCM)
LINKER_DT_SECTIONS()
/* Must be last in romable region */
SECTION_PROLOGUE(.last_section,(NOLOAD),)
SECTION_PROLOGUE(.last_section,,)
{
#ifdef CONFIG_LINKER_LAST_SECTION_ID
/* Fill last section with a word to ensure location counter and actual rom
* region data usage match. */
LONG(CONFIG_LINKER_LAST_SECTION_ID_PATTERN)
#endif
} GROUP_LINK_IN(ROMABLE_REGION)
/* To provide the image size as a const expression,
* calculate this value here. */
_flash_used = LOADADDR(.last_section) - __rom_region_start;
_flash_used = LOADADDR(.last_section) + SIZEOF(.last_section) - __rom_region_start;
}

View File

@ -322,12 +322,17 @@ SECTIONS
/* Must be last in romable region */
SECTION_PROLOGUE(.last_section,(NOLOAD),)
SECTION_PROLOGUE(.last_section,,)
{
#ifdef CONFIG_LINKER_LAST_SECTION_ID
/* Fill last section with a word to ensure location counter and actual rom
* region data usage match. */
LONG(CONFIG_LINKER_LAST_SECTION_ID_PATTERN)
#endif
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
/* To provide the image size as a const expression,
* calculate this value here. */
_flash_used = LOADADDR(.last_section) - __rom_region_start;
_flash_used = LOADADDR(.last_section) + SIZEOF(.last_section) - __rom_region_start;
}

View File

@ -399,13 +399,18 @@ GROUP_END(DTCM)
*/
#ifdef CONFIG_XIP
/* Must be last in romable region */
SECTION_PROLOGUE(.last_section,(NOLOAD),)
SECTION_PROLOGUE(.last_section,,)
{
#ifdef CONFIG_LINKER_LAST_SECTION_ID
/* Fill last section with a word to ensure location counter and actual rom
* region data usage match. */
LONG(CONFIG_LINKER_LAST_SECTION_ID_PATTERN)
#endif
} GROUP_LINK_IN(ROMABLE_REGION)
/* To provide the image size as a const expression,
* calculate this value here. */
__rom_region_end = LOADADDR(.last_section);
__rom_region_end = LOADADDR(.last_section) + SIZEOF(.last_section);
__rom_region_size = __rom_region_end - __rom_region_start;
#endif

View File

@ -360,13 +360,18 @@ GROUP_END(DTCM)
}
/* Must be last in romable region */
SECTION_PROLOGUE(.last_section,(NOLOAD),)
SECTION_PROLOGUE(.last_section,,)
{
#ifdef CONFIG_LINKER_LAST_SECTION_ID
/* Fill last section with a word to ensure location counter and actual rom
* region data usage match. */
LONG(CONFIG_LINKER_LAST_SECTION_ID_PATTERN)
#endif
} GROUP_LINK_IN(ROMABLE_REGION)
/* To provide the image size as a const expression,
* calculate this value here. */
__rom_region_end = LOADADDR(.last_section);
__rom_region_end = LOADADDR(.last_section) + SIZEOF(.last_section);
__rom_region_size = __rom_region_end - __rom_region_start;
}