cancel
Showing results for 
Search instead for 
Did you mean: 

Adding an uninitialized data section to a GCC build?

infoinfo989
Associate III
Posted on December 22, 2011 at 07:18

Perhaps the subject line is a bit cryptic, but does anybody know how to add uninitialized data sections to the linker script? The F4xx has two RAM banks. I want to use the smaller 64 kB as the normal RAM area (.bss etc) and the larger 128 kB RAM as an area for large data buffers, which would be declared using the __attribute__ in the C code. Here's what I've done...

In the linker script:

MEMORY
{
RAM_C (xrw) : ORIGIN = 0x10000000, LENGTH = 64K
RAM_D (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K
}

and also

/* This is the 128 kB RAM, used for data buffers that require DMA access. This RAM is not used by default - 
 the programmer
must explicitly specify using this RAM by something like: 
 uint8_t mybuffer[1024] __attribute__((section(''.buffram''))); 
Also, the programmer should NOT assume this RAM will be initialised at boot. */
.buffram:
{
. = ALIGN(4);
*(.buffram) /* .buffram section */
. = ALIGN(4);
} >RAM_D

Then in my C code I do (for example): volatile uint8_t buff0[16384] __attribute__((section(''.buffram''))); It's all great, everything compiles and links OK, no problems in that regards. BUT... The output hex file is huge. Because it contains a 64 kB section of .buffram section, all zeros. Put another way, it's kinda like it's treating this new data section as flash, in that it's putting it into the output hex file. I've been googling and reading LD documentation like crazy, but I'm missing some magic trick here. How do I keep this data section out of my hex file? Thanks. #problem-solved #corrupted-parameters #i-hate-this-word(tm)-editor #ccm
15 REPLIES 15
rosarium
Associate II
Posted on December 22, 2011 at 08:52

you have to also take care of the total stack size usage in the linker file(STM32f2xx_flash.icf)

define symbol __ICFEDIT_size_cstack__ = 0x14000; (chnge ths value as per ur reqmt)

define symbol __ICFEDIT_size_heap__   = 0x2600;

infoinfo989
Associate III
Posted on December 22, 2011 at 17:28

Yes, thanks, I've already done that. But my question is: how can I prevent this new data section from appearing in the output file?

Posted on December 22, 2011 at 18:29

.buffram (NOLOAD) :
{
. = ALIGN(4);
*(.buffram) /* .buffram section */
. = ALIGN(4);
} >RAM_D

or

/* collect all uninitialized .bss2 sections */
.bss2 (NOLOAD) : AT (0x10000000) {
. = ALIGN(4);
_sbss2 = .;
*(.bss2)
_ebss2 = .;
}

The NOLOAD bit is typically the one to use in ELF files to indicate there is no data or hex behind it.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
infoinfo989
Associate III
Posted on December 23, 2011 at 03:24

Thanks very much Clive - that seems to have fixed it.

Funnily enough I had been trying the NOLOAD previously, but as I discovered from looking at your post, the linker file is sensitive to spaces. I was missing a space in my file, which caused it to misbehave. It's working now.

pawel_popiolek
Associate II
Posted on February 14, 2012 at 09:26

Could You attach whole stm32_flash.ld file for atollic, because I can't do this well. Most my changes in standard .ld file ending with error. I need use the 64kB memory and (in future external NAND RAM).

I was trying to use ld file from DMA_FLASH_RAM (from stm32f4 discovery), but malloc function can't reserve more memory.

Posted on February 14, 2012 at 15:53

Could You attach whole stm32_flash.ld file for atollic, because I can't do this well. Most my changes in standard .ld file ending with error. I need use the 64kB memory and (in future external NAND RAM).

I was trying to use ld file from DMA_FLASH_RAM (from stm32f4 discovery), but malloc function can't reserve more memory.

You have a couple of problems here. I don't believe anyone in this thread is using Atollic. The thread has been dealing with the placement of static allocations in the memory map. The TrueSTUDIO\DMA_FLASH_RAM\stm32_flash.ld script doesn't describe the memory regions correctly. Unless I'm mistaken the 192KB is not a linear allocation, as there is only 128K at 0x20000000, the remaining 64KB is at 0x10000000. They also parked the stack at the end of the 128KB region. While I could probably fix the script, it won't fix problems intrinsic with using malloc/free in an embedded system, both in terms of fragmentation, allocation sizes, and the fact it will need to track two blocks of RAM, which is outside the scope of the linker script. For that you will need to review the dynamic allocation routines/library. A directed static allocation would look like this : volatile uint8_t buff0[16384] __attribute__((section(''.ccm''))); The script like this should work, by I don't have Atollic, so it's untested

/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x20020000; /* end of 128K RAM on AHB bus*/
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
RAM_CCM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K
MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
/* The program code and other data goes into FLASH */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >FLASH
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(.fini_array*))
KEEP (*(SORT(.fini_array.*)))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH
/* used by the startup to initialize data */
_sidata = .;
/* Initialized data sections goes into RAM, load LMA copy after code */
.data : AT ( _sidata )
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM
/* Uninitialized data section */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(4);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(4);
} >RAM
/* MEMORY_bank1 section, code must be located here explicitly */
/* Example: extern int foo(void) __attribute__ ((section (''.mb1text''))); */
.memory_b1_text :
{
*(.mb1text) /* .mb1text sections (code) */
*(.mb1text*) /* .mb1text* sections (code) */
*(.mb1rodata) /* read-only data (constants) */
*(.mb1rodata*)
} >MEMORY_B1
/* collect all uninitialized .ccm sections */
.ccm (NOLOAD) :
{
. = ALIGN(4);
_sccm = .;
__ccm_start__ = _sccm;
*(.ccm)
. = ALIGN(4);
_eccm = .;
__ccm_end__ = _eccm;
} >RAM_CCM
/* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
pawel_popiolek
Associate II
Posted on February 15, 2012 at 09:23

Thank You

It works fine, maybe I can't use malloc function, but memcpy works (but I don't know about reserving memory by this function, so it can be dangerous). I think that, I will use this memory using tables - it should be OK.

pawel_popiolek
Associate II
Posted on February 15, 2012 at 09:23

Could moderator delete this post? It's result of my bad in opera browser.

guoruipang
Associate II
Posted on June 13, 2014 at 08:45

Dear clive1 ,

i want to use the ccm (stm32f407) at the keil uVision , but i did't find the way how to write the scatter file ? could you give me a way how to use the ccm in the keil ? 

thank you .