Showing results for 
Search instead for 
Did you mean: 

Linker ld.exe cannot get *.o files...when using CCMRAM on a 32F303

Associate III

I would like to use CCMRAM on my STM32F303RD based hardware.

I use Atollic v9.3 and Cube F3 V1.10.

CCMRAM support has been implemented in startup file 'startup_stm32f303xe.s' as described in ST AN4296.

  • When I try to use a function in the CCMRAM, I add: __atribute__((section ("*.ccmram"))); in the function prototype and It works fine, code is uploaded in CCMRAM and run OK.
  • When I do not try to move any code in CCMRAM it's ok, soft run fine.
  • When I try to move a whole file in the CCMRAM and add xxxx.o (xxxx is name of the function in the linker file (STM32F303RD_FLASH.ld), on link time, ATOLLIC tell : ...bin/ld.exe: cannot find ***.o. Trials have been made with various files, all presents in /debug/core/drc directory ot the project.

That looks like a path issue, but no doubt ld has the right pass to access the.o files.

thanks for help

Clive1 (HNL)
Senior II

Surely the star is just used in the .LD to match against object file level naming like foo.ccmram


__atribute__((section (".ccmram")));

Associate III

Thanks, I should have been more specific, my bad :

Application Note describe 3 ways to get code in CCMRAM :

·        function per function

·        all functions of a c.file

·        all functions of a lib

The first work ok, the second is the one I want to use and pop the linker error, the 3rd is not tested.

The first method is adding  _atribute__((section ("*.ccmram")))  in the function prototype. It  works fine but you have to change one by one all functions in the .h file

The second method should allow to move all functions of a .c file in the CCMRAM. It consist of adding in the .LD file the name of the object file corresponding to the .c. This .o file has to be added where described in page 22 of the AN. When this method is used there’s no need to modify the function prototype. In that particular situation, the linker produce the following message in the console :

c:/program files (x86)/atollic/truestudio for stm32 9.3.0/armtools/bin/../lib/gcc/arm-atollic-eabi/6.3.1/../../../../arm-atollic-eabi/bin/ld.exe: cannot find xxxx.o, and this is where I get stuck !


And does said file exist with matching case? Should be in the same output directory as everything else. Check the command line for the compilation of the offending file.

Sounds more like it either didn't compile properly, or wasn't referenced properly. Super hard to tell though the key hole.

At an object level​ surely you could instruct the linker to place an objects *.text into the .CCMRAM section

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

I'm assuming a CDT-generated make.

In the linker command file:

  myregion (rx)           : ORIGIN = myregionstart, LENGTH = myregionlength
mysection :
  KEEP(*myobject.o (.text .text*))
} >myregion

The above moves the text sections of the object into mysection and maps them into myregion. The other sections of the object will go to their normal sections. The linker processes mappings as these in the order they occur in the command file. So assuming you wanted the text at a fixed address, this mapping must occur before your general mapping of text sections.

The .c file should be in your project explorer and compiled with the rest of your sources. The compiler puts its object's in a build configuration directory. You don't need to tell the linker where its object is.

The option #1 you'd mentioned can do the same, is preferred by most developers, and is implemented similarly in other toolchains.

Associate III

Thanks to both of you, it’s now more clear :

Main issue was a path issue : the .o file should be preceded by it’s relative path, in my case it was Core\Src\myfile.o, the new CubeMX template.

But when using this method, all the functions of the c file, including the ones coming with includes directives, are moved to CCMRAM, thus quickly filling the area in an uncontrolled manner

This is a good reason to use first method.