**** Advance Notice ****

This site will be closed on 31 December 2015,

Important Information for users of NXP LPCXpresso

This site is for users of Code Red branded products.

NXP LPCXpresso users should visit the LPCXpresso FAQ's for up-to-date information relevant to that product.

Differences between revisions 23 and 24
Deletions are marked like this. Additions are marked like this.
Line 114: Line 114:

Enhanced Managed Linker Scripts

Red Suite 3.6 / LPCXpresso 3.6 (Windows) and LPCXpresso 3.8 (Linux) introduced a number of major enhancements to the managed linker script mechanism, plus associated areas such as the New Project wizard, startup code and the default main.c file.

These enhancements were designed to reduce the number of circumstances where it is necessary to turn off the managed linker script mechanism and take direct control of the linker script used to build your project (as described in the FAQ Using your own linker scripts).

Multiple memory regions

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

The enhanced mechanism now supports placement into any of the defined banks for the target MCU, as displayed in

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


By default, data and bss items will be placed into the first bank of RAM listed. But you can control the placements of specific items into other banks as required. This placement is controlled via macros provided in a new header file which can be pulled into your project using #include <cr_section_macros.h> .

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 linker creates a new data (and equivalent bss) load section:

        .data_RAM2 : ALIGN(4)
        } > RamAHB32 AT>MFlash512

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

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

Or the __BSS macro:

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

Of course, if you do not place any data into these additional areas, then the linker does not create anything in those areas.

In order to initialize additional 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 initialize them.

The startup code has thus been updated, in order to carry out this initialization of multiple regions. It will now enter a loop reading this global section table, calling a subroutine to carry out the initialization of each region it finds in the Global Section Table.

'Noinit' Memory Sections

Code Red IDE v5.0.14 introduced support for placing data into sections which do not get initialized by the startup code. For more details, please see the FAQ

Reserved Memory Regions

Some NXP parts have drivers built into the ROM - for example, the CAN driver for certain LPC11 parts, and the USB driver for certain LPC13 parts. These drivers need some internal memory that is *always* at the start of the first RAM block. This is not configurable, so if the driver is used, then the application must not use that RAM. The linker creates a section that is placed first in the RAM. Note that it is not initialized in any way:

        .uninit_RESERVED : ALIGN(4)
        } > RamLoc32

To reserve this space, you would simply use a macro from "cr_section_macros.h" to define a buffer in that space:

__BSS(RESERVED) char CAN_driver_memory[256] ; // reserve 256 bytes for CAN driver

Note that the NXP IAP flash programming routines typically require memory to be reserved at the top of the first bank of on-chip RAM. For details of how to reserve this memory, see the FAQ Reserving RAM for IAP Flash Programming.

Code Read Protect

There is a new checkbox on the linker Target tab "Enable CRP" which is only visible for MCU families that support CRP (LPC2000, LPC1000). This will create the following in the text section of the linker script:

                . = 0x000002FC ; /* or 1FC for LPC2000 */

To use this, you need to #include <NXP/crp.h> which provides a macro which can be used to define the CRP, for example:

__CRP unsigned int CRP_WORD = CRP_NO_ISP ;

The CRP word is then placed at the correct location in Flash by the linker script.

The New Project wizard has also been enhanced so that CRP support can be enabled when you create a new project. This is enabled by default.

Note - before making use of CRP, you are strongly advised to read NXP's documentation on this functionality. You should take particular care as some CRP settings can disable some or all means of access to your MCU (including debug).

After Vectors

One consequence of using CRP is that the space between the end of the ISR vectors and the CRP is left unused. This means that typically an application built with CRP enabled will be larger than one built with CRP disabled.

In order to reduce this unused space before the CRP word, "cr_section_macros.h" defines the macro __AFTER_VECTORS. This macro can be used on a function definition to cause the linker to place the function immediately after the vectors (and thus before the CRP).

The default Code Red startup code 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. 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 (when CRP 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.


The default main.c created by the Quickstart Panel's new project wizard will contain "cr_section_macros.h" and (where appropriate) "NXP/crp.h" includes. You can view the contents of these includes by loading main.c into the editor, highlighting the include filename and pressing F3.

For appropriate MCUs, main.c will also define a CRP variable. When CRP support in the tools is enabled, this word will be placed appropriately by the linker script (as described above). When CRP support is not enabled, the linker will remove this variable in your image.

Linker script template

With the enhanced managed linker script mechanism, the Code Red IDE makes use of a template linker script which is then used together with the chosen MCU and other project settings (such as "Enable CRP") in order to create the managed linker script that is autogenerated into the Debug/Release subdirectory of your project.

However it is also possible to tweak this template for project specific requirements. One simple example of this might be to place the heap and stack in the RamAHB32 region (at 0x2007c000) for an LPC1768 project. To do this:

  1. Right click on your project in the Project Explorer view, and select New -> Folder to create a subdirectory within the project structure. This subdirectory must be called "linkscripts".

  2. Outside of the Code Red IDE, open up a file browser and navigate to <codered_ide_installdir>\Wizards\linker. Now copy the file link_template.ld from that subdirectory and paste it into the linkscripts subdirectory of your project.

  3. Open the project copy of link_template.ld up within the Code Red IDE and change the two lines towards the bottom of the file from:

        PROVIDE(${heap_symbol} = .);
        PROVIDE(_vStackTop = __top_${DATA} - ${STACK_OFFSET});
  • to:

        PROVIDE(${heap_symbol} = ADDR(.data_RAM2));
        PROVIDE(_vStackTop = __top_RamAHB32 - ${STACK_OFFSET});

If you now clean, then build your project, your modified template will be used rather than the default one to create the managed linker script file in the Debug/Release directory, and your application will use RamAHB32 for placing the heap and stack in.


Building old projects with new tools

If you have a managed linker script project created using an earlier version of the Code Red IDE, then you should be able to continue to build successfully with 3.6/3.8. But if you start to make use of some of the managed linker script related enhancements, then you will need to replace your original startup code file with the corresponding one created using the 3.6/3.8 new project wizard. [Note that if you no longer need to build your project with the older tools version, we would recommend replacing the startup code anyway.]

Building new projects with older tools

Projects created with 3.6/3.8 are not backwards compatible with earlier versions of the Code Red IDE. This is because the new startup code makes assumptions about the managed linker script that is used, which will not be true with earlier versions of the Code Red IDE.

However the new startup code does have the ability to be conditionally built in such a way that is compatible with the managed linker script generated by earlier tools versions. To use this, set the define "USE_OLD_STYLE_DATA_BSS_INIT" in the compiler (for CM0/CM3 based parts) or assembler (for ARM7/ARM9 based parts).

Note that new projects that make use of the enhancements introduced in 3.6/3.8 (such as multiple memory sections and CRP support) are not compatible with earlier tools versions, even with "USE_OLD_STYLE_DATA_BSS_INIT" define set. This define simply changes the assumptions of the startup code with regards to memory layout and available linker symbols.

EnhancedManagedLinkScripts (last edited 2013-04-19 13:08:09 by DerekMorris)