Content originally posted in LPCWare by mburton on Tue Feb 05 04:52:25 MST 2013
Hi Linas,
Yes, you can use that RAM for ordinary data storage. You need to do two things:
1 - modify the linker script so that it know about the new ram region.
Below is what I am currently using for a linker script. This is for a LPC1758 which has 2 extra RAM regions. Don't use the whole script just the parts that specify the ram regions. So, from the MEMORY section at the top
you need one of those lines (whichever is right for your chip, see datasheet), e.g.
RAM2(rwx) : ORIGIN = 0x20080000, LENGTH = 16k
Lower down in the script is a section that says put all stuff in .o files that are destined for section AHB_RAM1 into the region RAM2.
.ahb_ram1 (NOLOAD):
{
*.o (AHB_RAM1)
} >RAM2
2 - add an attribute that specifies the section the variable resides in to the C variable declaration(s) that you want to go in that region, e.g.:
uint8_t some_data __attribute__ ((section ("AHB_RAM1")));
That's all you have to do. Remember that these variables will not get zeroed like normal C variables do. Also, I don't think they can be initialised in the declaration, you have to initialise them in the code when it runs.
I hope this is useful.
Cheers,
Mark
-----------
/* Linker script to configure memory regions. */
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 512K
RAM (rwx) : ORIGIN = 0x10000000, LENGTH = 32K
RAM1(rwx) : ORIGIN = 0x2007C000, LENGTH = 16k
RAM2(rwx) : ORIGIN = 0x20080000, LENGTH = 16k
}
/* Library configurations */
GROUP(libgcc.a libc.a libm.a libnosys.a)
/* Linker script to place sections and symbol values. Should be used together
* with other linker script that defines memory regions FLASH and RAM.
* It references following symbols, which must be defined in code:
* Reset_Handler : Entry of reset handler
*
* It defines following symbols, which code can use without definition:
* __exidx_start
* __exidx_end
* __etext
* __data_start__
* __preinit_array_start
* __preinit_array_end
* __init_array_start
* __init_array_end
* __fini_array_start
* __fini_array_end
* __data_end__
* __bss_start__
* __bss_end__
* __end__
* end
* __HeapLimit
* __StackLimit
* __StackTop
* __stack
*/
ENTRY(__stext)
SECTIONS
{
.text :
{
__stext = .;
KEEP(*(.isr_vector))
*(.text*)
KEEP(*(.init))
KEEP(*(.fini))
/* .ctors */
*crtbegin.o(.ctors)
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
*(SORT(.ctors.*))
*(.ctors)
/* .dtors */
*crtbegin.o(.dtors)
*crtbegin?.o(.dtors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
*(SORT(.dtors.*))
*(.dtors)
*(.rodata*)
KEEP(*(.eh_frame*))
} > FLASH
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > FLASH
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > FLASH
__exidx_end = .;
__etext = .;
.data : AT (__etext)
{
__data_start__ = .;
*(vtable)
*(.data*)
. = ALIGN(4);
/* preinit data */
PROVIDE (__preinit_array_start = .);
*(.preinit_array)
PROVIDE (__preinit_array_end = .);
. = ALIGN(4);
/* init data */
PROVIDE (__init_array_start = .);
*(SORT(.init_array.*))
*(.init_array)
PROVIDE (__init_array_end = .);
. = ALIGN(4);
/* finit data */
PROVIDE (__fini_array_start = .);
*(SORT(.fini_array.*))
*(.fini_array)
PROVIDE (__fini_array_end = .);
. = ALIGN(4);
/* All data end */
__data_end__ = .;
} > RAM
.bss :
{
__bss_start__ = .;
*(.bss*)
*(COMMON)
__bss_end__ = .;
} > RAM
.ahb_ram0 (NOLOAD):
{
*.o (AHB_RAM0)
} >RAM1
.ahb_ram1 (NOLOAD):
{
*.o (AHB_RAM1)
} >RAM2
.heap :
{
__end__ = .;
end = __end__;
*(.heap*)
__HeapLimit = .;
} > RAM
/* .stack_dummy section doesn't contains any symbols. It is only
* used for linker to calculate size of stack sections, and assign
* values to stack symbols later */
.stack_dummy :
{
*(.stack)
} > RAM
/* Set stack top to end of RAM, and stack limit move down by
* size of stack_dummy section */
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
PROVIDE(__stack = __StackTop);
/* Check if data + heap + stack exceeds RAM limit */
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
}