mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-06 14:14:33 +02:00
Merge branch 'bugfix/flash_rodata_any_alignement' into 'master'
build: (Custom) App version info is now on a dedicated section Closes IDFGH-4927 See merge request espressif/esp-idf!12786
This commit is contained in:
@@ -134,3 +134,12 @@ REGION_ALIAS("rtc_data_location", rtc_data_seg );
|
|||||||
#else
|
#else
|
||||||
REGION_ALIAS("default_rodata_seg", dram0_0_seg);
|
REGION_ALIAS("default_rodata_seg", dram0_0_seg);
|
||||||
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If rodata default segment is placed in `drom0_0_seg`, then flash's first rodata section must
|
||||||
|
* also be first in the segment.
|
||||||
|
*/
|
||||||
|
#ifdef CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
ASSERT(_rodata_start == ORIGIN(default_rodata_seg),
|
||||||
|
".flash.appdesc section must be placed at the beginning of the rodata segment.")
|
||||||
|
#endif
|
||||||
|
@@ -233,13 +233,21 @@ SECTIONS
|
|||||||
"DRAM segment data does not fit.")
|
"DRAM segment data does not fit.")
|
||||||
|
|
||||||
/* When modifying the alignment, update tls_section_alignment in pxPortInitialiseStack */
|
/* When modifying the alignment, update tls_section_alignment in pxPortInitialiseStack */
|
||||||
.flash.rodata : ALIGN(0x10)
|
.flash.appdesc : ALIGN(0x10)
|
||||||
{
|
{
|
||||||
_rodata_start = ABSOLUTE(.);
|
_rodata_start = ABSOLUTE(.);
|
||||||
|
|
||||||
*(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */
|
*(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */
|
||||||
*(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */
|
*(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */
|
||||||
|
|
||||||
|
/* Create an empty gap within this section. Thanks to this, the end of this
|
||||||
|
* section will match .flah.rodata's begin address. Thus, both sections
|
||||||
|
* will be merged when creating the final bin image. */
|
||||||
|
. = ALIGN(ALIGNOF(.flash.rodata));
|
||||||
|
} >default_rodata_seg
|
||||||
|
|
||||||
|
.flash.rodata : ALIGN(0x10)
|
||||||
|
{
|
||||||
mapping[flash_rodata]
|
mapping[flash_rodata]
|
||||||
|
|
||||||
|
|
||||||
|
@@ -107,3 +107,12 @@ REGION_ALIAS("rtc_data_location", rtc_iram_seg );
|
|||||||
#else
|
#else
|
||||||
REGION_ALIAS("default_rodata_seg", dram0_0_seg);
|
REGION_ALIAS("default_rodata_seg", dram0_0_seg);
|
||||||
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If rodata default segment is placed in `drom0_0_seg`, then flash's first rodata section must
|
||||||
|
* also be first in the segment.
|
||||||
|
*/
|
||||||
|
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
ASSERT(_flash_rodata_dummy_start == ORIGIN(default_rodata_seg),
|
||||||
|
".flash_rodata_dummy section must be placed at the beginning of the rodata segment.")
|
||||||
|
#endif
|
||||||
|
@@ -251,6 +251,7 @@ SECTIONS
|
|||||||
*/
|
*/
|
||||||
.flash_rodata_dummy (NOLOAD):
|
.flash_rodata_dummy (NOLOAD):
|
||||||
{
|
{
|
||||||
|
_flash_rodata_dummy_start = .;
|
||||||
/* Start at the same alignement constraint than .flash.text */
|
/* Start at the same alignement constraint than .flash.text */
|
||||||
. = ALIGN(ALIGNOF(.flash.text));
|
. = ALIGN(ALIGNOF(.flash.text));
|
||||||
/* Create an empty gap as big as .flash.text section */
|
/* Create an empty gap as big as .flash.text section */
|
||||||
@@ -262,13 +263,21 @@ SECTIONS
|
|||||||
} > default_rodata_seg
|
} > default_rodata_seg
|
||||||
|
|
||||||
/* When modifying the alignment, don't forget to update tls_section_alignment in pxPortInitialiseStack */
|
/* When modifying the alignment, don't forget to update tls_section_alignment in pxPortInitialiseStack */
|
||||||
.flash.rodata : ALIGN(0x10)
|
.flash.appdesc : ALIGN(0x10)
|
||||||
{
|
{
|
||||||
_rodata_start = ABSOLUTE(.);
|
_rodata_start = ABSOLUTE(.);
|
||||||
|
|
||||||
*(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */
|
*(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */
|
||||||
*(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */
|
*(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */
|
||||||
|
|
||||||
|
/* Create an empty gap within this section. Thanks to this, the end of this
|
||||||
|
* section will match .flash.rodata's begin address. Thus, both sections
|
||||||
|
* will be merged when creating the final bin image. */
|
||||||
|
. = ALIGN(ALIGNOF(.flash.rodata));
|
||||||
|
} >default_rodata_seg
|
||||||
|
|
||||||
|
.flash.rodata : ALIGN(0x10)
|
||||||
|
{
|
||||||
mapping[flash_rodata]
|
mapping[flash_rodata]
|
||||||
|
|
||||||
*(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
|
*(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
|
||||||
|
@@ -136,3 +136,13 @@ REGION_ALIAS("rtc_data_location", rtc_data_seg );
|
|||||||
#else
|
#else
|
||||||
REGION_ALIAS("default_rodata_seg", dram0_0_seg);
|
REGION_ALIAS("default_rodata_seg", dram0_0_seg);
|
||||||
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If rodata default segment is placed in `drom0_0_seg`, then flash's first rodata section must
|
||||||
|
* also be first in the segment.
|
||||||
|
*/
|
||||||
|
#ifdef CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
ASSERT(_rodata_reserved_start == ORIGIN(default_rodata_seg),
|
||||||
|
".flash.appdesc section must be placed at the beginning of the rodata segment.")
|
||||||
|
#endif
|
||||||
|
@@ -252,7 +252,7 @@ SECTIONS
|
|||||||
} > dram0_0_seg
|
} > dram0_0_seg
|
||||||
|
|
||||||
/* When modifying the alignment, update tls_section_alignment in pxPortInitialiseStack */
|
/* When modifying the alignment, update tls_section_alignment in pxPortInitialiseStack */
|
||||||
.flash.rodata : ALIGN(0x10)
|
.flash.appdesc : ALIGN(0x10)
|
||||||
{
|
{
|
||||||
_rodata_reserved_start = ABSOLUTE(.);
|
_rodata_reserved_start = ABSOLUTE(.);
|
||||||
_rodata_start = ABSOLUTE(.);
|
_rodata_start = ABSOLUTE(.);
|
||||||
@@ -260,6 +260,14 @@ SECTIONS
|
|||||||
*(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */
|
*(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */
|
||||||
*(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */
|
*(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */
|
||||||
|
|
||||||
|
/* Create an empty gap within this section. Thanks to this, the end of this
|
||||||
|
* section will match .flah.rodata's begin address. Thus, both sections
|
||||||
|
* will be merged when creating the final bin image. */
|
||||||
|
. = ALIGN(ALIGNOF(.flash.rodata));
|
||||||
|
} >default_rodata_seg
|
||||||
|
|
||||||
|
.flash.rodata : ALIGN(0x10)
|
||||||
|
{
|
||||||
mapping[flash_rodata]
|
mapping[flash_rodata]
|
||||||
|
|
||||||
*(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
|
*(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
|
||||||
|
@@ -117,3 +117,12 @@ REGION_ALIAS("default_rodata_seg", drom0_0_seg);
|
|||||||
#else
|
#else
|
||||||
REGION_ALIAS("default_rodata_seg", dram0_0_seg);
|
REGION_ALIAS("default_rodata_seg", dram0_0_seg);
|
||||||
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If rodata default segment is placed in `drom0_0_seg`, then flash's first rodata section must
|
||||||
|
* also be first in the segment.
|
||||||
|
*/
|
||||||
|
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
ASSERT(_flash_rodata_dummy_start == ORIGIN(default_rodata_seg),
|
||||||
|
".flash_rodata_dummy section must be placed at the beginning of the rodata segment.")
|
||||||
|
#endif
|
||||||
|
@@ -282,6 +282,7 @@ SECTIONS
|
|||||||
*/
|
*/
|
||||||
.flash_rodata_dummy (NOLOAD):
|
.flash_rodata_dummy (NOLOAD):
|
||||||
{
|
{
|
||||||
|
_flash_rodata_dummy_start = .;
|
||||||
/* Start at the same alignement constraint than .flash.text */
|
/* Start at the same alignement constraint than .flash.text */
|
||||||
. = ALIGN(ALIGNOF(.flash.text));
|
. = ALIGN(ALIGNOF(.flash.text));
|
||||||
/* Create an empty gap as big as .flash.text section */
|
/* Create an empty gap as big as .flash.text section */
|
||||||
@@ -293,13 +294,21 @@ SECTIONS
|
|||||||
} > default_rodata_seg
|
} > default_rodata_seg
|
||||||
|
|
||||||
/* When modifying the alignment, don't forget to update tls_section_alignment in pxPortInitialiseStack */
|
/* When modifying the alignment, don't forget to update tls_section_alignment in pxPortInitialiseStack */
|
||||||
.flash.rodata : ALIGN(0x10)
|
.flash.appdesc : ALIGN(0x10)
|
||||||
{
|
{
|
||||||
_rodata_start = ABSOLUTE(.);
|
_rodata_start = ABSOLUTE(.);
|
||||||
|
|
||||||
*(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */
|
*(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */
|
||||||
*(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */
|
*(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */
|
||||||
|
|
||||||
|
/* Create an empty gap within this section. Thanks to this, the end of this
|
||||||
|
* section will match .flah.rodata's begin address. Thus, both sections
|
||||||
|
* will be merged when creating the final bin image. */
|
||||||
|
. = ALIGN(ALIGNOF(.flash.rodata));
|
||||||
|
} >default_rodata_seg
|
||||||
|
|
||||||
|
.flash.rodata : ALIGN(0x10)
|
||||||
|
{
|
||||||
mapping[flash_rodata]
|
mapping[flash_rodata]
|
||||||
|
|
||||||
*(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
|
*(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
|
||||||
|
18
tools/test_apps/build_system/ldalign_test/CMakeLists.txt
Normal file
18
tools/test_apps/build_system/ldalign_test/CMakeLists.txt
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# The following lines of boilerplate have to be in your project's
|
||||||
|
# CMakeLists in this exact order for cmake to work correctly
|
||||||
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
|
project(ldalign_test)
|
||||||
|
|
||||||
|
idf_build_get_property(python PYTHON)
|
||||||
|
idf_build_get_property(elf EXECUTABLE)
|
||||||
|
|
||||||
|
set(check_alignment "${CMAKE_CURRENT_LIST_DIR}/check_alignment.py")
|
||||||
|
set(readelf "${CMAKE_TOOLCHAIN_PREFIX}readelf")
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
TARGET ${elf}
|
||||||
|
POST_BUILD
|
||||||
|
COMMAND ${python} ${check_alignment} ${readelf} $<TARGET_FILE:${elf}>
|
||||||
|
)
|
7
tools/test_apps/build_system/ldalign_test/README.txt
Normal file
7
tools/test_apps/build_system/ldalign_test/README.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
Runs a build test to check alignment and position of `.flash.appdesc` and
|
||||||
|
`.flash.rodata` sections. Indeed, `.flash.appdesc` shall ALWAYS be aligned on
|
||||||
|
a 16-byte bounds, whereas `.flash.rodata` can have any alignment. In any case,
|
||||||
|
the end address of first one shall match the start address of the second one.
|
||||||
|
This will let both of them be merged when generating the final bin image.
|
||||||
|
The Python script that performs the checks, `check_alignment.py`, automatically
|
||||||
|
runs after the app is built.
|
64
tools/test_apps/build_system/ldalign_test/check_alignment.py
Normal file
64
tools/test_apps/build_system/ldalign_test/check_alignment.py
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
#
|
||||||
|
# http://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.
|
||||||
|
#
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
from typing import Tuple
|
||||||
|
|
||||||
|
argparser = argparse.ArgumentParser()
|
||||||
|
|
||||||
|
argparser.add_argument('readelf')
|
||||||
|
argparser.add_argument('elf')
|
||||||
|
|
||||||
|
args = argparser.parse_args()
|
||||||
|
|
||||||
|
# Get the content of the readelf command
|
||||||
|
contents = subprocess.check_output([args.readelf, '-S', args.elf]).decode()
|
||||||
|
|
||||||
|
|
||||||
|
# Define a class for readelf parsing error
|
||||||
|
class ParsingError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# Look for the start address and size of any section
|
||||||
|
def find_partition_info(sectionname): # type: (str) -> Tuple[int, int, int]
|
||||||
|
match = re.search(sectionname + r'\s+PROGBITS\s+([a-f0-9]+) [a-f0-9]+ ([a-f0-9]+) \d+\s+[A-Z]+ 0 0 (\d+)',
|
||||||
|
contents)
|
||||||
|
if not match:
|
||||||
|
raise ParsingError('ELF header parsing error')
|
||||||
|
# Return the address of the section, the size and the alignment
|
||||||
|
address = match.group(1)
|
||||||
|
size = match.group(2)
|
||||||
|
alignment = match.group(3)
|
||||||
|
return (int(address, 16), int(size, 16), int(alignment, 10))
|
||||||
|
|
||||||
|
|
||||||
|
# Get address and size for .flash.appdesc section
|
||||||
|
app_address, app_size, app_align = find_partition_info('.flash.appdesc')
|
||||||
|
|
||||||
|
# Same goes for .flash.rodata section
|
||||||
|
rodata_address, _, rodata_align = find_partition_info('.flash.rodata')
|
||||||
|
|
||||||
|
# Assert than everything is as expected:
|
||||||
|
# appdesc is aligned on 16
|
||||||
|
# rodata is aligned on 64
|
||||||
|
# appdesc ends where rodata starts
|
||||||
|
assert app_align == 16, '.flash.appdesc section should have been aligned on 16!'
|
||||||
|
assert rodata_align == 64, '.flash.rodata section should have been aligned on 64!'
|
||||||
|
assert app_address + app_size == rodata_address, ".flash.appdesc's end address and .flash.rodata's begin start must have no gap in between!"
|
@@ -0,0 +1,2 @@
|
|||||||
|
idf_component_register(SRCS "test_main.c"
|
||||||
|
INCLUDE_DIRS ".")
|
16
tools/test_apps/build_system/ldalign_test/main/test_main.c
Normal file
16
tools/test_apps/build_system/ldalign_test/main/test_main.c
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
const static uint32_t __attribute__ ((aligned (64))) testTab[] =
|
||||||
|
{
|
||||||
|
0xff445566, 0x44556677, 0x33221100,
|
||||||
|
0x88997755, 0x99887755, 0x88997755,
|
||||||
|
0x99546327, 0x7946fa9e, 0xa6b5f8ee,
|
||||||
|
0x12345678
|
||||||
|
};
|
||||||
|
|
||||||
|
void app_main(void)
|
||||||
|
{
|
||||||
|
/* Do something with the array, in order to avoid it being discarded. */
|
||||||
|
for (uint32_t i = 0; i < 10; i++)
|
||||||
|
printf ("%x\n", testTab[i]);
|
||||||
|
}
|
Reference in New Issue
Block a user