I am a beginner in embedded programming so to learn I'm trying to work with a minimalist program. I have the following program I try to execute.
My environment:
main.c
int main(void)
{
}
__attribute__((section(".isr_vector"))) void Reset_Handler(void)
{
char * my_pointer = (char *)0x20000000;
*my_pointer = 42;
main();
while(1) {
}
}
stm32.ld
MEMORY
{
FLASH : ORIGIN = 0x08000000, LENGTH = 256K
RAM : ORIGIN = 0x20000000, LENGTH = 48K
}
start = Reset_Handler;
ENTRY(Reset_Handler)
SECTIONS
{
.isr_vector :
{
*(.isr_vector)
} >FLASH
.text :
{
*(.text)
} >FLASH
}
Everything is compiled using the following command: arm-none-eabi-gcc -mthumb -march=armv7e-m -mcpu=cortex-m4 -nostdlib -Tstm32.ld -g -o main.elf main.c
.
This program does nothing, it's just a try to make it running and write something in memory.
Using OpenOCD and GDB I load the program on the board, and here is what I get with layout asm
in GDB.
| >0x8000000 <Reset_Handler> push {r7, lr} │
│ 0x8000002 <Reset_Handler+2> sub sp, #8 │
│ 0x8000004 <Reset_Handler+4> add r7, sp, #0 │
│ 0x8000006 <Reset_Handler+6> mov.w r3, #536870912 ; 0x20000000 │
│ 0x800000a <Reset_Handler+10> str r3, [r7, #4] │
│ 0x800000c <Reset_Handler+12> ldr r3, [r7, #4] │
│ 0x800000e <Reset_Handler+14> movs r2, #42 ; 0x2a │
│ 0x8000010 <Reset_Handler+16> strb r2, [r3, #0] │
│ 0x8000012 <Reset_Handler+18> bl 0x8000018 <main> │
│ 0x8000016 <Reset_Handler+22> b.n 0x8000016 <Reset_Handler+22> │
│ 0x8000018 <main> push {r7} │
│ 0x800001a <main+2> add r7, sp, #0 │
│ 0x800001c <main+4> movs r3, #0 │
│ 0x800001e <main+6> mov r0, r3 │
│ 0x8000020 <main+8> mov sp, r7 │
│ 0x8000022 <main+10> pop {r7} │
│ 0x8000024 <main+12> bx lr
My program seems to be loaded at the beginning of the FLASH memory, and I start on Reset_Handler, but I cannot run step by step, I'm not even sure whether the program is running.
If I add a breakpoint or use step
I get:
(gdb) b 11
Breakpoint 1 at 0x8000006: file main.c, line 11.
(gdb) continue
Continuing.
Note: automatically using hardware breakpoints for read-only addresses.
I've read the following questions / answers but that didn't help. I guess my program's linking is invalid or I may not do anything without initializing something.
Note: I am able to run a very minimalist assembly program in the board and debug it, but the embedded C & linking part are quite new.
Your code is fundamentally wrong.
First of all
__attribute__((section(".isr_vector"))) void Reset_Handler(void)
is wrong. The beginning of the flash is the default location of the vector table not the handlers code.
Vector table has a specific format and it has to be followed:
first 4 bytes is an initial stack pointer value
second 4 bytes is the address of the reset handler routine code.
the next 32 bits words are addresses of other exception and interrupt handlers.
MEMORY
{
FLASH : ORIGIN = 0x08000000, LENGTH = 256K
RAM : ORIGIN = 0x20000000, LENGTH = 48K
}
start = Reset_Handler;
ENTRY(Reset_Handler)
_RAM_END = ORIGIN(RAM_START) + 48K;
SECTIONS
{
.isr_vector :
{
*(.isr_vector)
} >FLASH
.text :
{
*(.text)
} >FLASH
}
then the C file.
extern uint32_t _RAM_END;
void Reset_Handler(void);
void __attribute__((section(".isr_vector"))) (*vector_tabler[])(void) = {(void (*)(void))&_RAM_END, Reset_Handler};
int main(void)
{
}
void Reset_Handler(void)
{
char * my_pointer = (char *)0x20000000;
*my_pointer = 42;
main();
while(1) {
}
}
BTW I would rather suggest to read the documentation before you start to do very low level stuff. I advice to use STM32 provided startup files and linker scripts before you get enough knowledge and experience to modify (or write new ones from the scratch).