Define Location of constant variable in flash - c

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}

Related

Padding or other reason code fails to fit, when placing variable at absolute address {C, Keil, ARM}

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

Compiling application to run not from the start of the flash stm32L4R9I

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.

What does the "Rva+Base" mean in a MSVC linker generated map file?

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.

Function call by address from map file of another project

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.

WinDBG extension - Breakpoint listing

Is there any way how can I get a list of breakpoints from within Windows Debugger Extension?
I'm using plain C (and I'm trying to avoid using COM interface they provide and I'm not even sure if that COM interface provides a way to do that).
I've read and researched wdbgexts.h and dbghelp.h but neither of them seem to contain any usable function or global variable, although there are some info on BPs in those files, such as DBGKD_GET_VERSION::BreakpointWithStatus.
Use IDebugControl::GetNumberBreakpoints, then IDebugControl::GetBreakpointByIndex.
Windows Debugger Extension provides function ULONG64 GetExpression(PCSTR lpExpression) (of course it's <sarcasm>well documented</sarcasm>)
#define GetExpression (ExtensionApis.lpGetExpressionRoutine)
which allows you to get results from any WinDBG expression like ?? #eip.
GetExpression( "#eip"); // Without `?? ` in the beginning
Next, if you take a look at:
Windows Debugger Help » Debugging Tools For Windows » Debuggers » Debugger References » Debugger Commands » Syntax Rules » Pseudo-Registers Syntax
You will find a line what looks like this:
$bpNumber - The address of the corresponding breakpoint. For example,
$bp3 (or $bp03) refers to the breakpoint whose breakpoint ID is 3.
Number is always a decimal number. If no breakpoint has an ID of
Number, $bpNumber evaluates to zero. For more information about
breakpoints, see Using Breakpoints.
So with some overhead you'll get this (working) solution:
#define MAX_BREAKPOINTS 100
DWORD i, addr;
CHAR buffer[] = "$bp\0\0\0\0\0\0\0\0\0\0\0\0";
for( i = 0; i < MAX_BREAKPOINTS; ++i){
// Appends string to BP prefix
itoa( i, buffer+3, 10);
addr = GetExpression( buffer);
if( !addr){
break;
}
// Do stuff
}
The only another solution is to use COM objects as Steve Johnson suggested.

Resources