I am working on firmware for a PIC32MX microcontroller. The program memory should be split into three segments:
startup_region
)program1
)program2
)The firmware is only stored in either Section 2 or 3. The other is reserved for future updates. As such the active region can safely override the other to store the update. A config bit is flipped and the main() function of Section 0 now jumps to the other program on reboot.
As such I need the linker to put all functions except isr
and main
into Section 1 and everything else into Section 2. Section 3 must be left completely empty, as it may be overridden in the future.
I already tried to achieve this by modifying the default linker script, however I had no success.
linkerscript.ld:
/* [...] */
INCLUDE procdefs.gld
/* [...] */
SECTIONS
{
/* [...] */
.text :
{
/* isr() and main() should be at the very first locations in program memory */
*(.text.isr)
*(.text.main)
/* [...] */
. = ALIGN(4) ;
} >kseg0_program_mem
.program1 :
{
*(*.text)
} >program1
/* [...] */
}
procdefs.gld:
/* [...] */
MEMORY
{
kseg0_program_mem (rx) : ORIGIN = 0x9D000000, LENGTH = 0x10000
startup_region (rx) : ORIGIN = 0x9D000000, LENGTH = 0x01000
program1 (rx) : ORIGIN = 0x9D002000, LENGTH = 0x07000
program2 (rx) : ORIGIN = 0x9D009000, LENGTH = 0x07000
kseg0_boot_mem : ORIGIN = 0x9FC00490, LENGTH = 0x970
/* [...] */
}
/* [...] */
This results in the following:
isr()
and main()
are where they are supposed to be (0x9D00000
is the KSEG0
virtual address of the beginning of the program flash)
.text 0x9d000000 0x94
*(.text.isr)
.text.isr 0x9d000000 0x60 build/default/production/main.o
0x9d000000 isr
*(.text.main)
.text.main 0x9d000060 0x34 build/default/production/main.o
0x9d000060 main
The program1
region is correctly placed and most object files are listed correctly (notice however, that main.o
is listed again -- it was already used).
.program1 0x9d002000 0xc44
*(*.text)
.text 0x9d002000 0x0 /opt/microchip/xc32/v2.10/bin/bin/../../lib/gcc/pic32mx/4.8.3/../../../../pic32mx/lib/./proc/32MX330F064H/crt0_mips32r2.o
.text 0x9d002000 0x0 /opt/microchip/xc32/v2.10/bin/bin/../../lib/gcc/pic32mx/4.8.3/../../../../pic32mx/lib/debug-exception-return.o
.text 0x9d002000 0x0 build/default/production/main.o
.text 0x9d002000 0x0 build/default/production/commands.o
/* [...] */
.text 0x9d002000 0x0 build/default/production/micro-ecc/uECC.o
However, some function are located outside of this region:
.text.uECC_verify
0x9d000b04 0x7c0
.text.uECC_verify
0x9d000b04 0x7c0 build/default/production/micro-ecc/uECC.o
0x9d000b04 uECC_verify
.text.vli_mmod_fast_secp256r1
0x9d0012c4 0x520
.text.vli_mmod_fast_secp256r1
0x9d0012c4 0x520 build/default/production/micro-ecc/uECC.o
I do not understand why this happens.
My questions are:
main
and isr
) into program1
.program2
, so that it remains free.I am compiling the software with the -ffunction-segments
switch, so that each function gets its own segment.
The original linkerscript also contains this suspicious looking comment:
/* Code Sections - Note that input sections *(.text) and *(.text.*)
are not mapped here. Starting in C32 v2.00, the best-fit allocator
locates them, so that .text may flow around absolute sections
as needed.
*/
The object file main.o is not the same as the function’s memory segment .tex.main
. If this object file produces some other text segments they will be placed elsewhere. This is what you see in your map file.
As @Ctx mentioned the syntax of your text segment is wrong instead of *(*.text)
it should be
.program1 :
{
*(.text*)
} >program1
This way all other text segments will be properly placed in the program1
memory.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With