mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-18 21:30:38 +01:00
Proper building for Flash
This commit is contained in:
2
INSTALL.txt
Normal file
2
INSTALL.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
- Download a toolchain from https://launchpad.net/gcc-arm-embedded/+download
|
||||
- Install openocd (tested with 0.8.0)
|
||||
30
Makefile
Normal file
30
Makefile
Normal file
@@ -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
|
||||
52
boot/crt0.c
Normal file
52
boot/crt0.c
Normal file
@@ -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) {
|
||||
}*/
|
||||
49
boot/stm32f429_flash.ld
Normal file
49
boot/stm32f429_flash.ld
Normal file
@@ -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) }*/
|
||||
}
|
||||
8
gdb_script.gdb
Normal file
8
gdb_script.gdb
Normal file
@@ -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
|
||||
1
openocd.cfg
Normal file
1
openocd.cfg
Normal file
@@ -0,0 +1 @@
|
||||
source [find board/stm32f429discovery.cfg]
|
||||
Reference in New Issue
Block a user