Reputation: 3955
I've spent most of my time developing for microcontrollers using tools and IDEs such as Atmel Studio, and abstracted from as to what goes on behind the scenes exactly.
Let's say in this case we are executing the code directly from flash which can be the case in embedded systems.
When we develop an application and flash it to the microcontroller using provided tools from the chip vendor, is it the loader / flasher that determines at what physical address in memory will be flashed?
I understand that the linker script defines memory offsets as to where the different sections such as .data and .txt should be placed, so is it actually this that ultimately determines at what address in the mcu flash everything should go?
Lets's say now that I discover a part of flash that is not used at all and I wish to put something else there (another application even), do I modify the linker script, create a new one, or how would I write to this particular location? I haven't fully grasped this yet.
Upvotes: 3
Views: 1230
Reputation: 1580
You asked if you should modify or create a new linker script. I would requirement that you modify the exciting linker script. I find them from time to time quite extensive. Why throw away what is already there while modifying it is only a few lines.
Some very common cases for micro controllers to change the linker script are:
Lets use the first as an example on how to write to firmware to different flash sectors. Important to know is that for this example the bootloader and the actual application are two separate projects each with their own compilation configuration or makefile. Each project also has its own linker script. Below part of both files is listed:
The bootloader:
/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 16K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K
CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K
}
The application:
/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x0800C000, LENGTH = (1M - 16K)
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K
CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K
}
Please not the differences in the definition of the FLASH. The bootloader flash start at the default. The size allocated for the bootloader is 16K. Important to note is that the total flash size of the example chip is 1M. This is seen in the size of the flash of the application project. But we do not allow the full 1M for the application as of course we need to reduce it by the size allocated for the bootloader. You can also see it does not start at the same address. It has an offset of 0xC000 which amounts for the 16k.
Before you can run and debug the application code you have to do two more things:
One final note: when you do something link this it is best to stick to the flash sectors of the chip. Often you can only delete a whole sector. Placing your next part of the code at the start of the next sector makes live easier.
The given examples are based on a linker file generated by Atollic TrueSTUDIO for STM32 for a STM32F4xx chip. Compilation is done using ARM gcc toolchain.
Upvotes: 1
Reputation: 665
Your idea is generally correct. A linker script, which is nothing more than a file with its specialized language that conveys certain information regarding memory and how they should be used, determines the layout of your program in the memory. Some linkers would accept such memory specifications via command line options as well.
Regarding your specific question, yes, you can write another firmware that occupies different memory addresses (than the first one) by modifying the second one's linker script, in particular, the starting address of the program image. This of course does not say anything about how these two pieces of firmware will run or communicate. Those are separate issues. You will also need to know the MCU's flash erasable page boundary so you can place the 2nd image in a different erasable page boundary.
In some firmware downloader / programmer, you may also be able to specify a different starting offset than what's specified in the firmware image. This is separate from the linker script process. There are a few uses for this. For example, your firmware maybe built to run from SRAM instead of directly from flash. Therefore at firmware download, it will need to be moved to a flash location, and at runtime, some kind of mechanism will be used to copy the code from the flash to SRAM where the program actually will run. There are other scenarios as well.
Upvotes: 4