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 < david.sidr...@nscdg.com> έγραψε: > 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:f.j.pa...@gmail.com] > Sent: Friday, March 26, 2021 9:17 AM > To: dev@nuttx.apache.org > 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 < > hartman.nat...@gmail.com> έγραψε: > > > On Fri, Mar 26, 2021 at 11:41 AM Gregory Nutt <spudan...@gmail.com> > 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