This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to configure RTT with a fixed address in IAR

Hello. I am using RTT successfully with nrf52 and IAR. But the start address for the RTT control block is a moving target: it changes whenever my code changes. I want to assign this block a specific memory section starting at 0x20000000 in ram and placing stack and heap thereafter. Therefore, I changed the SEGGER Real-time-Terminal control block (CB) initialization in SEGGER_RTT.c like this: Instead of the definition

SEGGER_RTT_CB _SEGGER_RTT;

that placed SEGGER_RTT on the stack, I define:

#pragma section = "RTT"
#define RTT_CONTROL_BLOCK_ADDRESS ((unsigned)__section_begin("RTT"))
#define _SEGGER_RTT (*((SEGGER_RTT_CB *) RTT_CONTROL_BLOCK_ADDRESS))

In the nrf52xxx_xxaa.icf configuration file, I added the following lines:

define symbol Size_RTT = 0x1000;
define block RTT       with alignment = 8, size = Size_RTT                  { };

define block FIXED_ORDER_RAM with fixed order { block RTT, block CSTACK, block HEAP };

and changed the place in directive

place in RAM_region   { readwrite, block CSTACK, block HEAP };

like so:

place in RAM_region   { readwrite,
                        first block FIXED_ORDER_RAM };

In the debugger, RTT_CONTROL_BLOCK_ADDRESS evaluates correctly to 0x20000000, but the J-Link Viewer does not find it. What am I doing wrong?

Thx in advance!

PS: The complete icf-file including my changes:

/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x00000000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x00000000;
define symbol __ICFEDIT_region_ROM_end__   = 0x0007FFFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__   = 0x2000FFFF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x2000;
define symbol __ICFEDIT_size_heap__   = 0x2000;
/**** End of ICF editor section. ###ICF###*/

define memory mem with size = 4G;
define region ROM_region   = mem:[from __ICFEDIT_region_ROM_start__   to __ICFEDIT_region_ROM_end__];
define region RAM_region   = mem:[from __ICFEDIT_region_RAM_start__   to __ICFEDIT_region_RAM_end__];

define block CSTACK    with alignment = 8, size = __ICFEDIT_size_cstack__   { };
define block HEAP      with alignment = 8, size = __ICFEDIT_size_heap__     { };

define symbol Size_RTT = 0x1000;
define block RTT       with alignment = 8, size = Size_RTT                  { };

define block FIXED_ORDER_RAM with fixed order { block RTT, block CSTACK, block HEAP };

initialize by copy { readwrite };
do not initialize  { section .noinit };

place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
place in ROM_region   { readonly };
place in RAM_region   { readwrite,
                        first block FIXED_ORDER_RAM };
  • Just to understand: what is the problem of having the RTT Control Block moving in RAM? By design the location isn't known, so the SEGGER software will search for it.

    My first guess is that you define the RTT CB outside the heap, but the software expect the CB to be in the heap. Is 'heap' meaning the RAM that is not the stack, or is it a special region for using malloc() and free()?

  • Eirik, thx for your questions. The main reason for a fixed address is that on some PC the search from SEGGER software fails. Second, we want to put the SEGGER control block in its own RAM block, so its power can be switch off in production while we are not debugging. The SEGGER software declares _SEGGER_RTT as an automatic variable, i.e. on the stack. The heap is used for dynamic variables (malloc() and free()) and is not used by the SEGGER code. I did not change CSTACK or HEAP definitions in the icf-file. I only added an RTT block and introduced the container block FIXED_ORDER_RAM to force fixed ordering of the blocks inside the RAM region (c.f. supp.iar.com/.../). The RTT block is intended to be placed outside CSTACK and HEAP, not controlled by any stack or heap mechanism at all.

  • Stephan, does search fail because it doesn't know with what device it works? I managed to fix it by executing on PC J-Link command exec SetRTTSearchRanges 0x20000000 0x3000. Not sure it it will help you though. You may need to increase 0x3000

  • Looks like I found a solution myself: In ICF one must define the section RTT_section:

    define block RTT with alignment = 8, size = Size_RTT { section RTT_section };
    

    and the block can just be put first into RAM:

    place in RAM_region   { first block RTT, readwrite, block CSTACK, block HEAP };
    

    In SEGGER_RTT.c, the definition of _SEGGER_RTT can be rewritten with "@" directive in order to place it in the previously introduced section:

    SEGGER_RTT_CB _SEGGER_RTT @ "RTT_section";
    

    Start of RTT block is at 0x20000000 as expected and other stuff will be placed thereafter.

    Comple ICF:

    /*###ICF### Section handled by ICF editor, don't touch! ****/
    /*-Editor annotation file-*/
    /* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
    /*-Specials-*/
    define symbol __ICFEDIT_intvec_start__ = 0x00000000;
    /*-Memory Regions-*/
    define symbol __ICFEDIT_region_ROM_start__ = 0x00000000;
    define symbol __ICFEDIT_region_ROM_end__   = 0x0007FFFF;
    define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
    define symbol __ICFEDIT_region_RAM_end__   = 0x2000FFFF;
    /*-Sizes-*/
    define symbol __ICFEDIT_size_cstack__ = 0x2000;
    define symbol __ICFEDIT_size_heap__   = 0x2000;
    /**** End of ICF editor section. ###ICF###*/
    
    define memory mem with size = 4G;
    define region ROM_region   = mem:[from __ICFEDIT_region_ROM_start__   to __ICFEDIT_region_ROM_end__];
    define region RAM_region   = mem:[from __ICFEDIT_region_RAM_start__   to __ICFEDIT_region_RAM_end__];
    
    define block CSTACK    with alignment = 8, size = __ICFEDIT_size_cstack__   { };
    define block HEAP      with alignment = 8, size = __ICFEDIT_size_heap__     { };
    
    define symbol Size_RTT = 0x1000;
    define block RTT       with alignment = 8, size = Size_RTT                  { section RTT_section };
    
    initialize by copy { readwrite };
    do not initialize  { section .noinit };
    
    place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
    place in ROM_region   { readonly };
    place in RAM_region   { first block RTT,
                            readwrite,
                            block CSTACK, block HEAP };
    
  • Alex, good idea. I did not try it because I just found a solution, but it might be helpful for others ;-)

Related