LPC55S69: USB SRAM usage in ROM

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

LPC55S69: USB SRAM usage in ROM

1,748 Views
EugeneHiihtaja
Senior Contributor I

Hi !

I try to see if USB_SRAM at ox50100000 can be used for keep some data over reboot.

And it seems to me it is wiped by 0x00 by ROM code every reboot even ISP USB flashing is not used.

SRAM4 area at 0x30040000 is keep data over reboot for example.

 

Could you look in what cases USB_RAM wiped ? All the time over reboot or in some cases.

Can it be disabled some how in any setting if USB ISP flashing is  not planned to be used at all ?

My application need a lot of SRAM and USB_SRAM need as well.

USB_SRAM is not mentioned in any Linked files and regular firmware is not counted it as bss are and not zeroed it for sure.

 

Regards,

Eugene

Labels (1)
0 Kudos
Reply
1 Reply

1,654 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Eugene,

This is SDK example, as you can see the the screenshot, the USB_SRAM space is used exactly. If you want to use the USB_RAM, you can use it as the following line:

For example, you can use the code to save the array to USB_RAM

#include "cr_section_macros.h"

__NOINIT(USB_RAM) char noinit_buffer[128];

For detailed information, pls refer to the following part.

Hope it can help you

BR

XiangJun Rong

Placement of specific code/data Items

Placement of specific code/data Items

It is possible to make changes to the placement of specific code/data items within the final image without modifying the FreeMarker linker script templates. Such placement can be controlled via macros provided in an MCUXpresso IDE supplied header file which can be pulled into your project using:

#include <cr_section_macros.h> 

Alternatively Introduced in MCUXpresso IDE version 10.2, the managed linker script mechanism now also provides a means of placing arbitrarily named code or data sections into a specified memory region of the generated image and is described in the next section. (See also Global data placement).

Placing code and data into different Memory Regions

Unlike the macros provided by cr_section_macros.h (described later), this method does not require any change to the source code declaring the affected code/data (which basically rename the generated code/data sections to match the memory region name). And in many cases it can avoid the need to provide project local FreeMarker linker script templates (described later in this chapter).

To place the code or data, you simply need to add the details of the section name, the memory region to place it in, and the type of the code/data, as per the below screenshot(s):

Figure 18.30. Adding an Extra Linker Section

Adding an Extra Linker Section

which will modify the generated linker script to contain the sections specified in the appropriate region:

Figure 18.31. Extra Linker Section Script

Extra Linker Section Script

The second example graphic shows both the placement of a constant data table and also the powerful technique of specifying a project source folder and placing the entire contents of that folder (flash2’s .text sections) into a chosen flash device. Using this scheme the user can drag and drop source files within the project structure to choose which location will be used for their linkage and so their flash storage.

Figure 18.32. Adding an Extra Linker 2 Section

Adding an Extra Linker 2 Section

Note: that the format of the “input section description” is as detailed in the GNU Linker documentation, which can be found within the IDE’s built-in help system :

Help -> Help Contents -> Tools (Compilers, Debugger, Utilities) -> GNU Linker -> Linker Scripts -> SECTIONS Command -> Input Section Description

or directly in the online GNU documentation at:

https://sourceware.org/binutils/docs/ld/Input-Section-Basics.html

Also, this functionality only allows you to add sections to the linker script, not to remove something that the managed linker script already puts in. Thus if you need to remove part of the generated linker script’s contents – then you will still need to modify the underlying FreeMarker linker script templates.

Finally, remember that the GNU linker script mechanism functions such that the first match encountered for a section will win (not the best match found). Thus this mechanism is just a request, not a guarantee. Always check the generated linker script and the map file output by the link step to confirm the expected placement of sections. In some problem cases, you may be able to force the required placement by use of an EXCLUDE in one memory region, as well as the section in the required region.

Placing data into different RAM blocks using Macros

Many MCUs provide more than one bank of RAM. By default the managed linker script mechanism will place all of the application data and bss (as well as the heap and stack) into the first bank of RAM.

However it is also possible to place specific data or bss items into any of the defined banks for the target MCU, as displayed in the Memory Configuration Editor, by decorating their definitions in your source code with macros from the cr_section_macros.h MCUXpresso IDE supplied header file

For simplicity, the additional memory regions are named sequentially, starting from 2, so RAM2, RAM3 etc (as well as using their “formal” region name – for example RamAHB32).

For example, the LPC1768 has a second bank of RAM at address 0x2007c000. The managed linker script mechanism creates a data (and equivalent bss) load section for this region thus:

.data_RAM2 : ALIGN(4) 

    FILL(0xff)
    *(.data.$RAM2*)
    *(.data.$RamAHB32*) 
} > RamAHB32 AT>MFlash512

To place data into this section, you can use the __DATA macro, thus:

// create an unitialised 1k buffer in RAM2
__DATA(RAM2) char data_buffer[1024]; 

Or the __BSS macro:

// create a zero-init buffer in RAM2
__BSS(RAM2) char bss_buffer[128];

In some cases you might need a finer level of granularity than just placing a variable into a specific memory bank, and rather need to place it at a specific address. In such a case you could then edit the predefined memory layout for your particular project using the “Memory Configuration Editor” to divide up (and rename) the existing banks of RAM. This then allows you to provide a specific named block of RAM into which to place the variable that you need at a specific address, again by using the attribute macros provided by the “cr_section_macros.h” header file.

Noinit Memory Sections

Normally global variables in an application will end up in either a “.data” (initialized) or “.bss” (zero-initialized) data section within your linked application. Then when your application starts executing, the startup code will automatically copy the initial values of “.data” sections from Flash to RAM, and zero-initialize “.bss” data sections directly in RAM.

MCUXpresso IDE’s managed linker script mechanism also supports the use of “.noinit” data within your application. Such data is similar to “.bss” except that it will not get zero-initialized during startup.

Note: Great care must be taken when using “.noinit” data such that your application code makes no assumptions about the initial value of such data. This normally means that your application code will need to explicitly set up such data before using it – otherwise the initial value of such a global variable will basically be random (i.e. it will depend upon the value that happens to be in RAM when your system powers up).

One common example of using such .noinit data items is in defining the frame buffer stored in SDRAM in applications which use an onchip LCD controller (for example NXP LPC178x and LPC408x parts).

Making global variables Noinit

The linker script generated by the MCUXpresso IDE managed linker script mechanism will contain a section for each RAM memory block to contain “.noinit” items, as well as the “.data” and “.bss” items. Note: For a particular RAM memory block, all “.data” items will be placed first, followed by “.bss” items, and then “.noinit” items.

However, normally for a particular RAM memory block where you are going to be put “.noinit” items, you would actually be making all of the data placed into that RAM “.noinit”.

The “cr_section_macros.h” header file then defines macros which can be used to place global variables into the appropriate “.noinit” section. First of all include this header file:

#include <cr_section_macros.h>

The __NOINIT macro can then be used thus:

// create a 128 byte noinit buffer in RAM2
__NOINIT(RAM2) char noinit_buffer[128];

And if you want “.noinit” items placed into the default RAM bank, then you can use the __NOINIT_DEF macro thus:

// create a noinit integer variable in the main block of RAM
__NOINIT_DEF int noinit_var ;

Placing code/rodata into different FLASH Blocks

Most MCUs only have one bank of Flash memory. But with some parts more than one bank may be available – and in such cases, by default, the managed linker script mechanism will still place all of the application code and rodata (consts) into the first bank of Flash (as displayed in the Memory Configuration Editor).

For example:

  • most of the LPC18 and LPC43xx parts containing internal Flash (such as LPC1857 and LPC4357) actually provide dual banks of Flash.

  • some MCUs have the ability to access external Flash (typically SPIFI) as well as their built-in internal Flash (e.g. LPC18xx, LPC40xx, LPC43xx, LPC546xx).

However it is also possible to place specific functions or rodata items into the second (or even third) bank of Flash. This placement is controlled via macros provided in the "cr_section_macros.h" header file.

For simplicity, the additional Flash region can be referenced as Flash2 (as well as using its “formal” region name – for example MFlashB512 – which will vary depending upon part).

First of all include this header file:

#include <cr_section_macros.h>

Then, for example, to place a rodata item into this section, you can use the __RODATA macro, thus:

__RODATA(Flash2) const int roarray[] = {10,20,30,40,50};

Or to place a function into it you can use __TEXT macro:

__TEXT(Flash2) void systick_delay(uint32_t delayTicks) { 
 :

In addition, the __RODATA_EXT and __TEXT_EXT macros can be used to place functions/rodata into a more specifically named section, for example:

__TEXT_EXT(Flash2,systick_delay) void systick_delay(uint32_t delayTicks) { 
 :

will be placed into the section “.text.$Flash2.systick_delay” rather than “.text.$Flash2”.

Placing specific functions into RAM Blocks

In most modern MCUs with built-in Flash memory, code is normally executed directly from Flash memory. Various techniques, such as prefetch buffering are used to ensure that code will execute with minimal or zero wait states, even a higher clock frequencies. Please see the documentation for the MCU that you are using for more details.

However it is also possible to place specific functions into any of the defined banks of RAM for the target MCU, as displayed in:

Project -> Properties -> C/C++ Build -> MCU settings

and sometimes there can be advantages in relocating small, time critical functions so that they run out of RAM instead of Flash.

For simplicity, the additional memory regions are named sequentially, starting from 2, (as well as using their “formal” region name – for example RamAHB32). So for a device with 3 RAM regions, alias names RAM, RAM2 and RAM3 will be available.

This placement is controlled via macros provided in a header file which can be pulled into your project using:

#include <cr_section_macros.h>

The macro __RAMFUNC can be used to locate a function into a specific RAM region.

For example, to place a function into the main RAM region, use:

__RAMFUNC(RAM) void fooRAM(void) {...

To place a function into the RAM2 region, use:

__RAMFUNC(RAM2) void fooRAM2(void) {...

Alternatively, RAM can be selected by formal name (as listed in the memory configuration editor), for example:

__RAMFUNC(RamAHB32) void HandlerRAM(void) {...

In order to initialize RAM based code (and data) into specified RAM banks, the managed linker script mechanism will create a “Global Section Table” in your image, directly after the vector table. This contains the addresses and lengths of each of the data (and bss) sections, so that the startup code can then perform the necessary initialization (copy code/data from Flash to RAM) .

Long branch veneers and Debugging

Due to the distance in the memory map between Flash memory and RAM, you will typically require a “long branch veneer” between the function in RAM and the calling function in Flash. The linker can automatically generate such a veneer for direct function calls, or you can effectively generate your own by using a call via a function pointer.

One point to note is that debugging code with a linker generated veneer can sometimes cause problems. This veneer will not have any source level debug information associated with it, so that if you try to step in to a call to your code in RAM, typically the debugger will step over it instead.

You can work around this by single stepping at the instruction level, setting a breakpoint in your RAM code, or by changing the function call from a direct one to a call via a function pointer.

Reducing Code Size when support for LPC CRP or Kinetis Flash Config Block is Enabled

One of the consequences of the way that LPC CRP and Kinetis Flash Configuration Blocks work is that the memory between the CPU’s vector table and the CRP word/ Flash Config Block is often left largely unused. This can typically increases the size of the application image by several hundred bytes (depending upon the MCU being used).

However this unused space can easily be reclaimed by choosing one or more functions to be placed into this unused memory. To do this, you simply need to decorate their definitions with the macro __AFTER_VECTORS which is supplied in the “cr_section_macros.h” header file

Obviously in order to do this effectively, you need to identify functions which will occupy as much of this unused memory as possible. The best way to do this is to look at the linker map file.

MCUXpresso IDE startup code already uses this macro to place the various initialization functions and default exception handlers that it contains into this space, thus reducing the ‘default’ unused space. But you can also place additional functions there by decorating their definitions with the macro, for example

__AFTER_VECTORS void myStartupFunction(void);

Note: you will get a link error if the __AFTER_VECTORS space grows beyond the CRP/Flash Configuration Block (when this support is enabled):

myproj_Debug.ld:98 cannot move location counter backwards (from 00000334 
to 000002fc)
collect2: ld returned 1 exit status
make: *** [myproj.axf] Error 1

In this case, you will need to remove the __AFTER_VECTORS macro from the definition of one or more of your functions.

pastedImage_1.png

0 Kudos
Reply