I am using the nxp imx rt 1024 board.
- I created a new standard c++ project in mcuxpresso.
- disabled the managed linker script and modified the “mcuxpresso generated linker script” :
.vector : ALIGN(4)
{
__vector_table_flash_start__ = ADDR(.vector) ;
KEEP(*(.isr_vector))
__vector_table_flash_end__ = ABSOLUTE(.) ;
. = ALIGN(4) ;
} >PROGRAM_FLASH
.got : ALIGN(4)
{
__global_offset_table_flash_start__ = LOADADDR(.got) ;
__global_offset_table_itc_start__ = ADDR(.got) ;
*(.got* .got.*)
__global_offset_table_flash_end__ = . ;
} >SRAM_DTC AT>PROGRAM_FLASH
I played around with vector tables to SRAM, but I don’t think it matters, so I am just pushing them to flash now. I’ll paste the entire linker script for reference.
GROUP (
"libgcc.a"
"libc_nano.a"
"libstdc++_nano.a"
"libm.a"
"libcr_newlib_nohost.a"
"crti.o"
"crtn.o"
"crtbegin.o"
"crtend.o"
)
MEMORY
{
/* Define each memory region */
/*0xE000ED08*/
PROGRAM_FLASH (rx) : ORIGIN = 0x60000000, LENGTH = 0x400000 /* 4M bytes (alias Flash) */
SRAM_DTC (rwx) : ORIGIN = 0x20000000, LENGTH = 0x10000 /* 64K bytes (alias RAM) */
SRAM_ITC (rwx) : ORIGIN = 0x0, LENGTH = 0x10000 /* 64K bytes (alias RAM2) */
SRAM_OC (rwx) : ORIGIN = 0x20200000, LENGTH = 0x20000 /* 128K bytes (alias RAM3) */
BOARD_SDRAM (rwx) : ORIGIN = 0x80000000, LENGTH = 0x1e00000 /* 30M bytes (alias RAM4) */
NCACHE_REGION (rwx) : ORIGIN = 0x81e00000, LENGTH = 0x200000 /* 2M bytes (alias RAM5) */
}
ENTRY(ResetISR)
SECTIONS
{
/* Image Vector Table and Boot Data for booting from external flash */
.boot_hdr : ALIGN(4)
{
__boot_hdr_start__ = ABSOLUTE(.) ;
KEEP(*(.boot_hdr.conf))
. = 0x1000 ;
KEEP(*(.boot_hdr.ivt))
. = 0x1020 ;
KEEP(*(.boot_hdr.boot_data))
. = 0x1030 ;
KEEP(*(.boot_hdr.dcd_data))
__boot_hdr_end__ = ABSOLUTE(.) ;
. = 0x2000 ;
} >PROGRAM_FLASH
.vector : ALIGN(4)
{
__vector_table_flash_start__ = ADDR(.vector) ;
KEEP(*(.isr_vector))
__vector_table_flash_end__ = ABSOLUTE(.) ;
. = ALIGN(4) ;
} >PROGRAM_FLASH
.got : ALIGN(4)
{
__global_offset_table_flash_start__ = LOADADDR(.got) ;
__global_offset_table_itc_start__ = ADDR(.got) ;
*(.got* .got.*)
__global_offset_table_flash_end__ = . ;
} >SRAM_DTC AT>PROGRAM_FLASH
/* MAIN TEXT SECTION */
.text : ALIGN(4)
{
/* Global Section Table */
__section_table_start = .;
__data_section_table = .;
LONG(LOADADDR(.data));
LONG( ADDR(.data));
LONG( SIZEOF(.data));
LONG(LOADADDR(.data_RAM2));
LONG( ADDR(.data_RAM2));
LONG( SIZEOF(.data_RAM2));
LONG(LOADADDR(.data_RAM3));
LONG( ADDR(.data_RAM3));
LONG( SIZEOF(.data_RAM3));
LONG(LOADADDR(.data_RAM4));
LONG( ADDR(.data_RAM4));
LONG( SIZEOF(.data_RAM4));
LONG(LOADADDR(.data_RAM5));
LONG( ADDR(.data_RAM5));
LONG( SIZEOF(.data_RAM5));
__data_section_table_end = .;
__bss_section_table = .;
LONG( ADDR(.bss));
LONG( SIZEOF(.bss));
LONG( ADDR(.bss_RAM2));
LONG( SIZEOF(.bss_RAM2));
LONG( ADDR(.bss_RAM3));
LONG( SIZEOF(.bss_RAM3));
LONG( ADDR(.bss_RAM4));
LONG( SIZEOF(.bss_RAM4));
LONG( ADDR(.bss_RAM5));
LONG( SIZEOF(.bss_RAM5));
__bss_section_table_end = .;
__section_table_end = . ;
/* End of Global Section Table */
*(.after_vectors*)
*(.text*)
*(.rodata .rodata.* .constdata .constdata.*)
. = ALIGN(4);
/* C++ constructors etc */
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
KEEP(*(.fini));
. = ALIGN(4);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))
. = ALIGN(4);
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*crtend.o(.dtors))
. = ALIGN(4);
/* End C++ */
} > PROGRAM_FLASH
/*
* for exception handling/unwind - some Newlib functions (in common
* with C++ and STDC++) use this.
*/
.ARM.extab : ALIGN(4)
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > PROGRAM_FLASH
.ARM.exidx : ALIGN(4)
{
__exidx_start = .;
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
__exidx_end = .;
} > PROGRAM_FLASH
_etext = .;
/* DATA section for SRAM_ITC */
.data_RAM2 : ALIGN(4)
{
FILL(0xff)
PROVIDE(__start_data_RAM2 = .) ;
PROVIDE(__start_data_SRAM_ITC = .) ;
*(.ramfunc.$RAM2)
*(.ramfunc.$SRAM_ITC)
*(.data.$RAM2)
*(.data.$SRAM_ITC)
*(.data.$RAM2.*)
*(.data.$SRAM_ITC.*)
. = ALIGN(4) ;
PROVIDE(__end_data_RAM2 = .) ;
PROVIDE(__end_data_SRAM_ITC = .) ;
} > SRAM_ITC AT>PROGRAM_FLASH
/* DATA section for SRAM_OC */
.data_RAM3 : ALIGN(4)
{
FILL(0xff)
PROVIDE(__start_data_RAM3 = .) ;
PROVIDE(__start_data_SRAM_OC = .) ;
*(.ramfunc.$RAM3)
*(.ramfunc.$SRAM_OC)
*(.data.$RAM3)
*(.data.$SRAM_OC)
*(.data.$RAM3.*)
*(.data.$SRAM_OC.*)
. = ALIGN(4) ;
PROVIDE(__end_data_RAM3 = .) ;
PROVIDE(__end_data_SRAM_OC = .) ;
} > SRAM_OC AT>PROGRAM_FLASH
/* DATA section for BOARD_SDRAM */
.data_RAM4 : ALIGN(4)
{
FILL(0xff)
PROVIDE(__start_data_RAM4 = .) ;
PROVIDE(__start_data_BOARD_SDRAM = .) ;
*(.ramfunc.$RAM4)
*(.ramfunc.$BOARD_SDRAM)
*(.data.$RAM4)
*(.data.$BOARD_SDRAM)
*(.data.$RAM4.*)
*(.data.$BOARD_SDRAM.*)
. = ALIGN(4) ;
PROVIDE(__end_data_RAM4 = .) ;
PROVIDE(__end_data_BOARD_SDRAM = .) ;
} > BOARD_SDRAM AT>PROGRAM_FLASH
/* DATA section for NCACHE_REGION */
.data_RAM5 : ALIGN(4)
{
FILL(0xff)
PROVIDE(__start_data_RAM5 = .) ;
PROVIDE(__start_data_NCACHE_REGION = .) ;
*(.ramfunc.$RAM5)
*(.ramfunc.$NCACHE_REGION)
*(.data.$RAM5)
*(.data.$NCACHE_REGION)
*(.data.$RAM5.*)
*(.data.$NCACHE_REGION.*)
. = ALIGN(4) ;
PROVIDE(__end_data_RAM5 = .) ;
PROVIDE(__end_data_NCACHE_REGION = .) ;
} > NCACHE_REGION AT>PROGRAM_FLASH
/* MAIN DATA SECTION */
.uninit_RESERVED (NOLOAD) : ALIGN(4)
{
_start_uninit_RESERVED = .;
KEEP(*(.bss.$RESERVED*))
. = ALIGN(4) ;
_end_uninit_RESERVED = .;
} > SRAM_DTC AT> SRAM_DTC
/* Main DATA section (SRAM_DTC) */
.data : ALIGN(4)
{
FILL(0xff)
_data = . ;
PROVIDE(__start_data_RAM = .) ;
PROVIDE(__start_data_SRAM_DTC = .) ;
*(vtable)
*(.ramfunc*)
KEEP(*(CodeQuickAccess))
KEEP(*(DataQuickAccess))
*(RamFunction)
*(.data*)
. = ALIGN(4) ;
_edata = . ;
PROVIDE(__end_data_RAM = .) ;
PROVIDE(__end_data_SRAM_DTC = .) ;
} > SRAM_DTC AT>PROGRAM_FLASH
/* BSS section for SRAM_ITC */
.bss_RAM2 : ALIGN(4)
{
PROVIDE(__start_bss_RAM2 = .) ;
PROVIDE(__start_bss_SRAM_ITC = .) ;
*(.bss.$RAM2)
*(.bss.$SRAM_ITC)
*(.bss.$RAM2.*)
*(.bss.$SRAM_ITC.*)
. = ALIGN (. != 0 ? 4 : 1) ; /* avoid empty segment */
PROVIDE(__end_bss_RAM2 = .) ;
PROVIDE(__end_bss_SRAM_ITC = .) ;
} > SRAM_ITC AT> SRAM_ITC
/* BSS section for SRAM_OC */
.bss_RAM3 : ALIGN(4)
{
PROVIDE(__start_bss_RAM3 = .) ;
PROVIDE(__start_bss_SRAM_OC = .) ;
*(.bss.$RAM3)
*(.bss.$SRAM_OC)
*(.bss.$RAM3.*)
*(.bss.$SRAM_OC.*)
. = ALIGN (. != 0 ? 4 : 1) ; /* avoid empty segment */
PROVIDE(__end_bss_RAM3 = .) ;
PROVIDE(__end_bss_SRAM_OC = .) ;
} > SRAM_OC AT> SRAM_OC
/* BSS section for BOARD_SDRAM */
.bss_RAM4 : ALIGN(4)
{
PROVIDE(__start_bss_RAM4 = .) ;
PROVIDE(__start_bss_BOARD_SDRAM = .) ;
*(.bss.$RAM4)
*(.bss.$BOARD_SDRAM)
*(.bss.$RAM4.*)
*(.bss.$BOARD_SDRAM.*)
. = ALIGN (. != 0 ? 4 : 1) ; /* avoid empty segment */
PROVIDE(__end_bss_RAM4 = .) ;
PROVIDE(__end_bss_BOARD_SDRAM = .) ;
} > BOARD_SDRAM AT> BOARD_SDRAM
/* BSS section for NCACHE_REGION */
.bss_RAM5 : ALIGN(4)
{
PROVIDE(__start_bss_RAM5 = .) ;
PROVIDE(__start_bss_NCACHE_REGION = .) ;
*(.bss.$RAM5)
*(.bss.$NCACHE_REGION)
*(.bss.$RAM5.*)
*(.bss.$NCACHE_REGION.*)
. = ALIGN (. != 0 ? 4 : 1) ; /* avoid empty segment */
PROVIDE(__end_bss_RAM5 = .) ;
PROVIDE(__end_bss_NCACHE_REGION = .) ;
} > NCACHE_REGION AT> NCACHE_REGION
/* MAIN BSS SECTION */
.bss : ALIGN(4)
{
_bss = .;
PROVIDE(__start_bss_RAM = .) ;
PROVIDE(__start_bss_SRAM_DTC = .) ;
*(.bss*)
*(COMMON)
. = ALIGN(4) ;
_ebss = .;
PROVIDE(__end_bss_RAM = .) ;
PROVIDE(__end_bss_SRAM_DTC = .) ;
PROVIDE(end = .);
} > SRAM_DTC AT> SRAM_DTC
/* NOINIT section for SRAM_ITC */
.noinit_RAM2 (NOLOAD) : ALIGN(4)
{
PROVIDE(__start_noinit_RAM2 = .) ;
PROVIDE(__start_noinit_SRAM_ITC = .) ;
*(.noinit.$RAM2)
*(.noinit.$SRAM_ITC)
*(.noinit.$RAM2.*)
*(.noinit.$SRAM_ITC.*)
. = ALIGN(4) ;
PROVIDE(__end_noinit_RAM2 = .) ;
PROVIDE(__end_noinit_SRAM_ITC = .) ;
} > SRAM_ITC AT> SRAM_ITC
/* NOINIT section for SRAM_OC */
.noinit_RAM3 (NOLOAD) : ALIGN(4)
{
PROVIDE(__start_noinit_RAM3 = .) ;
PROVIDE(__start_noinit_SRAM_OC = .) ;
*(.noinit.$RAM3)
*(.noinit.$SRAM_OC)
*(.noinit.$RAM3.*)
*(.noinit.$SRAM_OC.*)
. = ALIGN(4) ;
PROVIDE(__end_noinit_RAM3 = .) ;
PROVIDE(__end_noinit_SRAM_OC = .) ;
} > SRAM_OC AT> SRAM_OC
/* NOINIT section for BOARD_SDRAM */
.noinit_RAM4 (NOLOAD) : ALIGN(4)
{
PROVIDE(__start_noinit_RAM4 = .) ;
PROVIDE(__start_noinit_BOARD_SDRAM = .) ;
*(.noinit.$RAM4)
*(.noinit.$BOARD_SDRAM)
*(.noinit.$RAM4.*)
*(.noinit.$BOARD_SDRAM.*)
. = ALIGN(4) ;
PROVIDE(__end_noinit_RAM4 = .) ;
PROVIDE(__end_noinit_BOARD_SDRAM = .) ;
} > BOARD_SDRAM AT> BOARD_SDRAM
/* NOINIT section for NCACHE_REGION */
.noinit_RAM5 (NOLOAD) : ALIGN(4)
{
PROVIDE(__start_noinit_RAM5 = .) ;
PROVIDE(__start_noinit_NCACHE_REGION = .) ;
*(.noinit.$RAM5)
*(.noinit.$NCACHE_REGION)
*(.noinit.$RAM5.*)
*(.noinit.$NCACHE_REGION.*)
. = ALIGN(4) ;
PROVIDE(__end_noinit_RAM5 = .) ;
PROVIDE(__end_noinit_NCACHE_REGION = .) ;
} > NCACHE_REGION AT> NCACHE_REGION
/* DEFAULT NOINIT SECTION */
.noinit (NOLOAD): ALIGN(4)
{
_noinit = .;
PROVIDE(__start_noinit_RAM = .) ;
PROVIDE(__start_noinit_SRAM_DTC = .) ;
*(.noinit*)
. = ALIGN(4) ;
_end_noinit = .;
PROVIDE(__end_noinit_RAM = .) ;
PROVIDE(__end_noinit_SRAM_DTC = .) ;
} > SRAM_DTC AT> SRAM_DTC
/* Reserve and place Heap within memory map */
_HeapSize = 0x1000;
.heap : ALIGN(4)
{
_pvHeapStart = .;
. += _HeapSize;
. = ALIGN(4);
_pvHeapLimit = .;
} > SRAM_DTC
_StackSize = 0x1000;
/* Reserve space in memory for Stack */
.heap2stackfill :
{
. += _StackSize;
} > SRAM_DTC
/* Locate actual Stack in memory map */
.stack ORIGIN(SRAM_DTC) + LENGTH(SRAM_DTC) - _StackSize - 0: ALIGN(4)
{
_vStackBase = .;
. = ALIGN(4);
_vStackTop = . + _StackSize;
} > SRAM_DTC
/* Provide basic symbols giving location and size of main text
* block, including initial values of RW data sections. Note that
* these will need extending to give a complete picture with
* complex images (e.g multiple Flash banks).
*/
_image_start = LOADADDR(.text);
_image_end = LOADADDR(.data) + SIZEOF(.data);
_image_size = _image_end - _image_start;
}
Next I modified the startup code to copy the .got section to DTC sram. I debugged through, the entire .got table is moved uint32 by uint32 to DTC sram. I can see in my memory view that this indeed is copied perfectly. And lastly I set R9 to the start of my .got section in DTC sram.
//
// Copy global offset table to ram
//
global_offset_table_flash = const_cast<unsigned int*>(&__global_offset_table_flash_start__);
global_offset_table_itc = const_cast<unsigned int*>(&__global_offset_table_itc_start__);
global_offset_table_end_itc = const_cast<unsigned int*>(&__global_offset_table_flash_end__);
size =
reinterpret_cast<unsigned int>(&__global_offset_table_flash_end__) -
reinterpret_cast<unsigned int>(&__global_offset_table_itc_start__);
global_offset_table_size = static_cast<unsigned int>(&__global_offset_table_flash_end__ - &__global_offset_table_itc_start__);
for (index = 0u; index < size/sizeof(unsigned int); ++index)
{
global_offset_table_itc[index] = global_offset_table_flash[index];
}
__asm volatile ("LDR r9, = __global_offset_table_itc_start__");
I added the compiler arguments
-fPIC -mpic-register=r9 -msingle-pic-base -mno-pic-data-is-text-relative
resulting in this complete list of compiler arguments
-c -ffunction-sections -fdata-sections -ffreestanding -fno-builtin -fno-rtti -fno-exceptions -fPIC -mpic-register=r9 -msingle-pic-base -mno-pic-data-is-text-relative
I use these compiler arguments for both C and C++ compiler
The compiler version I use is
λ arm-none-eabi-gcc.exe --version
arm-none-eabi-gcc.exe (GNU Arm Embedded Toolchain 10.3-2021.07) 10.3.1 20210621 (release)
I can also push my small project to github if that helps.
Again, the problem is that in one scenario I compile and run my project compiled with -fPIC. Then my program crashes on Data access violation. The memory it’s accessing in the debugger seems perfectly valid. Maybe the indirection caused by the .got is causing the problem. But in the debugger I can see that mentioned variable is perfectly fine. The size of the list is zero in the debugger tool tip. Still when I execute that line of code, the program crashes.
When I compile without -fpic free rtos works just fine. So the only things which is clear to me is that I do something wrong when compiling with -fpic, but I have no clue what, nor do I have any idea how to proceed in figuring out what I do wrong.
Many many thanks for any contribution.
PS: again, if I need to share my project, say the word and I’ll push it to github