aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Doxyfile8
-rw-r--r--Makefile2
-rw-r--r--examples/efm32/tinygecko/Makefile.include97
-rw-r--r--examples/efm32/tinygecko/efm32-tg-stk3300/Makefile.include49
-rw-r--r--examples/efm32/tinygecko/efm32-tg-stk3300/README9
-rw-r--r--examples/efm32/tinygecko/efm32-tg-stk3300/lightswitch/Makefile22
-rw-r--r--examples/efm32/tinygecko/efm32-tg-stk3300/lightswitch/README13
-rw-r--r--examples/efm32/tinygecko/efm32-tg-stk3300/lightswitch/lightswitch-busywait.c40
-rw-r--r--examples/efm32/tinygecko/efm32-tg-stk3300/lightswitch/lightswitch-common.c88
-rw-r--r--examples/efm32/tinygecko/efm32-tg-stk3300/lightswitch/lightswitch-interrupt.c71
-rw-r--r--examples/efm32/tinygecko/efm32-tg-stk3300/lightswitch/lightswitch.c30
-rw-r--r--examples/efm32/tinygecko/efm32-tg-stk3300/miniblink/Makefile23
-rw-r--r--examples/efm32/tinygecko/efm32-tg-stk3300/miniblink/README9
-rw-r--r--examples/efm32/tinygecko/efm32-tg-stk3300/miniblink/miniblink.c71
-rw-r--r--include/libopencm3/efm32/memorymap.h37
-rw-r--r--include/libopencm3/efm32/tinygecko/cmu.h83
-rw-r--r--include/libopencm3/efm32/tinygecko/devicerevision.h30
-rw-r--r--include/libopencm3/efm32/tinygecko/emu.h125
-rw-r--r--include/libopencm3/efm32/tinygecko/gpio.h497
-rw-r--r--include/libopencm3/efm32/tinygecko/irq.h36
-rw-r--r--include/libopencm3/efm32/tinygecko/memorymap.h76
-rw-r--r--include/libopencm3/efm32/vector.h47
-rw-r--r--lib/efm32/tinygecko/EFM32TG840F32.ld15
-rw-r--r--lib/efm32/tinygecko/Makefile60
-rw-r--r--lib/efm32/tinygecko/devicerevision.c10
-rw-r--r--lib/efm32/tinygecko/gpio.c23
-rw-r--r--lib/efm32/tinygecko/tinygecko.ld78
-rw-r--r--lib/efm32/tinygecko/vector.c159
28 files changed, 1803 insertions, 5 deletions
diff --git a/Doxyfile b/Doxyfile
index e5b6a38..beb5dda 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -654,7 +654,7 @@ EXCLUDE_SYMLINKS = NO
# against the file with absolute path, so to exclude all test directories
# for example use the pattern */test/*
-EXCLUDE_PATTERNS =
+EXCLUDE_PATTERNS = *.d
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the
@@ -1413,13 +1413,13 @@ ENABLE_PREPROCESSING = YES
# compilation will be performed. Macro expansion can be done in a controlled
# way by setting EXPAND_ONLY_PREDEF to YES.
-MACRO_EXPANSION = NO
+MACRO_EXPANSION = YES
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
# then the macro expansion is limited to the macros specified with the
# PREDEFINED and EXPAND_AS_DEFINED tags.
-EXPAND_ONLY_PREDEF = NO
+EXPAND_ONLY_PREDEF = YES
# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
# pointed to by INCLUDE_PATH will be searched when a #include is found.
@@ -1447,7 +1447,7 @@ INCLUDE_FILE_PATTERNS =
# undefined via #undef or recursively expanded use the := operator
# instead of the = operator.
-PREDEFINED =
+PREDEFINED = __attribute__(x)=
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.
diff --git a/Makefile b/Makefile
index 3507791..09db92a 100644
--- a/Makefile
+++ b/Makefile
@@ -25,7 +25,7 @@ LIBDIR = $(DESTDIR)/$(PREFIX)/lib
SHAREDIR = $(DESTDIR)/$(PREFIX)/share/libopencm3/scripts
INSTALL = install
-TARGETS = stm32/f1 stm32/f2 stm32/f4 lpc13xx lm3s
+TARGETS = stm32/f1 stm32/f2 stm32/f4 lpc13xx lm3s efm32/tinygecko
# Be silent per default, but 'make V=1' will show all compiler calls.
ifneq ($(V),1)
diff --git a/examples/efm32/tinygecko/Makefile.include b/examples/efm32/tinygecko/Makefile.include
new file mode 100644
index 0000000..2426e98
--- /dev/null
+++ b/examples/efm32/tinygecko/Makefile.include
@@ -0,0 +1,97 @@
+##
+## This file is part of the libopencm3 project.
+##
+## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+## Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
+## Copyright (C) 2012 chrysn <chrysn@fsfe.org>
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program 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 General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program. If not, see <http://www.gnu.org/licenses/>.
+##
+
+PREFIX ?= arm-none-eabi
+#PREFIX ?= arm-elf
+CC = $(PREFIX)-gcc
+LD = $(PREFIX)-gcc
+OBJCOPY = $(PREFIX)-objcopy
+OBJDUMP = $(PREFIX)-objdump
+GDB = $(PREFIX)-gdb
+# Uncomment this line if you want to use the installed (not local) library.
+#TOOLCHAIN_DIR := $(shell dirname `which $(CC)`)/../$(PREFIX)
+TOOLCHAIN_DIR = ../../../../..
+CFLAGS += -Os -g -Wall -Wextra -I$(TOOLCHAIN_DIR)/include \
+ -fno-common -mcpu=cortex-m3 -mthumb -msoft-float -MD\
+ -D$(FAMILY)
+LDSCRIPT ?= ${TOOLCHAIN_DIR}/lib/efm32/tinygecko/$(MCU).ld
+LDFLAGS += -lc -lnosys -L$(TOOLCHAIN_DIR)/lib/efm32/tinygecko \
+ -T$(LDSCRIPT) -nostartfiles -Wl,--gc-sections \
+ -mthumb -march=armv7 -mfix-cortex-m3-ldrd -msoft-float
+OBJS += $(BINARY).o
+
+# Be silent per default, but 'make V=1' will show all compiler calls.
+ifneq ($(V),1)
+Q := @
+NULL := 2>/dev/null
+else
+LDFLAGS += -Wl,--print-gc-sections
+endif
+
+.SUFFIXES: .elf .bin .hex .srec .list .images
+.SECONDEXPANSION:
+.SECONDARY:
+
+all: images
+
+images: $(BINARY).images
+flash: $(BINARY).flash
+
+%.images: %.bin %.hex %.srec %.list
+ @#echo "*** $* images generated ***"
+
+%.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: $(OBJS) $(LDSCRIPT) $(TOOLCHAIN_DIR)/lib/efm32/tinygecko/libopencm3_efm32tinygecko.a
+ @#printf " LD $(subst $(shell pwd)/,,$(@))\n"
+ $(Q)$(LD) -o $(*).elf $(OBJS) -lopencm3_efm32tinygecko $(LDFLAGS)
+
+%.o: %.c Makefile
+ @#printf " CC $(subst $(shell pwd)/,,$(@))\n"
+ $(Q)$(CC) $(CFLAGS) -o $@ -c $<
+
+clean:
+ $(Q)rm -f *.o
+ $(Q)rm -f *.d
+ $(Q)rm -f *.elf
+ $(Q)rm -f *.bin
+ $(Q)rm -f *.hex
+ $(Q)rm -f *.srec
+ $(Q)rm -f *.list
+
+.PHONY: images clean
+
+-include $(OBJS:.o=.d)
+
diff --git a/examples/efm32/tinygecko/efm32-tg-stk3300/Makefile.include b/examples/efm32/tinygecko/efm32-tg-stk3300/Makefile.include
new file mode 100644
index 0000000..a2ad07a
--- /dev/null
+++ b/examples/efm32/tinygecko/efm32-tg-stk3300/Makefile.include
@@ -0,0 +1,49 @@
+##
+## This file is part of the libopencm3 project.
+##
+## Copyright (C) 2012 chrysn <chrysn@fsfe.org>
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program 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 General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program. If not, see <http://www.gnu.org/licenses/>.
+##
+
+MCU = EFM32TG840F32
+FAMILY = TINYGECKO
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../Makefile.include
+
+# FIXME: i'd much rather have this in a heredoc, but heredocs are not that easy
+# in makefiles. furthermore, this isn't caught by the clean target. actually,
+# i'd very much prefer using openocd anyway, this would also get rid of the
+# Default.ini and JLink.log files jlink.sh drops.
+
+# just the next hack: jlink, as shipped in energy micro's
+# energyAwareToolsBeta_30082011.tgz, needs its LD_LIBRARY_PATH explicitly set.
+# it provides a wrapper script, but that fails to pass on arguments. set this
+# path to the energymicro folder extracted from the tools, and we'll take care
+# of the test
+JLINKDIR = ${HOME}/energymicro/energymicro
+
+$(BINARY)-upload.sh:
+ rm -f "$@"
+ echo "exec device = EFM32TG840F32" >> "$@"
+ echo "exec EnableFlashDL" >> "$@"
+ echo "h" >> "$@"
+ echo "loadbin ${BINARY}.bin 0" >> "$@"
+ echo "r" >> "$@"
+ echo "go" >> "$@"
+ echo "q" >> "$@"
+ chmod +x "$@"
+
+upload: $(BINARY)-upload.sh $(BINARY).bin
+ LD_LIBRARY_PATH=$(JLINKDIR)/lib/ $(JLINKDIR)/bin/JLinkExe "$<" || echo "JLink exited with non-zero exit status, but that's normal."
diff --git a/examples/efm32/tinygecko/efm32-tg-stk3300/README b/examples/efm32/tinygecko/efm32-tg-stk3300/README
new file mode 100644
index 0000000..ffa3b59
--- /dev/null
+++ b/examples/efm32/tinygecko/efm32-tg-stk3300/README
@@ -0,0 +1,9 @@
+=========================
+EFM32-TG-STK3300 Examples
+=========================
+
+Examples in this directory are designed to be run on the Energy Micro EFM32
+Tiny Gecko Starter Kit, which is based on the EFM32TG840F32 MCU, has an onboard
+USB debug and power management interface, and a bunch of peripherials built in
+that demonstrate the chip's low power capabilities (LED, LCD display, light
+sensor, touch slider, LC sensor, push buttons).
diff --git a/examples/efm32/tinygecko/efm32-tg-stk3300/lightswitch/Makefile b/examples/efm32/tinygecko/efm32-tg-stk3300/lightswitch/Makefile
new file mode 100644
index 0000000..c6e785a
--- /dev/null
+++ b/examples/efm32/tinygecko/efm32-tg-stk3300/lightswitch/Makefile
@@ -0,0 +1,22 @@
+##
+## This file is part of the libopencm3 project.
+##
+## Copyright (C) 2012 chrysn <chrysn@fsfe.org>
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program 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 General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program. If not, see <http://www.gnu.org/licenses/>.
+##
+
+BINARY = lightswitch
+
+include ../Makefile.include
diff --git a/examples/efm32/tinygecko/efm32-tg-stk3300/lightswitch/README b/examples/efm32/tinygecko/efm32-tg-stk3300/lightswitch/README
new file mode 100644
index 0000000..41943dc
--- /dev/null
+++ b/examples/efm32/tinygecko/efm32-tg-stk3300/lightswitch/README
@@ -0,0 +1,13 @@
+============================================
+EFM32-TG-STK3300 Examples lightswitch README
+============================================
+
+This is a small example program for GPIO input and output, and how the device
+can be configured to use minimal power (although the example is merely
+scratching the surface of what is possible powersaving-wise).
+
+It's intended for the EFM32-TG-STK3300 eval board. It turn the User LED on when
+PB0 is pressed, and off when PB1 is pressed.
+
+Various implementations are offered (-busywait, -interrupt), and can configured
+in lightswitch.c.
diff --git a/examples/efm32/tinygecko/efm32-tg-stk3300/lightswitch/lightswitch-busywait.c b/examples/efm32/tinygecko/efm32-tg-stk3300/lightswitch/lightswitch-busywait.c
new file mode 100644
index 0000000..662d9df
--- /dev/null
+++ b/examples/efm32/tinygecko/efm32-tg-stk3300/lightswitch/lightswitch-busywait.c
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2012 chrysn <chrysn@fsfe.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/efm32/tinygecko/irq.h>
+#include <libopencm3/efm32/tinygecko/emu.h>
+
+#define ISER0 MMIO32(0xE000E100)
+#define ICER0 MMIO32(0xE000E180)
+#define ISPR0 MMIO32(0XE000E200)
+#define ICPR0 MMIO32(0XE000E280)
+
+/** @file Simplest implementation of the lightswitch mechanism. */
+
+int main(void)
+{
+ gpio_setup();
+
+ while(1) {
+ if (pb0_get())
+ led_on();
+ if (pb1_get())
+ led_off();
+ };
+}
diff --git a/examples/efm32/tinygecko/efm32-tg-stk3300/lightswitch/lightswitch-common.c b/examples/efm32/tinygecko/efm32-tg-stk3300/lightswitch/lightswitch-common.c
new file mode 100644
index 0000000..0cd1204
--- /dev/null
+++ b/examples/efm32/tinygecko/efm32-tg-stk3300/lightswitch/lightswitch-common.c
@@ -0,0 +1,88 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2012 chrysn <chrysn@fsfe.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file Common definitions used by all lightswitch implementations */
+
+#include <libopencm3/efm32/tinygecko/gpio.h>
+#include <libopencm3/efm32/tinygecko/cmu.h>
+
+/** The User LED is connected to PD7 to the plus side of the LED according to
+ * t0011_efm32_tiny_gecko_stk_user_manual.pdf figures 16.2 and 16.3 (called
+ * UIF_LED0)
+ */
+#define LED_PORT GPIO_PD
+#define LED_PIN GPIO7
+
+#define BUTTON0_PORT GPIO_PD
+#define BUTTON0_PORT_EXTIPSEL GPIO_EXTIPSEL_PORTD
+#define BUTTON0_PIN_NUMBER 8
+#define BUTTON0_PIN GPIO8
+#define BUTTON1_PORT GPIO_PB
+#define BUTTON1_PORT_EXTIPSEL GPIO_EXTIPSEL_PORTB
+#define BUTTON1_PIN_NUMBER 11
+#define BUTTON1_PIN GPIO11
+
+void gpio_setup(void);
+void led_on(void);
+void led_off(void);
+
+bool pb0_get(void);
+bool pb1_get(void);
+
+/**
+ * Enable GPIO, and set up port D7 as an output pin and D8 and B11 as input.
+ */
+
+void gpio_setup(void)
+{
+ // Before GPIO works, according to d0034_efm32tg_reference_manual.pdf
+ // note in section 28.3.7, we'll have to enable GPIO in CMU_HFPERCLKEN0
+
+ CMU_HFPERCLKEN0 |= CMU_HFPERCLKEN0_GPIO;
+
+ gpio_set_mode(LED_PORT, GPIO_MODE_PUSHPULL, LED_PIN);
+
+ // Button PB0 is connected to pin PD8 and pulled low when pushed,
+ // Botton PB1 to pin PB11 (sources as for LED). Pullups and debouncing
+ // are alreay in place in hardware, so no filtering or pullup is
+ // needed.
+
+ gpio_set_mode(BUTTON0_PORT, GPIO_MODE_INPUT, BUTTON0_PIN);
+ gpio_set_mode(BUTTON1_PORT, GPIO_MODE_INPUT, BUTTON1_PIN);
+}
+
+void led_on(void)
+{
+ gpio_set(LED_PORT, LED_PIN);
+}
+
+void led_off(void)
+{
+ gpio_clear(LED_PORT, LED_PIN);
+}
+
+bool pb0_get(void)
+{
+ return !gpio_get(GPIO_PD, GPIO8);
+}
+
+bool pb1_get(void)
+{
+ return !gpio_get(GPIO_PB, GPIO11);
+}
diff --git a/examples/efm32/tinygecko/efm32-tg-stk3300/lightswitch/lightswitch-interrupt.c b/examples/efm32/tinygecko/efm32-tg-stk3300/lightswitch/lightswitch-interrupt.c
new file mode 100644
index 0000000..f19423b
--- /dev/null
+++ b/examples/efm32/tinygecko/efm32-tg-stk3300/lightswitch/lightswitch-interrupt.c
@@ -0,0 +1,71 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2012 chrysn <chrysn@fsfe.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/efm32/tinygecko/irq.h>
+#include <libopencm3/efm32/tinygecko/emu.h>
+
+#define ISER0 MMIO32(0xE000E100)
+
+void interrupt_setup()
+{
+ // These are the ports the pin interrupts for 8 and 11 are to be
+ // configured to, and they should trigger on falling edge.
+
+ GPIO_EXTIPSELH = (BUTTON0_PORT_EXTIPSEL << ((BUTTON0_PIN_NUMBER-8)*4)) |
+ (BUTTON1_PORT_EXTIPSEL << ((BUTTON1_PIN_NUMBER-8)*4));
+
+ GPIO_EXTIFALL = BUTTON0_PIN | BUTTON1_PIN;
+
+ // Enable interrupts on the GPIO side
+
+ GPIO_INSENSE = GPIO_INSENSE_INT;
+ GPIO_IEN = BUTTON0_PIN | BUTTON1_PIN;
+
+ // Enable GPIO interrupts in NVIC
+
+ ISER0 = (1<<IRQ_GPIO_EVEN) | (1<<IRQ_GPIO_ODD);
+}
+
+int main(void)
+{
+ gpio_setup();
+ interrupt_setup();
+
+ while(1) {
+ emu_sleep_em1();
+ };
+}
+
+void gpio_even_isr()
+{
+ // Clearing the GPIO interrupt pending register. While the NVIC
+ // interrupt pending register gets cleared automatically once it jumps
+ // here, the pin's pending state has to be cleared explicitly.
+ // (Dispatch to different subroutines for different even pins that
+ // trigger an interrupt would happen here.)
+ GPIO_IFC = BUTTON0_PIN;
+ led_on();
+}
+
+void gpio_odd_isr()
+{
+ // See gpio_even_isr.
+ GPIO_IFC = BUTTON1_PIN;
+ led_off();
+}
diff --git a/examples/efm32/tinygecko/efm32-tg-stk3300/lightswitch/lightswitch.c b/examples/efm32/tinygecko/efm32-tg-stk3300/lightswitch/lightswitch.c
new file mode 100644
index 0000000..b8675f8
--- /dev/null
+++ b/examples/efm32/tinygecko/efm32-tg-stk3300/lightswitch/lightswitch.c
@@ -0,0 +1,30 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2012 chrysn <chrysn@fsfe.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file
+ * Example for switching the User LED of the EFM32-TG-STK330 eval board on and
+ * off using the buttons.
+ */
+
+#include "lightswitch-common.c"
+
+/** Change this include to -busywait, -interrupt, or -prs (not implemented
+ * yet). The overall behavior will not change, but different implementations
+ * will be used. */
+#include "lightswitch-busywait.c"
diff --git a/examples/efm32/tinygecko/efm32-tg-stk3300/miniblink/Makefile b/examples/efm32/tinygecko/efm32-tg-stk3300/miniblink/Makefile
new file mode 100644
index 0000000..a2e44dc
--- /dev/null
+++ b/examples/efm32/tinygecko/efm32-tg-stk3300/miniblink/Makefile
@@ -0,0 +1,23 @@
+##
+## This file is part of the libopencm3 project.
+##
+## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+## 2012 chrysn <chrysn@fsfe.org>
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program 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 General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program. If not, see <http://www.gnu.org/licenses/>.
+##
+
+BINARY = miniblink
+
+include ../Makefile.include
diff --git a/examples/efm32/tinygecko/efm32-tg-stk3300/miniblink/README b/examples/efm32/tinygecko/efm32-tg-stk3300/miniblink/README
new file mode 100644
index 0000000..d19e4fe
--- /dev/null
+++ b/examples/efm32/tinygecko/efm32-tg-stk3300/miniblink/README
@@ -0,0 +1,9 @@
+==========================================
+EFM32-TG-STK3300 Examples miniblink README
+==========================================
+
+This is the smallest-possible example program using libopencm3.
+
+It's intended for the EFM32-TG-STK3300 eval board. It should blink
+the user LED on the board.
+
diff --git a/examples/efm32/tinygecko/efm32-tg-stk3300/miniblink/miniblink.c b/examples/efm32/tinygecko/efm32-tg-stk3300/miniblink/miniblink.c
new file mode 100644
index 0000000..e9907d3
--- /dev/null
+++ b/examples/efm32/tinygecko/efm32-tg-stk3300/miniblink/miniblink.c
@@ -0,0 +1,71 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+ * 2012 chrysn <chrysn@fsfe.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/efm32/tinygecko/gpio.h>
+#include <libopencm3/efm32/tinygecko/cmu.h>
+
+void led_setup(void);
+void led_toggle(void);
+
+/** @file
+ * Minimal example for making the User LED of the EFM32-TG-STK330 eval board blink.
+ */
+
+/**
+ * Toggle the User LED in an infinite loop, with time between the toggling
+ * determined by a busy loop stupidly counting up.
+ */
+
+int main(void)
+{
+ int x;
+
+ led_setup();
+
+ while(1) {
+ for(x = 0; x < 200000; ++x) asm("mov r0,r0"); /* no-op, prevent compiler from optimizing this away */
+ led_toggle();
+ };
+}
+
+/**
+ * Enable GPIO, and set up port D7 as an output pin.
+ */
+
+void led_setup(void)
+{
+ // Before GPIO works, according to d0034_efm32tg_reference_manual.pdf
+ // note in section 28.3.7, we'll have to enable GPIO in CMU_HFPERCLKEN0
+
+ CMU_HFPERCLKEN0 |= CMU_HFPERCLKEN0_GPIO;
+
+ // The User LED is connected to PD7 to the plus side of the LED
+ // according to t0011_efm32_tiny_gecko_stk_user_manual.pdf figures 16.2
+ // and 16.3 (called UIF_LED0)
+
+ gpio_set_mode(GPIO_PD, GPIO_MODE_PUSHPULL, GPIO7);
+ // GPIO_PD_MODEL = GPIO_MODE_PUSHPULL<<(7*4);
+}
+
+void led_toggle(void)
+{
+ gpio_toggle(GPIO_PD, GPIO7);
+ // GPIO_PD_DOUTTGL = 1<<7;
+}
diff --git a/include/libopencm3/efm32/memorymap.h b/include/libopencm3/efm32/memorymap.h
new file mode 100644
index 0000000..481883c
--- /dev/null
+++ b/include/libopencm3/efm32/memorymap.h
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2012 chrysn <chrysn@fsfe.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file
+ *
+ * Dispatcher for the base address definitions, depending on the particular
+ * Gecko family.
+ *
+ * @see tinygecko/memorymap.h
+ */
+
+#ifndef LIBOPENCM3_EFM32_MEMORYMAP_H
+#define LIBOPENCM3_EFM32_MEMORYMAP_H
+
+#ifdef TINYGECKO
+# include <libopencm3/efm32/tinygecko/memorymap.h>
+#else
+# error "efm32 family not defined."
+#endif
+
+#endif
diff --git a/include/libopencm3/efm32/tinygecko/cmu.h b/include/libopencm3/efm32/tinygecko/cmu.h
new file mode 100644
index 0000000..b003289
--- /dev/null
+++ b/include/libopencm3/efm32/tinygecko/cmu.h
@@ -0,0 +1,83 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2012 chrysn <chrysn@fsfe.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file
+ *
+ * Definitions for the CMU (Clock Management Unit).
+ *
+ * This corresponds to the description in d0034_efm32tg_reference_manual.pdf
+ * section 11.
+ *
+ * @see CMU_registers
+ */
+/* FIXME: i'd prefer not to @see CMU_registers but have some direct link placed
+ * automatically from a file to its groups */
+
+#ifndef LIBOPENCM3_EFM32_TINYGECKO_CMU_H
+#define LIBOPENCM3_EFM32_TINYGECKO_CMU_H
+
+#include <libopencm3/cm3/common.h>
+#include <libopencm3/efm32/memorymap.h>
+
+/** These definitions reflect d0034_efm32tg_reference_manual.pdf section 11.4.
+ *
+ * @defgroup CMU_registers CMU registers
+ * @{ */
+
+#define CMU_CTRL MMIO32(CMU_BASE + 0x000)
+#define CMU_HFCORECLKDIV MMIO32(CMU_BASE + 0x004)
+#define CMU_HFPERCLKDIV MMIO32(CMU_BASE + 0x008)
+#define CMU_HFRCOCTRL MMIO32(CMU_BASE + 0x00C)
+#define CMU_LFRCOCTRL MMIO32(CMU_BASE + 0x010)
+#define CMU_AUXHFRCOCTRL MMIO32(CMU_BASE + 0x014)
+#define CMU_CALCTRL MMIO32(CMU_BASE + 0x018)
+#define CMU_CALCNT MMIO32(CMU_BASE + 0x01C)
+#define CMU_OSCENCMD MMIO32(CMU_BASE + 0x020)
+#define CMU_CMD MMIO32(CMU_BASE + 0x024)
+#define CMU_LFCLKSEL MMIO32(CMU_BASE + 0x028)
+#define CMU_STATUS MMIO32(CMU_BASE + 0x02C)
+#define CMU_IF MMIO32(CMU_BASE + 0x030)
+#define CMU_IFS MMIO32(CMU_BASE + 0x034)
+#define CMU_IFC MMIO32(CMU_BASE + 0x038)
+#define CMU_IEN MMIO32(CMU_BASE + 0x03C)
+#define CMU_HFCORECLKEN0 MMIO32(CMU_BASE + 0x040)
+#define CMU_HFPERCLKEN0 MMIO32(CMU_BASE + 0x044)
+#define CMU_SYNCBUSY MMIO32(CMU_BASE + 0x050)
+#define CMU_FREEZE MMIO32(CMU_BASE + 0x054)
+#define CMU_LFACLKEN0 MMIO32(CMU_BASE + 0x058)
+#define CMU_LFBCLKEN0 MMIO32(CMU_BASE + 0x060)
+#define CMU_LFAPRESC0 MMIO32(CMU_BASE + 0x068)
+#define CMU_LFBPRESC0 MMIO32(CMU_BASE + 0x070)
+#define CMU_PCNTCTRL MMIO32(CMU_BASE + 0x078)
+#define CMU_LCDCTRL MMIO32(CMU_BASE + 0x07C)
+#define CMU_ROUTE MMIO32(CMU_BASE + 0x080)
+#define CMU_LOCK MMIO32(CMU_BASE + 0x084)
+
+/** @} */
+
+/**
+ * This section is incomplete because i'm impatient and want a working result
+ * quickly
+ *
+ * @todo Include all bits and bit groups from the manual.
+ */
+
+#define CMU_HFPERCLKEN0_GPIO (1<<6)
+
+#endif
diff --git a/include/libopencm3/efm32/tinygecko/devicerevision.h b/include/libopencm3/efm32/tinygecko/devicerevision.h
new file mode 100644
index 0000000..c7c64aa
--- /dev/null
+++ b/include/libopencm3/efm32/tinygecko/devicerevision.h
@@ -0,0 +1,30 @@
+/* FIXME: proper documentation, see where this fits, if we need this at all
+ * etc. this was just a first attempt at implementing something easy with
+ * MMIO32. */
+
+/* this implements d0034_efm32tg_reference_manual.pdf's 7.3.4 "Device Revision"
+ * section */
+
+#ifndef LIBOPENCM3_EFM32_TINYGECKO_DEVICEREVISION_H
+#define LIBOPENCM3_EFM32_TINYGECKO_DEVICEREVISION_H
+
+#include <libopencm3/cm3/common.h>
+
+#define DEVICEREVISION_PID2 MMIO32(0xE00FFFE8)
+#define DEVICEREVISION_PID3 MMIO32(0xE00FFFEC)
+
+/* devicerevision_revision_get has a comment that would make these definitions
+ * obsolete; i'm not sure how far it is reasonable to parameterize everythin
+ * g*/
+#define DEVICEREVISION_REVISION_LENGTH 4
+#define DEVICEREVISION_REVISION_SHIFT 4
+#define DEVICEREVISION_REVISION_MASK (~(~0<<DEVICEREVISION_REVISION_LENGTH)<<DEVICEREVISION_REVISION_SHIFT) /* 0x000000f0, bits 7:4 */
+
+#define DEVICEREVISION_REVISION_A 0x00
+
+/* Read the device's hardcoded Revision. Return values can be compared against
+ * the DEVICEREVISION_REVISION_A constant, the only value given in the current
+ * specification. */
+extern u8 devicerevision_revision_get(void);
+
+#endif
diff --git a/include/libopencm3/efm32/tinygecko/emu.h b/include/libopencm3/efm32/tinygecko/emu.h
new file mode 100644
index 0000000..07327fd
--- /dev/null
+++ b/include/libopencm3/efm32/tinygecko/emu.h
@@ -0,0 +1,125 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2012 chrysn <chrysn@fsfe.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file
+ * @see EFM32TG_EMU
+ */
+
+/** Definitions for the EMU subsystem (Energy Management Unit).
+ *
+ * This corresponds to the description in d0034_efm32tg_reference_manual.pdf
+ * section 10.
+ *
+ * @defgroup EFM32TG_EMU EFM32 Tiny Gecko EMU
+ * @{
+ */
+
+#ifndef LIBOPENCM3_EFM32_TINYGECKO_EMU_H
+#define LIBOPENCM3_EFM32_TINYGECKO_EMU_H
+
+#include <libopencm3/cm3/common.h>
+#include <libopencm3/efm32/memorymap.h>
+
+/** Register definitions and register value definitions for the EMU subsystem
+ *
+ * @defgroup EFM32TG_EMU_regsandvals EFM32 Tiny Gecko EMU registers and values
+ * @{
+ */
+
+/** These definitions reflect d0034_efm32tg_reference_manual.pdf section 10.4
+ *
+ * @defgroup EFM32TG_EMU_registers EFM32 Tiny Gecko EMU registers
+ * @{
+ */
+
+#define EMU_CTRL MMIO32(EMU_BASE + 0x000) /**< @see EFM32TG_EMU_CTRL_bits */
+#define EMU_LOCK MMIO32(EMU_BASE + 0x008) /**< @see EFM32TG_EMU_LOCK_values */
+#define EMU_AUXCTRL MMIO32(EMU_BASE + 0x024) /**< @see EFM32TG_EMU_AUXCTRL_bits */
+
+/** @} */
+
+/** Bit states for the EMU_CTRL register
+ *
+ * See d0034_efm32tg_reference_manual.pdf section 10.5.1 for definitions, and
+ * 10.3.2 for details (especially on why EM4CTRL_TWO and _THREE are defined).
+ *
+ * @defgroup EFM32TG_EMU_CTRL_bits EFM32 Tiny Gecko EMU CTRL bits
+ * @{
+ */
+
+#define EMU_CTRL_EM4CTRL_TWO (2<<2)
+#define EMU_CTRL_EM4CTRL_THREE (3<<2)
+#define EMU_CTRL_EM2BLOCK (1<<1) /**< When this bit is set, no mode lower than EM1 will be entered */
+#define EMU_CTRL_EMVREG (1<<0) /**< When this bit is set, the voltage regulator will stay on in modes lower than EM1 */
+
+/** @} */
+
+/** Values for the EMU_LOCK register
+ *
+ * See d0034_efm32tg_reference_manual.pdf section 10.5.2. There seems not to be
+ * another mention of it.
+ *
+ * @defgroup EFM32TG_EMU_LOCK_values EFM32 Tiny Gecko EMU LOCK values
+ * @{
+ */
+
+#define EMU_LOCK_IS_UNLOCKED 0 /**< When the LOCK register reads as this value, it is open */
+#define EMU_LOCK_IS_LOCKED 1 /**< When the LOCK register reads as this value, it is locked */
+#define EMU_LOCK_SET_LOCKED 0 /**< Write this to the LOCK register to lock the EMU */
+#define EMU_LOCK_SET_UNLOCKED 0xade8 /**< Write this to the LOCK register to unlock the EMU */
+
+/** @} */
+
+/** Bit states for the EMU_AUXCTRL register
+ *
+ * See d0034_efm32tg_reference_manual.pdf section 10.5.3 for definition, and
+ * 9.5.3 for details.
+ *
+ * @defgroup EFM32TG_EMU_AUXCTRL_bits EFM32 Tiny Gecko EMU AUXCTRL bits
+ * @{
+ */
+
+#define EMU_AUXCTRL_HRCCLR (1<<0)
+
+/** @} */
+
+/** @} */
+
+/** EMU convenience functions
+ *
+ * These functions can be used to send the chip to low energy modes.
+ *
+ * @todo Implement other sleep modes than EM1. Implement WFI vs WFE waits.
+ *
+ * @defgroup EFM32TG_EMU_convenience EFM32 Tiny Gecko EMU convenience functions
+ * @{
+ */
+
+/** Put the system into EM1 low energy mode. */
+static void emu_sleep_em1(void)
+{
+ /* FIXME: set SLEEPDEEP to 0 */
+ __asm__("wfi");
+}
+
+/** @} */
+
+/** @} */
+
+#endif
diff --git a/include/libopencm3/efm32/tinygecko/gpio.h b/include/libopencm3/efm32/tinygecko/gpio.h
new file mode 100644
index 0000000..1f4ae69
--- /dev/null
+++ b/include/libopencm3/efm32/tinygecko/gpio.h
@@ -0,0 +1,497 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2012 chrysn <chrysn@fsfe.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file
+ * @see EFM32TG_GPIO
+ */
+
+/** Definitions for the GPIO subsystem (General Purpose Input Output).
+ *
+ * This corresponds to the description in d0034_efm32tg_reference_manual.pdf
+ * section 28.
+ *
+ * @defgroup EFM32TG_GPIO EFM32 Tiny Gecko GPIO
+ * @{
+ */
+
+#ifndef LIBOPENCM3_EFM32_TINYGECKO_GPIO_H
+#define LIBOPENCM3_EFM32_TINYGECKO_GPIO_H
+
+#include <libopencm3/cm3/common.h>
+#include <libopencm3/efm32/memorymap.h>
+
+/** Register definitions and register value definitions for the GPIO subsystem
+ *
+ * @defgroup EFM32TG_GPIO_regsandvals EFM32 Tiny Gecko GPIO registers and values
+ * @{
+ */
+
+/** These definitions reflect d0034_efm32tg_reference_manual.pdf section 28.4
+ *
+ * The bulk of the registers defined here (like GPIO_PA_CTRL) will not be used
+ * inside the convenience functions, but are provided for direct access.
+ *
+ * @todo This section could profit from bit-banding.
+ *
+ * @defgroup EFM32TG_GPIO_registers EFM32 Tiny Gecko GPIO registers
+ * @{
+ */
+#define GPIO_Px_CTRL(port) MMIO32(port + 0x000) /**< @see EFM32TG_GPIO_Px_CTRL_bits */
+#define GPIO_Px_MODEL(port) MMIO32(port + 0x004) /**< @see EFM32TG_GPIO_MODE_values */
+#define GPIO_Px_MODEH(port) MMIO32(port + 0x008) /**< @see EFM32TG_GPIO_MODE_values */
+#define GPIO_Px_DOUT(port) MMIO32(port + 0x00C) /**< @see EFM32TG_GPIO_pinnumberbits */
+#define GPIO_Px_DOUTSET(port) MMIO32(port + 0x010) /**< @see EFM32TG_GPIO_pinnumberbits */
+#define GPIO_Px_DOUTCLR(port) MMIO32(port + 0x014) /**< @see EFM32TG_GPIO_pinnumberbits */
+#define GPIO_Px_DOUTTGL(port) MMIO32(port + 0x018) /**< @see EFM32TG_GPIO_pinnumberbits */
+#define GPIO_Px_DIN(port) MMIO32(port + 0x01C) /**< @see EFM32TG_GPIO_pinnumberbits */
+#define GPIO_Px_PINLOCKN(port) MMIO32(port + 0x020) /**< @see EFM32TG_GPIO_pinnumberbits */
+
+#define GPIO_PA (GPIO_BASE + 0x000)
+#define GPIO_PA_CTRL GPIO_Px_CTRL(GPIO_PA)
+#define GPIO_PA_MODEL GPIO_Px_MODEL(GPIO_PA)
+#define GPIO_PA_MODEH GPIO_Px_MODEH(GPIO_PA)
+#define GPIO_PA_DOUT GPIO_Px_DOUT(GPIO_PA)
+#define GPIO_PA_DOUTSET GPIO_Px_DOUTSET(GPIO_PA)
+#define GPIO_PA_DOUTCLR GPIO_Px_DOUTCLR(GPIO_PA)
+#define GPIO_PA_DOUTTGL GPIO_Px_DOUTTGL(GPIO_PA)
+#define GPIO_PA_DIN GPIO_Px_DIN(GPIO_PA)
+#define GPIO_PA_PINLOCKN GPIO_Px_PINLOCKN(GPIO_PA)
+
+#define GPIO_PB (GPIO_BASE + 0x024)
+#define GPIO_PB_CTRL GPIO_Px_CTRL(GPIO_PB)
+#define GPIO_PB_MODEL GPIO_Px_MODEL(GPIO_PB)
+#define GPIO_PB_MODEH GPIO_Px_MODEH(GPIO_PB)
+#define GPIO_PB_DOUT GPIO_Px_DOUT(GPIO_PB)
+#define GPIO_PB_DOUTSET GPIO_Px_DOUTSET(GPIO_PB)
+#define GPIO_PB_DOUTCLR GPIO_Px_DOUTCLR(GPIO_PB)
+#define GPIO_PB_DOUTTGL GPIO_Px_DOUTTGL(GPIO_PB)
+#define GPIO_PB_DIN GPIO_Px_DIN(GPIO_PB)
+#define GPIO_PB_PINLOCKN GPIO_Px_PINLOCKN(GPIO_PB)
+
+#define GPIO_PC (GPIO_BASE + 0x048)
+#define GPIO_PC_CTRL GPIO_Px_CTRL(GPIO_PC)
+#define GPIO_PC_MODEL GPIO_Px_MODEL(GPIO_PC)
+#define GPIO_PC_MODEH GPIO_Px_MODEH(GPIO_PC)
+#define GPIO_PC_DOUT GPIO_Px_DOUT(GPIO_PC)
+#define GPIO_PC_DOUTSET GPIO_Px_DOUTSET(GPIO_PC)
+#define GPIO_PC_DOUTCLR GPIO_Px_DOUTCLR(GPIO_PC)
+#define GPIO_PC_DOUTTGL GPIO_Px_DOUTTGL(GPIO_PC)
+#define GPIO_PC_DIN GPIO_Px_DIN(GPIO_PC)
+#define GPIO_PC_PINLOCKN GPIO_Px_PINLOCKN(GPIO_PC)
+
+#define GPIO_PD (GPIO_BASE + 0x06C)
+#define GPIO_PD_CTRL GPIO_Px_CTRL(GPIO_PD)
+#define GPIO_PD_MODEL GPIO_Px_MODEL(GPIO_PD)
+#define GPIO_PD_MODEH GPIO_Px_MODEH(GPIO_PD)
+#define GPIO_PD_DOUT GPIO_Px_DOUT(GPIO_PD)
+#define GPIO_PD_DOUTSET GPIO_Px_DOUTSET(GPIO_PD)
+#define GPIO_PD_DOUTCLR GPIO_Px_DOUTCLR(GPIO_PD)
+#define GPIO_PD_DOUTTGL GPIO_Px_DOUTTGL(GPIO_PD)
+#define GPIO_PD_DIN GPIO_Px_DIN(GPIO_PD)
+#define GPIO_PD_PINLOCKN GPIO_Px_PINLOCKN(GPIO_PD)
+
+#define GPIO_PE (GPIO_BASE + 0x090)
+#define GPIO_PE_CTRL GPIO_Px_CTRL(GPIO_PE)
+#define GPIO_PE_MODEL GPIO_Px_MODEL(GPIO_PE)
+#define GPIO_PE_MODEH GPIO_Px_MODEH(GPIO_PE)
+#define GPIO_PE_DOUT GPIO_Px_DOUT(GPIO_PE)
+#define GPIO_PE_DOUTSET GPIO_Px_DOUTSET(GPIO_PE)
+#define GPIO_PE_DOUTCLR GPIO_Px_DOUTCLR(GPIO_PE)
+#define GPIO_PE_DOUTTGL GPIO_Px_DOUTTGL(GPIO_PE)
+#define GPIO_PE_DIN GPIO_Px_DIN(GPIO_PE)
+#define GPIO_PE_PINLOCKN GPIO_Px_PINLOCKN(GPIO_PE)
+
+#define GPIO_PF (GPIO_BASE + 0x0B4)
+#define GPIO_PF_CTRL GPIO_Px_CTRL(GPIO_PF)
+#define GPIO_PF_MODEL GPIO_Px_MODEL(GPIO_PF)
+#define GPIO_PF_MODEH GPIO_Px_MODEH(GPIO_PF)
+#define GPIO_PF_DOUT GPIO_Px_DOUT(GPIO_PF)
+#define GPIO_PF_DOUTSET GPIO_Px_DOUTSET(GPIO_PF)
+#define GPIO_PF_DOUTCLR GPIO_Px_DOUTCLR(GPIO_PF)
+#define GPIO_PF_DOUTTGL GPIO_Px_DOUTTGL(GPIO_PF)
+#define GPIO_PF_DIN GPIO_Px_DIN(GPIO_PF)
+#define GPIO_PF_PINLOCKN GPIO_Px_PINLOCKN(GPIO_PF)
+
+#define GPIO_EXTIPSELL MMIO32(GPIO_BASE + 0x100) /**< @see EFM32TG_GPIO_EXTIP_values */
+#define GPIO_EXTIPSELH MMIO32(GPIO_BASE + 0x104) /**< @see EFM32TG_GPIO_EXTIP_values */
+#define GPIO_EXTIRISE MMIO32(GPIO_BASE + 0x108) /**< @see EFM32TG_GPIO_pinnumberbits */
+#define GPIO_EXTIFALL MMIO32(GPIO_BASE + 0x10C) /**< @see EFM32TG_GPIO_pinnumberbits */
+#define GPIO_IEN MMIO32(GPIO_BASE + 0x110) /**< @see EFM32TG_GPIO_pinnumberbits */
+#define GPIO_IF MMIO32(GPIO_BASE + 0x114) /**< @see EFM32TG_GPIO_pinnumberbits */
+#define GPIO_IFS MMIO32(GPIO_BASE + 0x118) /**< @see EFM32TG_GPIO_pinnumberbits */
+#define GPIO_IFC MMIO32(GPIO_BASE + 0x11C) /**< @see EFM32TG_GPIO_pinnumberbits */
+#define GPIO_ROUTE MMIO32(GPIO_BASE + 0x120) /**< @see EFM32TG_GPIO_ROUTE_bits */
+#define GPIO_INSENSE MMIO32(GPIO_BASE + 0x124) /**< @see EFM32TG_GPIO_INSENSE_bits */
+#define GPIO_LOCK MMIO32(GPIO_BASE + 0x128) /**< @see EFM32TG_GPIO_LOCK_values */
+#define GPIO_CTRL MMIO32(GPIO_BASE + 0x12C) /**< @see EFM32TG_GPIO_CTRL_bits */
+#define GPIO_CMD MMIO32(GPIO_BASE + 0x130) /**< @see EFM32TG_GPIO_CMD_bits */
+#define GPIO_EM4WUEN MMIO32(GPIO_BASE + 0x134) /**< @see EFM32TG_GPIO_EM4WUEN_bits */
+#define GPIO_EM4WUPOL MMIO32(GPIO_BASE + 0x138) /**< @see EFM32TG_GPIO_EM4WUPOL_bits */
+#define GPIO_EM4WUCAUSE MMIO32(GPIO_BASE + 0x13C) /**< @see EFM32TG_GPIO_EM4WUCAUSE_bits */
+
+/** @} */
+
+/** Pin number bits
+ *
+ * Provided for convenience. They can be used on the GPIO_Px_DOUT,
+ * GPIO_Px_DOUTSET, GPIO_Px_DOUTCLR, GPIO_Px_DOUTTGL, GPIO_Px_DIN,
+ * GPIO_Px_PINLOCKN, GPIO_Px_EXTIRISE, GPIO_Px_EXTIFALL, GPIO_IEN, GPIO_IF,
+ * GPIO_IFS, and GPIO_IFC registers.
+ *
+ * @defgroup EFM32TG_GPIO_pinnumberbits EFM32 Tiny Gecko GPIO pin number bits
+ * @{
+ */
+
+#define GPIO0 (1 << 0)
+#define GPIO1 (1 << 1)
+#define GPIO2 (1 << 2)
+#define GPIO3 (1 << 3)
+#define GPIO4 (1 << 4)
+#define GPIO5 (1 << 5)
+#define GPIO6 (1 << 6)
+#define GPIO7 (1 << 7)
+#define GPIO8 (1 << 8)
+#define GPIO9 (1 << 9)
+#define GPIO10 (1 << 10)
+#define GPIO11 (1 << 11)
+#define GPIO12 (1 << 12)
+#define GPIO13 (1 << 13)
+#define GPIO14 (1 << 14)
+#define GPIO15 (1 << 15)
+#define GPIO_ALL 0xffff
+
+/** @} */
+
+/** Bit states for the GPIO_Px_CTRL register
+ *
+ * They are named as in d0034_efm32tg_reference_manual.pdf's section
+ * 28.5.1.
+ *
+ * @defgroup EFM32TG_GPIO_Px_CTRL_bits EFM32 Tiny Gecko GPIO Px CTRL bits
+ * @{
+ */
+
+#define GPIO_CTRL_DRIVEMODE_STANDARD 0 /**< 6mA drive current */
+#define GPIO_CTRL_DRIVEMODE_LOWEST 1 /**< 0.5mA drive current */
+#define GPIO_CTRL_DRIVEMODE_HIGH 2 /**< 20mA drive current */
+#define GPIO_CTRL_DRIVEMODE_LOW 3 /**< 2mA drive current */
+
+/** @} */
+
+/** These are the modes defined for the MODEx fields in the GPIO_Px_MODEL and
+ * GPIO_Px_MODEH registers.
+ *
+ * These bit state definitions are not localized, meaning that they have to be
+ * bitshifted by multiples of 4 to configure other pins than 0; configurations
+ * for pins 0 to 7 go to GPIO_Px_MODEL (shifted by 4*pin), configurations for
+ * pins 8 to 15 go to GPIO_Px_MODEH (shifted by 4*(pin-8)).
+ *
+ * For example, to set the mode for the 3rd pin of port A to pushpull, set
+ * `GPIO_PA_MODEL = GPIO_MODE_PUSHPULL << (3*4);`.
+ *
+ * @todo Update the example as soon as there are convenience functions to do
+ * this properly.
+ *
+ * They are named as in d0034_efm32tg_reference_manual.pdf's sections
+ * 28.5.2/28.5.3. For explanations of what they really do, rather see section
+ * 28.3.1.
+ *
+ * @defgroup EFM32TG_GPIO_MODE_values EFM32 Tiny Gecko GPIO MODE values
+ * @{
+ */
+
+#define GPIO_MODE_DISABLED 0
+#define GPIO_MODE_INPUT 1
+#define GPIO_MODE_INPUTPULL 2
+#define GPIO_MODE_INPUTPULLFILTER 3
+#define GPIO_MODE_PUSHPULL 4
+#define GPIO_MODE_PUSHPULLDRIVE 5
+#define GPIO_MODE_WIREDOR 6
+#define GPIO_MODE_WIREDORPULLDOWN 7
+#define GPIO_MODE_WIREDAND 8
+#define GPIO_MODE_WIREDANDFILTER 9
+#define GPIO_MODE_WIREDANDPULLUP 10
+#define GPIO_MODE_WIREDANDPULLUPFILTER 11
+#define GPIO_MODE_WIREDANDDRIVE 12
+#define GPIO_MODE_WIREDANDDRIVEFILTER 13
+#define GPIO_MODE_WIREDANDDRIVEPULLUP 14
+#define GPIO_MODE_WIREDANDDRIVEPULLUPFILTER 15
+#define GPIO_MODE_MASK 0x0f
+
+/** @} */
+
+/** These are the modes defined for the EXTIPSELx fields in the GPIO_EXTIPSELL
+ * and GPIO_EXTIPSELH registers.
+ *
+ * These bit state definitions are not localized, meaning that they have to be
+ * bitshifted by multiples of 4 to configure other pins than 0; configurations
+ * for pins 0 to 7 go to GPIO_EXTIPSELL (shifted by 4*pin), configurations for
+ * pins 8 to 15 go to GPIO_EXTIPSELH (shifted by 4*(pin-8)).
+ *
+ * They are named as in d0034_efm32tg_reference_manual.pdf's sections
+ * 28.5.10/28.5.11. For explanations of what they do, rather see section
+ * 28.3.5.
+ *
+ * @defgroup EFM32TG_GPIO_EXTIP_values EFM32 Tiny Gecko GPIO EXTIPSEL values
+ * @{
+ */
+
+#define GPIO_EXTIPSEL_PORTA 0 /**< Port A pin x selected for external interrupt x */
+#define GPIO_EXTIPSEL_PORTB 1 /**< Port B pin x selected for external interrupt x */
+#define GPIO_EXTIPSEL_PORTC 2 /**< Port C pin x selected for external interrupt x */
+#define GPIO_EXTIPSEL_PORTD 3 /**< Port D pin x selected for external interrupt x */
+#define GPIO_EXTIPSEL_PORTE 4 /**< Port E pin x selected for external interrupt x */
+#define GPIO_EXTIPSEL_PORTF 5 /**< Port F pin x selected for external interrupt x */
+
+/** @} */
+
+/** Bit states for the GPIO_ROUTE register
+ *
+ * See d0034_efm32tg_reference_manual.pdf section 28.5.18 for definitions, and
+ * 28.3.4.1 for explanations.
+ *
+ * @defgroup EFM32TG_GPIO_ROUTE_bits EFM32 Tiny Gecko GPIO ROUTE bits
+ * @{
+ */
+
+#define GPIO_ROUTE_SWLOCATION_MASK (0x03<<8)
+#define GPIO_ROUTE_SWLOCATION_LOC0 (0<<8) /**< Route SW pins to location 0 (see chip data sheet for exact pins */
+#define GPIO_ROUTE_SWLOCATION_LOC1 (1<<8) /**< Route SW pins to location 1 (see chip data sheet for exact pins */
+#define GPIO_ROUTE_SWLOCATION_LOC2 (2<<8) /**< Route SW pins to location 2 (see chip data sheet for exact pins */
+#define GPIO_ROUTE_SWLOCATION_LOC3 (3<<8) /**< Route SW pins to location 3 (see chip data sheet for exact pins */
+
+#define GPIO_ROUTE_SWOPEN (1<<2) /**< Serial Wire Viewer Output pin enabled */
+#define GPIO_ROUTE_SWDIOPEN (1<<1) /**< Serial Wire Data pin enabled */
+#define GPIO_ROUTE_SWCLKPEN (1<<0) /**< Serial Wire Clock pin enabled */
+
+/** @} */
+
+/** Bit states for the GPIO_INSENSE register
+ *
+ * See d0034_efm32tg_reference_manual.pdf section 28.5.19 for definitions, and
+ * 28.3.7 for details.
+ *
+ * @defgroup EFM32TG_GPIO_INSENSE_bits EFM32 Tiny Gecko GPIO INSENSE bits
+ * @{
+ */
+
+#define GPIO_INSENSE_PRS (1<<1) /**< Input sensing for PRS enabled */
+#define GPIO_INSENSE_INT (1<<0) /**< Input sensing for interrupts enabled */
+
+/** @} */
+
+/** Values for the GPIO_LOCK register
+ *
+ * See d0034_efm32tg_reference_manual.pdf section 28.5.20 for definitions, and
+ * 28.3.1.1 for explanations.
+ *
+ * @defgroup EFM32TG_GPIO_LOCK_values EFM32 Tiny Gecko GPIO LOCK bits
+ * @{
+ */
+
+#define GPIO_LOCK_IS_UNLOCKED 0 /**< When the LOCK register reads as this value, it is open */
+#define GPIO_LOCK_IS_LOCKED 1 /**< When the LOCK register reads as this value, it is locked */
+#define GPIO_LOCK_SET_LOCKED 0 /**< Write this to the LOCK register to lock down GPIO */
+#define GPIO_LOCK_SET_UNLOCKED 0xa543 /**< Write this to the LOCK register to unlock the GPIO */
+
+/** @} */
+
+/** Bit states for the GPIO_CTRL register
+ *
+ * See d0034_efm32tg_reference_manual.pdf section 28.5.21 for definitions, and
+ * 28.3.4 for explanations.
+ *
+ * @defgroup EFM32TG_GPIO_CTRL_bits EFM32 Tiny Gecko GPIO CTRL bits
+ * @{
+ */
+
+#define GPIO_CTRL_EM4RET (1<<0) /**< Retention of states in EM4 */
+
+/** @} */
+
+/** Bit states for the GPIO_CMD register
+ *
+ * See d0034_efm32tg_reference_manual.pdf section 28.5.22 for definitions and
+ * figure 28.5 in case you wonder if that register is mentioned anywhere else
+ * at all.
+ *
+ * @defgroup EFM32TG_GPIO_CMD_bits EFM32 Tiny Gecko GPIO CMD bits
+ * @{
+ */
+
+#define GPIO_CMD_EM4WUCLR (1<<0) /**< Write this flag to clear EM4 wakeup requests */
+
+/** @} */
+
+/** Bit states for the GPIO_EM4WUEN register
+ *
+ * See d0034_efm32tg_reference_manual.pdf section 28.5.23 for definitions, and
+ * 28.3.2 for explanations.
+ *
+ * @defgroup EFM32TG_GPIO_EM4WUEN_bits EFM32 Tiny Gecko GPIO EM4WUEN bits
+ * @{
+ */
+
+#define GPIO_EM4WUEN_A0 0x01 /**< Wake up from EM4 on A0 activity */
+#define GPIO_EM4WUEN_A6 0x02 /**< Wake up from EM4 on A6 activity */
+#define GPIO_EM4WUEN_C9 0x04 /**< Wake up from EM4 on C9 activity */
+#define GPIO_EM4WUEN_F1 0x08 /**< Wake up from EM4 on F1 activity */
+#define GPIO_EM4WUEN_F3 0x10 /**< Wake up from EM4 on F3 activity */
+#define GPIO_EM4WUEN_E13 0x20 /**< Wake up from EM4 on E13 activity */
+
+/** @} */
+
+/** Bit states for the GPIO_EM4WUPOL register
+ *
+ * See d0034_efm32tg_reference_manual.pdf section 28.5.24 for definitions, and
+ * 28.3.2 for explanations.
+ *
+ * @defgroup EFM32TG_GPIO_EM4WUPOL_bits EFM32 Tiny Gecko GPIO EM4WUPOL bits
+ * @{
+ */
+
+#define GPIO_EM4WUPOL_A0 0x01 /**< High wake up from EM4 on A0 */
+#define GPIO_EM4WUPOL_A6 0x02 /**< High wake up from EM4 on A6 */
+#define GPIO_EM4WUPOL_C9 0x04 /**< High wake up from EM4 on C9 */
+#define GPIO_EM4WUPOL_F1 0x08 /**< High wake up from EM4 on F1 */
+#define GPIO_EM4WUPOL_F3 0x10 /**< High wake up from EM4 on F3 */
+#define GPIO_EM4WUPOL_E13 0x20 /**< High wake up from EM4 on E13 */
+
+/** @} */
+
+/** Bit states for the GPIO_EM4WUCAUSE register
+ *
+ * See d0034_efm32tg_reference_manual.pdf section 28.5.25 for definitions, and
+ * 28.3.2 for explanations.
+ *
+ * @defgroup EFM32TG_GPIO_EM4WUCAUSE_bits EFM32 Tiny Gecko GPIO EM4WUCAUSE bits
+ * @{
+ */
+
+#define GPIO_EM4WUCAUSE_A0 0x01 /**< Woke up from EM4 on A0 */
+#define GPIO_EM4WUCAUSE_A6 0x02 /**< Woke up from EM4 on A6 */
+#define GPIO_EM4WUCAUSE_C9 0x04 /**< Woke up from EM4 on C9 */
+#define GPIO_EM4WUCAUSE_F1 0x08 /**< Woke up from EM4 on F1 */
+#define GPIO_EM4WUCAUSE_F3 0x10 /**< Woke up from EM4 on F3 */
+#define GPIO_EM4WUCAUSE_E13 0x20 /**< Woke up from EM4 on E13 */
+
+/** @} */
+
+/** @} */
+
+/** GPIO convenience functions
+ *
+ * These functions try to be close to the STM32 F1 utility functions where
+ * possible.
+ *
+ * The functions intentionally don't cover all the possible read- and write
+ * operations to the GPIO registers. For example, reading the configured output
+ * strength for a port is rarely required.
+ *
+ * Many convenience functions are static to allow inlining by the compiler.
+ *
+ * @todo Implement all the non-trivial but useful convenience functions.
+ *
+ * @defgroup EFM32TG_GPIO_convenience EFM32 Tiny Gecko GPIO convenience functions
+ * @{
+ */
+
+/** Set a whole GPIO port's out data to a particular value
+ *
+ * \param gpioport Address of a GPIO port to use (eg GPIO_PA)
+ * \param gpios Bit pattern the output of the port will be configured to (eg GPIO6|GPIO3 to switch pins 6 and 3 to high and all the others to low)
+ */
+static void gpio_port_write(u32 gpioport, u16 data)
+{
+ GPIO_Px_DOUT(gpioport) = data;
+}
+/** Set some bits in a GPIO port's out data
+ *
+ * \param gpioport Address of a GPIO port to use (eg GPIO_PA)
+ * \param gpios GPIO pin(s) to be set to 1 (eg GPIO6|GPIO3 to switch pins 6 and 3 to high and leave all the others in their previous state)
+ */
+static void gpio_set(u32 gpioport, u16 gpios)
+{
+ GPIO_Px_DOUTSET(gpioport) = gpios;
+}
+/** Clear some bits in a GPIO port's out data
+ *
+ * \param gpioport Address of a GPIO port to use (eg GPIO_PA)
+ * \param gpios GPIO pin(s) to be set to 0 (eg GPIO6|GPIO3 to switch pins 6 and 3 to low and leave all the others in their previous state)
+ */
+static void gpio_clear(u32 gpioport, u16 gpios)
+{
+ GPIO_Px_DOUTCLR(gpioport) = gpios;
+}
+/** Toggle some bits in a GPIO port's out data
+ *
+ * \param gpioport Address of a GPIO port to use (eg GPIO_PA)
+ * \param gpios GPIO pin(s) that will be toggled (eg GPIO6|GPIO3 to toggle the output directions of pins 6 and 3 and leave all the others in their previous state)
+ */
+static void gpio_toggle(u32 gpioport, u16 gpios)
+{
+ GPIO_Px_DOUTTGL(gpioport) = gpios;
+}
+
+/** Read input bits from a GPIO's port in data
+ *
+ * \param gpioport Address of a GPIO port to use (eg GPIO_PA)
+ * \returns Current value of the in register of the given port
+ */
+static u16 gpio_port_read(u32 gpioport)
+{
+ return GPIO_Px_DIN(gpioport);
+}
+/** Read input bits from a GPIO's port in data
+ *
+ * \param gpioport Address of a GPIO port to use (eg GPIO_PA)
+ * \param gpios Bits that will be read (eg GPIO6|GPIO3 to read pins 6 and 3)
+ * \returns Bit pattern that contains 1 in all pin positions that currently read as high (eg GPIO6 if port A's 6th pin is currently high and the 3rd pin is low)
+ */
+static u16 gpio_get(u32 gpioport, u16 gpios)
+{
+ return gpio_port_read(gpioport) & gpios;
+}
+
+/** Configure a particular pin configuration on one or more pins
+ *
+ * This function is not atomic. It has to be made sure that it is not
+ * interrupted by other code that modifies the port's configuration.
+ *
+ * \param gpioport Address of a GPIO port to use (eg GPIO_PA)
+ * \param mode Pin configuration mode to set (eg GPIO_MODE_INPUT)
+ * \param gpios Pins to configure (eg GPIO6|GPIO3 to set the mode on pins 6 and 3)
+ */
+void gpio_set_mode(u32 gpioport, u8 mode, u16 gpios);
+
+/** Configure the alternate drive strength for a port
+ *
+ * \param gpioport Address of a GPIO port to use (eg GPIO_PA)
+ * \param strength Alternate drive strength to configure for the port (eg GPIO_CTRL_DRIVEMODE_HIGH)
+ */
+static void gpio_set_strength(u32 gpioport, u8 strength)
+{
+ GPIO_Px_CTRL(gpioport) = strength;
+}
+
+/** @} */
+
+/** @} */
+
+#endif
diff --git a/include/libopencm3/efm32/tinygecko/irq.h b/include/libopencm3/efm32/tinygecko/irq.h
new file mode 100644
index 0000000..ee0c631
--- /dev/null
+++ b/include/libopencm3/efm32/tinygecko/irq.h
@@ -0,0 +1,36 @@
+/** @file
+ *
+ * Definitions of interrupt names on EFM32 Tiny Gecko systems
+ *
+ * The names and numbers are taken from d0034_efm32tg_reference_manual.pdf table 4.1.
+ */
+
+#ifndef LIBOPENCM3_EFM32_TINYGECKO_VECTOR_H
+#define LIBOPENCM3_EFM32_TINYGECKO_VECTOR_H
+
+#define IRQ_DMA 0
+#define IRQ_GPIO_EVEN 1
+#define IRQ_TIMER0 2
+#define IRQ_USART0_RX 3
+#define IRQ_USART0_TX 4
+#define IRQ_ACMP01 5
+#define IRQ_ADC0 6
+#define IRQ_DAC0 7
+#define IRQ_I2C0 8
+#define IRQ_GPIO_ODD 9
+#define IRQ_TIMER1 10
+#define IRQ_USART1_RX 11
+#define IRQ_USART1_TX 12
+#define IRQ_LESENSE 13
+#define IRQ_LEUART0 14
+#define IRQ_LETIMER0 15
+#define IRQ_PCNT0 16
+#define IRQ_RTC 17
+#define IRQ_CMU 18
+#define IRQ_VCMP 19
+#define IRQ_LCD 20
+#define IRQ_MSC 21
+#define IRQ_AES 22
+#define IRQ_COUNT 23 /**< See also d0002_efm32_cortex-m3_reference_manual.pdf's table 1.1's "number of interrupts" line, which shows that there are really no more interrupts and it is sufficient to allocate only 23 slots. */
+
+#endif
diff --git a/include/libopencm3/efm32/tinygecko/memorymap.h b/include/libopencm3/efm32/tinygecko/memorymap.h
new file mode 100644
index 0000000..87395b5
--- /dev/null
+++ b/include/libopencm3/efm32/tinygecko/memorymap.h
@@ -0,0 +1,76 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2012 chrysn <chrysn@fsfe.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file
+ *
+ * Layout of the system address space of Tiny Gecko devices.
+ *
+ * This reflects d0034_efm32tg_reference_manual.pdf figure 5.2.
+ */
+
+/* The common cortex-m3 definitions were verified from
+ * d0034_efm32tg_reference_manual.pdf figure 5.2. The CM3 ROM Table seems to be
+ * missing there. The details (everything based on SCS_BASE) was verified from
+ * d0002_efm32_cortex-m3_reference_manual.pdf table 4.1, and seems to fit, but
+ * there are discrepancies. */
+#include <libopencm3/cm3/memorymap.h>
+
+#define CODE_BASE 0x00000000
+
+#define SRAM_BASE 0x20000000
+#define SRAM_BASE_BITBAND 0x22000000
+
+#define PERIPH_BASE 0x40000000
+#define PERIPH_BASE_BITBAND 0x42000000
+
+/* Details of the "Code" section */
+
+#define FLASH_BASE (CODE_BASE + 0x00000000)
+#define USERDATA_BASE (CODE_BASE + 0x0fe00000)
+#define LOCKBITS_BASE (CODE_BASE + 0x0fe04000)
+#define CHIPCONFIG_BASE (CODE_BASE + 0x0fe08000)
+#define CODESPACESRAM_BASE (CODE_BASE + 0x10000000)
+
+/* Tiny Gecko peripherial definitions */
+
+#define VCMP_BASE (PERIPH_BASE + 0x00000000)
+#define ACMP0_BASE (PERIPH_BASE + 0x00001000)
+#define ACMP1_BASE (PERIPH_BASE + 0x00001400)
+#define ADC_BASE (PERIPH_BASE + 0x00002000)
+#define DAC0_BASE (PERIPH_BASE + 0x00004000)
+#define GPIO_BASE (PERIPH_BASE + 0x00006000) /**< @see gpio.h */
+#define I2C0_BASE (PERIPH_BASE + 0x0000a000)
+#define USART0_BASE (PERIPH_BASE + 0x0000c000)
+#define USART1_BASE (PERIPH_BASE + 0x0000c400)
+#define TIMER0_BASE (PERIPH_BASE + 0x00010000)
+#define TIMER1_BASE (PERIPH_BASE + 0x00010400)
+#define RTC_BASE (PERIPH_BASE + 0x00080000)
+#define LETIMER0_BASE (PERIPH_BASE + 0x00082000)
+#define LEUART0_BASE (PERIPH_BASE + 0x00084000)
+#define PCNT0_BASE (PERIPH_BASE + 0x00086000)
+#define WDOG_BASE (PERIPH_BASE + 0x00088000)
+#define LCD_BASE (PERIPH_BASE + 0x0008a000)
+#define LESENSE_BASE (PERIPH_BASE + 0x0008c000)
+#define MSC_BASE (PERIPH_BASE + 0x000c0000)
+#define DMA_BASE (PERIPH_BASE + 0x000c2000)
+#define EMU_BASE (PERIPH_BASE + 0x000c6000)
+#define CMU_BASE (PERIPH_BASE + 0x000c8000) /**< @see cmu.h */
+#define RMU_BASE (PERIPH_BASE + 0x000ca000)
+#define PRS_BASE (PERIPH_BASE + 0x000cc000)
+#define AES_BASE (PERIPH_BASE + 0x000e0000)
diff --git a/include/libopencm3/efm32/vector.h b/include/libopencm3/efm32/vector.h
new file mode 100644
index 0000000..ae6b9ba
--- /dev/null
+++ b/include/libopencm3/efm32/vector.h
@@ -0,0 +1,47 @@
+/** @file
+ *
+ * Definitions for handling vector tables.
+ *
+ * This implements d0002_efm32_cortex-m3_reference_manual.pdf's figure 2.2.
+ *
+ * The structure of the vector table is implemented independently of the system
+ * vector table starting at memory position 0x0, as it can be relocated to
+ * other memory locations too.
+ *
+ * The exact size of a vector interrupt table depends on the number of
+ * interrupts IRQ_COUNT, which is defined per family.
+ */
+
+#ifndef LIBOPENCM3_EFM32_VECTOR_H
+#define LIBOPENCM3_EFM32_VECTOR_H
+
+#include <libopencm3/cm3/common.h>
+
+#ifdef TINYGECKO
+# include <libopencm3/efm32/tinygecko/irq.h>
+#else
+# error "efm32 family not defined."
+#endif
+
+/** Type of an interrupt function. Only used to avoid hard-to-read function
+ * pointers in the efm32_vector_table_t struct. */
+typedef void (*efm32_vector_table_entry_t)(void);
+
+typedef struct {
+ unsigned int *initial_sp_value; /**< The value the stack pointer is set to initially */
+ efm32_vector_table_entry_t reset;
+ efm32_vector_table_entry_t nmi;
+ efm32_vector_table_entry_t hard_fault;
+ efm32_vector_table_entry_t memory_manage_fault;
+ efm32_vector_table_entry_t bus_fault;
+ efm32_vector_table_entry_t usage_fault;
+ efm32_vector_table_entry_t reserved_x001c[4];
+ efm32_vector_table_entry_t sv_call;
+ efm32_vector_table_entry_t reserved_debug;
+ efm32_vector_table_entry_t reserved_x0034;
+ efm32_vector_table_entry_t pend_sv;
+ efm32_vector_table_entry_t systick;
+ efm32_vector_table_entry_t irq[IRQ_COUNT];
+} efm32_vector_table_t;
+
+#endif
diff --git a/lib/efm32/tinygecko/EFM32TG840F32.ld b/lib/efm32/tinygecko/EFM32TG840F32.ld
new file mode 100644
index 0000000..f7baa90
--- /dev/null
+++ b/lib/efm32/tinygecko/EFM32TG840F32.ld
@@ -0,0 +1,15 @@
+/* lengths from d011_efm32tg840_datasheet.pdf table 1.1, offset from
+ * d0034_efm32tg_reference_manual.pdf figure 5.2.
+ *
+ * the origins and memory structure are constant over all tinygeckos, but the
+ * MEMORY section requires the use of constants, and has thus to be duplicated
+ * over the chip variants.
+ * */
+
+MEMORY
+{
+ rom (rx) : ORIGIN = 0, LENGTH = 32k
+ ram (rwx) : ORIGIN = 0x20000000, LENGTH = 4k
+}
+
+INCLUDE tinygecko.ld;
diff --git a/lib/efm32/tinygecko/Makefile b/lib/efm32/tinygecko/Makefile
new file mode 100644
index 0000000..a2bffc1
--- /dev/null
+++ b/lib/efm32/tinygecko/Makefile
@@ -0,0 +1,60 @@
+##
+## This file is part of the libopencm3 project.
+##
+## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+## Copyright (C) 2012 chrysn <chrysn@fsfe.org>
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program 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 General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program. If not, see <http://www.gnu.org/licenses/>.
+##
+
+LIBNAME = libopencm3_efm32tinygecko
+FAMILY = TINYGECKO
+
+PREFIX ?= arm-none-eabi
+#PREFIX ?= arm-elf
+CC = $(PREFIX)-gcc
+AR = $(PREFIX)-ar
+CFLAGS = -Os -g -Wall -Wextra -I../../../include -fno-common \
+ -mcpu=cortex-m3 -mthumb -Wstrict-prototypes \
+ -ffunction-sections -fdata-sections -MD -D$(FAMILY)
+# ARFLAGS = rcsv
+ARFLAGS = rcs
+OBJS = vector.o devicerevision.o gpio.o
+
+VPATH += ../
+
+# Be silent per default, but 'make V=1' will show all compiler calls.
+ifneq ($(V),1)
+Q := @
+endif
+
+all: $(LIBNAME).a
+
+$(LIBNAME).a: $(OBJS)
+ @printf " AR $(subst $(shell pwd)/,,$(@))\n"
+ $(Q)$(AR) $(ARFLAGS) $@ $^
+
+%.o: %.c
+ @printf " CC $(subst $(shell pwd)/,,$(@))\n"
+ $(Q)$(CC) $(CFLAGS) -o $@ -c $<
+
+clean:
+ @printf " CLEAN lib/efm32/tinygecko\n"
+ $(Q)rm -f *.o *.d
+ $(Q)rm -f $(LIBNAME).a
+
+.PHONY: clean
+
+-include $(OBJS:.o=.d)
+
diff --git a/lib/efm32/tinygecko/devicerevision.c b/lib/efm32/tinygecko/devicerevision.c
new file mode 100644
index 0000000..216ab1b
--- /dev/null
+++ b/lib/efm32/tinygecko/devicerevision.c
@@ -0,0 +1,10 @@
+#include <libopencm3/efm32/tinygecko/devicerevision.h>
+
+u8 devicerevision_revision_get(void)
+{
+ /* probably this is more elegant, more readable and closer to the spec,
+ * and i'll just get used to doing things like that:
+ return (DEVICEREVISION_PID2 & 0xf0) | ((DEVICEREVISION_PID3 & 0xf0) >> 4);
+ */
+ return ((DEVICEREVISION_PID2 & DEVICEREVISION_REVISION_MASK) >> DEVICEREVISION_REVISION_SHIFT << DEVICEREVISION_REVISION_LENGTH) | ((DEVICEREVISION_PID3 & DEVICEREVISION_REVISION_MASK) >> DEVICEREVISION_REVISION_SHIFT);
+}
diff --git a/lib/efm32/tinygecko/gpio.c b/lib/efm32/tinygecko/gpio.c
new file mode 100644
index 0000000..6e49f17
--- /dev/null
+++ b/lib/efm32/tinygecko/gpio.c
@@ -0,0 +1,23 @@
+#include <libopencm3/efm32/tinygecko/gpio.h>
+
+void gpio_set_mode(u32 gpioport, u8 mode, u16 gpios)
+{
+ u8 i;
+ u32 modemaskl = 0, modesetl = 0, modemaskh = 0, modeseth = 0;
+
+ for (i = 0; i < 8; ++i)
+ {
+ if (gpios & (1<<i)) {
+ modemaskl |= GPIO_MODE_MASK << (i*4);
+ modesetl |= mode << (i*4);
+ }
+ if (gpios & (0x100<<i)) {
+ modemaskh |= GPIO_MODE_MASK << (i*4);
+ modeseth |= mode << (i*4);
+ }
+ }
+ GPIO_Px_MODEL(gpioport) &= ~modemaskl;
+ GPIO_Px_MODEL(gpioport) |= modesetl;
+ GPIO_Px_MODEH(gpioport) &= ~modemaskh;
+ GPIO_Px_MODEH(gpioport) |= modeseth;
+}
diff --git a/lib/efm32/tinygecko/tinygecko.ld b/lib/efm32/tinygecko/tinygecko.ld
new file mode 100644
index 0000000..db3b81f
--- /dev/null
+++ b/lib/efm32/tinygecko/tinygecko.ld
@@ -0,0 +1,78 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>,
+ * 2012 chrysn <chrysn@fsfe.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Generic linker script for EFM32 targets using libopencm3. */
+
+/* Memory regions must be defined in the ld script which includes this one. */
+
+/* Enforce emmition of the vector table. */
+EXTERN (vector_table)
+
+/* Define the entry point of the output file. */
+ENTRY(reset_handler)
+
+/* Define sections. */
+SECTIONS
+{
+ . = ORIGIN(rom);
+
+ .text : {
+ *(.vectors) /* Vector table */
+ *(.text*) /* Program code */
+ . = ALIGN(4);
+ *(.rodata*) /* Read-only data */
+ . = ALIGN(4);
+ _etext = .;
+ } >rom
+
+ . = ORIGIN(ram);
+
+ .data : AT(_etext) {
+ _data = .;
+ *(.data*) /* Read-write initialized data */
+ . = ALIGN(4);
+ _edata = .;
+ } >ram
+
+ .bss : {
+ *(.bss*) /* Read-write zero initialized data */
+ *(COMMON)
+ . = ALIGN(4);
+ _ebss = .;
+ } >ram AT >rom
+
+ /*
+ * The .eh_frame section appears to be used for C++ exception handling.
+ * You may need to fix this if you're using C++.
+ */
+ /DISCARD/ : { *(.eh_frame) }
+
+ /*
+ * Another section used by C++ stuff, appears when using newlib with
+ * 64bit (long long) printf support - discard it for now.
+ */
+ /DISCARD/ : { *(.ARM.exidx) }
+
+ . = ALIGN(4);
+ end = .;
+}
+
+PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram));
+
diff --git a/lib/efm32/tinygecko/vector.c b/lib/efm32/tinygecko/vector.c
new file mode 100644
index 0000000..fb8fbd4
--- /dev/null
+++ b/lib/efm32/tinygecko/vector.c
@@ -0,0 +1,159 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>,
+ * 2012 chrysn <chrysn@fsfe.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/efm32/tinygecko/irq.h>
+#include <libopencm3/efm32/vector.h>
+
+#define WEAK __attribute__ ((weak))
+
+/* Symbols exported by the linker script(s). */
+extern unsigned _etext, _data, _edata, _ebss, _stack;
+
+void main(void);
+void blocking_handler(void);
+
+void WEAK reset_handler(void);
+void WEAK nmi_handler(void);
+void WEAK hard_fault_handler(void);
+void WEAK mem_manage_handler(void);
+void WEAK bus_fault_handler(void);
+void WEAK usage_fault_handler(void);
+void WEAK sv_call_handler(void);
+void WEAK debug_monitor_handler(void);
+void WEAK pend_sv_handler(void);
+void WEAK sys_tick_handler(void);
+
+void WEAK dma_isr(void);
+void WEAK gpio_even_isr(void);
+void WEAK timer0_isr(void);
+void WEAK usart0_rx_isr(void);
+void WEAK usart0_tx_isr(void);
+void WEAK acmp01_isr(void);
+void WEAK adc0_isr(void);
+void WEAK dac0_isr(void);
+void WEAK i2c0_isr(void);
+void WEAK gpio_odd_isr(void);
+void WEAK timer1_isr(void);
+void WEAK usart1_rx_isr(void);
+void WEAK usart1_tx_isr(void);
+void WEAK lesense_isr(void);
+void WEAK leuart0_isr(void);
+void WEAK letimer0_isr(void);
+void WEAK pcnt0_isr(void);
+void WEAK rtc_isr(void);
+void WEAK cmu_isr(void);
+void WEAK vcmp_isr(void);
+void WEAK lcd_isr(void);
+void WEAK msc_isr(void);
+void WEAK aes_isr(void);
+
+__attribute__ ((section(".vectors")))
+efm32_vector_table_t vector_table = {
+ .initial_sp_value = &_stack,
+ .reset = reset_handler,
+ .nmi = nmi_handler,
+ .hard_fault = hard_fault_handler,
+ .memory_manage_fault = mem_manage_handler,
+ .bus_fault = bus_fault_handler,
+ .usage_fault = usage_fault_handler,
+ .sv_call = sv_call_handler,
+ .pend_sv = pend_sv_handler,
+ .systick = sys_tick_handler,
+ .irq = {
+ [IRQ_DMA] = dma_isr,
+ [IRQ_GPIO_EVEN] = gpio_even_isr,
+ [IRQ_TIMER0] = timer0_isr,
+ [IRQ_USART0_RX] = usart0_rx_isr,
+ [IRQ_USART0_TX] = usart0_tx_isr,
+ [IRQ_ACMP01] = acmp01_isr,
+ [IRQ_ADC0] = adc0_isr,
+ [IRQ_DAC0] = dac0_isr,
+ [IRQ_I2C0] = i2c0_isr,
+ [IRQ_GPIO_ODD] = gpio_odd_isr,
+ [IRQ_TIMER1] = timer1_isr,
+ [IRQ_USART1_RX] = usart1_rx_isr,
+ [IRQ_USART1_TX] = usart1_tx_isr,
+ [IRQ_LESENSE] = lesense_isr,
+ [IRQ_LEUART0] = leuart0_isr,
+ [IRQ_LETIMER0] = letimer0_isr,
+ [IRQ_PCNT0] = pcnt0_isr,
+ [IRQ_RTC] = rtc_isr,
+ [IRQ_CMU] = cmu_isr,
+ [IRQ_VCMP] = vcmp_isr,
+ [IRQ_LCD] = lcd_isr,
+ [IRQ_MSC] = msc_isr,
+ [IRQ_AES] = aes_isr,
+ }
+};
+
+void WEAK reset_handler(void)
+{
+ volatile unsigned *src, *dest;
+
+ __asm__("MSR msp, %0" : : "r"(&_stack));
+
+ for (src = &_etext, dest = &_data; dest < &_edata; src++, dest++)
+ *dest = *src;
+
+ while (dest < &_ebss)
+ *dest++ = 0;
+
+ /* Call the application's entry point. */
+ main();
+}
+
+void blocking_handler(void)
+{
+ while (1) ;
+}
+
+#pragma weak nmi_handler = blocking_handler
+#pragma weak hard_fault_handler = blocking_handler
+#pragma weak mem_manage_handler = blocking_handler
+#pragma weak bus_fault_handler = blocking_handler
+#pragma weak usage_fault_handler = blocking_handler
+#pragma weak sv_call_handler = blocking_handler
+#pragma weak debug_monitor_handler = blocking_handler
+#pragma weak pend_sv_handler = blocking_handler
+#pragma weak sys_tick_handler = blocking_handler
+
+#pragma weak dma_isr = blocking_handler
+#pragma weak gpio_even_isr = blocking_handler
+#pragma weak timer0_isr = blocking_handler
+#pragma weak usart0_rx_isr = blocking_handler
+#pragma weak usart0_tx_isr = blocking_handler
+#pragma weak acmp01_isr = blocking_handler
+#pragma weak adc0_isr = blocking_handler
+#pragma weak dac0_isr = blocking_handler
+#pragma weak i2c0_isr = blocking_handler
+#pragma weak gpio_odd_isr = blocking_handler
+#pragma weak timer1_isr = blocking_handler
+#pragma weak usart1_rx_isr = blocking_handler
+#pragma weak usart1_tx_isr = blocking_handler
+#pragma weak lesense_isr = blocking_handler
+#pragma weak leuart0_isr = blocking_handler
+#pragma weak letimer0_isr = blocking_handler
+#pragma weak pcnt0_isr = blocking_handler
+#pragma weak rtc_isr = blocking_handler
+#pragma weak cmu_isr = blocking_handler
+#pragma weak vcmp_isr = blocking_handler
+#pragma weak lcd_isr = blocking_handler
+#pragma weak msc_isr = blocking_handler
+#pragma weak aes_isr = blocking_handler