I'm using STM32F407 Discovery Kit and when I try to write something to RAM it doesn't work.
.thumb
.syntax unified
.cpu cortex-m4
.section .bss
NIZ: .space 4
// Start of text section
.section .text
///////////////////////////////////////////////////////////////////////////////
// Vectors
///////////////////////////////////////////////////////////////////////////////
// Vector table start
// Add all other processor specific exceptions/interrupts in order here
.long __StackTop // Top of the stack. from linker script
.long _start +1 // reset location, +1 for thumb mode
_start:
adr r0, NIZ // address of the variable in RAM
ldr r1, [r0] // load the value from RAM to r1
ldr r1, =0xFE // store random value to r1
str r1, [r0] // store value from r1 to RAM
ldr r1, [r0] // here r1 should contain 0xFE but does not
end: b end
This is a sample program to demonstrate the problem.
The address that gets loaded into r0 is 0x08000008 but this is wrong as RAM region is in 0x20000000 as defined in linker script:
/* linker script for STM32F407VG chip */
MEMORY {
rom (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 128K
}
SECTIONS {
.text ORIGIN(rom) :
{
KEEP(*(.vectors)) /* Vector table */
*(.text*) /* Program code */
*(.rodata*) /* Read only data */
. = ALIGN(4);
__etext = .;
}
_sidata = .;
.data ORIGIN(ram) : AT ( ADDR (.text) + SIZEOF (.text) )
{
__data_start__ = .;
*(.data*) /* Read-write initialized data */
. = ALIGN(4);
__data_end__ = .;
}
.bss ADDR (.data) + SIZEOF (.data):
{
__bss_start__ = .;
. = ALIGN(4);
*(.bss*) /* Read-write zero initialized data */
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
}
}
__StackTop = ORIGIN(ram) + LENGTH(ram);
__text_size = SIZEOF (.text);
__data_size = SIZEOF (.data);
__bss_size = SIZEOF (.bss);
My project is a clone of this: https://github.com/fcayci/stm32f4-assembly
So my guess is the address is somehow in the wrong range and I'm not sure what causes this or how to fix it.
EDIT:
readelf -s Debug/stm32f4-asm.elf ✔
Symbol table '.symtab' contains 27 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 08000000 0 SECTION LOCAL DEFAULT 1 .text
2: 20000000 0 SECTION LOCAL DEFAULT 2 .data
3: 20000000 0 SECTION LOCAL DEFAULT 3 .bss
4: 00000000 0 SECTION LOCAL DEFAULT 4 .ARM.attributes
5: 00000000 0 SECTION LOCAL DEFAULT 5 .debug_line
6: 00000000 0 SECTION LOCAL DEFAULT 6 .debug_info
7: 00000000 0 SECTION LOCAL DEFAULT 7 .debug_abbrev
8: 00000000 0 SECTION LOCAL DEFAULT 8 .debug_aranges
9: 00000000 0 SECTION LOCAL DEFAULT 9 .debug_str
10: 00000000 0 FILE LOCAL DEFAULT ABS ./test.o
11: 20000000 0 NOTYPE LOCAL DEFAULT 3 NIZ
12: 20000000 0 NOTYPE LOCAL DEFAULT 3 $d
13: 08000008 0 NOTYPE LOCAL DEFAULT 1 _start
14: 08000000 0 NOTYPE LOCAL DEFAULT 1 $d
15: 08000008 0 NOTYPE LOCAL DEFAULT 1 $t
16: 08000016 0 NOTYPE LOCAL DEFAULT 1 end
17: 00000000 0 NOTYPE GLOBAL DEFAULT ABS __data_size
18: 20000000 0 NOTYPE GLOBAL DEFAULT 2 __data_start__
19: 08000018 0 NOTYPE GLOBAL DEFAULT 1 _sidata
20: 08000018 0 NOTYPE GLOBAL DEFAULT 1 __etext
21: 00000004 0 NOTYPE GLOBAL DEFAULT ABS __bss_size
22: 20000000 0 NOTYPE GLOBAL DEFAULT 3 __bss_start__
23: 20000000 0 NOTYPE GLOBAL DEFAULT 2 __data_end__
24: 20000004 0 NOTYPE GLOBAL DEFAULT 3 __bss_end__
25: 20020000 0 NOTYPE GLOBAL DEFAULT 3 __StackTop
26: 00000018 0 NOTYPE GLOBAL DEFAULT ABS __text_size
readelf -s Debug/test.o ✔
Symbol table '.symtab' contains 17 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 SECTION LOCAL DEFAULT 1 .text
2: 00000000 0 SECTION LOCAL DEFAULT 3 .data
3: 00000000 0 SECTION LOCAL DEFAULT 4 .bss
4: 00000000 0 NOTYPE LOCAL DEFAULT 4 NIZ
5: 00000000 0 NOTYPE LOCAL DEFAULT 4 $d
6: 00000008 0 NOTYPE LOCAL DEFAULT 1 _start
7: 00000000 0 NOTYPE LOCAL DEFAULT 1 $d
8: 00000008 0 NOTYPE LOCAL DEFAULT 1 $t
9: 00000016 0 NOTYPE LOCAL DEFAULT 1 end
10: 00000000 0 SECTION LOCAL DEFAULT 7 .debug_info
11: 00000000 0 SECTION LOCAL DEFAULT 9 .debug_abbrev
12: 00000000 0 SECTION LOCAL DEFAULT 5 .debug_line
13: 00000000 0 SECTION LOCAL DEFAULT 12 .debug_str
14: 00000000 0 SECTION LOCAL DEFAULT 10 .debug_aranges
15: 00000000 0 SECTION LOCAL DEFAULT 13 .ARM.attributes
16: 00000000 0 NOTYPE GLOBAL DEFAULT UND __StackTop
readelf -l Debug/stm32f4-asm.elf ✔
Elf file type is EXEC (Executable file)
Entry point 0x8000000
There are 2 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x010000 0x08000000 0x08000000 0x00018 0x00018 R E 0x10000
LOAD 0x020000 0x20000000 0x08000018 0x00000 0x00004 RW 0x10000
Section to Segment mapping:
Segment Sections...
00 .text
01 .data .bss
So my guess is the address is somehow in the wrong range and I'm not sure what causes this or how to fix it.
Sorry for asking you about the outputs of readelf
; I just checked on my computer and found out that it is not a linking problem but an assembler problem.
The following line is the issue:
ADR R0, NIZ
According to the official ARM documentation (not the GNU documentation), the ADR
instruction is only allowed if the symbol (here: NIZ
) is in the same section (and the same file) as the ADR
instruction.
GNU assembler should print an error message because the symbol NIZ
and the ADR
instruction are in different sections; however, it silently ignores the error and generates wrong code!
The following line worked for me:
LDR R0, =NIZ