I am quite new to linker script concepts.
I have ran into some strange problems.
the sections does not seem to have the right addresses for VMA.
For example if we look at the .data sections the VMA that has been provided in inside LMA+size.
(meaning that during start-up once I copy the data from LMA to VMA the last bytes of LMA addresses will have been overwritten)
This is how the result looks like, see .data and you will see what I mean:
Sections:
Idx Name Size VMA LMA File off Algn
0 .rcw 00000008 20000000 20000000 00010000 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .init 00000628 20000008 20000008 00010008 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
2 .text 000177f8 20000630 20000630 00010630 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
3 .flash_data 00000010 20017e28 20017e28 00027e28 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
4 .rodata 00000ec0 20017e38 20017e38 00027e38 2**4
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .xcptn 000008e8 20019000 20019000 00029000 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
6 .extram 00002080 2001a000 200198e8 0002a000 2**13
CONTENTS, ALLOC, LOAD, DATA
7 .data 000008f0 2001c080 2001b968 0002c080 2**3
CONTENTS, ALLOC, LOAD, DATA
8 .got 00000010 2001c970 2001c258 0002c970 2**2
CONTENTS, ALLOC, LOAD, CODE
9 .got2 00000220 2001c980 2001c268 0002c980 2**2
CONTENTS, ALLOC, LOAD, DATA
10 .sdata 00000038 2001cba0 2001c488 0002cba0 2**2
CONTENTS, ALLOC, LOAD, DATA
11 .sbss 00000088 2001cbd8 2001c4c0 0002cbd8 2**2
ALLOC
12 .bss 0000bbbc 2001cc60 2001c548 0002cbd8 2**2
ALLOC
13 .isrvectbl 00000d88 2002881c 20028104 0002cbd8 2**2
ALLOC
14 .debug_aranges 00001618 00000000 00000000 0002cbd8 2**3
CONTENTS, READONLY, DEBUGGING
15 .debug_pubnames 00002843 00000000 00000000 0002e1f0 2**0
CONTENTS, READONLY, DEBUGGING
16 .debug_info 0003f23a 00000000 00000000 00030a33 2**0
CONTENTS, READONLY, DEBUGGING
17 .debug_abbrev 00009c89 00000000 00000000 0006fc6d 2**0
CONTENTS, READONLY, DEBUGGING
18 .debug_line 0000ae64 00000000 00000000 000798f6 2**0
CONTENTS, READONLY, DEBUGGING
19 .debug_frame 00003bb8 00000000 00000000 0008475c 2**2
CONTENTS, READONLY, DEBUGGING
20 .debug_str 00007b24 00000000 00000000 00088314 2**0
CONTENTS, READONLY, DEBUGGING
21 .debug_loc 00015465 00000000 00000000 0008fe38 2**0
CONTENTS, READONLY, DEBUGGING
22 .debug_ranges 00001768 00000000 00000000 000a52a0 2**3
CONTENTS, READONLY, DEBUGGING
23 .comment 00000750 00000000 00000000 000a6a08 2**0
CONTENTS, READONLY
24 .gnu.attributes 00000012 00000000 00000000 000a7158 2**0
CONTENTS, READONLY
the following ld-script is the one that has been provided to me:
ENTRY(__start)
/*
*****************************************************************
* PE_MPC5554_rom.ld
* GNU powerpc-eabispe Linker Script for the MPC5554
* By default, this application runs in internal flash, SRAM, and cache
* c. 2005, P&E Microcomputer Systems, Inc.
* REV AUTHOR DATE DESCRIPTION OF CHANGE
* --- ----------- ---------- ---------------------
* 0.1 C.Baker FSL 19/Jul/06 Changed memory layout, stack
* variables, and filename.
* 0.2 C.Baker FSL 21/Sep/06 Changed stack in cache address.
*****************************************************************
*/
MEMORY
{
/* 32M External SRAM */
ext_ram : org = 0x20000000, len = 0x02000000 /* 32M on the G3 board */
/* Internal Flash RCW */
/* MPC5567 2M Internal Flash, but subtract two 128K blocks for use by emulated eeprom. */
/* but subtract one 128K block for use by BAM. */
/* MPC5567 80K Internal SRAM */
flash_rcw : org = 0x00000000, len = 0x8
int_flash : org = 0x00000008, len = 0x001BFFF8
int_sram : org = 0x40000000, len = 0x14000
/* e4_flash is reserved for emulated eeprom in partition 9 of the High Address Space. */
e4_flash : org = 0x001C0000, len = 0x40000
}
/* The performance of applications can, potentially, be improved by locking */
/* the stack into the cache. However, as this complicates debugging (e.g., */
/* function parameters are not visible from GDB) it is only advisable for */
/* production code, not during development. Set STACK_IN_CACHE to 1 in the */
/* application's "config.inc" to lock the stack into cache. Otherwise, set */
/* STACK_IN_CACHE to 0, and the stack will be placed at the top of the */
/* internal RAM. */
/* Stack Address Parameters */
/* __SP_END = DEFINED( STACK_IN_CACHE ) ? 0x40040000 : 0x40013000; */
__SP_END = 0x40013000;
__STACK_SIZE = 0x1000;
__SP_INIT = __SP_END + __STACK_SIZE;
/*
Optionally define this variable with the address of heap
__heap_start = __SP_END;
*/
/****************************************************************/
SECTIONS
{
.rcw :
{
KEEP( *(.rcw) )
} > ext_ram
/* CRT0 startup code */
.pecrt0 ALIGN(8) :
{
*(.pecrt0)
PEFILL = .;
. = ALIGN(8);
} > ext_ram
.interp ALIGN(8) :
{
*(.interp)
. = ALIGN(8);
} > ext_ram
.hash ALIGN(8) :
{
*(.hash)
. = ALIGN(8);
} > ext_ram
.dynsym ALIGN(8) :
{
*(.dynsym)
. = ALIGN(8);
} > ext_ram
.dynstr ALIGN(8) :
{
*(.dynstr)
. = ALIGN(8);
} > ext_ram
.rela.dyn ALIGN(8) :
{
*(.rela.init)
*(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
*(.rela.fini)
*(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
*(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
*(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
*(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
*(.rela.ctors)
*(.rela.dtors)
*(.rela.got)
*(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*)
*(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*)
*(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*)
*(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*)
*(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
. = ALIGN(8);
} > ext_ram
.init ALIGN(8) :
{
PROVIDE (__init = .);
KEEP( *(.init) )
. = ALIGN(8);
} > ext_ram
.text ALIGN(8) :
{
*(.text)
*(.text.*)
*(.gnu.warning)
*(.gnu.linkonce.t*)
__eabi = (.); /*PE*/
LONG(0x4E800020);
. = ALIGN(8);
} > ext_ram
.fini ALIGN(8) :
{
/*PROVIDE (__fini = .);*/
KEEP( *(.fini) )
. = ALIGN(8);
} > ext_ram
.flash_data ALIGN(8) :
{
KEEP( *(.flash_data))
. = ALIGN(8);
} > ext_ram
.rodata ALIGN(8) :
{
. = ALIGN(8);
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r*)
. = ALIGN(8);
} > ext_ram
.rodata1 ALIGN(8) :
{
*(.rodata1)
. = ALIGN(8);
} > ext_ram
.PPC.EMB.apuinfo ALIGN(8) :
{
*(.PPC.EMB.apuinfo)
. = ALIGN(8);
} > ext_ram AT > ext_ram
/* ISR table for software vector mode */
.isrvectbl ALIGN(0x800) : ONLY_IF_RO
{
KEEP( *(.isrvectbl) )
} > ext_ram
PROVIDE (__EXCEPT_START__ = .);
/* IVOR4Handler */
.xcptn ALIGN(8) :
{
KEEP( *(.xcptn) )
. = ALIGN(8);
} > ext_ram
PROVIDE (__EXCEPT_END__ = .);
etext = .;
_etext = .;
__etext = .;
/******************************************************************/
NEXT_LOAD_ADDR = .;
__EXTDATA_ROM = .;
.extram : AT (NEXT_LOAD_ADDR)
{
*(.extram)
. = ALIGN(4);
} > ext_ram
/******************************************************************/
NEXT_LOAD_ADDR = NEXT_LOAD_ADDR + SIZEOF(.extram);
/*NEXT_LOAD_ADDR = .;
__DATA_ROM = .;*/
__DATA_ROM = NEXT_LOAD_ADDR;
/* .PPC.EMB.sdata2 0x20100000 : AT (NEXT_LOAD_ADDR)*/
.PPC.EMB.sdata2 : AT (NEXT_LOAD_ADDR)
{
_SDA2_BASE_ = .;
__SDATA2_START__ = .;
*(.PPC.EMB.sdata2)
. = ALIGN(8);
} > ext_ram
NEXT_LOAD_ADDR = NEXT_LOAD_ADDR + SIZEOF(.PPC.EMB.sdata2);
.sdata2 : AT (NEXT_LOAD_ADDR)
{
*(.sdata2)
. = ALIGN(8);
} > ext_ram
NEXT_LOAD_ADDR = NEXT_LOAD_ADDR + SIZEOF(.sdata2);
.PPC.EMB.sbss2 : AT (NEXT_LOAD_ADDR)
{
*(.PPC.EMB.sbss2)
. = ALIGN(8);
} > ext_ram
NEXT_LOAD_ADDR = NEXT_LOAD_ADDR + SIZEOF(.PPC.EMB.sbss2);
.sbss2 : AT (NEXT_LOAD_ADDR)
{
*(.sbss2)
__SBSS2_END__ = .;
. = ALIGN(8);
} > ext_ram
NEXT_LOAD_ADDR = NEXT_LOAD_ADDR + SIZEOF(.sbss2);
.data :
{
*(.data)
*(.data.*)
*(.gnu.linkonce.d*)
CONSTRUCTORS
. = ALIGN(8);
} > ext_ram
NEXT_LOAD_ADDR = NEXT_LOAD_ADDR + SIZEOF(.data);
.data1 :
{
*(.data1)
. = ALIGN(8);
} > ext_ram
NEXT_LOAD_ADDR = NEXT_LOAD_ADDR + SIZEOF(.data1);
PROVIDE (__GOT_START__ = .);
.got :
{
*(.got)
. = ALIGN(8);
} > ext_ram
NEXT_LOAD_ADDR = NEXT_LOAD_ADDR + SIZEOF(.got);
.got.plt :
{
*(.got.plt)
. = ALIGN(8);
} > ext_ram
PROVIDE (__GOT_END__ = .);
NEXT_LOAD_ADDR = NEXT_LOAD_ADDR + SIZEOF(.got.plt);
.got1 :
{
*(.got1)
. = ALIGN(8);
} > ext_ram
NEXT_LOAD_ADDR = NEXT_LOAD_ADDR + SIZEOF(.got1);
PROVIDE (__GOT2_START__ = .);
.got2 :
{
*(.got2)
. = ALIGN(8);
} > ext_ram
NEXT_LOAD_ADDR = NEXT_LOAD_ADDR + SIZEOF(.got2);
PROVIDE (__CTOR_LIST__ = .);
.ctors :
{
/*KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))*/
KEEP (*(.ctors))
. = ALIGN(8);
} > ext_ram
NEXT_LOAD_ADDR = NEXT_LOAD_ADDR + SIZEOF(.ctors);
PROVIDE (__CTOR_END__ = .);
PROVIDE (__DTOR_LIST__ = .);
.dtors : AT (NEXT_LOAD_ADDR)
{
/*KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))*/
KEEP (*(.dtors))
. = ALIGN(8);
} > ext_ram
NEXT_LOAD_ADDR = NEXT_LOAD_ADDR + SIZEOF(.dtors);
PROVIDE (__DTOR_END__ = .);
PROVIDE (__FIXUP_START__ = .);
.fixup : AT (NEXT_LOAD_ADDR)
{
*(.fixup)
. = ALIGN(8);
} > ext_ram
NEXT_LOAD_ADDR = NEXT_LOAD_ADDR + SIZEOF(.fixup);
PROVIDE (__FIXUP_END__ = .);
PROVIDE (__GOT2_END__ = .);
.dynamic : AT (NEXT_LOAD_ADDR)
{
*(.dynamic)
. = ALIGN(8);
} > ext_ram
NEXT_LOAD_ADDR = NEXT_LOAD_ADDR + SIZEOF(.dynamic);
.plt : AT (NEXT_LOAD_ADDR)
{
*(.plt)
. = ALIGN(8);
} > ext_ram
NEXT_LOAD_ADDR = NEXT_LOAD_ADDR + SIZEOF(.plt);
/* We want the small data sections together, so single-instruction offsets
can access them all, and initialized data all before uninitialized, so
we can shorten the on-disk segment size. */
__SDATA_ROM = .;
.sdata :
{
__SDATA_START__ = .;
_SDA_BASE_ = .;
*(.sdata)
. = ALIGN(8);
} > ext_ram
NEXT_LOAD_ADDR = NEXT_LOAD_ADDR + SIZEOF(.sdata);
.PPC.EMB.sdata0 : AT (NEXT_LOAD_ADDR)
{
__SDATA_END__ = .;
. = ALIGN(8);
} > ext_ram
__DATA_ROM_END = .;
edata = .;
_edata = .;
__edata = .;
/******************************************************************/
.sbss BLOCK (4):
{
PROVIDE (__sbss_start = .);
PROVIDE (___sbss_start = .);
*(.sbss)
*(.scommon)
*(.dynsbss)
} > ext_ram
.PPC.EMB.sbss0 BLOCK (4):
{
*(.PPC.EMB.sbss0)
PROVIDE (__sbss_end = .);
PROVIDE (___sbss_end = .);
PROVIDE (__SBSS_END__ = .);
} > ext_ram
.bss BLOCK (4):
{
PROVIDE (__bss_start = .);
PROVIDE (___bss_start = .);
*(.dynbss)
*(.bss)
*(COMMON)
PROVIDE (__bss_end = .);
} > ext_ram
.isrvectbl BLOCK (4) (NOLOAD): ONLY_IF_RW
{
. = ALIGN(0x800);
KEEP( *(.isrvectbl) )
} > ext_ram
/* ISR table for software vector mode */
/******************************************************************/
/*
Heap grows from lower to higer addresses
Stack grows from higer to lower addresses
*/
/* Define position of heap */
/* Default to location contiguous with .bss section in RAM */
_end = DEFINED (__heap_start) ? __heap_start : ALIGN(8);
PROVIDE(end = _end);
PROVIDE(__end = _end);
/******************************************************************/
.gcc_except_table : {*(.gcc_except_table)}
/* These are needed for ELF backends which have not yet been
converted to the new style linker. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* */
.eh_frame 0 : { *(.eh_frame) }
/******************************************************************/
__SRAM_CPY_START = ADDR(.PPC.EMB.sdata2);
__IV_ADDR = ADDR(.xcptn);
__SRAM_LOAD = (_end);
__SRAM_LOAD_SIZE = (SIZEOF(.flash_data) / 4);
__EXTRAM_CPY_START = ADDR(.extram);
__EXTRAM_CPY_END = ADDR(.extram)+SIZEOF(.extram);
__BSS_SIZE = ((__bss_end - __bss_start) / 4);
__SBSS_SIZE = ((__sbss_end - __sbss_start) / 4);
TEMPSIZE = SIZEOF(.PPC.EMB.sdata2)+SIZEOF(.sdata2)+SIZEOF(.PPC.EMB.sbss2)+SIZEOF(.sbss2)+SIZEOF(.data)+SIZEOF(.data1);
TEMPSIZE = TEMPSIZE + SIZEOF(.got)+SIZEOF(.got.plt)+SIZEOF(.got1)+SIZEOF(.got2)+SIZEOF(.ctors);
TEMPSIZE = TEMPSIZE + SIZEOF(.dtors)+SIZEOF(.fixup)+SIZEOF(.dynamic)+SIZEOF(.plt);
TEMPSIZE = TEMPSIZE + SIZEOF(.sdata)+SIZEOF(.PPC.EMB.sdata0);
__ROM_COPY_SIZE = (TEMPSIZE);
__DATA_VMA = ADDR(.data);
__DATA_LMA = LOADADDR(.data);
__DATA_LMA_END = __DATA_LMA + SIZEOF(.data);
__GOT_VMA = ADDR(.got);
__GOT_LMA = LOADADDR(.got);
__GOT_LMA_END = __GOT_LMA + SIZEOF(.got);
__GOT2_VMA = ADDR(.got2);
__GOT2_LMA = LOADADDR(.got2);
__GOT2_LMA_END = __GOT_LMA + SIZEOF(.got2);
__SDATA_VMA = ADDR(.sdata);
__SDATA_LMA = LOADADDR(.sdata);
__SDATA_LMA_END = __SDATA_LMA + SIZEOF(.sdata);
}
EDIT1:
I get no error/warning when I make all.
The linker is suppose to build everything for external memory with starts at 0x20 000000.
It seems your linker skript tries to compress the image for storage in flash.
During runtime your image is copied to other addresses maybe because of MMU alignment restrictions.
Does the linker emit an error message or is this just that your code does not behave correctly at runtime?
The copy problem you mentioned can be easily bypassed if you copy the sections "backwards".
Copy the last item of the .data section to its runtime address, then copy the next-to-last item to its runtime address...
Related
I am writing a project with STM32H7. The project contains RTC, SPI, USART, SD Card, timers, and I2C.
In order to have more RAM, I have brought the data and bss to RAM_D1.
I did this by changing the linker file.
As next steps I want to implement Ethernet. However, I realized that in order for Ethernet to work, I need to only use RAM_D1.
The problem is when I bring the heap and stack to RAM_D1, the project stops working.
Can someone please help?
I include the linker script before and after bringing everything to RAM_D1.
Thank you in advance for your help.
I include the linker files before and after change below.
Before changing, everything works at this stage:
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x20020000; /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200; /* required amount of heap */
_Min_Stack_Size = 0x8000; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
DTCMRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
RAM_D1 (xrw) : ORIGIN = 0x24000000, LENGTH = 512K
RAM_D2 (xrw) : ORIGIN = 0x30000000, LENGTH = 288K
RAM_D3 (xrw) : ORIGIN = 0x38000000, LENGTH = 64K
ITCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 2048K
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
/* The program code and other data goes into FLASH */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >FLASH
/* Constant data goes into FLASH */
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} >FLASH
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH
/* used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM_D1 AT> FLASH
/* Uninitialized data section */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM_D1
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(4);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(4);
} >DTCMRAM
/* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}
After changing the RAM section for heap and stack, at this stage the program stops working
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x20020000; /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200; /* required amount of heap */
_Min_Stack_Size = 0x8000; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
DTCMRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
RAM_D1 (xrw) : ORIGIN = 0x24000000, LENGTH = 512K
RAM_D2 (xrw) : ORIGIN = 0x30000000, LENGTH = 288K
RAM_D3 (xrw) : ORIGIN = 0x38000000, LENGTH = 64K
ITCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 2048K
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
/* The program code and other data goes into FLASH */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >FLASH
/* Constant data goes into FLASH */
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} >FLASH
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH
/* used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM_D1 AT> FLASH
/* Uninitialized data section */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM_D1
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(4);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(4);
} >RAM_D1
/* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}
Your help is greatly appreciated, thank you in advance.
Your _estack variable (which is end of RAM address) is still set to 0x2002000, which is DTCRAM location + it's size (128K). To get everything working, change your _estack variable to this:
_estack = 0x24080000; /* end of RAM */
What is Address of D1 Memory + it's size (512K). (0x24000000 + (512 * 1024))
I have done something silly probably but can't find the error:
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x10004000; /* end of CCMRAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x100; /* required amount of heap */
_Min_Stack_Size = 0x1000; /* required amount of stack */
/* Specify the memory areas */
_configLength = 2K;
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K
CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 16K
CONFIG (rx) : ORIGIN = 0x8000000 + 512K - _configLength, LENGTH = _configLength
FLASH (rx) : ORIGIN = 0x8000000 + 32K, LENGTH = 512K - _configLength - 32K
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
.sizedata :
{
. = ALIGN(4);
KEEP(*(.sizedata))
KEEP(*(.sizedata*))
. = ALIGN(4);
} >FLASH
/* The program code and other data goes into FLASH */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >FLASH
/* Constant data goes into FLASH */
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} >FLASH
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH
_ROMEND = .;
/* used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >CCMRAM AT> FLASH
_ROMSIZE = _ROMEND + SIZEOF(.data) - ORIGIN(FLASH);
_siconfig = LOADADDR(.configsection);
.configsection :
{
. = ALIGN(4);
_sconfig = .;
/*KEEP(*(.configsection))
(.configsection*)*/
. = ALIGN(4);
_econfig = _sconfig + _configLength;
} > CONFIG
_sisram = LOADADDR(.sram);
/* CCM-RAM section
*
* IMPORTANT NOTE!
* If initialized variables will be placed in this section,
* the startup code needs to be modified to copy the init-values.
*/
.sram :
{
. = ALIGN(4);
_ssram = .; /* create a global symbol at ccmram start */
*(.ram)
*(.ram*)
. = ALIGN(4);
_esram = .; /* create a global symbol at ccmram end */
} >RAM
/* Uninitialized data section */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >CCMRAM
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(8);
} >CCMRAM
/* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
*(.configsection)
*(.configsection*)
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}
If you kindly could take a look :) The elf file is OK. I can program & debug program.
I run command:
arm-none-eabi-gcc -T STM32F100XB_FLASH.ld -o main.elf main.c lcd.c c2b.c startup_stm32f100xb.s system_stm32f10x.c stm32f10x_gpio.c stm32f10x_rcc.c -specs=nosys.specs
but got error like this
/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/bin/ld:STM32F100XB_FLASH.ld:1: syntax error
collect2: error: ld returned 1 exit status
syntax error in this file(STM32F100XB_FLASH):
0
/* Entry Point */
ENTRY(Reset_Handler)
0
/* Highest address of the user mode stack */
_estack = 0x20001FFF; /* end of RAM */
0
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */
0
/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K
}
0
/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
0
/* The program code and other data goes into FLASH */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
0
KEEP (*(.init))
KEEP (*(.fini))
0
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >FLASH
0
/* Constant data goes into FLASH */
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} >FLASH
0
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH
0
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH
0
/* used by the startup to initialize data */
_sidata = LOADADDR(.data);
0
/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
0
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM AT> FLASH
0
/* Uninitialized data section */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
0
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM
0
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(4);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(4);
} >RAM
0
0
/* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
0
.ARM.attributes 0 : { *(.ARM.attributes) }
}
Thas Linker script file publish by st.com in STM32Cube_FW_F1_V1.4.0.zip firmware file for STMCUBEMX ( I extracted that and find some file including STM32F100XB_FLASH.ld)
but when change linker script file with other one not official! compile and link successfully.
arm-none-eabi-gcc -T stm32f100.ld -o main.elf main.c lcd.c c2b.c startup_stm32f100xb.s system_stm32f10x.c stm32f10x_gpio.c stm32f10x_rcc.c -specs=nosys.specs
and the stm32f100.ld file:
/*
Linker script for STM32F10x_128K_8K
modified from
http://www.codesourcery.com/archives/arm-gnu/msg02972.html
http://communities.mentor.com/community/cs/archives/arm-gnu/msg02972.html
*/
/*
There will be a link error if there is not this amount of RAM free at the
end.
*/
_Minimum_Stack_Size = 256;
ENTRY(Reset_Handler)
/* Memory Spaces Definitions */
MEMORY
{
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 8K
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K
}
__ram_start__ = ORIGIN(RAM);
__ram_size__ = LENGTH(RAM);
__ram_end__ = __ram_start__ + __ram_size__;
_estack = __ram_end__;
/* highest address of the user mode stack */
PROVIDE ( _Stack_Limit = _estack - _Minimum_Stack_Size );
/* Sections Definitions */
SECTIONS
{
.text :
{
KEEP(*(.isr_vector)) /* Startup code */
*(.text) /* code */
*(.text.*) /* remaining code */
*(.rodata) /* read-only data (constants) */
*(.rodata.*)
*(.glue_7)
*(.glue_7t)
*(.vfp11_veneer)
*(.v4_bx)
*(.ARM.extab* .gnu.linkonce.armextab.*)
} >FLASH
/* for exception handling/unwind - some Newlib functions (in
common with C++ and STDC++) use this. */
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > FLASH
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > FLASH
__exidx_end = .;
. = ALIGN(4);
_etext = .;
/* This is used by the startup in order to initialize the .data secion
*/
_sidata = _etext;
/* This is the initialized data section
The program executes knowing that the data is in the RAM
but the loader puts the initial values in the FLASH (inidata).
It is one task of the startup to copy the initial values from FLASH to
RAM. */
.data : AT ( _sidata )
{
. = ALIGN(4);
/* This is used by the startup in order to initialize the .data
secion */
_sdata = . ;
*(.data)
*(.data.*)
. = ALIGN(4);
/* This is used by the startup in order to initialize the .data
secion */
_edata = . ;
} >RAM
/* This is the uninitialized data section */
.bss :
{
. = ALIGN(4);
/* This is used by the startup in order to initialize the .bss
secion */
_sbss = .;
__bss_start__ = _sbss;
*(.bss)
*(.bss.*)
*(COMMON)
. = ALIGN(4);
/* This is used by the startup in order to initialize the .bss
secion */
_ebss = . ;
__bss_end__ = _ebss;
} >RAM
PROVIDE ( end = _ebss );
PROVIDE ( _end = _ebss );
PROVIDE ( _exit = _ebss );
PROVIDE (_stackend = ORIGIN(RAM) + LENGTH(RAM) - _Minimum_Stack_Size);
/* This is the user stack section
This is just to check that there is enough RAM left for the User mode
stack
It should generate an error if it's full.
*/
._usrstack :
{
. = ALIGN(4);
_susrstack = . ;
. = . + _Minimum_Stack_Size ;
. = ALIGN(4);
_eusrstack = . ;
} >RAM
/* after that it's only debugging information. */
/* remove the debugging information from the standard libraries */
/*
DISCARD :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
*/
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
}
Whats wrong with STM32F100XB_FLASH.ld???
All the zeroes that you have at the beginning of lines are wrong and that's what ld is telling you.
0 <-- error
/* Entry Point */
ENTRY(Reset_Handler)
0 <-- error
/* Highest address of the user mode stack */
_estack = 0x20001FFF; /* end of RAM */
0 <-- error
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */
0 <-- error
...
The file in the package is indeed broken, as are all the files from this folder (Drivers/CMSIS/Device/ST/STM32F1xx/Source/Templates/gcc/linker/). My suggestion would be to use any of the files from the Projects/ folder and just change the values of flash/ram addresses and sizes to match your device (you can take them from the file which is broken).
If you just take this one - Projects/STM32VL-Discovery/Examples/ADC/ADC_Regular_injected_groups/TrueSTUDIO/STM32VL-Discovery/STM32F100VB_FLASH.ld - then you won't need to change anything, as the sizes and addresses are OK for your device (assuming it's a device with 128kB of flash and 8kB of RAM).
my code here:
void _init(void) {return;}
int main(void)
{
/* STM32F2xx HAL library initialization:
- Configure the Flash prefetch, instruction and Data caches
- Configure the Systick to generate an interrupt each 1 msec
- Set NVIC Group Priority to 4
- Global MSP (MCU Support Package) initialization
*/
HAL_Init();
/* Configure the system clock to 64 MHz */
SystemClock_Config();
/* Enable CRC clock */
__CRC_CLK_ENABLE();
Example_Status = 1;
Example_Status = 2;
Example_Status = 3;
.....
and my gdb on my stm32 using stlink-texane are as follow:
(gdb) s
main () at main.c:74
74 __CRC_CLK_ENABLE();
(gdb) s
77 Example_Status = 3;
(gdb) p Example_status
No symbol "Example_status" in current context.
(gdb) p Example_Status
$1 = 139640994
(gdb) n
74 __CRC_CLK_ENABLE();
(gdb) n
77 Example_Status = 3;
(gdb) n
183 Example_Status = ExampleECCKeyGenSignVerif();
(gdb) p Example_Status
$2 = 139640994
i am wondering why the Example_Status outcome not = 3 ?
and the storage of the variable are
arm-none-eabi-objdump --syms main.o | grep Example_Status
00000000 l d .bss.Example_Status 00000000 .bss.Example_Status
00000000 g O .bss.Example_Status 00000004 Example_Status
and my linker file are here:
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x20010000; /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x000;; /* required amount of heap */
_Min_Stack_Size = 0x000;; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 128K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
/* The program code and other data goes into FLASH */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >FLASH
/* Constant data goes into FLASH */
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} >FLASH
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH
/* used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM AT> FLASH
/* Uninitialized data section */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(8);
} >RAM
/* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}
This is my first linux project, i would appreicate if someone can help~
thanks
Edited for adding "disassemble /m"
75 Example_Status = 1;
0x080002ac <+24>: and.w r3, r3, #33554432 ; 0x2000000
0x080002b0 <+28>: cmp r3, #0
---Type <return> to continue, or q <return> to quit---
76 Example_Status = 2;
0x080002b2 <+30>: beq.n 0x80002a8 <main+20>
0x080002b4 <+32>: ldr r3, [pc, #60] ; (0x80002f4 <main+96>)
0x080002b6 <+34>: movw r2, #1795 ; 0x703
77 Example_Status = 3;
0x080002b8 <+36>: strb r3, [r0, #8]
0x080002ba <+38>: str r2, [r3, #0]
0x080002bc <+40>: ldr r2, [pc, #44] ; (0x80002ec <main+88>)
//
(gdb) n
75 Example_Status = 1;
(gdb) n
76 Example_Status = 2;
(gdb) p Example_Status
$1 = 140166176
(gdb) s
When compiling, and you want reliable debugging, do not compile with optimization-level higher than 0:
gcc -O0 mycode.c -o mycode.o -c
I made my own bootloader for an STM32L1 board.
My algorithm is simple :
- first, I erase the memory I need to write my new program on my flash.
- then, I write 4 bytes per 4 bytes my new program ( I receive it from the USART of the board)
then i push the RESET button of my card, and nothing happens ...
My new program should blink a LED but nothing happens and I d'ont understand why ...
Do i have to write my own RESET function?
Here is my code if you want to give a try.
void BootLoader(void) {
//clear all ITs
USART_ITConfig_boot( USART1, USART_IT_RXNE, 0);
uint32_t start_adr, end_adr;
uint8_t status, i;
uint8_t buffer[4096];
uint8_t sizeRcv[2];
uint16_t tailleSector = 0x1000;
uint32_t adr;
uint8_t nbSector = 0;
//size fixée en dur
uint16_t k = 0;
uint8_t size1 = 0;
uint8_t size2 = 0;
uint16_t sizeBin = 0;
//taille sector
uint16_t tailleSecteurDec = 4096;
SendString_boot("BOOTLOADER ON.....\r\n", USART2);
//adress
//First Sector
start_adr = WRITE_START_ADDR;
end_adr = start_adr + tailleSector;
//erasing flags
FLASH_ClearFlag_boot(
FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR
| FLASH_FLAG_SIZERR | FLASH_FLAG_OPTVERR
| FLASH_FLAG_OPTVERRUSR | FLASH_FLAG_RDERR);
FLASH_Unlock_boot();
sizeBin = 51400;
nbSector = (uint8_t) (sizeBin / tailleSecteurDec) + 1;
if(nbSector > 30){
SendString_boot("cannot overrite memory : too much sectors used\r\n",USART2);
}
for (i = 0; i <= (127 - 1); i++) {
if(end_adr < 0x0808FFFF){
status = Flash_Erase(start_adr, end_adr);
start_adr = end_adr;
end_adr = end_adr + tailleSector;
SendString_boot(" ERASING SECTOR DONE \r\n", USART2);
}
else{
SendString_boot("END OF FLASH MEMORY\r\n", USART2);
}
}
SendString_boot("ERASING COMPLETE\r\n", USART2);
start_adr = WRITE_START_ADDR;
//receive frames
adr = WRITE_START_ADDR;
do {
SendString_boot("ACK_READY", USART1);
SendString_boot("ACK_READY\r\n", USART2);
//receive 32 bytes
if (sizeBin - k > 4096)
Receive_Data_boot(buffer, 4096);
else
Receive_Data_boot(buffer, sizeBin - k);
//write 32 bytes in memory
if (sizeBin - k > 4096)
status = Flash_Write(adr, buffer, 4096);
else
status = Flash_Write(adr, buffer, sizeBin - k);
//on check si on ecrit bien au bon endroit
//increment cpt
k = k + 4096;
adr = adr + 0x1000;
i++;
//check CRC
//TODO
SendString_boot("...FLASH DONE ON ", USART2);
SendString_boot("\r\n", USART2);
SendString_boot(" SECTOR DONE \r\n", USART2);
} while (k < sizeBin);
SendString_boot("END", USART1);
SendString_boot("ACK_END\r\n", USART2);
FLASH_Lock_boot();
}
The linker script is:
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x20014000; /* end of 96K RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
BOOT (rx) : ORIGIN = 0x0801E000, LENGTH = 8K
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K-8K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 80K
MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
/* The program code and other data goes into FLASH */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >FLASH
/* Constant data goes into FLASH */
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} >FLASH
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH
/* used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
*(.RamFunc) /* .RamFunc sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM AT> FLASH
/* Uninitialized data section */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(4);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(4);
} >RAM
/* MEMORY_bank1 section, code must be located here explicitly */
/* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */
.memory_b1_text :
{
*(.mb1text) /* .mb1text sections (code) */
*(.mb1text*) /* .mb1text* sections (code) */
*(.mb1rodata) /* read-only data (constants) */
*(.mb1rodata*)
} >MEMORY_B1
/* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.bootsection :
{
. = ALIGN(4);
KEEP(*(.bootsection)) /* Bootloader code */
. = ALIGN(4);
} >BOOT
.ARM.attributes 0 : { *(.ARM.attributes) }
}
Receive_data_boot code :
void Receive_Data_boot(uint8_t * buffer, int size) {
uint16_t i = 0;
do {
buffer[i] = Uart2ReadChar_boot();
i++;
} while (i < size);
}
uint8_t Uart2ReadChar_boot(void) {
while(USART_GetFlagStatus_boot(USART1, USART_FLAG_RXNE) == 0);
return USART_ReceiveData_boot(USART1);
}
uint16_t USART_ReceiveData_boot(USART_TypeDef_boot* USARTx)
{
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH_BOOT(USARTx));
SendChar_boot((uint8_t)USARTx->DR,USART1);
/* Receive Data */
return ((uint16_t)(USARTx->DR & (uint16_t)0x01FF));
}
To start your new program from FLASH after RESET the following conditions must be satisfied:
Written image contains correct Reset_Handler which will be executed after POR. Typically this is defined in startup.S and ended with something like:
bl SystemInit
bl main
bx lr
Pin BOOT0 of your processor must be set 0.
Example.
From startup.S:
.section .isr_vector,"a",%progbits
.type g_pfnVectors, %object
.size g_pfnVectors, .-g_pfnVectors
g_pfnVectors:
.word _estack
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
...
From program assembly listing:
08008fd8 <Reset_Handler>:
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
/* Copy the data segment initializers from flash to SRAM */
movs r1, #0
8008fd8: 2100 movs r1, #0
From hex-file:
:020000040800F2
:1000000000000220D98F0008F9070008FD0700084A
Note address 0x08008fd9 in hex file (:1000000000000220D98F0008F9070008FD0700084A) that match Reset_Handler with LSB set (Thumb2-mode).