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

Reply via email to