0

Hi,

Due to the nature of the internal RAM of the RZ/A1H I would like to map portions of the code and data into particular pages of internal RAM. Previous Renesas tool chains had #pragma extensions for this purpose application notes on ROM to RAM section mapping were supplied. Does the GNUARM-NONE-EABI tool chain support this? If so is there any documentation or an application note to demonstrate this?

Best regards,

GNU Tools Support コメントが編集されました
Thank you for choosing the GNUARM-NONE-EABI toolchain.
Yes, the GNUARM-NONE-EABI toolchain allows the user to map portions of the code and data into particular pages of internal memory.
The documentation which describe how to write your linker script can be found in the toolchain installation folder > Documentation > GNU Manuals > Using ld > 3. Linker Scripts.
If you don’t like the default implementation, you can write your own linker script as shown in the 3.3 sub-chapter: Simple Linker Script Example.

Another solution for mapping portions of code in particular memory regions is provided by the __attribute__ ((section (“section-name”))) keyword.
You will find the documentation for this attribute in your toolchain installation folder > Documentation > GNU Manuals > Using gcc > 6.30 Declaring Attributes of Functions > section (“section-name”).
By default, all of your written code goes the .text section, but E2studio allows you to create your own sections in the memory regions of your choosing.
You can see the memory sections used by your project by right-clicking it > Renesas Tool Settings -> Linker -> Sections.
There, at the Section tab, you can add more sections by clicking the third button (Add section) below the Section Viewer label.
By clicking it, a new section (named section1) is automatically created and then you can set its details in the right panel: name, starting address, etc.
Then, by using the attribute __attribute__ ((section (“section-name”))) keyword for any declared variable or function, it will map that variable/function in your ‘section1’ defined section.
If you have any more questions, or you require any help with the script, please let us know.

Best regards,
Darius,
The GNU Tools Support Team

• Hi Darius,

Thanks, I’ll am really struggling with the linker script! The question is about section mapping, I don’t know that the question was particularly clear.

So the linker creates an executable image which is linked to the address 0x1800 0000. Within that image I’d like sections of code and data to be placed at 0x6000 0000 and 0x4800 000.

The code at 0x1800 0000 will initialise the SDRAM, SRAM, L1 Cache, L2 Cache and TLB then copy sections of code and initialised data to the respective destinations.

The question is how do I tell the linker that the functions in a particular section (which it has assigned an address within the 0x18XX XXXX range) are “mapped” to addresses 0x6XXX XXXX and 0x48XX XXX?

Can you make a simple project with a linker script that demonstrates this?

Best regards,

Please let us know if we have answered your question in full or if you need any further assistance from us.

If we do not receive any feedback within 24 hours, this thread will be closed, but may be re-opened later on if needed.

Thank you,
The GNU Tools Support Team

• Hi,

Please keep this open as it is still full un-answered & time is required to put a sample project together.

Best regards,

Just checking in to see if you still need us to keep this open, or if you had submitted the project already in a private support request?

Thank you,
The GNU Tools Support Team

• Hi,

The project posted was a static library to demonstrate a bug in the compiler. This project does not use the linker & as such would not involve section mapping.

I’ll post another project for demonstration of section mapping.

I’ll also post a separate project to demonstrate all the bugs in the tool integration.

I’m quite busy so please be patient.

Cheers,

• Hi,

I am still struggling with section mapping in the linker. My linker script looks like this:

/***********************************************************************************
* File: HardwareDebug.ld
* Date: 19/04/2016
*
* $Workfile:$
* $Revision:$
* $Project:$ Swarm Systems Hawk
* $Compiler:$ GNUARM-NONEV16.01-EABI
* $Target:$ RZ/A1H
* $State:$ Stab

* (‘Exp’erimental/’Stab’le/’Rel’eased)
* $Date$
*
* Description : Linker script file for RZA1/H RSK HardwareDebug build
*
*
* A: 1 The Mount, Old Blandford Road, Salisbury, Wiltshire. SP2 8BZ
* T: 01722 341 027
* W: http://www.ardware.co.uk
*
**********************************************************************************/

/**********************************************************************************
Set the output format
***********************************************************************************/

OUTPUT_FORMAT(“elf32-littlearm”, “elf32-bigarm”, “elf32-littlearm”)
OUTPUT_ARCH(arm)
ENTRY(start)

/**********************************************************************************
Define the memory available on the RSK
***********************************************************************************/
MEMORY
{
/* On-Chip Data retention RAM >>> DISABLED AT RESET <<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ROM IMAGE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< SRAM

/******************************************************************************
System initialisation
******************************************************************************/

.system_init :
{
/* We need the code that initialises the system up until
the point that the section initialisation has taken place
to reside in one section which is not mapped to another
place. This section has all the code & data to do this */
*reset_handler.o (.text) . = ALIGN(0x04);
*peripheral_init_basic.o (.text) . = ALIGN(0x04);
*rza_io_regrw.o (.text) . = ALIGN(0x04);
/* Put the code from the initsect function here */
*initsect.o (.text) . = ALIGN(0x04);
/* Also put the initialised data section here */
*initsect.o (.init_data) . = ALIGN(0x04);
} > SRAM

/******************************************************************************
Executable code & read only data
******************************************************************************/

.code :
{
gExecutableCodeRomStart = .;
gExecutableCodeRamStart = .;
PROVIDE_HIDDEN (__exidx_start = .);
*(.init)
PROVIDE_HIDDEN (__exidx_end = .);
*(.text)
*(.fini)
*(.jcr)
__CTOR_LIST__ = .;
. = ALIGN(2);
__ctors = .;
*(.ctors)
__ctors_end = .;
__CTOR_END__ = .;
__DTOR_LIST__ = .;
___dtors = .;
*(.dtors)
___dtors_end = .;
__DTOR_END__ = .;
. = ALIGN(2);
_mdata = .;
_srodata = .;
*(.rodata)*(.rodata.*) . = ALIGN(0x04);
_erodata = .;
gExecutableCodeRomEnd = .;
} > SRAM

/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> RAM IMAGE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<SRAM
/* TODO: Move */
.bss :
{
gUnintialisedDataRamStart = .;
*(.bss)
*(.bss.**)
*(COMMON)
gUnintialisedDataRamEnd = .;
} > SRAM

/******************************************************************************
Heaps
******************************************************************************/

{
/* The L1 cache line size is 32 bytes. To avoid cache synchronisation
problems the malloc functions will align allocations to 32 byte boundaries.
However in order for the scheme to work the area assigned to the heap
must be aligned to a 32byte boundary as well */
gSRamHeapStart = ALIGN(0x20);
} > SRAM

{
gSRamHeapEnd = .;
} > SRAM_END

{
/* The L2 cache line size is 32 bytes. To avoid cache synchronisation
problems the malloc functions will align allocations to 32 byte boundaries.
However in order for the scheme to work the area assigned to the heap
must be aligned to a 32byte boundary as well */
gSDRamHeapStart = .;
} > SDRAM

{
gSDRamHeapEnd = ALIGN(0x20);
} > SDRAM_END

/******************************************************************************
Stacks & TLB
******************************************************************************/

/* The application does not require the data retention function.
The area is not usable until the processor is running the application
code as it is disabled on reset. Assign the stacks & TLB to this memory
which would otherwise be unused. Ensure System control register 3 SYSCR3
is initialised before stack pointers are loaded */
{
irq_stack_start = .;
. += 8k;
. = ALIGN(0x08);
irq_stack_end = .;
} >RRAM
{
fiq_stack_start = .;
. += 4k;
. = ALIGN(0x08);
fiq_stack_end = .;
} >RRAM
{
PROVIDE(svc_stack_start = .);
. += 8k;
. = ALIGN(0x08);
svc_stack_end = .;
} >RRAM
{
abt_stack_start = .;
. += 4k;
. = ALIGN(0x08);
abt_stack_end = .;
} >RRAM
{
program_stack_start = .;
. += 8k;
. = ALIGN(0x08);
program_stack_end = .;
} >RRAM
.ttb_mmu1 :
{
ttb_mmu1_base = .;
. += 32k;
. = ALIGN(0x04);
ttb_mmu1_end = .;
} >RRAM
}

/**********************************************************************************
EOF
***********************************************************************************/

The section initialisation code looks like this:

/***********************************************************************************
* File: initsect.c
* Date: 20/07/2016
*
* $Workfile:$
* $Revision:$
* $Project:$ Swarm Systems Hawk
* $Compiler:$ GNUARM-NONEV16.01-EABI
* $Target:$ RZ/A1H
* $State:$ Stab

* (‘Exp’erimental/’Stab’le/’Rel’eased)
* $Date$
*
* Description : Section initialisation function
*
*
* A: 1 The Mount, Old Blandford Road, Salisbury, Wiltshire. SP2 8BZ
* T: 01722 341 027
* W: http://www.ardware.co.uk
*
**********************************************************************************/

/***********************************************************************************
External symbols defined in the linker script
***********************************************************************************/

extern char gInitialisedDataRomStart;
extern char gInitialisedDataRomEnd;
extern char gInitialisedDataRamStart;

extern char gExecutableCodeRomStart;
extern char gExecutableCodeRomEnd;
extern char gExecutableCodeRamStart;

extern char gUnintialisedDataRamStart;
extern char gUnintialisedDataRamEnd;

/***********************************************************************************
Constant data
***********************************************************************************/

/* ROM to RAM mapped section table for C/C++ run time library initialisation */
static const struct _DSEC
{
/* Start address of the initialised data section in ROM */
void *pvRomStart;
/* End address of the initialised data section in ROM */
void *pvRomEnd;
/* Start address of the initialised data section in RAM */
void *pvRamStart;
} gpCopyTable[] __attribute__((section(“.init_data”))) =
{
/* The initialised data section copied to RAM */
{
&gInitialisedDataRomStart,
&gInitialisedDataRomEnd,
&gInitialisedDataRamStart
},
/* The code section copied to RAM */
{
&gExecutableCodeRomStart,
&gExecutableCodeRomEnd,
&gExecutableCodeRamStart
},
/* TODO: Add all initialised sections here */

};
/* The non-initialised data section table for C run time library
initialisation */
static const struct _BSEC
{
/* Start address of non-initialised data section */
void *pvRamStart;
/* End address of non-initialised data section */
void *pvRamEnd;
} gpZeroTable[] __attribute__((section(“.init_data”))) =
{
{
&gUnintialisedDataRamStart,
&gUnintialisedDataRamEnd
},
/* TODO: Add all other sections here */
};

/***********************************************************************************
Public Functions
***********************************************************************************/

/***********************************************************************************
* Function Name: initsect
* Description : Function to perform section initialisation
* Arguments : none
* Return Value : none
***********************************************************************************/
void initsect(void)
{
register unsigned int uiCount;
{
register struct _DSEC *pCopyTable = (struct _DSEC*)gpCopyTable;
/* Calculate the number of entries in the mapped Data Table */
uiCount = sizeof(gpCopyTable) / sizeof(struct _DSEC);
while (uiCount–)
{
/* Allow a RAM based build (HardwareDebug) to link the initialised
data so that no copying is required – with the caveat that the
code will only be run once before being down loaded to RAM again.
Therefore check that the ROM and RAM are not the same before
performing the copy */
if (pCopyTable->pvRomStart != pCopyTable->pvRamStart)
{
register char *pbyDestination = (char*)pCopyTable->pvRamStart;
register char *pbySource = (char*)pCopyTable->pvRomStart;
register unsigned int uiLength
= (unsigned int)(pCopyTable->pvRomEnd – pCopyTable->pvRomStart);
/* Copy the section */
while (uiLength–)
{
*pbyDestination++ = *pbySource++;
}
}
pCopyTable++;
}
}
{
register struct _BSEC *pZeroTable = (struct _BSEC*)gpZeroTable;
/* Calculate the number of entries in the Non-initialised Data Table */
uiCount = sizeof(gpZeroTable) / sizeof(struct _BSEC);
while (uiCount–)
{
register char *pbyDestination = pZeroTable->pvRamStart;
register unsigned int uiLength
= (unsigned int)(pZeroTable->pvRamEnd – pZeroTable->pvRamStart);
/* Initialise the section to 0 */
while (uiLength–)
{
*pbyDestination++ = (char)0;
}
pZeroTable++;
}
}
}
/***********************************************************************************
End of function initsect
***********************************************************************************/

/***********************************************************************************
End Of File
***********************************************************************************/

However I cannot figure out the syntax to map the sections .code and .data into the memory area SDRAM.

I have tried things like:

{
gExecutableCodeRomStart = .;
gExecutableCodeRamStart = .;
PROVIDE_HIDDEN (__exidx_start = .);
*(.init)
PROVIDE_HIDDEN (__exidx_end = .);
*(.text)
*(.fini)
*(.jcr)
__CTOR_LIST__ = .;
. = ALIGN(2);
__ctors = .;
*(.ctors)
__ctors_end = .;
__CTOR_END__ = .;
__DTOR_LIST__ = .;
___dtors = .;
*(.dtors)
___dtors_end = .;
__DTOR_END__ = .;
. = ALIGN(2);
_mdata = .;
_srodata = .;
*(.rodata)*(.rodata.*) . = ALIGN(0x04);
_erodata = .;
gExecutableCodeRomEnd = .;
} > SRAM

{
gExecutableCodeRamStart .= ALIGN(0x04);
SIZEOF(.code)
} > SDRAM

but ld just barfs on the syntax.

Can you show me how to modify the script to achieve this?

Cheers,

• Hi,

It appears that the symbols in the linker script are interpreted as formatting commands in this box. The question above, in plain text, can be found here:

Cheers,

Thank you for providing this information.

If you want your .code and .data section to be loaded from SDRAM, simply add AT > SDRAM after the > SRAM instruction from the section’s end.

e.g:
code :
{

} > SRAM AT > SDRAM
That will ensure that the section will be loaded at start of the SDRAM memory even though its relocation address is SRAM.

A more detailed description of a linker script section can be found at: https://sourceware.org/binutils/docs/ld/Output-Section-Description.html#Output-Section-Description

Kind regards,
Darius,
The GNU Tools Support Team

• Hi,

Thank you for your continued support. In this case I am trying to map .code which is loaded into SRAM to SDRAM. So I need the following addresses from the linker:

gExecutableCodeRamStart = The start address the linker has located the code to run at in SDRAM

Best regards,

If you want to load the .code section into SRAM, then copy it to SDRAM, and you will have access to the begin\end addresses of this region. I suggest to modify your .code section from your linker script as follows:

.code :
{
gExecutableCodeRamStart = .;
PROVIDE_HIDDEN (__exidx_start = .);
*(.init)
PROVIDE_HIDDEN (__exidx_end = .);
*(.text)
*(.fini)
*(.jcr)
__CTOR_LIST__ = .;
. = ALIGN(2);
__ctors = .;
*(.ctors)
__ctors_end = .;
__CTOR_END__ = .;
__DTOR_LIST__ = .;
___dtors = .;
*(.dtors)
___dtors_end = .;
__DTOR_END__ = .;
. = ALIGN(2);
_mdata = .;
_srodata = .;
*(.rodata)*(.rodata.*) . = ALIGN(0x04);
_erodata = .;
gExecutableCodeRamEnd = .;
} > SDRAM AT > SRAM

The assignments:

gExecutableCodeRamStart = .;
gExecutableCodeRamEnd = .;

mean the following:

* gExecutableCodeRamStart will have, when the program is running, the start address value of the .code section
* gExecutableCodeRamEnd will have,when the program is running. the end value of the.code section
* gExecutableCodeRomStart will have the address from where the .code is copied in the SDRAM.
* gExecutableCodeRomEnd will have the address from where the .code + sizeof(.code) is copied in the SDRAM.