From 7a262a6be06498ad48088de6ff7c37068af368af Mon Sep 17 00:00:00 2001 From: Tony DiCola Date: Wed, 5 Aug 2015 01:45:45 +0000 Subject: [PATCH] Initial commit with blink example. --- .gitignore | 4 + Makefile | 93 ++++++++++++++ dash.ld | 35 ++++++ examples/Makefile.include | 54 ++++++++ examples/Makefile.rules | 250 ++++++++++++++++++++++++++++++++++++++ examples/blink/Makefile | 7 ++ examples/blink/blink.c | 92 ++++++++++++++ 7 files changed, 535 insertions(+) create mode 100644 Makefile create mode 100644 dash.ld create mode 100644 examples/Makefile.include create mode 100644 examples/Makefile.rules create mode 100644 examples/blink/Makefile create mode 100644 examples/blink/blink.c diff --git a/.gitignore b/.gitignore index bbf313b..436bb7b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +*.d +*.map + # Object files *.o *.ko @@ -27,6 +30,7 @@ *.i*86 *.x86_64 *.hex +*.bin # Debug files *.dSYM/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d0e4e8b --- /dev/null +++ b/Makefile @@ -0,0 +1,93 @@ +## Dash Example Makefile +## Author: Tony DiCola +## +## This file is based on the libopencm3-examples project which is released with +## the following license: +## +## Copyright (C) 2009 Uwe Hermann +## +## This library is free software: you can redistribute it and/or modify +## it under the terms of the GNU Lesser General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public License +## along with this library. If not, see . +## + +PREFIX ?= arm-none-eabi + +# Be silent per default, but 'make V=1' will show all compiler calls. +ifneq ($(V),1) +Q := @ +# Do not print "Entering directory ...". +MAKEFLAGS += --no-print-directory +endif + +OPENCM3_DIR := $(realpath libopencm3) +EXAMPLE_RULES = elf + +all: build + +bin: EXAMPLE_RULES += bin +hex: EXAMPLE_RULES += hex +srec: EXAMPLE_RULES += srec +list: EXAMPLE_RULES += list +images: EXAMPLE_RULES += images + +bin: build +hex: build +srec: build +list: build +images: build + +build: lib examples + +lib: + $(Q)if [ ! "`ls -A libopencm3`" ] ; then \ + printf "######## ERROR ########\n"; \ + printf "\tlibopencm3 is not initialized.\n"; \ + printf "\tPlease run:\n"; \ + printf "\t$$ git submodule init\n"; \ + printf "\t$$ git submodule update\n"; \ + printf "\tbefore running make.\n"; \ + printf "######## ERROR ########\n"; \ + exit 1; \ + fi + $(Q)$(MAKE) -C libopencm3 + +EXAMPLE_DIRS:=$(sort $(dir $(wildcard ./examples/*/Makefile))) +$(EXAMPLE_DIRS): lib + @printf " BUILD $@\n"; + $(Q)$(MAKE) --directory=$@ OPENCM3_DIR=$(OPENCM3_DIR) $(EXAMPLE_RULES) + +examples: $(EXAMPLE_DIRS) + $(Q)true + +clean: $(EXAMPLE_DIRS:=.clean) styleclean + $(Q)$(MAKE) -C libopencm3 clean + +stylecheck: $(EXAMPLE_DIRS:=.stylecheck) +styleclean: $(EXAMPLE_DIRS:=.styleclean) + + +%.clean: + $(Q)if [ -d $* ]; then \ + printf " CLEAN $*\n"; \ + $(MAKE) -C $* clean OPENCM3_DIR=$(OPENCM3_DIR) || exit $?; \ + fi; + +%.styleclean: + $(Q)$(MAKE) -C $* styleclean OPENCM3_DIR=$(OPENCM3_DIR) + +%.stylecheck: + $(Q)$(MAKE) -C $* stylecheck OPENCM3_DIR=$(OPENCM3_DIR) + + +.PHONY: build lib examples $(EXAMPLE_DIRS) install clean stylecheck styleclean \ + bin hex srec list images diff --git a/dash.ld b/dash.ld new file mode 100644 index 0000000..4780963 --- /dev/null +++ b/dash.ld @@ -0,0 +1,35 @@ +/* + * Dash Linker Configuration + * Author: Tony DiCola + * + * This file is based on the libopencm3-examples project which is released with + * the following license: + * + * Copyright (C) 2009 Uwe Hermann + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +/* + * Define memory regions for Dash's STM32F205GR6 CPU, with 1 megabyte of flash + * and 128 kilobytes of memory. + */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 1024K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 128K +} + +/* Include the common ld script. */ +INCLUDE libopencm3_stm32f2.ld diff --git a/examples/Makefile.include b/examples/Makefile.include new file mode 100644 index 0000000..905d241 --- /dev/null +++ b/examples/Makefile.include @@ -0,0 +1,54 @@ +## +## Dash Example Makefile Includes +## Author: Tony DiCola +## +## This file is based on the libopencm3-examples project which is released with +## the following license: +## +## Copyright (C) 2009 Uwe Hermann +## Copyright (C) 2010 Piotr Esden-Tempski +## Copyright (C) 2011 Fergus Noble +## +## This library is free software: you can redistribute it and/or modify +## it under the terms of the GNU Lesser General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public License +## along with this library. If not, see . +## + +LIBNAME = opencm3_stm32f2 +DEFS = -DSTM32F2 + +FP_FLAGS ?= -msoft-float +ARCH_FLAGS = -mthumb -mcpu=cortex-m3 $(FP_FLAGS) -mfix-cortex-m3-ldrd + +LDSCRIPT = ../../dash.ld + +OPENCM3_DIR := ../../libopencm3 + + +################################################################################ +# OpenOCD specific variables + +OOCD ?= openocd +OOCD_INTEFACE ?= stlink-v2 +OOCD_BOARD ?= + +################################################################################ +# Black Magic Probe specific variables +# Set the BMP_PORT to a serial port and then BMP is used for flashing +BMP_PORT ?= + +################################################################################ +# texane/stlink specific variables +#STLINK_PORT ?= :4242 + + +include ../Makefile.rules diff --git a/examples/Makefile.rules b/examples/Makefile.rules new file mode 100644 index 0000000..74369ed --- /dev/null +++ b/examples/Makefile.rules @@ -0,0 +1,250 @@ +## +## Dash Example Makefile Rules +## Author: Tony DiCola +## +## This file is based on the libopencm3-examples project which is released with +## the following license: +## +## Copyright (C) 2009 Uwe Hermann +## Copyright (C) 2010 Piotr Esden-Tempski +## Copyright (C) 2013 Frantisek Burian +## +## This library is free software: you can redistribute it and/or modify +## it under the terms of the GNU Lesser General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public License +## along with this library. If not, see . +## + +# Be silent per default, but 'make V=1' will show all compiler calls. +ifneq ($(V),1) +Q := @ +NULL := 2>/dev/null +endif + +############################################################################### +# Executables + +PREFIX ?= arm-none-eabi + +CC := $(PREFIX)-gcc +CXX := $(PREFIX)-g++ +LD := $(PREFIX)-gcc +AR := $(PREFIX)-ar +AS := $(PREFIX)-as +OBJCOPY := $(PREFIX)-objcopy +OBJDUMP := $(PREFIX)-objdump +GDB := $(PREFIX)-gdb +STFLASH = $(shell which st-flash) +STYLECHECK := /checkpatch.pl +STYLECHECKFLAGS := --no-tree -f --terse --mailback +STYLECHECKFILES := $(shell find . -name '*.[ch]') + + +############################################################################### +# Source files + +LDSCRIPT ?= $(BINARY).ld + +OBJS += $(BINARY).o + + +ifeq ($(strip $(OPENCM3_DIR)),) +# user has not specified the library path, so we try to detect it + +# where we search for the library +LIBPATHS := ./libopencm3 ../../../../libopencm3 ../../../../../libopencm3 + +OPENCM3_DIR := $(wildcard $(LIBPATHS:=/locm3.sublime-project)) +OPENCM3_DIR := $(firstword $(dir $(OPENCM3_DIR))) + +ifeq ($(strip $(OPENCM3_DIR)),) +$(warning Cannot find libopencm3 library in the standard search paths.) +$(error Please specify it through OPENCM3_DIR variable!) +endif +endif + +ifeq ($(V),1) +$(info Using $(OPENCM3_DIR) path to library) +endif + +INCLUDE_DIR = $(OPENCM3_DIR)/include +LIB_DIR = $(OPENCM3_DIR)/lib +SCRIPT_DIR = $(OPENCM3_DIR)/scripts + +############################################################################### +# C flags + +CFLAGS += -std=c99 +CFLAGS += -Os -g +CFLAGS += -Wextra -Wshadow -Wimplicit-function-declaration +CFLAGS += -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes +CFLAGS += -fno-common -ffunction-sections -fdata-sections + +############################################################################### +# C++ flags + +CXXFLAGS += -Os -g +CXXFLAGS += -Wextra -Wshadow -Wredundant-decls -Weffc++ +CXXFLAGS += -fno-common -ffunction-sections -fdata-sections + +############################################################################### +# C & C++ preprocessor common flags + +CPPFLAGS += -MD +CPPFLAGS += -Wall -Wundef +CPPFLAGS += -I$(INCLUDE_DIR) $(DEFS) + +############################################################################### +# Linker flags + +LDFLAGS += --static -nostartfiles +LDFLAGS += -L$(LIB_DIR) +LDFLAGS += -T$(LDSCRIPT) +LDFLAGS += -Wl,-Map=$(*).map +LDFLAGS += -Wl,--gc-sections +ifeq ($(V),99) +LDFLAGS += -Wl,--print-gc-sections +endif + +############################################################################### +# Used libraries + +LDLIBS += -l$(LIBNAME) +LDLIBS += -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group + +############################################################################### +############################################################################### +############################################################################### + +.SUFFIXES: .elf .bin .hex .srec .list .map .images +.SECONDEXPANSION: +.SECONDARY: + +all: elf + +elf: $(BINARY).elf +bin: $(BINARY).bin +hex: $(BINARY).hex +srec: $(BINARY).srec +list: $(BINARY).list + +images: $(BINARY).images +flash: $(BINARY).flash +stlink-flash: $(BINARY).stlink-flash + +$(LDSCRIPT): + ifeq (,$(wildcard $(LDSCRIPT))) + $(error Unable to find specified linker script: $(LDSCRIPT)) + endif + +%.images: %.bin %.hex %.srec %.list %.map + @#printf "*** $* images generated ***\n" + +%.bin: %.elf + @#printf " OBJCOPY $(*).bin\n" + $(Q)$(OBJCOPY) -Obinary $(*).elf $(*).bin + +%.hex: %.elf + @#printf " OBJCOPY $(*).hex\n" + $(Q)$(OBJCOPY) -Oihex $(*).elf $(*).hex + +%.srec: %.elf + @#printf " OBJCOPY $(*).srec\n" + $(Q)$(OBJCOPY) -Osrec $(*).elf $(*).srec + +%.list: %.elf + @#printf " OBJDUMP $(*).list\n" + $(Q)$(OBJDUMP) -S $(*).elf > $(*).list + +%.elf %.map: $(OBJS) $(LDSCRIPT) $(LIB_DIR)/lib$(LIBNAME).a + @#printf " LD $(*).elf\n" + $(Q)$(LD) $(LDFLAGS) $(ARCH_FLAGS) $(OBJS) $(LDLIBS) -o $(*).elf + +%.o: %.c + @#printf " CC $(*).c\n" + $(Q)$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -o $(*).o -c $(*).c + +%.o: %.cxx + @#printf " CXX $(*).cxx\n" + $(Q)$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -o $(*).o -c $(*).cxx + +%.o: %.cpp + @#printf " CXX $(*).cpp\n" + $(Q)$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -o $(*).o -c $(*).cpp + +clean: + @#printf " CLEAN\n" + $(Q)$(RM) *.o *.d *.elf *.bin *.hex *.srec *.list *.map + +stylecheck: $(STYLECHECKFILES:=.stylecheck) +styleclean: $(STYLECHECKFILES:=.styleclean) + +# the cat is due to multithreaded nature - we like to have consistent chunks of text on the output +%.stylecheck: % + $(Q)$(SCRIPT_DIR)$(STYLECHECK) $(STYLECHECKFLAGS) $* > $*.stylecheck; \ + if [ -s $*.stylecheck ]; then \ + cat $*.stylecheck; \ + else \ + rm -f $*.stylecheck; \ + fi; + +%.styleclean: + $(Q)rm -f $*.stylecheck; + + +%.stlink-flash: %.bin + @printf " FLASH $<\n" + $(Q)$(STFLASH) write $(*).bin 0x8000000 + +ifeq ($(STLINK_PORT),) +ifeq ($(BMP_PORT),) +ifeq ($(OOCD_SERIAL),) +%.flash: %.hex + @printf " FLASH $<\n" + @# IMPORTANT: Don't use "resume", only "reset" will work correctly! + $(Q)$(OOCD) -f interface/$(OOCD_INTERFACE).cfg \ + -f board/$(OOCD_BOARD).cfg \ + -c "init" -c "reset init" \ + -c "flash write_image erase $(*).hex" \ + -c "reset" \ + -c "shutdown" $(NULL) +else +%.flash: %.hex + @printf " FLASH $<\n" + @# IMPORTANT: Don't use "resume", only "reset" will work correctly! + $(Q)$(OOCD) -f interface/$(OOCD_INTERFACE).cfg \ + -f board/$(OOCD_BOARD).cfg \ + -c "ft2232_serial $(OOCD_SERIAL)" \ + -c "init" -c "reset init" \ + -c "flash write_image erase $(*).hex" \ + -c "reset" \ + -c "shutdown" $(NULL) +endif +else +%.flash: %.elf + @printf " GDB $(*).elf (flash)\n" + $(Q)$(GDB) --batch \ + -ex 'target extended-remote $(BMP_PORT)' \ + -x $(SCRIPT_DIR)/black_magic_probe_flash.scr \ + $(*).elf +endif +else +%.flash: %.elf + @printf " GDB $(*).elf (flash)\n" + $(Q)$(GDB) --batch \ + -ex 'target extended-remote $(STLINK_PORT)' \ + -x $(SCRIPT_DIR)/stlink_flash.scr \ + $(*).elf +endif + +.PHONY: images clean stylecheck styleclean elf bin hex srec list + +-include $(OBJS:.o=.d) diff --git a/examples/blink/Makefile b/examples/blink/Makefile new file mode 100644 index 0000000..ae8d3f9 --- /dev/null +++ b/examples/blink/Makefile @@ -0,0 +1,7 @@ +# Dash Blink Example Makefile +# Copyright (c) 2015 Tony DiCola +# Released under a MIT license: http://opensource.org/licenses/MIT + +BINARY = blink + +include ../Makefile.include diff --git a/examples/blink/blink.c b/examples/blink/blink.c new file mode 100644 index 0000000..1b28ada --- /dev/null +++ b/examples/blink/blink.c @@ -0,0 +1,92 @@ +// Dash Blink Example +// +// Cycle through blinking the red, green, blue LEDs on the dash every second. +// To access the LEDs the following GPIOs are used: +// - Red = PB6 +// - Green = PB7 +// - Blue = PA8 +// When the GPIO is pulled down to a low level the LED will turn on. +// +// Copyright (c) 2015 Tony DiCola +// Released under a MIT license: http://opensource.org/licenses/MIT +#include +#include +#include +#include + + +// Global state: +volatile uint32_t systick_millis = 0; // Millisecond counter. + + +// Delay for the specified number of milliseconds. +// This is implemented by configuring the systick timer to increment a count +// every millisecond and then busy waiting in a loop. +static void delay(uint32_t milliseconds) { + uint32_t target = systick_millis + milliseconds; + while (target > systick_millis); +} + +// Setup the systick timer to increment a count every millisecond. This is +// useful for implementing a delay function based on wall clock time. +static void systick_setup(void) { + // The Dash has a 26mhz external crystal and the CPU will run at that speed + // if no other clock changes are applied. To make the systick timer reset + // every millisecond (or 1000 times a second) set its reload value to: + // CPU_CLOCK_HZ / 1000 + systick_set_reload(26000); + // Set the systick clock source to the main CPU clock and enable it and its + // reload interrupt. + systick_set_clocksource(STK_CSR_CLKSOURCE_AHB); + systick_counter_enable(); + systick_interrupt_enable(); +} + +// Systick timer reload interrupt handler. Called every time the systick timer +// reaches its reload value. +void sys_tick_handler(void) { + // Increment the global millisecond count. + systick_millis++; +} + +// Setupo and configure the GPIOs to control the LEDs on the Dash. +static void gpio_setup(void) { + // Enable the GPIO clocks for the two GPIO ports that will be used (A & B). + rcc_periph_clock_enable(RCC_GPIOA); + rcc_periph_clock_enable(RCC_GPIOB); + + // Set each LED GPIO as an output. + gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO8); // PA8, blue LED + gpio_mode_setup(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO6); // PB6, red LED + gpio_mode_setup(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO7); // PB7, green LED +} + + +int main(void) { + // Setup systick timer and GPIOs. + systick_setup(); + gpio_setup(); + + // Main loop. + while (true) { + // Light the red LED. Note that LEDs light up when the GPIO is pulled low + // with the gpio_clear function, and turn off when pulled high with the + // gpio_set function. + gpio_clear(GPIOB, GPIO6); // Red LED on + gpio_set(GPIOB, GPIO7); // Green LED off + gpio_set(GPIOA, GPIO8); // Blue LED off + delay(1000); // Wait 1 second (1000 milliseconds). + // Now light just the green LED. + gpio_set(GPIOB, GPIO6); // Red LED off + gpio_clear(GPIOB, GPIO7); // Green LED on + gpio_set(GPIOA, GPIO8); // Blue LED off + delay(1000); + // Finally light just the blue LED. + gpio_set(GPIOB, GPIO6); // Red LED off + gpio_set(GPIOB, GPIO7); // Green LED off + gpio_clear(GPIOA, GPIO8); // Blue LED on + delay(1000); + } + + return 0; +}