diff --git a/include/libopencm3/stm32/common/st_usbfs_v2.h b/include/libopencm3/stm32/common/st_usbfs_v2.h
new file mode 100644
index 00000000..d85f4427
--- /dev/null
+++ b/include/libopencm3/stm32/common/st_usbfs_v2.h
@@ -0,0 +1,109 @@
+/** @addtogroup usb_defines
+ */
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * 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 .
+ */
+
+/* THIS FILE SHOULD NOT BE INCLUDED DIRECTLY !
+ * Use top-level
+ *
+ * Additional definitions for F0 devices :
+ * -F0x0 (RM0360),
+ * -F04x, F0x2, F0x8 (RM0091)
+ */
+
+/** @cond */
+#ifdef LIBOPENCM3_ST_USBFS_H
+/** @endcond */
+#ifndef LIBOPENCM3_ST_USBFS_V2_H
+#define LIBOPENCM3_ST_USBFS_V2_H
+
+#include
+
+/*****************************************************************************/
+/* Module definitions */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/* Register definitions */
+/*****************************************************************************/
+
+#define USB_LPMCSR_REG (&MMIO32(USB_DEV_FS_BASE + 0x54))
+#define USB_BCDR_REG (&MMIO32(USB_DEV_FS_BASE + 0x58))
+
+/*****************************************************************************/
+/* Register values */
+/*****************************************************************************/
+
+/* --- USB control register masks / bits ----------------------------------- */
+
+#define USB_CNTR_L1REQM (1 << 7)
+#define USB_CNTR_L1RESUME (1 << 5)
+
+/* --- USB interrupt status register masks / bits -------------------------- */
+
+#define USB_ISTR_L1REQ (1 << 7)
+
+/* --- LPM control and status register USB_LPMCSR Values --------------------*/
+
+#define USB_LPMCSR_BESL_SHIFT 4
+#define USB_LPMCSR_BESL (15 << USB_LPMCSR_BESL_SHIFT)
+
+#define USB_LPMCSR_REMWAKE (1 << 3)
+#define USB_LPMCSR_LPMACK (1 << 1)
+#define USB_LPMCSR_LPMEN (1 << 0)
+
+/* --- Battery Charging Detector Values ----------------------------------------------------------*/
+
+#define USB_BCDR_DPPU (1 << 15)
+#define USB_BCDR_PS2DET (1 << 7)
+#define USB_BCDR_SDET (1 << 6)
+#define USB_BCDR_PDET (1 << 5)
+#define USB_BCDR_DCDET (1 << 4)
+#define USB_BCDR_SDEN (1 << 3)
+#define USB_BCDR_PDEN (1 << 2)
+#define USB_BCDR_DCDEN (1 << 1)
+#define USB_BCDR_BCDEN (1 << 0)
+
+/* --- USB BTABLE registers ------------------------------------------------ */
+
+#define USB_EP_TX_ADDR(ep) \
+ ((uint16_t *)(USB_PMA_BASE + (USB_GET_BTABLE + (ep) * 8 + 0) * 1))
+
+#define USB_EP_TX_COUNT(ep) \
+ ((uint16_t *)(USB_PMA_BASE + (USB_GET_BTABLE + (ep) * 8 + 2) * 1))
+
+#define USB_EP_RX_ADDR(ep) \
+ ((uint16_t *)(USB_PMA_BASE + (USB_GET_BTABLE + (ep) * 8 + 4) * 1))
+
+#define USB_EP_RX_COUNT(ep) \
+ ((uint16_t *)(USB_PMA_BASE + (USB_GET_BTABLE + (ep) * 8 + 6) * 1))
+
+/* --- USB BTABLE manipulators --------------------------------------------- */
+
+#define USB_GET_EP_TX_BUFF(ep) \
+ (USB_PMA_BASE + (uint8_t *)(USB_GET_EP_TX_ADDR(ep) * 1))
+
+#define USB_GET_EP_RX_BUFF(ep) \
+ (USB_PMA_BASE + (uint8_t *)(USB_GET_EP_RX_ADDR(ep) * 1))
+
+#endif
+/** @cond */
+#else
+#error "st_usbfs_v2.h should not be included directly, only via st_usbfs.h"
+#endif
+/** @endcond */
+
diff --git a/include/libopencm3/stm32/f0/st_usbfs.h b/include/libopencm3/stm32/f0/st_usbfs.h
new file mode 100644
index 00000000..7b65d2b8
--- /dev/null
+++ b/include/libopencm3/stm32/f0/st_usbfs.h
@@ -0,0 +1,27 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * 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 .
+ */
+/* THIS FILE SHOULD NOT BE INCLUDED DIRECTLY !
+ * Use top-level
+ */
+
+#ifndef LIBOPENCM3_ST_USBFS_H
+# error Do not include directly !
+#else
+
+#include
+
+#endif
diff --git a/include/libopencm3/stm32/st_usbfs.h b/include/libopencm3/stm32/st_usbfs.h
index 6befced9..f0d1f5f4 100644
--- a/include/libopencm3/stm32/st_usbfs.h
+++ b/include/libopencm3/stm32/st_usbfs.h
@@ -23,7 +23,9 @@
#include
#include
-#if defined(STM32F1)
+#if defined(STM32F0)
+# include
+#elif defined(STM32F1)
# include
#elif defined(STM32F3)
# include
diff --git a/include/libopencm3/usb/usbd.h b/include/libopencm3/usb/usbd.h
index e2447c38..449b48a1 100644
--- a/include/libopencm3/usb/usbd.h
+++ b/include/libopencm3/usb/usbd.h
@@ -55,6 +55,7 @@ typedef struct _usbd_device usbd_device;
extern const usbd_driver st_usbfs_v1_usb_driver;
extern const usbd_driver stm32f107_usb_driver;
extern const usbd_driver stm32f207_usb_driver;
+extern const usbd_driver st_usbfs_v2_usb_driver;
#define otgfs_usb_driver stm32f107_usb_driver
#define otghs_usb_driver stm32f207_usb_driver
diff --git a/lib/stm32/f0/Makefile b/lib/stm32/f0/Makefile
index 0378e730..152f2d7a 100644
--- a/lib/stm32/f0/Makefile
+++ b/lib/stm32/f0/Makefile
@@ -44,6 +44,9 @@ OBJS += gpio_common_all.o gpio_common_f0234.o crc_common_all.o \
spi_common_f03.o flash_common_f01.o dac_common_all.o \
timer_common_all.o rcc_common_all.o crs.o
+OBJS += usb.o usb_control.o usb_standard.o
+OBJS += st_usbfs_core.o st_usbfs_v2.o
+
VPATH += ../../usb:../:../../cm3:../common
include ../../Makefile.include
diff --git a/lib/stm32/st_usbfs_v2.c b/lib/stm32/st_usbfs_v2.c
new file mode 100644
index 00000000..db2cf7cf
--- /dev/null
+++ b/lib/stm32/st_usbfs_v2.c
@@ -0,0 +1,93 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2010 Gareth McMullin
+ * Copyright (C) 2014 Kuldeep Singh Dhaka
+ *
+ * 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 .
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include "../usb/usb_private.h"
+#include "common/st_usbfs_core.h"
+
+static usbd_device *st_usbfs_v2_usbd_init(void);
+
+const struct _usbd_driver st_usbfs_v2_usb_driver = {
+ .init = st_usbfs_v2_usbd_init,
+ .set_address = st_usbfs_set_address,
+ .ep_setup = st_usbfs_ep_setup,
+ .ep_reset = st_usbfs_endpoints_reset,
+ .ep_stall_set = st_usbfs_ep_stall_set,
+ .ep_stall_get = st_usbfs_ep_stall_get,
+ .ep_nak_set = st_usbfs_ep_nak_set,
+ .ep_write_packet = st_usbfs_ep_write_packet,
+ .ep_read_packet = st_usbfs_ep_read_packet,
+ .poll = st_usbfs_poll,
+};
+
+/** Initialize the USB device controller hardware of the STM32. */
+static usbd_device *st_usbfs_v2_usbd_init(void)
+{
+ rcc_periph_clock_enable(RCC_USB);
+ SET_REG(USB_CNTR_REG, 0);
+ SET_REG(USB_BTABLE_REG, 0);
+ SET_REG(USB_ISTR_REG, 0);
+
+ /* Enable RESET, SUSPEND, RESUME and CTR interrupts. */
+ SET_REG(USB_CNTR_REG, USB_CNTR_RESETM | USB_CNTR_CTRM |
+ USB_CNTR_SUSPM | USB_CNTR_WKUPM);
+ SET_REG(USB_BCDR_REG, USB_BCDR_DPPU);
+ return &st_usbfs_dev;
+}
+
+void st_usbfs_copy_to_pm(volatile void *vPM, const void *buf, uint16_t len)
+{
+ /*
+ * This is a bytewise copy, so it always works, even on CM0(+)
+ * that don't support unaligned accesses.
+ */
+ const uint8_t *lbuf = buf;
+ volatile uint16_t *PM = vPM;
+ uint32_t i;
+ for (i = 0; i < len; i += 2) {
+ *PM++ = (uint16_t)lbuf[i+1] << 8 | lbuf[i];
+ }
+}
+
+/**
+ * Copy a data buffer from packet memory.
+ *
+ * @param buf Source pointer to data buffer.
+ * @param vPM Destination pointer into packet memory.
+ * @param len Number of bytes to copy.
+ */
+void st_usbfs_copy_from_pm(void *buf, const volatile void *vPM, uint16_t len)
+{
+ uint16_t *lbuf = buf;
+ const volatile uint16_t *PM = vPM;
+ uint8_t odd = len & 1;
+
+ for (len >>= 1; len; PM++, lbuf++, len--) {
+ *lbuf = *PM;
+ }
+
+ if (odd) {
+ *(uint8_t *) lbuf = *(uint8_t *) PM;
+ }
+}
diff --git a/tests/gadget-zero/Makefile.stm32f072disco b/tests/gadget-zero/Makefile.stm32f072disco
new file mode 100644
index 00000000..b9f668bd
--- /dev/null
+++ b/tests/gadget-zero/Makefile.stm32f072disco
@@ -0,0 +1,43 @@
+##
+## This file is part of the libopencm3 project.
+##
+## 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 .
+##
+
+BOARD = stm32f072disco
+PROJECT = usb-gadget0-$(BOARD)
+BUILD_DIR = bin-$(BOARD)
+
+SHARED_DIR = ../shared
+
+CFILES = main-$(BOARD).c
+CFILES += usb-gadget0.c
+
+VPATH += $(SHARED_DIR)
+
+INCLUDES += $(patsubst %,-I%, . $(SHARED_DIR))
+
+OPENCM3_DIR=../..
+
+### This section can go to an arch shared rules eventually...
+LDSCRIPT = ../../lib/stm32/f0/stm32f07xzb.ld
+OPENCM3_LIB = opencm3_stm32f0
+OPENCM3_DEFS = -DSTM32F0
+#FP_FLAGS ?= -mfloat-abi=hard -mfpu=fpv4-sp-d16
+ARCH_FLAGS = -mthumb -mcpu=cortex-m0 $(FP_FLAGS)
+#OOCD_INTERFACE = stlink-v2
+#OOCD_TARGET = stm32f4x
+OOCD_FILE = openocd.stm32f072disco.cfg
+
+include ../rules.mk
diff --git a/tests/gadget-zero/main-stm32f072disco.c b/tests/gadget-zero/main-stm32f072disco.c
new file mode 100644
index 00000000..20286bee
--- /dev/null
+++ b/tests/gadget-zero/main-stm32f072disco.c
@@ -0,0 +1,66 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2015 Karl Palsson
+ *
+ * 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 .
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include "usb-gadget0.h"
+
+// no trace on cm0 #define ER_DEBUG
+#ifdef ER_DEBUG
+#define ER_DPRINTF(fmt, ...) \
+ do { printf(fmt, ## __VA_ARGS__); } while (0)
+#else
+#define ER_DPRINTF(fmt, ...) \
+ do { } while (0)
+#endif
+
+#include "trace.h"
+void trace_send_blocking8(int stimulus_port, char c) {
+ (void)stimulus_port;
+ (void)c;
+}
+
+
+int main(void)
+{
+ rcc_clock_setup_in_hsi48_out_48mhz();
+ crs_autotrim_usb_enable();
+ rcc_set_usbclk_source(HSI48);
+ rcc_set_sysclk_source(HSI48);
+
+ /* LED on custom board for boot progress */
+ rcc_periph_clock_enable(RCC_GPIOC);
+ gpio_mode_setup(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO7);
+ gpio_set(GPIOC, GPIO7);
+
+ usbd_device *usbd_dev = gadget0_init(&st_usbfs_v2_usb_driver, "stm32f072disco");
+
+ ER_DPRINTF("bootup complete\n");
+ gpio_clear(GPIOC, GPIO7);
+ while (1) {
+ usbd_poll(usbd_dev);
+ }
+
+}
+
diff --git a/tests/gadget-zero/openocd.stm32f072disco.cfg b/tests/gadget-zero/openocd.stm32f072disco.cfg
new file mode 100644
index 00000000..b16f9693
--- /dev/null
+++ b/tests/gadget-zero/openocd.stm32f072disco.cfg
@@ -0,0 +1,14 @@
+source [find interface/stlink-v2.cfg]
+set WORKAREASIZE 0x4000
+source [find target/stm32f0x.cfg]
+
+# serial of my f072 disco board.
+hla_serial "Q?o\x06PgHW#$\x16?"
+
+# no trace on cm0
+#tpiu config internal swodump.stm32f4disco.log uart off 168000000
+
+# Uncomment to reset on connect, for grabbing under WFI et al
+reset_config srst_only srst_nogate
+# reset_config srst_only srst_nogate connect_assert_srst
+
diff --git a/tests/gadget-zero/test_gadget0.py b/tests/gadget-zero/test_gadget0.py
index 6c22ae50..1b579662 100644
--- a/tests/gadget-zero/test_gadget0.py
+++ b/tests/gadget-zero/test_gadget0.py
@@ -9,6 +9,7 @@ import unittest
DUT_SERIAL = "stm32f4disco"
#DUT_SERIAL = "stm32f103-generic"
#DUT_SERIAL = "stm32l1-generic"
+#DUT_SERIAL = "stm32f072disco"
class find_by_serial(object):
def __init__(self, serial):