├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── my-common-code ├── api-asm.S ├── api-asm.h ├── api.c └── api.h ├── my-project ├── Makefile └── my-project.c └── rules.mk /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | *.elf 3 | *.bin 4 | generated.*.ld 5 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libopencm3"] 2 | path = libopencm3 3 | url = https://github.com/libopencm3/libopencm3 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This template should be considered released into the public domain. 2 | Where not possible, please consider it available under your choice 3 | of the MIT, ISC, Apache2 or BSD-2-clause licenses. 4 | 5 | This only applies to the template code. libopencm3 itself has it's own license. 6 | 7 | You should replace this file with the license of your _own_ project if you are 8 | using this as a template! 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Easy "clone and go" repository for a libopencm3 based project. 2 | 3 | # Instructions 4 | 1. git clone --recurse-submodules https://github.com/libopencm3/libopencm3-template.git your-project 5 | 2. cd your-project 6 | 3. make -C libopencm3 # (Only needed once) 7 | 4. make -C my-project 8 | 9 | If you have an older git, or got ahead of yourself and skipped the ```--recurse-submodules``` 10 | you can fix things by running ```git submodule update --init``` (This is only needed once) 11 | 12 | # Directories 13 | * my-project contains your application 14 | * my-common-code contains something shared. 15 | 16 | # As a template 17 | You should replace this with your _own_ README if you are using this 18 | as a template. 19 | -------------------------------------------------------------------------------- /my-common-code/api-asm.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Example of a pure assembly file 3 | * For most people, this is normally unnecessary, you can use inline 4 | * ASM in a C file, if you even need to use ASM at all. 5 | * However, if you reallllly like doing this sort of thing, here's how :) 6 | */ 7 | 8 | .syntax unified 9 | .thumb 10 | .section .text 11 | 12 | #include 13 | 14 | .global rev_bytes 15 | .func rev_bytes /* only used for debugger */ 16 | .type rev_bytes, STT_FUNC 17 | rev_bytes: 18 | rev r0, r0 19 | bx lr 20 | -------------------------------------------------------------------------------- /my-common-code/api-asm.h: -------------------------------------------------------------------------------- 1 | #include 2 | /** 3 | * Reverse bytes in words 4 | * @param in word in form abcd 5 | * @returns word in form dcba 6 | */ 7 | uint32_t rev_bytes(uint32_t in); 8 | -------------------------------------------------------------------------------- /my-common-code/api.c: -------------------------------------------------------------------------------- 1 | 2 | #include "api.h" 3 | 4 | int my_func(int a) 5 | { 6 | return a * 3; 7 | } 8 | -------------------------------------------------------------------------------- /my-common-code/api.h: -------------------------------------------------------------------------------- 1 | int my_func(int a); 2 | -------------------------------------------------------------------------------- /my-project/Makefile: -------------------------------------------------------------------------------- 1 | PROJECT = awesomesauce 2 | BUILD_DIR = bin 3 | 4 | SHARED_DIR = ../my-common-code 5 | CFILES = my-project.c 6 | CFILES += api.c 7 | AFILES += api-asm.S 8 | 9 | # TODO - you will need to edit these two lines! 10 | DEVICE=stm32f407vgt6 11 | OOCD_FILE = board/stm32f4discovery.cfg 12 | 13 | # You shouldn't have to edit anything below here. 14 | VPATH += $(SHARED_DIR) 15 | INCLUDES += $(patsubst %,-I%, . $(SHARED_DIR)) 16 | OPENCM3_DIR=../libopencm3 17 | 18 | include $(OPENCM3_DIR)/mk/genlink-config.mk 19 | include ../rules.mk 20 | include $(OPENCM3_DIR)/mk/genlink-rules.mk 21 | -------------------------------------------------------------------------------- /my-project/my-project.c: -------------------------------------------------------------------------------- 1 | #include "api.h" 2 | #include "api-asm.h" 3 | 4 | int main(void) { 5 | /* add your own code */ 6 | uint32_t rev = 0xaabbccdd; 7 | rev = rev_bytes(rev); 8 | return my_func(rev); 9 | } 10 | -------------------------------------------------------------------------------- /rules.mk: -------------------------------------------------------------------------------- 1 | # This version of rules.mk expects the following to be defined before 2 | # inclusion.. 3 | ### REQUIRED ### 4 | # OPENCM3_DIR - duh 5 | # PROJECT - will be the basename of the output elf, eg usb-gadget0-stm32f4disco 6 | # CFILES - basenames only, eg main.c blah.c 7 | # CXXFILES - same for C++ files. Must have cxx suffix! 8 | # DEVICE - the full device name, eg stm32f405ret6 9 | # _or_ 10 | # LDSCRIPT - full path, eg ../../examples/stm32/f4/stm32f4-discovery/stm32f4-discovery.ld 11 | # OPENCM3_LIB - the basename, eg: opencm3_stm32f4 12 | # OPENCM3_DEFS - the target define eg: -DSTM32F4 13 | # ARCH_FLAGS - eg, -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 14 | # (ie, the full set of cpu arch flags, _none_ are defined in this file) 15 | # 16 | ### OPTIONAL ### 17 | # INCLUDES - fully formed -I paths, if you want extra, eg -I../shared 18 | # BUILD_DIR - defaults to bin, should set this if you are building multiarch 19 | # OPT - full -O flag, defaults to -Os 20 | # CSTD - defaults -std=c99 21 | # CXXSTD - no default. 22 | # OOCD_INTERFACE - eg stlink-v2 23 | # OOCD_TARGET - eg stm32f4x 24 | # both only used if you use the "make flash" target. 25 | # OOCD_FILE - eg my.openocd.cfg 26 | # This overrides interface/target above, and is used as just -f FILE 27 | ### TODO/FIXME/notes ### 28 | # No support for stylecheck. 29 | # No support for BMP/texane/random flash methods, no plans either 30 | # No support for magically finding the library. 31 | # C++ hasn't been actually tested with this..... sorry bout that. ;) 32 | # Second expansion/secondary not set, add this if you need them. 33 | 34 | BUILD_DIR ?= bin 35 | OPT ?= -Os 36 | CSTD ?= -std=c99 37 | 38 | # Be silent per default, but 'make V=1' will show all compiler calls. 39 | # If you're insane, V=99 will print out all sorts of things. 40 | V?=0 41 | ifeq ($(V),0) 42 | Q := @ 43 | NULL := 2>/dev/null 44 | endif 45 | 46 | # Tool paths. 47 | PREFIX ?= arm-none-eabi- 48 | CC = $(PREFIX)gcc 49 | CXX = $(PREFIX)g++ 50 | LD = $(PREFIX)gcc 51 | OBJCOPY = $(PREFIX)objcopy 52 | OBJDUMP = $(PREFIX)objdump 53 | OOCD ?= openocd 54 | 55 | OPENCM3_INC = $(OPENCM3_DIR)/include 56 | 57 | # Inclusion of library header files 58 | INCLUDES += $(patsubst %,-I%, . $(OPENCM3_INC) ) 59 | 60 | OBJS = $(CFILES:%.c=$(BUILD_DIR)/%.o) 61 | OBJS += $(CXXFILES:%.cxx=$(BUILD_DIR)/%.o) 62 | OBJS += $(AFILES:%.S=$(BUILD_DIR)/%.o) 63 | GENERATED_BINS = $(PROJECT).elf $(PROJECT).bin $(PROJECT).map $(PROJECT).list $(PROJECT).lss 64 | 65 | TGT_CPPFLAGS += -MD 66 | TGT_CPPFLAGS += -Wall -Wundef $(INCLUDES) 67 | TGT_CPPFLAGS += $(INCLUDES) $(OPENCM3_DEFS) 68 | 69 | TGT_CFLAGS += $(OPT) $(CSTD) -ggdb3 70 | TGT_CFLAGS += $(ARCH_FLAGS) 71 | TGT_CFLAGS += -fno-common 72 | TGT_CFLAGS += -ffunction-sections -fdata-sections 73 | TGT_CFLAGS += -Wextra -Wshadow -Wno-unused-variable -Wimplicit-function-declaration 74 | TGT_CFLAGS += -Wredundant-decls -Wstrict-prototypes -Wmissing-prototypes 75 | 76 | TGT_CXXFLAGS += $(OPT) $(CXXSTD) -ggdb3 77 | TGT_CXXFLAGS += $(ARCH_FLAGS) 78 | TGT_CXXFLAGS += -fno-common 79 | TGT_CXXFLAGS += -ffunction-sections -fdata-sections 80 | TGT_CXXFLAGS += -Wextra -Wshadow -Wredundant-decls -Weffc++ 81 | 82 | TGT_ASFLAGS += $(OPT) $(ARCH_FLAGS) -ggdb3 83 | 84 | TGT_LDFLAGS += -T$(LDSCRIPT) -L$(OPENCM3_DIR)/lib -nostartfiles 85 | TGT_LDFLAGS += $(ARCH_FLAGS) 86 | TGT_LDFLAGS += -specs=nano.specs 87 | TGT_LDFLAGS += -Wl,--gc-sections 88 | # OPTIONAL 89 | #TGT_LDFLAGS += -Wl,-Map=$(PROJECT).map 90 | ifeq ($(V),99) 91 | TGT_LDFLAGS += -Wl,--print-gc-sections 92 | endif 93 | 94 | # Linker script generator fills this in for us. 95 | ifeq (,$(DEVICE)) 96 | LDLIBS += -l$(OPENCM3_LIB) 97 | endif 98 | # nosys is only in newer gcc-arm-embedded... 99 | #LDLIBS += -specs=nosys.specs 100 | LDLIBS += -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group 101 | 102 | # Burn in legacy hell fortran modula pascal yacc idontevenwat 103 | .SUFFIXES: 104 | .SUFFIXES: .c .S .h .o .cxx .elf .bin .list .lss 105 | 106 | # Bad make, never *ever* try to get a file out of source control by yourself. 107 | %: %,v 108 | %: RCS/%,v 109 | %: RCS/% 110 | %: s.% 111 | %: SCCS/s.% 112 | 113 | all: $(PROJECT).elf $(PROJECT).bin 114 | flash: $(PROJECT).flash 115 | 116 | # error if not using linker script generator 117 | ifeq (,$(DEVICE)) 118 | $(LDSCRIPT): 119 | ifeq (,$(wildcard $(LDSCRIPT))) 120 | $(error Unable to find specified linker script: $(LDSCRIPT)) 121 | endif 122 | else 123 | # if linker script generator was used, make sure it's cleaned. 124 | GENERATED_BINS += $(LDSCRIPT) 125 | endif 126 | 127 | # Need a special rule to have a bin dir 128 | $(BUILD_DIR)/%.o: %.c 129 | @printf " CC\t$<\n" 130 | @mkdir -p $(dir $@) 131 | $(Q)$(CC) $(TGT_CFLAGS) $(CFLAGS) $(TGT_CPPFLAGS) $(CPPFLAGS) -o $@ -c $< 132 | 133 | $(BUILD_DIR)/%.o: %.cxx 134 | @printf " CXX\t$<\n" 135 | @mkdir -p $(dir $@) 136 | $(Q)$(CXX) $(TGT_CXXFLAGS) $(CXXFLAGS) $(TGT_CPPFLAGS) $(CPPFLAGS) -o $@ -c $< 137 | 138 | $(BUILD_DIR)/%.o: %.S 139 | @printf " AS\t$<\n" 140 | @mkdir -p $(dir $@) 141 | $(Q)$(CC) $(TGT_ASFLAGS) $(ASFLAGS) $(TGT_CPPFLAGS) $(CPPFLAGS) -o $@ -c $< 142 | 143 | $(PROJECT).elf: $(OBJS) $(LDSCRIPT) $(LIBDEPS) 144 | @printf " LD\t$@\n" 145 | $(Q)$(LD) $(TGT_LDFLAGS) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $@ 146 | 147 | %.bin: %.elf 148 | @printf " OBJCOPY\t$@\n" 149 | $(Q)$(OBJCOPY) -O binary $< $@ 150 | 151 | %.lss: %.elf 152 | $(OBJDUMP) -h -S $< > $@ 153 | 154 | %.list: %.elf 155 | $(OBJDUMP) -S $< > $@ 156 | 157 | %.flash: %.elf 158 | @printf " FLASH\t$<\n" 159 | ifeq (,$(OOCD_FILE)) 160 | $(Q)(echo "halt; program $(realpath $(*).elf) verify reset" | nc -4 localhost 4444 2>/dev/null) || \ 161 | $(OOCD) -f interface/$(OOCD_INTERFACE).cfg \ 162 | -f target/$(OOCD_TARGET).cfg \ 163 | -c "program $(realpath $(*).elf) verify reset exit" \ 164 | $(NULL) 165 | else 166 | $(Q)(echo "halt; program $(realpath $(*).elf) verify reset" | nc -4 localhost 4444 2>/dev/null) || \ 167 | $(OOCD) -f $(OOCD_FILE) \ 168 | -c "program $(realpath $(*).elf) verify reset exit" \ 169 | $(NULL) 170 | endif 171 | 172 | clean: 173 | rm -rf $(BUILD_DIR) $(GENERATED_BINS) 174 | 175 | .PHONY: all clean flash 176 | -include $(OBJS:.o=.d) 177 | 178 | --------------------------------------------------------------------------------