MPLAB X32 compiler and moving function to RAM causes linker error - c

I'm using Microchips XC32 C compiler and tools to build an executable for a SAM E70 processor.
I have to create a function that is executed from RAM and not ROM/Flash because this function uses special instructions to read a unique 128 bits at the beginning of Flash.
So I've defined the beginning of the function like this:
__ramfunc__ void ReadUniqueID(uint32_t *pdwUniqueID)
{
uint32_t status;
if (pdwUniqueID == NULL)
return;
printf("ReadUniqueID begin\r\n", pdwUniqueID[0]);
According to the documentation __ramfunc__ is supposed to ensure that the function is executed from ram.
However, when linking, the following errors occur.
c:\program files\microchip\xc32\v3.01\bin\bin\..\..\lib\gcc\pic32c\8.3.1\..\..\..\..\bin\bin/pic32c-ld.exe: Link Warning: attributes for input section '.RAMFUNC$.__stub' conflict with output section '.RAMFUNC$'
c:\program files\microchip\xc32\v3.01\bin\bin\..\..\lib\gcc\pic32c\8.3.1\..\..\..\..\bin\bin/pic32c-ld.exe: section .text.Reset_Handler%184 LMA [0044ba08,0044bb8b] overlaps section .text%180 LMA [0044b3bc,0044ba0f]
c:\program files\microchip\xc32\v3.01\bin\bin\..\..\lib\gcc\pic32c\8.3.1\..\..\..\..\bin\bin/pic32c-ld.exe: section .bss%44 VMA [2045fff4,2045ffff] overlaps section .RAMFUNC$ VMA [2045ff58,20460007]
Link Error: can't load section .RAMFUNC$ contents
Any help or pointers would be greatly appreciated.

Problem turned out to be that I was using printf() in the "ramfunc" function. Removed the printf()'s and all is working as expected.

Related

Is it possible to access a C variable from a linker script

Let's say for example I need to get the size of the process loaded into memory then I define this in my code:
#include <stdio.h>
ssize_t prog_sz;
int main()
{
printf("%x\n", prog_sz);
}
then I have a linker script accessing it with a line like this proc_sz = .
NOTE: all linker scripts I test with my programs always produce errors which is why I specified only a line from the script. For example something as simple as this without that line I first talked about:
SECTIONS
{
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss) }
}
produces annoying errors like these:
/usr/bin/ld: a.out: error: PHDR segment not covered by LOAD segment
/usr/bin/ld: /usr/lib/x86_64-linux-gnu/libc_nonshared.a(elf-init.oS): in function `__libc_csu_init':
(.text+0x9): undefined reference to `__init_array_start'
/usr/bin/ld: (.text+0x20): undefined reference to `__init_array_end'
/usr/bin/ld: a.out: hidden symbol `__init_array_end' isn't defined
/usr/bin/ld: final link failed: bad value
collect2: error: ld returned 1 exit status
even an example from the ld info documentation produces that annoying error. Maybe you can help me solve that issue too.
It looks like you have two separate issues.
The first issue involves the symbol/variable prog_sz. The approach that you have shown will just cause the linker to try and create another symbol named prog_sz, which would not likely accomplish the goal.
Without further detail on exactly what is being done, I will present three objectives and their solution:
Set the variable prog_sz to contain the address of a symbol defined in the linker file.
Define the symbol in your command file with a different name, such as prog_sz__. You can then add directly above the declaration of prog_sz in your code the line:
extern char prog_sz;
The type char does not really matter here. This statement is just necessary to tell the compiler that the symbol will be defined somewhere else. After this, you can assign the address of the symbol to prog_sz by modifying your definition to:
size_t prog_sz = (size_t)(&prog_sz__);
Using & tells the program to store the address associated with symbol prog_sz__ in variable prog_sz. This will assign the symbol defined in your linker script to your variable prog_sz.
Position the variable at a fixed location using the linker script there is a way to do this.
Assuming that you are using the GNU toolchain, when you are building use the GCC option -fdata-sections. This will place each variable into its own data section. Be aware that your .bss and .data sections will be replaced with a section for each variable prefixed .data or .bss and you may need to use a wildcard * to capture the .bss and .data sections.
You can then add a section just below the location in the linker file where . is set to the desired address.
For example:
SECTION
{
...
. = where_i_want_prog_sz;
prog_sz_section :
{
* (.bss.prog_sz)
}
...
}
Note that this will store prog_sz at a specific location, but will not set prog_sz to the value of the location.
Treat a linker symbol defined in the command file as a size_t variable.
Define the variable using the extern keyword: extern size_t prog_sz;
This tells the compiler that the symbol is defined elsewhere but will be of type size_t. Keep in mind, if this is what is being done, then you will need to be sure that the memory location is not being used for anything else, otherwise prog_sz may overlap other data in the system.
Regarding the second issue, which is the list of linker error messages, I believe that you may not have the linker configured correctly. Symbols __init_array_end and __init_array_start are related to initializing the C programming environment. I would suggest reviewing the linker settings and documentation to make sure that the program is properly configured. If you are using the GNU toolchain, you can find documentation here:
https://sourceware.org/binutils/docs-2.37/

what is linker attribute command to put code in flash instead of RAM?

I'm out of RAM and need to move my non-critical speed code to flash.
Need to know the linker 'attribute' command to select flash.
I'm using mbed online IDE to build for NUCLEO (STM32)f091RC.
But maybe mbed uses a common attribute setting for flash.
I cannot find any help on mbed linker .
I don't know your linker file structure, but the most probably is that you have .text section which is written in FLASH (99% sure). If you want to force section of your function you must use this attribute just before declaration and definition: __attribute__ ((long_call, section (".text")))
You can also make a macro to this like that:
#define FLASH_FUNC __attribute__ ((long_call, section (".text")))
and use it like this:
in .h file:
FLASH_FUNC void MyFoo(void);
int .c file
FLASH_FUNC void MyFoo(void)
{
//foo
}

How do I specify manual relocation for GCC code?

I am in a situation in an embedded system (an xtensa processor) where I need to manually override a symbol, but the symbol happens to be in the middle of another symbol. When I try using -Wl,--wrap=symbol it won't work, since the symbol isn't its own thing.
What I need to do is specify (preferably in a GCC .S, though .c is okay) where the code will end up. Though the actual symbol will be located somewhere random by the compiler, I will be memcpying the code into the correct place.
40101388 <replacement_user_vect>:
40101388: 13d100 wsr.excsave1 a0
4010138b: 002020 esync
4010138e: 011fc5 call0 4010258c <_UserExceptionVector_1>
My problem is GCC creates the assembly with relative jumps assuming the code will be located where it is in flash, while the eventual location will be fixed in an interrupt vector. How do I tell GCC / GNU as "put the code wherever you feel like, but, trust me it will actually execute from {here}"
Though my code is at 0x40101388 (GCC decided) it will eventually reside and execute from 0x40100050. How do I trick GCC by telling it "put the code HERE" but pretend it's located "HERE"
EDIT: I was able to get around this, as it turns out, the function I needed to modify was held in the linker script, individually. I was able to just switch it out in the linker script. Though I still would love to know the answer, I now have a work-around.
In the linker script each output section has two associated addresses: VMA and LMA -- the address for which the code is linked and the address where the code will be loaded.
Put the code that needs to be relocated into separate section, add an output section to your linker script with desired VMA and LMA and put an input section matching the name of the code section inside it.
E.g. the following C code
void f(void) __attribute__((section(".relocatable1.text")))
{
...
}
extern char _relocatable1_lma[];
extern char _relocatable1_vma_start[];
extern char _relocatable1_vma_end[];
void relocatable1_copy(void)
{
memcpy(_relocatable1_vma_start, _relocatable1_lma,
_relocatable1_vma_end - _relocatable1_vma_start);
}
Together with the following piece of ld script, with VMA substituted with the desired target code location
SECTIONS {
...
.some_section : { ... }
.relocatable1 VMA : AT(LOADADDR(.some_section) + SIZEOF(.some_section)) {
_relocatable1_vma_start = . ;
*(.relocatable1.literal .relocatable1.text) ;
_relocatable1_vma_end = . ;
}
_relocatable1_lma = LOADADDR(.relocatable1) ;
...
}
should do what you want.

How to write function at particular memory location in flash memory? Is there any directive for that?

How to write function at particular memory location in flash memory? Is there any directive for that? Do i need particular linker?
If you are using keil ide you can place a function at a specific address using .ARM.__at_address as the section name. To place the function add at 0x20000, specify:
int add(int n1,int n2) __attribute__((section(".ARM.__at_0x20000")));
int add(int n1,int n2)
{
return n1+n2;
}
Do you use the keil toolchain?
If yes, perhaps http://www.keil.com/support/docs/359.htm helps.
Edit:
The .obj file is generated by the compiler. I am not sure what you mean with 'how can i configure .obj file'.
The linker mentioned above takes the obj files, links them together and places code and variables.
You should start with a project which compiles and links without errors.
Then you have:
- Some c files. One of them with your function.
- A linkfile with the settings for the linker.
- A makefile or some kind of batchfile which calls compiler and linker with the necessary arguments.
If you have that, you can look into the m51 file for the name of the symbol for your function.
The m51 file is a textfile generated by the lx51 linker with interesting information about which symbols are there and what the linker has done with them.
The keil documentation for the linker I mentioned says: The compiler creates a symbol name for the function using the following format: ?PR?function_name?file_name.
This means: You will find the names of all functions of your project in the m51 file. If your function is in file file_x and named func_x. The symbol name will be PR?func_x?file_x
In http://www.keil.com/support/man/docs/lx51/lx51_segments.htm you can find some information about the usage of the SEGMENTS directive of the lx51 linker. According to that:
SEGMENTS (PR?func_x?file_x(C:0x1234))
should place your function to address 0x1234 in code memory.
Actually I have no keil toolchain. Therefore I cannot test all that myself.
But I am sure that you can manage that yourself if you start with a simple working example, change things step by step and check what happens.
Good Luck.
Helmut
Use ORG directive.
For example, for a function to start at location 2000H
ORG 2000H
MY_FUNC:
: YOUR CODE HERE
RET

Place a function at very start of binary

I'm working on a toy operating system and bootloader. I'm trying to write the kernel in C, and then convert it to binary for direct jumping to from the bootloader (i.e., I'm not loading an ELF or anything like that).
I've got the linker file setup with the proper origin (I'm loading the kernel to address 0xC0000000) and confirm with objdump that it's using it correctly. However, it's not placing my entry point at the start (0xC0000000) like I wanted. I guess that's not what the ENTRY directive is for.
My problem is simply that I want to place a particular function, kernel_main at address 0xC0000000. Is there a way I can accomplish this using gcc for compiling and linking?
Here is what the relevant parts of my linker file look like:
ENTRY(kernel_main)
SECTIONS
{
/* Origin */
. = 0xC0000000;
.text BLOCK(4K) : ALIGN(4K)
{
*(.text)
}
/* etc. */
}
The ENTRY linker command tells the linker which symbol the loader should jump to when it loads the program. If you're making your own operating system it's really not used since there is no loader.
Instead, as you know, the program simply starts at the first code address.
To make place a special segment of code first, you could place it in a special code segment, and put it first in the list:
.text BLOCK(4K) : ALIGN(4K)
{
*(.text.boot) *(.text)
}
The segments in the list is placed in the order they are given.
The ENTRY directive is only useful for output formats that support an entrypoint. Since you're using a binary output, this won't work. What you can do is write a small stub in a separate source file (i.e. entry.c or entry.asm or whatever). Then, in the ld script, before the *(.text) line, you can put entry.o(.text). This instructs ld to load the symbols from a specific object file (whereas * denotes all object files). So the new ld script would look like this:
ENTRY(kernel_main)
SECTIONS
{
/* Origin */
. = 0xC0000000;
.text BLOCK(4K) : ALIGN(4K)
{
entry.o(.text)
*(.text)
}
/* etc. */
}
As long as entry.o contains just one function (that simply calls your kernel main), this should work.

Resources