Goal: This post tries to explain what objects are placed where in RAM when using the GCC toolchain.

It's intended as self-documentation. When using the LCD, you need large continuous chunks of memory for the frame buffers.

Memory is limited on controllers. Continuous large blocks even more so.

To be able to reserve these buffers, it's useful to understand where the linker places code, data, stacks and housekeeping blocks.

Knowing their position and size - and knowing if you can move things without side effects - are the hooks to eek out maximum available memory for buffers and custom logic.

Not a goal of this post:  Explain the non-RAM ranges or how to try and save data or code size during development.

 

RX65N RAM

 

The controller has two RAM ranges.

 

on-chip RAMSize (bytes)Start addressEnd address
Standard RAM

0x00040000 / 262144

0x000000000x0003FFFF
Expansion RAM

0x00060000 / 393216

0x008000000x0085FFFF
Total RAM0x000A0000 / 655360

 

The first range is available on all RX65N devices. The Expansion RAM is dependent on the particular device.

The R5F565NEDDFB on the Envision kit has the full 640K.

source: ammended memory map from the Renesas RX65N datasheet

 

640K is plenty. However, because the memory is not continuous, reserving two 130560130560 blocks (the buffer size for a 480 wide * 272 high * 2 bytes for colour) will need proper care.

It's not a desperate situation - 2 blocks fit in the expansion RAM. But for a larger display, they wouldn't.

 

What Goes to RAM

 

The objects that will go to RAM are:

  • the start address and top pointer of the heap
  • the two stacks (istack for interrupts, ustack for user)
  • data (yours and that from linked in libraries)
  • Dynamically allocated memory will go to the heap. The heap in this controller is of a fixed size in this RAM region and grows up towards its tail.

 

image: the Smart Configurator in e2 studio: define the istack, ustack and heap sizes

 

The linker command file and related assembler file generated by the project wizard and the Smart Configurator place all of that in the Standard RAM area.

 

The Linker Memory Areas

 

The GCC linker command file is where you define what is placed where by the link and load process.

You define what blocks of memory are available, where they are located and the size (if your controller supports it, also if you can read/write/execute in that area). You can also use it to define blocks that aren't available.

Then you define what parts of your code go to those areas.

Typically, you have memory regions, output + input sections and assignments.

  • region: an area of memory. It has address and size.
  • output section: a container that can be filled with code or data, and that's placed within a region, either at the next available address or at a fixed point
  • input section: a named container, belonging to an output section, where that GCC toolchain assign code and data to. It's complex but your variables and code will be assigned to a particular input section.
    Input sections are then placed within the output section they are assigned to.

You could think of input sections as data that's inputted (gathered) into the output section. The output sections are then outputted (placed) to memory regions.

Assignments are labels that are internally used by the toolchain, but also available to you if you want to assign a memory area to a particular address without hardcoding that address in your code.

 

For our controller, the memory areas are:

image: The 4 ranges defined in the linker file

 

I'm ignoring OFS and ROM in this post. (just for info: your code goes to ROM (flash) and is executed from there)

The RAM and RAM2 blocks are the standard and expansion RAM. This is our focus.

note: the loader file generated by e2 studio's project wizard has a bug. It places expansion ram on ox0008000 instead of 0x00800000. Fix that manually after generating a project.

 

View What's Where in RAM

 

Eclipse has a graphical editor that helps you lay out the memory and its use. That includes a graphic overview of the memory.

 

image: the Eclipse linker file viewer

 

That will give you an overview of how the linker will place objects. What it will not show is the complete picture with the stacks allocated.

To see that, you can use the GCC linker's map file, and the handy AMAP viewer.

 

image: AMAP viewer showing the sections in a Renesas RX65N GCC map file

 

The map file is generated during the build process, so you need a compilable program (I just created a empty Renesas C program for the GCC toolchain, with Smart Configurator support).

The advantage is that it has factual data about how much space is taken by runtime library data, stacks, data, and their exact locations.

 

Objects Placed in RAM

 

As seen earlier, all objects that go to RAM are placed in the standard RAM area by the default linker script. RAM2 is not used by default. So the linker will not place anything in expansion RAM.

The standard RAM region has a number of output sections. Some consecutive, some at a fixed address:

image: output sections assigned to standard RAM

 

The tree board startup sections (r_bsp_*) are placed on fixed addresses. All the rest are placed where the linker sees fit within the RAM region.

A good explanation is available from wikipedia.

  • .data contains initialised global and static variables, and the heap start and end points.
  • .gcc_exec contains nothing
  • .bss contains the uninitialised global and static variables and the heap.
  • the stacks contain values pushed on the stack, such as parameters and variables declared within a function.
    They have a fixed size set in the startup assembler code. They are set to NOLOAD so won't be initialised.
  • .r_bsp_NULL, I believe is used for the board upbring code. It reserves 100 bytes.
    For some reason it's not visible in the AMAP viewer but it's the area between end of .bss and start of the stacks. It's content is copied from a ROM address at startup.

 

For a program built without debug information, yet without optimisation, here's the content of the RAM region:

 

image: extract from the AMAP tool showing RAM region objects.

 

I did a first attempt in fixing LCD buffers at a fixed free spot in Renesas RX65 Envision Kit - part 10: Reserve LCD Frame Buffer in Expansion RAM with GCC.

That was done with the knowledge that the expansion RAM was unused.

With the info of this post at hand, I should be able to come up with a good strategy to allocate buffers for the LCD display in standard RAM too...