Why would the address of reset vector differ when two firmwares are linked with the same linker script? - cortex-m3

I have a Cortex-M3 chip and on it I am running a bootloader that uses eCos. The bootloader, after checking for firmware updates etc, jumps to another location (BASE_ADDRESS_OF_APP + 0x19) on the ROM where the actual application resides (also compiled with eCos).
Now instead of running the normal firmware, I want to run my CppUTests compiled for the Cortex-M3 target. So I am able to compile and link my tests for the target platform, using the ecos glibc, but not the actual operating system. But when I load it on to my board using JTAG, it doesn't run.
After some investigation using arm-eabi-objdump, I found out that the reset vector of the CppUTest firmare is at an offset of 0x490 as opposed to an offset of 0x18 for the normal firmware. My suspicion is that this is the reason why the tests are never executed. Is this correct?
How is it possible that the two firmwares have different starting addresses when I am linking them with the same linker script?
How can I make sure that the starting point of the test program is the same as the starting point of the application?

It depends on how your linker script is written, if your entry point address is not set to a static location in the linker script, then there could be the chance that other data/code is put in the object file before your entry point, effectively moving the location of your entry point and indeed causing problems.
I typically solve this by creating a new section with only 1 symbol in it, and a jump/branch instruction as follows:
.section entryPointSection
b myCodeEntryPoint
Then in your linker script put the entryPointSection at the hard coded address that your bootloader will jump to.
The myCodeEntryPoint label can be the name of a C function (or assembly label if necessary) that is in the normal .text section and can be linked anywhere within reach of the jmp. It will become your entry point, but you don't really care where it is because the linker should find it and link it properly.
Consider posting your linker script if you have further questions.

Related

How do I add a missing peripheral register to a STM32 MCU model in Renode?

I am trying out this MCU / SoC emulator, Renode.
I loaded their existing model template under platforms/cpus/stm32l072.repl, which just includes the repl file for stm32l071 and adds one little thing.
When I then load & run a program binary built with STM32CubeIDE and ST's LL library, and the code hits the initial function of SystemClock_Config(), where the Flash:ACR register is being probed in a loop, to observe an expected change in value, it gets stuck there, as the Renode Monitor window is outputting:
[WARNING] sysbus: Read from an unimplemented register Flash:ACR (0x40022000), returning a value from SVD: 0x0
This seems to be expected, not all existing templates model nearly everything out of the box. I also found that the stm32L071 model is missing some of the USARTs and NVIC channels. I saw how, probably, the latter might be added, but there seems to be not a single among the default models defining that Flash:ACR register that I could use as example.
How would one add such a missing register for this particular MCU model?
Note1: For this test, I'm using a STM32 firmware binary which works as intended on actual hardware, e.g. a devboard for this MCU.
Note2:
The stated advantage of Renode over QEMU, which does apparently not emulate peripherals, is also allowing to stick together a more complex system, out of mocked external e.g. I2C and other devices (apparently C# modules, not yet looked into it).
They say "use the same binary as on the real system".
Which is my reason for trying this out - sounds like a lot of potential for implementing systems where the hardware is not yet fully available, and also automatted testing.
So the obvious thing, commenting out a lot of parts in init code, to only test some hardware-independent code while sidestepping such issues, would defeat the purpose here.
If you want to just provide the ACR register for the flash to pass your init, use a tag.
You can either provide it via REPL (recommended, like here https://github.com/renode/renode/blob/master/platforms/cpus/stm32l071.repl#L175) or via RESC.
Assuming that your software would like to read value 0xDEADBEEF. In the repl you'd use:
sysbus:
init:
Tag <0x40022000, 0x40022003> "ACR" 0xDEADBEEF
In the resc or in the Monitor it would be just:
sysbus Tag <0x40022000, 0x40022003> "ACR" 0xDEADBEEF
If you want more complex logic, you can use a Python peripheral, as described in the docs (https://renode.readthedocs.io/en/latest/basic/using-python.html#python-peripherals-in-a-platform-description):
flash: Python.PythonPeripheral # sysbus 0x40022000
size: 0x1000
initable: false
filename: "script_with_complex_python_logic.py"
```
If you really need advanced implementation, then you need to create a complete C# model.
As you correctly mentioned, we do not want you to modify your binary. But we're ok with mocking some parts we're not interested in for a particular use case if the software passes with these mocks.
Disclaimer: I'm one of the Renode developers.

Passing kernel params from U-Boot to ARM Linux when device tree is used

I've been investigating a change to some embedded software inasmuch as we want U-Boot to be able to pass specific command-line parameters to the kernel, ones that aren't necessarily known in advance.
This is so that the kernel can tell which U-Boot partition it was started by (we have two copies, one in /dev/mmc3boot0 and /dev/mmc3boot1, and they both share a single (redundant) environment space, so we can't use that alone to uniquely identify the instance).
One thought was to simply have each U-Boot write its ID to the shared environment when it boots but that has the downside that there are variants out there that do not currently do this. So, if we boot from one that does, it will write its ID and, if we then boot from one that doesn't, it will not change the ID back to blank, leading to incorrect information if we rely on that.
This is why we thought to use a kernel parameter - since older style U-Boot instances never supply an ID, we know it's running in boot0. The newer style would provide their actual ID so we could then search the two boot partitions to see which one it was in.
To that end, I've modified U-Boot so that it sets up ATAGs to pass through the extra parameter needed. Specifically:
I've define CONFIG_SYS_BOOT_GET_CMDLINE in arch\arm\include\asm\config.h so that boot_get_cmdline() is called.
I've modified that boot_get_cmdline() function so that it sets up a specific parameter before appending the normal parameters. In other words, rather than just plugh=xyzzy, we now get uboot_instance=42 plugh=xyzzy.
This all compiles fine and U-Boot successfully starts the kernel but the extra information is not being reflected in the Linux kernel, which has its kernel parameters set to the regular plugh=xyzzy.
On further research, it appears that we are falling afoul of the two possible ways to invoke the kernel. One of these is with ATAGs and one is with a flattened device tree (FDT), and they appear to be mutually exclusive (the kernel startup code selects one or the other based on signatures passed in with the pointer referencing either the ATAGs or FDT structure).
So my question is this. Given that the device tree is meant to be a fixed structure for the device you're describing, how do you pass arbitrary kernel command line parameters (calculated at runtime) when the bootloader is invoking the kernel?
You can use a dummy environment variable for your platform in include/configs/<board>.h.
For example, assume you have the following (simplified) UBoot environment variables for booting:
bootcmd=run mmcargs
run loadimage loadfdt
bootz ${loadaddr} - ${fdt_addr}
mmcargs=setenv bootargs blah=blah
This uses mmcargs to set up the kernel command line to use. What we need to do is to insert that dummy environment variable in a way that current UBoot instances supply nothing and new ones supply the actual ID. This is done simply with the following change:
mmcargs=setenv bootargs ${uboot_id_stanza} blah=blah
Then, during the initialization of the board, you can set this variable using env_set API, specifically by writing your own custom board_late_init of the board init code in board/<vendor>/<init_code>.c.
The following line should be placed at the end of the board_late_init function:
setenv("uboot_id_stanza", "uboot_id=<uniqueId>");
That way, the uboot_id variable setting is added to the kernel command line but, since you didn't do a saveenv, it doesn't become persistent. Every UBoot instance will set the correct ID (including old ones that don't set an ID).

Confusions about address binding

Compile time. If you know at compile time where the process will reside
in memory, then absolute code can be generated. For example, if you know
that a user process will reside starting at location R, then the generated
compiler code will start at that location and extend up from there. If, at
some later time, the starting location changes, then it will be necessary
to recompile this code. The MS-DOS .COM-format programs are bound at
compile time.
What can be the reason of the starting location to change? Can it be
because of context switching/swapping ?
Does absolute code means binary code?
Load time. If it is not known at compile time where the process will reside
in memory, then the compiler must generate relocatable code. In this case,
final binding is delayed until load time. If the starting address changes, we
need only reload the user code to incorporate this changed value.
How is relocatable code different from absolute code? Does it contain info about base,limit and relocation register?
How is reloading more efficient then recompiling as they mentioned only reload means no recompiling only reload?
Execution time. If the process can be moved during its execution from
one memory segment to another, then binding must be delayed until run
time. .
Why it may be needed to move a process during it's execution?
The compile-time and load-time address-binding methods generate
identical logical and physical addresses. However, the execution-time address-binding scheme results in differing logical and physical addresses.
How compile and load-time methods generate identical logical and physical addresses?
To begin with, I would find a better source for your information. What you have is very poor.
What can be the reason of the starting location to change? Can it be because of context switching/swapping ?
You change the code or need the code to be loaded at a different location in memory.
Does absolute code means binary code?
No. They are independent concepts.
How is relocatable code different from absolute code? Does it contain info about base,limit and relocation register?
Relocatable code uses relative addresses, generally relative to the program counter.
(Base limit and relocation registers would be a system specific ocncept).
How is reloading more efficient then recompiling as they mentioned only reload means no recompiling only reload?
Let's say two different programs use the same dynamic library. They made need to have loaded at different locations in memory. It's not an efficiency issue.
Why it may be needed to move a process during it's execution?
This is what was done in ye olde days before virtual memory. To my knowledge no one does this any more.
How compile and load-time methods generate identical logical and physical addresses?
I don't know what the &^54 they are talking about. That statement makes no sense.
Dynamic libraries (.dll .so) are relocatable, because they might appear at different adresses in different applications, but in order to save memory, the operating system only has one copy in physical memory (virtual memory is great), and each application has read only access.
Same happens for applications that are relocatable. For security, it is also wize that the addresses are random - some remote attacks are slighty harder

uC/OS-II How to dynamically load a task

Basically, when my system is running, I would like the user to ftp some new code to the SD card, and dynamically load the new function and create a task to run in the system. This is normal for Linux. For example, I can compile a SO, and dynamically load into the memory.
How to do it in uC/OS II or III?
This is not a service uC/OS-II or uC/OS-III can provide by itself.
You would need a program loader that is able to read an ELF file, copy its relevant sections (ex .text, .rodata, etc.) in memory according to load addresses specified and allocate memory for uninitialized memory sections. You would then be able to create a new uC/OS task and pass it the function pointer that corresponds to the ELF entry point.
Most embedded systems don't have a Memory Management Unit (MMU) and thus you would need to pay special care to the linking process to make sure any of those sections don't overlap with any code that would already running on your target. Depending on your toolchain, that would most likely involve carefully crafting your linker script.
Another option that would avoid the problem of potential overlapping of the memory space would be to use a toolchain that can produce position independent code and load the ELF in the heap of your main application or in any other allocated and available memory space that is allocated by your main application.
Yet another option would be to produce relocatable code and use or build a program linker that is able to process relocations at runtime, when you want to load the uploaded code.

Section load address and execution address in linker script

I'm writing a customized linker script for a bare-metal ARM application. The application is stored in a flash memory, at the moment I have a bootup code copying the whole application in SDRAM, and continuing execution in SDRAM for speed purpose. I want to modify this script to run the whole code from flash directly, but I have problems understanding certain elements.
In the linker script below, the .ram_data section has an execution address in RAM and a load address in ROM (both sections in SDRAM). From what I understand the execution address is used by the linker to do the symbol resolution of all elements which are not PC relative, but what about the load address? In the context of a bare-metal ARM there is no such thing as a program loader, and there is no way the linker can have any influence on where I write the program in flash, so what is it actually used for?
In the same way, how can the linker have any influence on the SDRAM being (rx) or (rw) at run-time? Does it actually change anything when I modify those options in the memory regions?
MEMORY
{
RAM(rw) : ORIGIN = 0x00001000, LENGTH = 12M-4K
ROM(rx) : ORIGIN = 0x007f1000, LENGTH = 60K
}
SECTIONS
{
.startup :
{ ... } > VECTOR
.rom_text :
{ ... } > ROM
.ram_data :
{
_data_start = .;
*(.data*)
_data_end = .;
} > RAM AT>ROM
.ram_bss :
{ ... } > RAM
}
Given your example linker script, these two questions are related.
From what I understand the execution address is used by the linker to do the symbol resolution of all elements which are not PC relative, but what about the load address?
In the same way, how can the linker have any influence on the SDRAM being (rx) or (rw) at run-time? Does it actually change anything when I modify those options in the memory regions?
The LOAD address is useful as everything must be programmed to FLASH. This is why .ram_data should have AT>ROM. It is telling the linker that the data will LOAD from the ROM/Flash. You have to make some assembler boot code that will copy it from flash to SDRAM in this case.
The 2nd question can be answered by putting >ROM for the .ram_data section. If you do this, the linker will complain that a write-able section is being placed in read-only memory. It is good to mark the MEMORY sections with read/write information as it can help to make sure you have the sections in the correct places. Ie, it is a cross check on the information you give the linker.
A mistake where >RAM AT>ROM is instead just >ROM makes the concepts/questions similar.
From what I understand the execution address is used by the linker to do the symbol resolution of all elements which are not PC relative, but what about the load address? In the context of a bare-metal ARM there is no such thing as a program loader, and there is no way the linker can have any influence on where I write the program in flash, so what is it actually used for?
That information is stored in the ELF executable, and is used by tools like objcopy to determine how the binary file (e.g, .bin or .hex) is laid out. Ultimately, it ends up telling your programmer where to put the program.
In the same way, how can the linker have any influence on the SDRAM being (rx) or (rw) at run-time? Does it actually change anything when I modify those options in the memory regions?
In this particular use case, I believe those flags are informational only. They're primarily used for dynamic-loaded programs.