mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'bugfix/flash_rodata_any_alignement_v4.3' into 'release/v4.3'
build: Fix cache issue and add dedicated section for (Custom) App version info (backport v4.3) See merge request espressif/esp-idf!13448
This commit is contained in:
commit
9f6e09d0d3
@ -134,3 +134,12 @@ REGION_ALIAS("rtc_data_location", rtc_data_seg );
|
||||
#else
|
||||
REGION_ALIAS("default_rodata_seg", dram0_0_seg);
|
||||
#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
|
||||
|
@ -270,14 +270,23 @@ SECTIONS
|
||||
ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)),
|
||||
"DRAM segment data does not fit.")
|
||||
|
||||
/* When modifying the alignment, update tls_section_alignment in pxPortInitialiseStack */
|
||||
.flash.rodata : ALIGN(0x10)
|
||||
.flash.appdesc : ALIGN(0x10)
|
||||
{
|
||||
_rodata_start = ABSOLUTE(.);
|
||||
|
||||
*(.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! */
|
||||
|
||||
/* 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)
|
||||
{
|
||||
_flash_rodata_start = ABSOLUTE(.);
|
||||
|
||||
mapping[flash_rodata]
|
||||
|
||||
|
||||
@ -335,6 +344,8 @@ SECTIONS
|
||||
. = ALIGN(4);
|
||||
} >default_rodata_seg
|
||||
|
||||
_flash_rodata_align = ALIGNOF(.flash.rodata);
|
||||
|
||||
.flash.text :
|
||||
{
|
||||
_stext = .;
|
||||
|
@ -107,3 +107,12 @@ REGION_ALIAS("rtc_data_location", rtc_iram_seg );
|
||||
#else
|
||||
REGION_ALIAS("default_rodata_seg", dram0_0_seg);
|
||||
#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
|
||||
|
@ -283,21 +283,40 @@ SECTIONS
|
||||
_flash_cache_start = ABSOLUTE(0);
|
||||
} > default_code_seg
|
||||
|
||||
/**
|
||||
* This dummy section represents the .flash.text section but in default_rodata_seg.
|
||||
* Thus, it must have its alignement and (at least) its size.
|
||||
*/
|
||||
.flash_rodata_dummy (NOLOAD):
|
||||
{
|
||||
. = SIZEOF(.flash.text);
|
||||
_flash_rodata_dummy_start = .;
|
||||
/* Start at the same alignement constraint than .flash.text */
|
||||
. = ALIGN(ALIGNOF(.flash.text));
|
||||
/* Create an empty gap as big as .flash.text section */
|
||||
. = . + SIZEOF(.flash.text);
|
||||
/* Prepare the alignement of the section above. Few bytes (0x20) must be
|
||||
* added for the mapping header. */
|
||||
. = ALIGN(0x10000) + 0x20;
|
||||
_rodata_reserved_start = .;
|
||||
} > default_rodata_seg
|
||||
|
||||
/* 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_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! */
|
||||
|
||||
/* 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)
|
||||
{
|
||||
_flash_rodata_start = ABSOLUTE(.);
|
||||
|
||||
mapping[flash_rodata]
|
||||
|
||||
*(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
|
||||
|
@ -136,3 +136,13 @@ REGION_ALIAS("rtc_data_location", rtc_data_seg );
|
||||
#else
|
||||
REGION_ALIAS("default_rodata_seg", dram0_0_seg);
|
||||
#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
|
||||
|
@ -265,8 +265,7 @@ SECTIONS
|
||||
_bss_end = ABSOLUTE(.);
|
||||
} > dram0_0_seg
|
||||
|
||||
/* When modifying the alignment, update tls_section_alignment in pxPortInitialiseStack */
|
||||
.flash.rodata : ALIGN(0x10)
|
||||
.flash.appdesc : ALIGN(0x10)
|
||||
{
|
||||
_rodata_reserved_start = ABSOLUTE(.);
|
||||
_rodata_start = ABSOLUTE(.);
|
||||
@ -274,6 +273,16 @@ SECTIONS
|
||||
*(.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! */
|
||||
|
||||
/* 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)
|
||||
{
|
||||
_flash_rodata_start = ABSOLUTE(.);
|
||||
|
||||
mapping[flash_rodata]
|
||||
|
||||
*(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
|
||||
@ -330,6 +339,8 @@ SECTIONS
|
||||
. = ALIGN(4);
|
||||
} >default_rodata_seg
|
||||
|
||||
_flash_rodata_align = ALIGNOF(.flash.rodata);
|
||||
|
||||
.flash.text :
|
||||
{
|
||||
_stext = .;
|
||||
|
@ -117,3 +117,12 @@ REGION_ALIAS("default_rodata_seg", drom0_0_seg);
|
||||
#else
|
||||
REGION_ALIAS("default_rodata_seg", dram0_0_seg);
|
||||
#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
|
||||
|
@ -314,21 +314,40 @@ SECTIONS
|
||||
_flash_cache_start = ABSOLUTE(0);
|
||||
} > default_code_seg
|
||||
|
||||
/**
|
||||
* This dummy section represents the .flash.text section but in default_rodata_seg.
|
||||
* Thus, it must have its alignement and (at least) its size.
|
||||
*/
|
||||
.flash_rodata_dummy (NOLOAD):
|
||||
{
|
||||
. = SIZEOF(.flash.text);
|
||||
_flash_rodata_dummy_start = .;
|
||||
/* Start at the same alignement constraint than .flash.text */
|
||||
. = ALIGN(ALIGNOF(.flash.text));
|
||||
/* Create an empty gap as big as .flash.text section */
|
||||
. = . + SIZEOF(.flash.text);
|
||||
/* Prepare the alignement of the section above. Few bytes (0x20) must be
|
||||
* added for the mapping header. */
|
||||
. = ALIGN(0x10000) + 0x20;
|
||||
_rodata_reserved_start = .;
|
||||
} > default_rodata_seg
|
||||
|
||||
/* 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_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! */
|
||||
|
||||
/* 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)
|
||||
{
|
||||
_flash_rodata_start = ABSOLUTE(.);
|
||||
|
||||
mapping[flash_rodata]
|
||||
|
||||
*(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
|
||||
@ -382,6 +401,8 @@ SECTIONS
|
||||
. = ALIGN(4);
|
||||
} > default_rodata_seg
|
||||
|
||||
_flash_rodata_align = ALIGNOF(.flash.rodata);
|
||||
|
||||
/* Marks the end of IRAM code segment */
|
||||
.iram0.text_end (NOLOAD) :
|
||||
{
|
||||
|
@ -225,18 +225,58 @@ StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxC
|
||||
extern uint32_t __global_pointer$;
|
||||
uint8_t* task_thread_local_start;
|
||||
uint8_t* threadptr;
|
||||
extern char _thread_local_start, _thread_local_end, _rodata_start;
|
||||
extern char _thread_local_start, _thread_local_end, _flash_rodata_start;
|
||||
|
||||
/* Byte pointer, so that subsequent calculations don't depend on sizeof(StackType_t). */
|
||||
uint8_t* sp = (uint8_t*) pxTopOfStack;
|
||||
|
||||
/* Set up TLS area */
|
||||
/* Set up TLS area.
|
||||
* The following diagram illustrates the layout of link-time and run-time
|
||||
* TLS sections.
|
||||
*
|
||||
* +-------------+
|
||||
* |Section: | Linker symbols:
|
||||
* |.flash.rodata| ---------------
|
||||
* 0x0+-------------+ <-- _flash_rodata_start
|
||||
* ^ | |
|
||||
* | | Other data |
|
||||
* | | ... |
|
||||
* | +-------------+ <-- _thread_local_start
|
||||
* | |.tbss | ^
|
||||
* v | | |
|
||||
* 0xNNNN|int example; | | (thread_local_size)
|
||||
* |.tdata | v
|
||||
* +-------------+ <-- _thread_local_end
|
||||
* | Other data |
|
||||
* | ... |
|
||||
* | |
|
||||
* +-------------+
|
||||
*
|
||||
* Local variables of
|
||||
* pxPortInitialiseStack
|
||||
* -----------------------
|
||||
* +-------------+ <-- pxTopOfStack
|
||||
* |.tdata (*) | ^
|
||||
* ^ |int example; | |(thread_local_size
|
||||
* | | | |
|
||||
* | |.tbss (*) | v
|
||||
* | +-------------+ <-- task_thread_local_start
|
||||
* 0xNNNN | | | ^
|
||||
* | | | |
|
||||
* | | | |_thread_local_start - _rodata_start
|
||||
* | | | |
|
||||
* | | | v
|
||||
* v +-------------+ <-- threadptr
|
||||
*
|
||||
* (*) The stack grows downward!
|
||||
*/
|
||||
|
||||
uint32_t thread_local_sz = (uint32_t) (&_thread_local_end - &_thread_local_start);
|
||||
thread_local_sz = ALIGNUP(0x10, thread_local_sz);
|
||||
sp -= thread_local_sz;
|
||||
task_thread_local_start = sp;
|
||||
memcpy(task_thread_local_start, &_thread_local_start, thread_local_sz);
|
||||
threadptr = task_thread_local_start - (&_thread_local_start - &_rodata_start);
|
||||
threadptr = task_thread_local_start - (&_thread_local_start - &_flash_rodata_start);
|
||||
|
||||
/* Simulate the stack frame as it would be created by a context switch interrupt. */
|
||||
sp -= RV_STK_FRMSZ;
|
||||
|
@ -189,7 +189,7 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
|
||||
#endif
|
||||
uint32_t *threadptr;
|
||||
void *task_thread_local_start;
|
||||
extern int _thread_local_start, _thread_local_end, _rodata_start;
|
||||
extern int _thread_local_start, _thread_local_end, _flash_rodata_start, _flash_rodata_align;
|
||||
// TODO: check that TLS area fits the stack
|
||||
uint32_t thread_local_sz = (uint8_t *)&_thread_local_end - (uint8_t *)&_thread_local_start;
|
||||
|
||||
@ -248,24 +248,25 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
|
||||
frame->vpri = 0xFFFFFFFF;
|
||||
#endif
|
||||
|
||||
/* Init threadptr reg and TLS vars */
|
||||
/* Init threadptr register and set up TLS run-time area.
|
||||
* The diagram in port/riscv/port.c illustrates the calculations below.
|
||||
*/
|
||||
task_thread_local_start = (void *)(((uint32_t)pxTopOfStack - XT_CP_SIZE - thread_local_sz) & ~0xf);
|
||||
memcpy(task_thread_local_start, &_thread_local_start, thread_local_sz);
|
||||
threadptr = (uint32_t *)(sp + XT_STK_EXTRA);
|
||||
/* Calculate THREADPTR value:
|
||||
/* Calculate THREADPTR value.
|
||||
* The generated code will add THREADPTR value to a constant value determined at link time,
|
||||
* to get the address of the TLS variable.
|
||||
* The constant value is calculated by the linker as follows
|
||||
* (search for 'tpoff' in elf32-xtensa.c in BFD):
|
||||
* offset = address - tls_section_vma + align_up(TCB_SIZE, tls_section_alignment)
|
||||
* where TCB_SIZE is hardcoded to 8. There doesn't seem to be a way to propagate
|
||||
* the section alignment value from the ld script into the code, so it is hardcoded
|
||||
* in both places.
|
||||
* where TCB_SIZE is hardcoded to 8.
|
||||
* Note this is slightly different compared to the RISC-V port, where offset = address - tls_section_vma.
|
||||
*/
|
||||
const uint32_t tls_section_alignment = 0x10; /* has to be in sync with ALIGN value of .flash.rodata section */
|
||||
const uint32_t tls_section_alignment = (uint32_t) &_flash_rodata_align; /* ALIGN value of .flash.rodata section */
|
||||
const uint32_t tcb_size = 8; /* Unrelated to FreeRTOS, this is the constant from BFD */
|
||||
const uint32_t base = (tcb_size + tls_section_alignment - 1) & (~(tls_section_alignment - 1));
|
||||
*threadptr = (uint32_t)task_thread_local_start - ((uint32_t)&_thread_local_start - (uint32_t)&_rodata_start) - base;
|
||||
*threadptr = (uint32_t)task_thread_local_start - ((uint32_t)&_thread_local_start - (uint32_t)&_flash_rodata_start) - base;
|
||||
|
||||
#if XCHAL_CP_NUM > 0
|
||||
/* Init the coprocessor save area (see xtensa_context.h) */
|
||||
|
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]);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user