Oh, sorry.
Attached again as .txt. Is it OK now?
> A tool that takes the Kconfig + chip+ memorymap and make a linker include
> file and the config code for the heap may be the way to go.
I am pretty sure that a "tool" will not be able to cover all use cases.
Over the years I had to make custom scripts to account for:
* Bootloaders
* Binary blops
* Firmware headers
* ROM files
* DMA buffers
* External memories
etc etc..
Do you believe that a tool can be made that can handle everything?
Στις Παρ, 26 Μαρ 2021 στις 6:37 μ.μ., ο/η David Sidrane <
[email protected]> έγραψε:
> I am just thinking out load...
>
> I agree this has to come from one place. But I do think it is just the
> linker file.
>
> Currently we have
> The arch memroymap h files have the base addresses, sizes - This is the
> Reference manuals counterpart, it covers all the sub members of the chips)
> The chip.h files that has sizes - This is the Data Sheet counterpart, it
> covers one or more of the sub members of the chips)
> The Kconfig - More flexible from a users stand point.
> The heap c files - buried semantics - not good
> linker file - the boards usage specific.
>
> I like using the linker file, but Kconfig is build time - no file
> modification
>
> Just moving things to the linker file does not fix the ordering or adding
> issues. (it is link time not compile time)
>
> A tool that takes the Kconfig + chip+ memorymap and make a linker include
> file and the config code for the heap may be the way to go.
>
> David
>
>
> -----Original Message-----
> From: Fotis Panagiotopoulos [mailto:[email protected]]
> Sent: Friday, March 26, 2021 9:17 AM
> To: [email protected]
> Subject: Re: How to ensure HEAP will not overlap static DMA buffer?
>
> I face similar problems (with a different use case) on an STM32F4.
> The thing is that although the linker script belongs to the board logic and
> thus it is freely customizable, the heap regions are hard-coded in the arch
> files.
>
> So, I started working on PR #2277 (
> https://github.com/apache/incubator-nuttx/pull/2277), but unfortunately I
> had to pause the development on this.
> The idea is similar to what you describe here. Everything can be defined in
> the linkerscript (addresses, order, sizeses etc).
>
> I was thinking a lot of any alternatives on this. I came to the conclusion
> that Kconfig is the wrong tool for this job.
> You lose all compile-time (and CI) checks and can easily be misconfigured.
> I am also afraid that we will end up with a few dozen "hacks" like above or
> like STM32_CCMEXCLUDE (I never liked this option....).
> And no matter what you do, you will never be able to satisfy any crazy
> memory mappings that any project may need.
>
> A similar issue to this is Issue #2001 (
> https://github.com/apache/incubator-nuttx/issues/2001).
> This was my first crash while trying out NuttX :)
> In short, there is the assumption that the main stack will always reside
> between BSS and Heap, again being very restrictive.
>
>
> Στις Παρ, 26 Μαρ 2021 στις 5:46 μ.μ., ο/η Nathan Hartman <
> [email protected]> έγραψε:
>
> > On Fri, Mar 26, 2021 at 11:41 AM Gregory Nutt <[email protected]>
> wrote:
> >
> > > Missing bit of logic:
> > >
> > > >> Speaking of the linker, is there a way to use a combination of the
> > > >> linker script and __attribute__ incantations in the code to detect
> > > >> automatically the size that g_sram4_reserve should be and entirely
> > > >> eliminate the need for the user to specify the start and end of each
> > > >> region in Kconfig?
> > > >
> > > > Are you thinking of something like this in the linker script:
> > > >
> > > > .sram4_reserve :
> > > > {
> > > > _sram4_reserve_begin = ABSOLUTE(.);
> > > > *(.sram4)
> > > > _sram4_reserve_end = ABSOLUTE(.);
> > > > }
> > > >
> > > > And in the C code:
> > > >
> > > We need to lie to C and tell it what to think those symbols are:
> > >
> > > EXTERN const uint32_t _sram4_reserve_begin
> > > EXTERN const uint32_t _sram4_reserve_begin
> >
> >
> >
> > Ah, yes, otherwise those symbols would be undefined. Later the linker
> will
> > resolve them to the correct addresses.
> >
> >
> > > #define SRAM4_RESERVE_BEGIN &_sram4_reserve_begin
> > > > #define SRAM4_RESERVE_END &_sram4_reserve_end
> > > >
> > > > The implied size depends on the size of all .sram4 sections. I
> assume
> > > > this would be positioned at the beginning of SRAM4 and the size of
> the
> > > > region that could be added to the heap would be SRAM4_RESERVE_END
> > > > through SRAM_END.
> > > >
> > > You can see this same kind of thing in, for example,
> > > arch/arm/src/common/arm_internal.h
> >
> >
> >
> > Great! Thanks
> >
> > Nathan
> >
>
/*
* Linker script configurator.
* This file provides with the default settings for the linker script.
* It can be used as is, or used as a template for project specific
* configuration.
*
* The MEMORY command describes the various memory sections, to be
* used during linking.
* All used sections are aliased bellow, to the memory defined areas.
* They can be located anywhere, and even on different order (e.g. if
* the BSS memory is before Data memory, then these two sections will
* be swapped accordingly.
*
* Furthermore some General Puprose sections are provided for both the
* Flash and RAM memories. These sections can include anything, by the
* help of the file section_macros.h, or can be ommited, using the
* DONT_LINK memory definition. The GP flash sections, can be addressed
* but discarded from the final .hex file, by defining them, and setting
* STORE to DONT_LINK.
*/
/*
* ST32F42xxI memory setup.
*/
MEMORY
{
FLASH0 (rx) : ORIGIN = 0x00000000, LENGTH = 48k /*
Bootloader. */
FLASH1 (rx) : ORIGIN = 0x00000000, LENGTH = 0 /*
Bootloader NVData. Already accounted above. */
FLASH2 (rx) : ORIGIN = 0x0000C000, LENGTH = 976k /* Kernel. */
FLASH3 (rx) : ORIGIN = 0x00100000, LENGTH = 16k /*
Settings storage. */
FLASH4 (rx) : ORIGIN = 0x00120000, LENGTH = 128k /* Control
script storage. */
FLASH5 (rx) : ORIGIN = 0x00000000, LENGTH = 0
RAM0 (xrw) : ORIGIN = 0x10000000, LENGTH = 4k /*
Core-coupled RAM. Exception stack. */
RAM1 (xrw) : ORIGIN = 0x10001000, LENGTH = 42k /*
Core-coupled RAM. Thread stacks, BSS & DATA. */
RAM2 (xrw) : ORIGIN = 0x1000B800, LENGTH = 18k /*
Core-coupled RAM. Main stack. */
RAM3 (xrw) : ORIGIN = 0x20000000, LENGTH = 192k /* Heap. */
RAM4 (xrw) : ORIGIN = 0x00000000, LENGTH = 0
RAM5 (xrw) : ORIGIN = 0x00000000, LENGTH = 0
BACKUP_RAM (xrw): ORIGIN = 0x40024000, LENGTH = 4k
DONT_LINK : ORIGIN = 0x00000000, LENGTH = 0
}
/*
* Flash region to be used for the bootloader.
*/
REGION_ALIAS("BOOTLOADER_FLASH", FLASH0);
/*
* Flash region to be used for code text, including
* the vector table and the startup code. Thus normally
* should start at address 0.
*/
REGION_ALIAS("TEXT_FLASH", FLASH2);
/*
* Flash region to be used for read only data.
*/
REGION_ALIAS("RODATA_FLASH", FLASH2);
/*
* Flash region to be used for data segment initializers.
*/
REGION_ALIAS("TEXTDATA_FLASH", FLASH2);
/*
* RAM region to be used for the data segment.
*/
REGION_ALIAS("DATA_RAM", RAM1);
/*
* RAM region to be used for the BSS segment.
*/
REGION_ALIAS("BSS_RAM", RAM1);
/*
* RAM region to be used for storing non-initialized variables.
*/
REGION_ALIAS("NOINIT_RAM", RAM1);
/*
* RAM region to be used for the exception/interrupt stack.
* If enabled, the application will run in thread (non-privileged)
* mode, and the appropriate bits will be set to the core registers.
* Else the application will run with a single stack.
*/
REGION_ALIAS("EXCEPTION_STACK_RAM", RAM0);
/*
* Size of exception/interrupt stack.
*/
PROVIDE(__exception_stack_size__ = 0x1000);
/*
* RAM region to be used for the heap.
*/
REGION_ALIAS("HEAP_RAM", RAM3);
/*
* RAM region to be used for the main stack.
*/
REGION_ALIAS("MAIN_STACK_RAM", RAM2);
/*
* Size of the main stack.
*/
PROVIDE(__main_stack_size__ = 0x4800);
/*
* General puprose Flash region 1.
*/
REGION_ALIAS("GP_FLASH1", FLASH3);
/*
* General puprose Flash region 1, store section.
*/
REGION_ALIAS("GP_FLASH1_STORE", FLASH3);
/*
* General puprose Flash region 2.
*/
REGION_ALIAS("GP_FLASH2", FLASH4);
/*
* General puprose Flash region 2, store section.
*/
REGION_ALIAS("GP_FLASH2_STORE", FLASH4);
/*
* General puprose Flash region 3.
*/
REGION_ALIAS("GP_FLASH3", DONT_LINK);
/*
* General puprose Flash region 3, store section.
*/
REGION_ALIAS("GP_FLASH3_STORE", DONT_LINK);
/*
* General puprose Flash region 4.
*/
REGION_ALIAS("GP_FLASH4", DONT_LINK);
/*
* General puprose Flash region 4, store section.
*/
REGION_ALIAS("GP_FLASH4_STORE", DONT_LINK);
/*
* General puprose RAM region 1.
*/
REGION_ALIAS("GP_RAM1", DONT_LINK);
/*
* General puprose RAM region 1, store section.
*/
REGION_ALIAS("GP_RAM1_STORE", DONT_LINK);
/*
* General puprose RAM region 2.
*/
REGION_ALIAS("GP_RAM2", DONT_LINK);
/*
* General puprose RAM region 2, store section.
*/
REGION_ALIAS("GP_RAM2_STORE", DONT_LINK);
/* Bootloader data address. */
PROVIDE(__boot_data__ = 0x8000);
INCLUDE rules.ld
/*
* Linker script.
*/
/*
* Set the output format. Currently set for Cortex M architectures,
* may need to be modified if the library has to support other MCUs,
* or completelly removed. (This is not strictly necessary.)
*/
OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
/*
* Just refering a function included in the vector table, and that
* it is defined in the same file with it, so the vector table does
* not get optimized out.
*/
EXTERN(Reset_Handler)
/*
* Include any needed standard lirbaries.
*/
INCLUDE libraries.ld
/*
* Stack start pointer. Here set to the end of the stack
* memory, as in most architectures (including all the
* new ARM ones), the stack starts from the maximum address
* and grows towards the bottom.
*/
__stack = ORIGIN(MAIN_STACK_RAM) + LENGTH(MAIN_STACK_RAM);
/*
* General Purpose RAM sections, address and size symbols.
*/
__gp_ram1_start__ = ORIGIN(GP_RAM1);
__gp_ram1_size__ = LENGTH(GP_RAM1);
__gp_ram1_end__ = __gp_ram1_start__ + __gp_ram1_size__;
__gp_ram2_start__ = ORIGIN(GP_RAM2);
__gp_ram2_size__ = LENGTH(GP_RAM2);
__gp_ram2_end__ = __gp_ram2_start__ + __gp_ram2_size__;
/*
* Programm entry function. Used by the debugger only.
*/
ENTRY(_start)
/*
* Memory Allocation Sections
*/
SECTIONS
{
/*
* This should normally evaluate to address 0, as the bootloader
* has to be executed before anything else.
*/
. = ORIGIN(BOOTLOADER_FLASH);
/*
* Place the bootloader blop before anything else.
*/
.bootloader : ALIGN(4)
{
FILL(0xFF)
__bootloader_start__ = ABSOLUTE(.);
KEEP(*(.text.bootloader))
__bootloader_end__ = ABSOLUTE(.);
} > BOOTLOADER_FLASH
/*
* Now this should point to the firmware start address.
*/
. = ORIGIN(TEXT_FLASH);
/*
* First link the vector table.
*/
.vectors : ALIGN(4)
{
FILL(0xFF)
__vectors_start__ = ABSOLUTE(.);
KEEP(*(.vectors))
} > TEXT_FLASH
/*
* Set the firmware header.
*/
.header : ALIGN(4)
{
. = ORIGIN(TEXT_FLASH) + 0x200; /* Ensure that the address is
constant. */
FILL(0xFF)
__firmware_header__ = ABSOLUTE(.);
KEEP(*(.header))
} > TEXT_FLASH
/*
* Set any after-vectors text.
*/
.after_vectors : ALIGN(4)
{
FILL(0xFF)
KEEP(*(.after_vectors))
*(.after_vectors .after_vectors.*)
} > TEXT_FLASH
/*
* Start of text.
*/
_text = .;
/*
* Text section
*/
.text : ALIGN(4)
{
*(.text)
*(.text.*)
*(.glue_7t)
*(.glue_7)
*(.gcc*)
} > TEXT_FLASH
/*
* Arm section unwinding.
* If removed may cause random crashes.
*/
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > TEXT_FLASH
/*
* Arm stack unwinding.
* If removed may cause random crashes.
*/
.ARM.exidx :
{
__exidx_start = .;
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
__exidx_end = .;
} > TEXT_FLASH
/*
* Section used by C++ to access eh_frame.
* Generaly not used, but it doesn't harm to be there.
*/
.eh_frame_hdr :
{
*(.eh_frame_hdr)
} > TEXT_FLASH
/*
* Stack unwinding code.
* Generaly not used, but it doesn't harm to be there.
*/
.eh_frame : ONLY_IF_RO
{
*(.eh_frame)
} > TEXT_FLASH
/*
* Read-only data. Consts should also be here.
*/
.rodata : ALIGN(4)
{
. = ALIGN(4);
__rodata_start__ = .;
*(.rodata)
*(.rodata.*)
. = ALIGN(4);
__rodata_end__ = .;
} > RODATA_FLASH
/*
* End of text.
*/
_etext = .;
/*
* Data section.
*/
.data : ALIGN(4)
{
FILL(0xFF)
. = ALIGN(4);
PROVIDE(__textdata__ = LOADADDR(.data));
PROVIDE(__data_start__ = .);
*(.data)
*(.data.*)
*(.ramtext)
. = ALIGN(4);
PROVIDE(__data_end__ = .);
} > DATA_RAM AT > TEXTDATA_FLASH
/*
* BSS section.
*/
.bss (NOLOAD) : ALIGN(4)
{
. = ALIGN(4);
PROVIDE(_bss_start = .);
__bss_start__ = .;
*(.bss)
*(.bss.*)
*(COMMON)
. = ALIGN(4);
PROVIDE(_bss_end = .);
__bss_end__ = .;
PROVIDE(end = .);
} > BSS_RAM
/*
* Non-initialized variables section.
* A variable should be explicitly placed
* here, aiming in speeding-up boot time.
*/
.noinit (NOLOAD) : ALIGN(4)
{
__noinit_start__ = .;
*(.noinit .noinit.*)
. = ALIGN(4) ;
__noinit_end__ = .;
} > NOINIT_RAM
/* Special section for process stack.*/
.exceptionStack :
{
. = ALIGN(8);
__exception_stack_start__ = .;
. += __exception_stack_size__;
KEEP(*(.exceptionStack))
. = ALIGN(8);
__exception_stack_end__ = .;
} > EXCEPTION_STACK_RAM
/*
* Heap section.
*/
.heap (NOLOAD) :
{
. = ALIGN(4);
__heap_start__ = .;
. = ORIGIN(HEAP_RAM) + LENGTH(HEAP_RAM);
__heap_end__ = .;
. = ALIGN(4);
} > HEAP_RAM
PROVIDE(__heap_size__ = SIZEOF(.heap));
/*
* Main stack section.
*/
.mainStack (NOLOAD) :
{
. = ALIGN(8);
__main_stack_start__ = .;
. += __main_stack_size__;
KEEP(*(.mainStack))
. = ALIGN(8);
__main_stack_end__ = .;
} > MAIN_STACK_RAM
/*
* General purpose Flash 1.
*/
.gp_flash1 : ALIGN(4)
{
FILL(0xFF)
__gp_flash1_start__ = ORIGIN(GP_FLASH1);
. = __gp_flash1_start__;
KEEP(*(.gp_flash1))
__gp_flash1_end__ = __gp_flash1_start__ + LENGTH(GP_FLASH1);
. = __gp_flash1_end__;
FILL(0xFF)
} > GP_FLASH1 AT > GP_FLASH1_STORE
/*
* General purpose Flash 2.
*/
.gp_flash2 : ALIGN(4)
{
FILL(0xFF)
__gp_flash2_start__ = ORIGIN(GP_FLASH2);
. = __gp_flash2_start__;
KEEP(*(.gp_flash2))
__gp_flash2_end__ = __gp_flash2_start__ + LENGTH(GP_FLASH2);
. = __gp_flash2_end__;
FILL(0xFF)
} > GP_FLASH2 AT > GP_FLASH2_STORE
/*
* General purpose Flash 3.
*/
.gp_flash3 : ALIGN(4)
{
FILL(0xFF)
__gp_flash3_start__ = ORIGIN(GP_FLASH3);
. = __gp_flash3_start__;
KEEP(*(.gp_flash3))
__gp_flash3_end__ = __gp_flash3_start__ + LENGTH(GP_FLASH3);
. = __gp_flash3_end__;
FILL(0xFF)
} > GP_FLASH3 AT > GP_FLASH3_STORE
/*
* General purpose Flash 4.
*/
.gp_flash4 : ALIGN(4)
{
FILL(0xFF)
__gp_flash4_start__ = ORIGIN(GP_FLASH4);
. = __gp_flash4_start__;
KEEP(*(.gp_flash4))
__gp_flash4_end__ = __gp_flash4_start__ + LENGTH(GP_FLASH4);
. = __gp_flash4_end__;
FILL(0xFF)
} > GP_FLASH4 AT > GP_FLASH4_STORE
/*
* General purpose RAM 1, data.
* Variables must be explicitly set here, and must be
* correctly characterized as data in order to be
* initialized.
*/
.gp_ram1_data : ALIGN(4)
{
. = ALIGN(4);
__gp_ram1_textdata__ = LOADADDR(.gp_ram1_data);
__gp_ram1_data_start__ = .;
*(.gp_ram1.data)
*(.gp_ram1.data.*)
. = ALIGN(4);
__gp_ram1_data_end__ = .;
} > GP_RAM1 AT > GP_RAM1_STORE
/*
* General purpose RAM 2, BSS.
* Variables must be explicitly set here, and must be
* correctly characterized as BSS in order to be
* zero initialized.
*/
.gp_ram1_bss (NOLOAD) : ALIGN(4)
{
. = ALIGN(4);
__gp_ram1_bss_start__ = .;
*(.gp_ram1.bss)
*(.gp_ram1.bss.*)
. = ALIGN(4);
__gp_ram1_bss_end__ = .;
} > GP_RAM1
/*
* General purpose RAM 1, noinit.
* Variables must be explicitly set here, and must be
* correctly characterized as noinit in order not to
* be initialized.
*/
.gp_ram1_noinit (NOLOAD) : ALIGN(4)
{
. = ALIGN(4);
__gp_ram1_noinit_start__ = .;
*(.gp_ram1.noinit)
*(.gp_ram1.noinit.*)
. = ALIGN(4);
__gp_ram1_noinit_end__ = .;
} > GP_RAM1
/*
* General purpose RAM 2, data.
* Variables must be explicitly set here, and must be
* correctly characterized as data in order to be
* initialized.
*/
.gp_ram2_data : ALIGN(4)
{
. = ALIGN(4);
__gp_ram2_textdata__ = LOADADDR(.gp_ram2_data);
__gp_ram2_data_start__ = .;
*(.gp_ram2.data)
*(.gp_ram2.data.*)
. = ALIGN(4);
__gp_ram2_data_end__ = .;
} > GP_RAM2 AT > GP_RAM2_STORE
/*
* General purpose RAM 2, BSS.
* Variables must be explicitly set here, and must be
* correctly characterized as BSS in order to be
* zero initialized.
*/
.gp_ram2_bss (NOLOAD) : ALIGN(4)
{
. = ALIGN(4);
__gp_ram2_bss_start__ = .;
*(.gp_ram2.bss)
*(.gp_ram2.bss.*)
. = ALIGN(4);
__gp_ram2_bss_end__ = .;
} > GP_RAM2
/*
* General purpose RAM 2, noinit.
* Variables must be explicitly set here, and must be
* correctly characterized as noinit in order not to
* be initialized.
*/
.gp_ram2_noinit (NOLOAD) : ALIGN(4)
{
. = ALIGN(4);
__gp_ram2_noinit_start__ = .;
*(.gp_ram2.noinit)
*(.gp_ram2.noinit.*)
. = ALIGN(4);
__gp_ram2_noinit_end__ = .;
} > GP_RAM2
/*
* Backup RAM.
*/
.backup_ram (NOLOAD) : ALIGN(4)
{
__backup_ram_start__ = .;
__backup_ram_size__ = 0x1000;
__backup_ram_end__ = __backup_ram_start__ + __backup_ram_size__;
} > BACKUP_RAM
}
INCLUDE aliases.ld