Access peripheral SRAM

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Access peripheral SRAM

1,123 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Linas on Tue Feb 05 01:13:21 MST 2013
Hello,

My LPC1756 has 32 SRAM. 16 KB SRAM is accessible directly. Other 16 is dedicated for peripherals. Is it possible
to use this part of SRAM for ordinary data storage? How to access and allocate it in the source code?



Best,

Linas
Labels (1)
0 Kudos
Reply
3 Replies

1,006 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Linas on Fri Feb 08 07:44:42 MST 2013
Thank you for your answer.
0 Kudos
Reply

1,005 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mburton on Tue Feb 05 11:10:33 MST 2013
Hi, I replied to this hours ago but the reply appears to have got lost. Try again...

Briefly, you need to modify your loader script to define the new RAM regions and then add an attribute to the C declarations you want to reside in that region. The example loader script (attached as a .txt file, should be .ld) is for the lpc1758 which has two extra RAM regions. RAM1 and RAM2 are the memory regions defined with:

  RAM1(rwx) : ORIGIN = 0x2007C000, LENGTH = 16k
  RAM2(rwx) : ORIGIN = 0x20080000, LENGTH = 16k

The linker is told to put stuff into those regions with:

.ahb_ram0 (NOLOAD):
{
*.o (AHB_RAM0)
} >RAM1
.ahb_ram1 (NOLOAD):
{
*.o (AHB_RAM1)
} >RAM2

In the C source you need to add an attribute to the variable declaration that tells the linker where the variable is going to reside, like this:

uint8_t myVariableInExtraRam __attribute__ ((section ("AHB_RAM1")));

You need to initialise the variable in code, it won't get zeroed like normal C externals.

Cheers,

Mark

0 Kudos
Reply

1,005 Views
lpcware
NXP Employee
NXP Employee
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")
}
0 Kudos
Reply