Skip to content

Latest commit

 

History

History
149 lines (136 loc) · 6.1 KB

startup.md

File metadata and controls

149 lines (136 loc) · 6.1 KB

Startup notes

With a microcontroller we flash the program into non-volatile memory which contains the complete program. For program execution RAM is used which is volatile, it will be cleared upon powering down the device.

If we have a static variable defined like this:

.data
one: .word 1

.text

  ldr r0, =one

So this instruction is loading the address on the label oneinto register r0. gT If we inspect the memory of this:

(gdb) p/x $r0
$7 = 0x20000000

This is the end of the .text section, and also the start of the RAM section. The issue is that one above is initialized to 1 but this value is in the Flash memory unit. The address of one is a location in RAM but the value stored in that location is undefined, whatever was there before or zero:

(gdb) x/d $r0
0x20000000:	1745707070

Variables like one above that need to be initialized will have a portion of the program memory (RAM memory) set aside for that value.

Note that the following is specific to an example found in nrf/misc/startup.s and not the general case.

       Flash Memory                                  Ram Memory
   +-------------------+                          +-------------------+
   |                   |                          |                   |
   |                   |                          |                   |
   |                   |                          |                   |
   |                   |                          |                   |
   |                   |                          |                   |
   |                   |                          |                   |
   |                   |                          |                   |
   |                   |                          |                   |
   |                   |                          |                   |
   |                   |                          |                   |
   |                   |                          |                   |
   |                   |                          |                   |
   |                   |                          |                   |
   |                   |                          |                   |
   +-------------------+                          +-------------------+
   |                   |                          |                   |
   |                   |                          |                   |
   |                   |                          |                   |
   |                   |                          |     Data          |
   |                   |                          |                   |
   |                   |                          |                   |
   |                   |                          |                   |
   |                   |                          |                   |
   |                   |                          |                   |
   +-------------------+<-- _end_data             +-------------------+ 0x20000000
   |                   |                          |                   |
   |                   |                          |                   |
   |   .data           |<-- _start_data           |                   |
   |                   |<-- _end_text             |                   |
   |   Code            |  ----------------------> |   Code            |
   |                   |                          |                   |
   |                   |                          |                   |
   |    .text          |                          |                   |
   +-------------------+ 0x00000000               +-------------------+ 0x00000000
  ldr r0, =one
  ldr r1, =_end_text    // end of .text segment in Flash memory.
  ldr r2, =_start_data  // start of .data segment in RAM memory.
  ldr r3, =_end_data    // end of .data segment in RAM memory.
r0             0x20000000          536870912   // one
r1             0x90                144         // _end_text
r2             0x20000000          536870912s  // _start_data
r3             0x2000000c          536870924   // _end_data

If we look at _start_data and end_data we can see that the difference is C hex which is 12 in decimal. And we have 3 words (32 bits/4 bytes) and 3*4=12 so we have three variables. And r0 which shows the address of one which also looks as expected. But the value of one is not what we would expect, it should be 1 in our case.

Notice that what is happeing is that the .data section is copied/mapped from flash to RAM but this is readonly memory and our data (the addresses of our variables one, two, and three are in the Data part of RAM starting with 0x20000000 and after a reset the data in these location could be anything. What we need to to in our ResetHandler which in our assembly examples is just the "main/start" function is to reach into the Code RAM memory and get the values for these variable and copy them into the Data RAM locations.

So we have _end_text which is a symbol that is created by the linker via the linker_script.ld:

  .text : { 
	  *(.text) 
	  _end_text = .;
  } > FLASH

We can inspect the values in the Code memory using the address of _end_text

(gdb) x/1 _end_text
0x90:	1
(gdb) x/1 _end_text + 4
0x94:	2
(gdb) x/1 _end_text + 8
0x98:	3

So we can see that the values for our variables are there. What we need to do now is to copy them into the Data RAM memory locations.

So we have to compare the current variable_address with the _end_data address and if the current variable_address is less than _end_data then we should copy/mov the value from the current_flash_mem to the current variable_address and then increment both pointers.

(gdb) p/t (int*)one
$4 = 1
(gdb) p/t (int*)two
$5 = 10
(gdb) p/d (int*)two
$6 = 2
(gdb) p/d (int*)three
$7 = 3

If you have have a global variable that is a string, for example:

plain_text:
    .ascii        "hello\n"

The to print the contents we need to use the address of the label, and then cast the value to a char pointer:

(gdb) p (char*) &plain_text
$22 = 0x2000000e "hello\n"