commit 1b8d5201de9483b9dd0f4baecfe83d6b93687cb2 Author: Romain Goyet Date: Sat May 2 13:25:27 2015 +0200 Proper building for Flash diff --git a/INSTALL.txt b/INSTALL.txt new file mode 100644 index 000000000..0a26cd3a1 --- /dev/null +++ b/INSTALL.txt @@ -0,0 +1,2 @@ +- Download a toolchain from https://launchpad.net/gcc-arm-embedded/+download +- Install openocd (tested with 0.8.0) diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..693cd3d61 --- /dev/null +++ b/Makefile @@ -0,0 +1,30 @@ +CC=arm-none-eabi-gcc +LD=arm-none-eabi-ld.bfd +GDB=arm-none-eabi-gdb +OBJCOPY=arm-none-eabi-objcopy +CFLAGS=-march=armv7e-m -mcpu=cortex-m4 -mthumb -std=c99 -g + +objs := boot/crt0.o src/blinky.o + +run: boot.elf + $(GDB) -x gdb_script.gdb boot.elf + +boot.hex: boot.elf + @echo "OBJCOPY $@" + @$(OBJCOPY) -O ihex boot.elf boot.hex + +boot.bin: boot.elf + @echo "OBJCOPY $@" + @$(OBJCOPY) -O binary boot.elf boot.bin + +boot.elf: $(objs) + @echo "LD $@" + @$(LD) -T boot/stm32f429_flash.ld $(objs) -o $@ + +%.o: %.c + @echo "CC $@" + @$(CC) $(CFLAGS) -c $< -o $@ + +clean: + @echo "CLEAN" + @rm -f $(objs) boot.elf boot.bin boot.hex diff --git a/boot/crt0.c b/boot/crt0.c new file mode 100644 index 000000000..b230598e3 --- /dev/null +++ b/boot/crt0.c @@ -0,0 +1,52 @@ +typedef long uint32_t; + +extern const void * _data_segment_start_flash; +extern const void * _data_segment_start_ram; +extern const void * _data_segment_end_ram; + +void reset(void); + +/* Interrupt Service Routines are void->void functions */ +typedef void(*ISR)(void); + +/* Notice: The Cortex-M4 expects all jumps to be made at an odd address when + * jumping to Thumb code. For example, if you want to execute Thumb code at + * address 0x100, you'll have to jump to 0x101. Luckily, this idiosyncrasy is + * properly handled by the C compiler that will generate proper addresses when + * using function pointers. */ + +#define INITIALISATION_VECTOR_SIZE 0x6B + +ISR InitialisationVector[INITIALISATION_VECTOR_SIZE] + __attribute__((section(".isr_vector_table"))) + = { + 0x20010000, //FIXME: This is the stack pointer! + reset, + 0, + 0, + 0 +}; + +void blink(void); + +void reset(void) { + // This is where execution start after reset. + // Many things are not initialized yet so the code here has to pay attention. + + /* Copy data segment to RAM + * The data segment is R/W but its initialization value matters. It's stored + * in Flash, but linked as if it were in RAM. Now's our opportunity to copy + * it. Note that until then the data segment (e.g. global variables) contains + * garbage values and should not be used. */ +// int dataSegmentSize = &_data_segment_end_ram - &_data_segment_start_ram; + uint32_t * ramPointer = (uint32_t *)&_data_segment_start_ram; + uint32_t * flashPointer = (uint32_t *)&_data_segment_start_flash; + while (ramPointer < (uint32_t *)&_data_segment_end_ram) { + *ramPointer++ = *flashPointer++; + } + + blink(); +} +/* +void _start(void) { +}*/ diff --git a/boot/stm32f429_flash.ld b/boot/stm32f429_flash.ld new file mode 100644 index 000000000..d05d1e685 --- /dev/null +++ b/boot/stm32f429_flash.ld @@ -0,0 +1,49 @@ +MEMORY { + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 192K + CCM (rwx) : ORIGIN = 0x10000000, LENGTH = 64K +} + +SECTIONS { + .isr_vector_table ORIGIN(FLASH) : { + /* We're explicitly asking for the ISR vector table to be at the beginning + * of the Flash memory. This is what the STM32F42xx expects when booting. + * See ST/RM0090/p70 */ + *(.isr_vector_table) + /*LONG(0x20010000);*/ /* Stack pointer */ + /*LONG(0x00000201);*/ /* Reset vector */ + /* CAUTION: The least significant bit of the reset + * vector should be set to indicate Thumb code */ + } >FLASH + + .text : { + . = ALIGN(4); + *(.text) + } >FLASH + + .rodata : { + . = ALIGN(4); + *(.rodata) + } >FLASH + + .data : { + /* The data section is written to Flash but linked as if it were in RAM. + * This is required because its initial value matters (so it has to be in + * persistant memory in the first place), but it is a R/W area of memory + * so it will have to live in RAM upon execution (in linker lingo, that + * translate to the data segment having a LMA in Flash and a VMA in RAM). + * This means we'll have to copy it from Flash to RAM on initialization. + * To do this, we'll need to know the source location of the data segment + * (in Flash), the target location (in RAM), and the size of the segment. + * That's why we're defining three symbols that we'll use in the initial- + * -ization routine. */ + . = ALIGN(4); + _data_segment_start_flash = LOADADDR(.data); + _data_segment_start_ram = .; + *(.data) + _data_segment_end_ram = .; + } >RAM AT> FLASH + /*. = 0x8000000; + .data : { *(.data) } + .bss : { *(.bss) }*/ +} diff --git a/gdb_script.gdb b/gdb_script.gdb new file mode 100644 index 000000000..cb172ef4d --- /dev/null +++ b/gdb_script.gdb @@ -0,0 +1,8 @@ +# Let's connect to OpenOCD +target remote localhost:3333 + +# Load our executable +load boot.elf + +# Tell OpenOCD to reset and halt +monitor reset halt diff --git a/openocd.cfg b/openocd.cfg new file mode 100644 index 000000000..ca96a1c4b --- /dev/null +++ b/openocd.cfg @@ -0,0 +1 @@ +source [find board/stm32f429discovery.cfg]