Hi everyone here is my issue.
I have two distincts projects, first has a linker file mapped as the following:
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 0x0000C400
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
}
Second a linker file as the following:
MEMORY
{
rom (rx) : ORIGIN = 0x0800C400, LENGTH = 0x00019CFC
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
}
Both of the projects runs on the same MCU and are burned in flash separatly. In my second project I would like to map pointers on functions declared in the first project. I tried the code below but it doesn't work, at execution debugger tels me that the symbol could not be found, but according to the .map file of the first project the address (0x0800458C) is mapped on the function I want to use.
uint32_t (*Myfunction)(void);
int main(void)
{
Myfunction = ((uint32_t(*) (void)) 0x0800458C); // address in the first project
Myfunction();
}
Does anybody have experienced this ?
Thanks !!
EDIT: It seems to work with Keil IDE when in directly include .symbols file in project. But with CoIDE (eclipse based) it doesn't work. I'm still trying to figure out this issue.
Did you try this:
Linker script: insert absolute address of the function to the generated code
I think the last answer might be what your looking for.
Related
Trying to figure out why keil is failing to link program with variable placed at absolute address. If same program is being compiled without that variable being placed at absolute address - all is OK.
Failing to link:
const uint16_t CRC __attribute__((section(".ARM.__at_0x1FDFC"))) = 0xAE20;
Error: L6985E: Unable to automatically place AT section main.o(.ARM.__at_0x1FDFC) with required base address 0x0001fdfc. Please manually place in the scatter file using the --no_autoat option.
All same, just CRC placed not in absolute address:
const uint16_t CRC /*__attribute__((section(".ARM.__at_0x1FDFC")))*/ = 0xAE20;
Program Size: Code=116924 RO-data=11352 RW-data=1536 ZI-data=14808
Moving absolute address a bit further:
const uint16_t CRC __attribute__((section(".ARM.__at_0x1FE2C"))) = 0xAE20;
Program Size: Code=116924 RO-data=11356 RW-data=1536 ZI-data=14808
End of bin file with last example:
When seeing bin content it seems like CRC could be placed in original location, also there is more free space after CRC. So even program is on limit of not fitting in, it should fit. Question why Keil fails to link it and how I could fit it in?
compiler:
ArmClang.exe --version
Product: MDK-ARM Cortex-M0/M0+/M23 5.36
Component: ARM Compiler 6.16
Tool: armclang [5dfeb700]
Target: unspecified-arm-none-unspecified
I have an steval-stwinkt1 board, that i am trying to enable support for DFU mode.
I flashed costume boot loader firmware on to the the start of the flash (0x8000000) that lets you load into another firmware that was uploaded by the DFU mode or to stay in the current program to flash new firmware throw the USB.
i used this st tutorial- https://www.youtube.com/watch?v=n_LDXOQHerU
I tried the .dfu package that comes with the STM32Cube and i saw that the program ran successfully so i assume that the bootloader works.
but when i try to make my own DFU package from my software the software never loads and i get hard fault. i moved the software according to the ST totorial & some research i done to 0x800C000 by changin the following lines:
in the FLASH.ld file:
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 2048K
to:
FLASH (rx) : ORIGIN = 0x800C000, LENGTH = 2048K
and in the stm32l4r9xx.h changed FLASH_BASE to:
#define FLASH_BASE (0x0800C000UL)
on another try i tried instead of changing FLASH_BASE to change VECT_TAB_OFFSET but it still didnt work.
to make the dfu package i use dfu-tool (i use linux) and use this command:
dfu-tool convert dfuse software.bin software.dfu
also tried to convert the hex int dfu package using the official tool that is used in the tutorial i used and still didnt work
what do i need to change to make my software works when i load the dfu package?
thanks
itay
It appears to me that you have overlooked the fact that your application-dedicated flash size is not going to be 2048K anymore, since your custom bootloader is now placed at the start of the flash. Therefore, you need to subtract the app's flash origin from the total flash size:
FLASH (rx) : ORIGIN = 0x800C000, LENGTH = 2048K - (ORIGIN(FLASH) - 0x8000000)
In such cases, a suggestion would be to try to debug the hard fault using the HardFault_Handler() and a bit of coding. You will then be able to extract and analyze the link register, program counter, program status register, etc. at the moment when hard fault occurred.
I compiled a C program and linked with the Microsoft linker link.exe.
The linker generated a *.map file. Below are some snippets:
Start Length Name Class
0001:00000000 00000180H .text CODE
0001:00000180 00049158H .text$mn CODE
0002:00000000 000090c4H .rdata DATA
0002:000090c4 00000130H .rdata$zzzdbg DATA
0003:00000000 00002060H .data DATA
0003:00002060 00001370H .bss DATA
0004:00000000 00002790H .pdata DATA
0005:00000000 000003e4H .xdata DATA
Address Publics by Value Rva+Base Lib:Object
0002:000000c0 _gVar 0000000000049660 MyLib:File1.obj
My understanding is:
The .rdata section has the index 0002 with the length 0x90c4.
The _gVar global variable has the Address like 0002:000000c0, so it lives in the .rdata seciton with the section offset 0xc0.
The base address of the .rdata section is decided by the loader at runtime.
My confusion is about the Rva+Base column.
I checked the binary file at offset 0x49660. It contains exactly the value I assigned for the _gVar. So it seems Rva+Base is the offset from the beginning of the file.
But I think the Rva + Base should equal to absolute virtual address, which can only be decided by the loader at runtime.
How could it be the file offset? Or an unfortunate typo in the column name?
(Btw, I searched a lot for an authoritative reference about the .map file generated by link.exe. But no luck so far. If anyone can share some resource, it will be deeply appreciated.)
ADD 1 - 5:31 PM 4/8/2019
Based on 500 - Internal Server Error's comment, I use CFF Explorer to verify the PE sections. It looks like below:
According to the PE sepc:
Virtual Address: For executable images, the address of the first byte of the section relative to the image base when the section is
loaded into memory.
Raw Address/PointerToRawData: The file pointer to the first page of the section within the COFF file.
These 2 columns have the same data in my scenario.
And in the PE Optional Header, the ImageBase is 0 (this is because of my link flag /BASE:0):
When linker generated the .map file, it has no knowledge about where the image will be loaded at runtime. So it has to use the ImageBase=0 to calculate the Rva+Base column.
The _gVar's absolute virtual address = ImageBase(0) + .rdata Virtual Address(0x495A0) + offset into .rdata (0xc0) = 0x49660
In my case,
The Virtual Address column has the same value as Raw Address column.
And ImageBase = 0 has the same effect of file beginning offset = 0
So the final absolute virtual address equals the file offset, but this is only specific to my scenario.
I'm trying to make a simple operating system kernel higher half. When using Grub as a bootloader as I am, there must also be some lower half (32 bit) code. Because I want to keep this 32 bit code as brief as possible, I do not want to write an ELF loader in it just to load the 64 bit code because that would be patently absurd (this is in fact the most common solution, but I would like to avoid it if possible).
I discovered that linker scripts allow load addresses that differ from virtual addresses. This is useful so that I can load the 64 bit sections to fit in a small binary and then use virtual memory to map the proper virtual addresses to the physical addresses they were loaded at. This works except that the low text section is not put in the text segment. The entry point, _start, is in this section.
I can't put the low text section (where _start resides) in the text segment unless I specify the text segment in a PHDRS command. Of course, using this command makes the linker decide to take a pass on generating the normally expected segments. When I do this too, the sections end up overlapping and I am not entirely sure why. I specify the segments in the order data, rodata, text, and the sections are the same, and yet their load memory addresses are assigned with rodata and data swapped and all three overlapping.
Here is my linker script:
ENTRY(_start)
PHDRS {
.low PT_LOAD FILEHDR PHDRS;
.data PT_LOAD;
.rodata PT_LOAD;
.text PT_LOAD;
}
SECTIONS {
. = 1M;
.data_low BLOCK(4K) : ALIGN(4K) {
*(.bss_low)
} : .low
.rodata_low BLOCK(4K) : ALIGN(4K) {
KEEP(*(.multiboot_low))
*(.rodata_low)
} : .low
.text_low BLOCK(4K) : ALIGN(4K) {
*(.text_low)
} : .low
.stack 0xC0000000 : AT(0x200000) ALIGN(4K) {
*(.bootstrap_stack)
} : .data
_LADD_ = LOADADDR(.stack) + SIZEOF(.stack);
.data BLOCK(4K) : AT(_LADD_) ALIGN(4K) {
*(COMMON)
*(.bss)
} : .data
_LADD_ += SIZEOF(.data);
.rodata BLOCK(4K) : AT(_LADD_) ALIGN(4K) {
*(.rodata)
} : .rodata
_LADD_ += SIZEOF(.rodata);
.text BLOCK(4K) : AT(_LADD_) ALIGN(4K) {
*(.text)
} : .text
}
I do not think the code is relevant to this error. When I link my object files using this linker script (additionally with -n --gc-sections), I get this error:
ld: section .data loaded at [0000000000200020,000000000020103f] overlaps section .rodata loaded at [0000000000200010,00000000002000d0]
ld: section .text loaded at [00000000002000d1,00000000002017ce] overlaps section .data loaded at [0000000000200020,000000000020103f]
The load memory addresses are in the order rodata, data, text, even though I expect they should be in the order data, rodata, text since the sections are specified in that order with AT specifiers with monotonically non decreasing positions (assuming the sections do not have negative size).
I should specify that I am using "segment" to mean one of the entries in the ELF program header (PHDRS in the linker script) and "section" to mean one of the entries in the ELF section header (SECTIONS in the linker script). I believe this to be correct terminology but acknowledge that I have an understanding of linker files and the ELF format that is limited at best. For whatever reason, Grub will not load an ELF file if its entry point is not in a segment.
Why indeed are the sections not in the order I expect them to be in, and how can I make them be? Thank you.
I have an embedded application that also has a bootloader, my goal is to be able to get the version of the bootloader and other information within the application, all information is constant, and thus I thought of placing them at the beginning of the bootloader code section, so the application can easily read the data which is allways going to be at the same address.
So far I have defined something like
const char bootloader_info[4] = {0x01,0x02,0x03,0x04};
and defining in the linker script
__bootloader_info = 0xD000 /*Where exactly should this line be placed?*/
However the variable ends placed in the data section...
What I have done now is to define a new section in the linker script and place it before the init code, although it works I think it is not the right way
const char __attribute__((section (".versioninfo"))) bootloader_info[4] = {0x01,0x02,0x03,0x04};
.
versioninfo (rx) : ORIGIN = 0xD000, LENGTH = 0x0000
rom (rx) : ORIGIN = 0xD000, LENGTH = 0x27B0
-------
.text :
{
. = ALIGN(2);
KEEP(*(.versioninfo)) /*info gets added at the beginning of .text*/
KEEP(*(.init .init.*))
KEEP...
What should be the right way of achieving this using a gcc toolchain, and why did the first method didn't work?
EDIT
I was not defining a section, I actually don't know what was that. To define a section it goes like this:
.versioninfo :
{
KEEP(*(.versioninfo))
} > versioninfo
Now it complains if the data is bigger than the section, so I guess it is better than before, I still would like to hear another aproaches or why the first method didn't work, thanks
You must define your section as follow:
_versioninfo_start_address = 0x0000D000;
.versioninfo _versioninfo_start_address :
{
KEEP(*(.versioninfo)) ;
} > // place here the region where to this section has to be stored
Then you can define your variable:
const char __attribute__((section (".versioninfo"))) bootloader_info[4] = {0x01,0x02,0x03,0x04}