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
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
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).
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):
which will modify the generated linker script to contain the sections specified in the appropriate region:
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.
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.
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.
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).
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 ;
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”.
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) .
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.
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.