│ Section │ Description │ ├─────────┼──────────────────────────────────────────────┤ │ data │ static initialized, initial values in flash │ │ bss │ static unassigned, cleared │ │ heap │ dynamically allocated, user managed │ │ stack │ automatically allocated, stack frame managed │My bootstrap since the first boot.c already initializes the stack. I need now to copy the initial values from flash to the data section and clear the bss section.
You can check your understanding of the C memory model by looking at the C test code below and figuring where the linker will allocate the variables.
/** Test code: main.c *********************************************************/ const char hexa[] = "0123456789abcdef" ; long first = 1 ; long i ; int main( void) { static char c = 'a' ; char *cp = &c ; *cp += i ; i += hexa[ 13] - c + first++ ; return 0 ; }
first
and c
, for a
total of 8 bytes as sections are word aligned.
i
for a total of 4 bytes.
hexa
with all the const data
located after the code. As it is a zero terminated string, it occupies 17 bytes
and is padded with 3 zero for word alignment.
first
and
c
for a total of 8 bytes located after the const data.
cp
, it is dynamically managed by
the code generated by the C compiler.
main()
, hexa
and c
are unchanged, first
has the value 2, i
has the
value 4 and cp
has been deallocated.
I add the symbols defined by the linker script:
__etext
, start of initial value copy in FLASH.
__data_start
, start of initialized data in RAM.
__bss_start
, start of unitialized data in RAM, it is the same
location as __data_end
.
__bss_end
, first location after the bss section.
Reset_handler()
to:
main()
C function.
main()
has been executed.
/* Memory locations defined by linker script */ extern long __StackTop ; /* &__StackTop points after end of stack */ void Reset_Handler( void) ; /* Entry point for execution */ extern const long __etext[] ; /* start of initialized data copy in flash */ extern long __data_start__[] ; extern long __bss_start__[] ; extern long __bss_end__ ; /* &__bss_end__ points after end of bss */ /* Interrupt vector table: * 1 Stack Pointer reset value * 15 System Exceptions * NN Device specific Interrupts */ typedef void (*isr_p)( void) ; isr_p const isr_vector[ 2] __attribute__((section(".isr_vector"))) = { (isr_p) &__StackTop, /* System Exceptions */ Reset_Handler } ; extern int main( void) ; void Reset_Handler( void) { const long *f ; /* from, source constant data from FLASH */ long *t ; /* to, destination in RAM */ /* Assume: ** __bss_start__ == __data_end__ ** All sections are 4 bytes aligned */ f = __etext ; for( t = __data_start__ ; t < __bss_start__ ; t += 1) *t = *f++ ; while( t < &__bss_end__) *t++ = 0 ; main() ; for( ;;) ; } /** Test code: main.c *********************************************************/ const char hexa[] = "0123456789abcdef" ; long first = 1 ; long i ; int main( void) { static char c = 'a' ; char *cp = &c ; *cp += i ; i += hexa[ 13] - c + first++ ; return 0 ; }
$ make cstartup.bin cstartup.elf text data bss dec hex filename 121 8 4 133 85 cstartup.elf cstartup.bin rm cstartup.o cstartup.elfIf I look further in the cstartup.map generated by the linker.
.text 0x08000000 0x79 *(.isr_vector) .isr_vector 0x08000000 0x8 cstartup.o 0x08000000 isr_vector *(.text*) .text 0x08000008 0x34 cstartup.o 0x08000008 Reset_Handler .text.startup 0x0800003c 0x2c cstartup.o 0x0800003c main *(.rodata*) .rodata 0x08000068 0x11 cstartup.o 0x08000068 hexa .data 0x20000000 0x8 load address 0x0800007c 0x20000000 __data_start__ = . *(.data*) .data 0x20000000 0x8 cstartup.o 0x20000004 first 0x20000008 . = ALIGN (0x4) 0x20000008 __data_end__ = . .bss 0x20000008 0x4 load address 0x08000084 0x20000008 . = ALIGN (0x4) 0x20000008 __bss_start__ = . *(.bss*) .bss 0x20000008 0x0 cstartup.o *(COMMON) COMMON 0x20000008 0x4 cstartup.o 0x20000008 i 0x2000000c . = ALIGN (0x4) 0x2000000c __bss_end__ = . *(.stack*) 0x20001000 __StackTop = (ORIGIN (RAM) + LENGTH (RAM))
hexa
is located in .rodata at 0x08000068
first
is located in .data at 0x20000004
i
is located in .bss at 0x20000008
c
is not listed as it doesn’t have global scope, but I can
guess it’s located at 0x20000000.
c
is at offset 0x7c, which also means that c
has
been located at 0x20000000.
$ hexdump -C cstartup.bin 00000000 00 10 00 20 09 00 00 08 10 b5 08 4a 08 4b 09 49 |... .......J.K.I| 00000010 8b 42 06 d3 00 21 08 4a 93 42 05 d3 00 f0 0e f8 |.B...!.J.B......| 00000020 fe e7 01 ca 01 c3 f3 e7 02 c3 f5 e7 7c 00 00 08 |............|...| 00000030 00 00 00 20 08 00 00 20 0c 00 00 20 30 b5 08 49 |... ... ... 0..I| 00000040 08 48 0a 78 04 68 4b 68 12 19 d2 b2 5d 1c 9b 1a |.H.x.hKh....]...| 00000050 64 33 1b 19 4d 60 03 60 0a 70 00 20 30 bd c0 46 |d3..M`.`.p. 0..F| 00000060 00 00 00 20 08 00 00 20 30 31 32 33 34 35 36 37 |... ... 01234567| 00000070 38 39 61 62 63 64 65 66 00 00 00 00 61 00 00 00 |89abcdef....a...| 00000080 01 00 00 00 |....| 00000084
main()
has been
executed.
Next, I will merge the C startup initialization with the ledtick code.