diff --git a/boards/stm32f4discovery/include/periph_conf.h b/boards/stm32f4discovery/include/periph_conf.h
index 78dc28001324b764f6058def2ab7071834868435..c5a0638e7cbf6283df1afb82d10d76af66de6799 100644
--- a/boards/stm32f4discovery/include/periph_conf.h
+++ b/boards/stm32f4discovery/include/periph_conf.h
@@ -14,6 +14,7 @@
  * @name       Peripheral MCU configuration for the STM32F4discovery board
  *
  * @author      Hauke Petersen <hauke.petersen@fu-berlin.de>
+ * @author      Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
  */
 
 #ifndef __PERIPH_CONF_H
@@ -193,40 +194,52 @@
  * @name SPI configuration
  * @{
  */
-#define SPI_NUMOF           (0U)                                                /* TODO !!!!!!! */
-#define SPI_0_EN            0
-#define SPI_1_EN            0
+#define SPI_NUMOF           (2U)
+#define SPI_0_EN            1
+#define SPI_1_EN            1
+#define SPI_IRQ_PRIO        1
 
 /* SPI 0 device config */
-#define SPI_0_DEV
-#define SPI_0_CLKEN()
-#define SPI_0_IRQ
-#define SPI_0_IRQ_HANDLER
-#define SPI_0_IRQ_PRIO
-/* SPI 1 pin configuration */
-#define SPI_0_PORT
-#define SPI_0_PINS
-#define SPI_1_PORT_CLKEN()
-#define SPI_1_SCK_AFCFG()
-#define SPI_1_MISO_AFCFG()
-#define SPI_1_MOSI_AFCFG()
+#define SPI_0_DEV               SPI1
+#define SPI_0_CLKEN()           (RCC->APB2ENR |= RCC_APB2ENR_SPI1EN)
+#define SPI_0_CLKDIS()          (RCC->APB2ENR &= ~RCC_APB2ENR_SPI1EN)
+#define SPI_0_IRQ               SPI1_IRQn
+#define SPI_0_IRQ_HANDLER       isr_spi1
+/* SPI 0 pin configuration */
+#define SPI_0_SCK_PORT          GPIOA
+#define SPI_0_SCK_PIN           5
+#define SPI_0_SCK_AF            5
+#define SPI_0_SCK_PORT_CLKEN()  (RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN)
+#define SPI_0_MISO_PORT         GPIOA
+#define SPI_0_MISO_PIN          6
+#define SPI_0_MISO_AF           5
+#define SPI_0_MISO_PORT_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN)
+#define SPI_0_MOSI_PORT         GPIOA
+#define SPI_0_MOSI_PIN          7
+#define SPI_0_MOSI_AF           5
+#define SPI_0_MOSI_PORT_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN)
 
 /* SPI 1 device config */
-#define SPI_1_DEV
-#define SPI_1_CLKEN()
-#define SPI_1_IRQ
-#define SPI_1_IRQ_HANDLER
-#define SPI_1_IRQ_PRIO
+#define SPI_1_DEV               SPI2
+#define SPI_1_CLKEN()           (RCC->APB1ENR |= RCC_APB1ENR_SPI2EN)
+#define SPI_1_CLKDIS()          (RCC->APB1ENR &= ~RCC_APB1ENR_SPI2EN)
+#define SPI_1_IRQ               SPI2_IRQn
+#define SPI_1_IRQ_HANDLER       isr_spi2
 /* SPI 1 pin configuration */
-#define SPI_1_PORT
-#define SPI_1_PINS
-#define SPI_1_PORT_CLKEN()
-#define SPI_1_SCK_AFCFG()
-#define SPI_1_MISO_AFCFG()
-#define SPI_1_MOSI_AFCFG()
+#define SPI_1_SCK_PORT          GPIOB
+#define SPI_1_SCK_PIN           13
+#define SPI_1_SCK_AF            5
+#define SPI_1_SCK_PORT_CLKEN()  (RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN)
+#define SPI_1_MISO_PORT         GPIOB
+#define SPI_1_MISO_PIN          14
+#define SPI_1_MISO_AF           5
+#define SPI_1_MISO_PORT_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN)
+#define SPI_1_MOSI_PORT         GPIOB
+#define SPI_1_MOSI_PIN          15
+#define SPI_1_MOSI_AF           5
+#define SPI_1_MOSI_PORT_CLKEN() (RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN)
 /** @} */
 
-
 /**
  * @name I2C configuration
  * @{
diff --git a/cpu/stm32f4/periph/spi.c b/cpu/stm32f4/periph/spi.c
new file mode 100644
index 0000000000000000000000000000000000000000..48008af83202a7a55ca1aa9b712cae0eeba60cb3
--- /dev/null
+++ b/cpu/stm32f4/periph/spi.c
@@ -0,0 +1,536 @@
+/*
+ * Copyright (C) 2014 Hamburg University of Applied Sciences
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @ingroup     cpu_stm32f4
+ * @{
+ *
+ * @file
+ * @brief       Low-level SPI driver implementation
+ *
+ * @author      Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
+ *
+ * @}
+ */
+#include <stdio.h>
+
+#include "board.h"
+#include "cpu.h"
+#include "periph/spi.h"
+#include "periph_conf.h"
+#include "thread.h"
+#include "sched.h"
+#include "vtimer.h"
+
+#define ENABLE_DEBUG (0)
+#include "debug.h"
+
+/* guard this file in case no SPI device is defined */
+#if SPI_NUMOF
+
+typedef struct {
+    char(*cb)(char data);
+} spi_state_t;
+
+static inline void irq_handler_transfer(SPI_TypeDef *spi, spi_t dev);
+
+static spi_state_t spi_config[SPI_NUMOF];
+
+int spi_init_master(spi_t dev, spi_conf_t conf, spi_speed_t speed)
+{
+
+    uint8_t speed_devider;
+    SPI_TypeDef *spi_port;
+
+    switch (speed) {
+        case SPI_SPEED_100KHZ:
+            return -2;          /* not possible for stm32f4 */
+            break;
+        case SPI_SPEED_400KHZ:
+            speed_devider = 7;  /* makes 656 kHz */
+            break;
+        case SPI_SPEED_1MHZ:
+            speed_devider = 6;  /* makes 1.3 MHz */
+            break;
+        case SPI_SPEED_5MHZ:
+            speed_devider = 4;  /* makes 5.3 MHz */
+            break;
+        case SPI_SPEED_10MHZ:
+            speed_devider = 3;  /* makes 10.5 MHz */
+            break;
+        default:
+            return -2;
+    }
+
+    switch (dev) {
+#if SPI_0_EN
+        case SPI_0:
+            spi_port = SPI_0_DEV;
+            /* enable clocks */
+            SPI_0_CLKEN();
+            SPI_0_SCK_PORT_CLKEN();
+            SPI_0_MISO_PORT_CLKEN();
+            SPI_0_MOSI_PORT_CLKEN();
+
+            /***************** GPIO-Init *****************/
+            /* Set GPIOs to AF mode */
+            SPI_0_SCK_PORT->MODER &= ~(3 << (2 * SPI_0_SCK_PIN));
+            SPI_0_SCK_PORT->MODER |= (2 << (2 * SPI_0_SCK_PIN));
+            SPI_0_MISO_PORT->MODER &= ~(3 << (2 * SPI_0_MISO_PIN));
+            SPI_0_MISO_PORT->MODER |= (2 << (2 * SPI_0_MISO_PIN));
+            SPI_0_MOSI_PORT->MODER &= ~(3 << (2 * SPI_0_MOSI_PIN));
+            SPI_0_MOSI_PORT->MODER |= (2 << (2 * SPI_0_MOSI_PIN));
+            /* Set speed */
+            SPI_0_SCK_PORT->OSPEEDR &= ~(3 << (2 * SPI_0_SCK_PIN));
+            SPI_0_SCK_PORT->OSPEEDR |= (3 << (2 * SPI_0_SCK_PIN));
+            SPI_0_MISO_PORT->OSPEEDR &= ~(3 << (2 * SPI_0_MISO_PIN));
+            SPI_0_MISO_PORT->OSPEEDR |= (3 << (2 * SPI_0_MISO_PIN));
+            SPI_0_MOSI_PORT->OSPEEDR &= ~(3 << (2 * SPI_0_MOSI_PIN));
+            SPI_0_MOSI_PORT->OSPEEDR |= (3 << (2 * SPI_0_MOSI_PIN));
+            /* Set to push-pull configuration */
+            SPI_0_SCK_PORT->OTYPER &= ~(1 << SPI_0_SCK_PIN);
+            SPI_0_MISO_PORT->OTYPER &= ~(1 << SPI_0_MISO_PIN);
+            SPI_0_MOSI_PORT->OTYPER &= ~(1 << SPI_0_MOSI_PIN);
+            /* Configure push-pull resistors */
+            SPI_0_SCK_PORT->PUPDR &= ~(3 << (2 * SPI_0_SCK_PIN));
+            SPI_0_SCK_PORT->PUPDR |= (2 << (2 * SPI_0_SCK_PIN));
+            SPI_0_MISO_PORT->PUPDR &= ~(3 << (2 * SPI_0_MISO_PIN));
+            SPI_0_MISO_PORT->PUPDR |= (2 << (2 * SPI_0_MISO_PIN));
+            SPI_0_MOSI_PORT->PUPDR &= ~(3 << (2 * SPI_0_MOSI_PIN));
+            SPI_0_MOSI_PORT->PUPDR |= (2 << (2 * SPI_0_MOSI_PIN));
+            /* Configure GPIOs to for the SPI0 alternate function */
+#if (SPI_0_SCK_PIN < 8)
+            SPI_0_SCK_PORT->AFR[0] &= ~(0xf << (4 * SPI_0_SCK_PIN));
+            SPI_0_SCK_PORT->AFR[0] |= (SPI_0_SCK_AF << (4 * SPI_0_SCK_PIN));
+
+#else
+            SPI_0_SCK_PORT->AFR[1] &= ~(0xf << (4 * (SPI_0_SCK_PIN - 8)));
+            SPI_0_SCK_PORT->AFR[1] |= (SPI_0_SCK_AF << (4 * (SPI_0_SCK_PIN - 8)));
+#endif
+
+#if (SPI_0_MISO_PIN < 8)
+            SPI_0_MISO_PORT->AFR[0] &= ~(0xf << (4 * SPI_0_MISO_PIN));
+            SPI_0_MISO_PORT->AFR[0] |= (SPI_0_MISO_AF << (4 * SPI_0_MISO_PIN));
+#else
+            SPI_0_MISO_PORT->AFR[1] &= ~(0xf << (4 * (SPI_0_MISO_PIN - 8)));
+            SPI_0_MISO_PORT->AFR[1] |= (SPI_0_MISO_AF << (4 * (SPI_0_MISO_PIN - 8)));
+#endif
+
+#if (SPI_0_MOSI_PIN < 8)
+            SPI_0_MOSI_PORT->AFR[0] &= ~(0xf << (4 * SPI_0_MOSI_PIN));
+            SPI_0_MOSI_PORT->AFR[0] |= (SPI_0_MOSI_AF << (4 * SPI_0_MOSI_PIN));
+#else
+            SPI_0_MOSI_PORT->AFR[1] &= ~(0xf << (4 * (SPI_0_MOSI_PIN - 8)));
+            SPI_0_MOSI_PORT->AFR[1] |= (SPI_0_MOSI_AF << (4 * (SPI_0_MOSI_PIN - 8)));
+#endif
+            break;
+#endif /* SPI_0_EN */
+#if SPI_1_EN
+        case SPI_1:
+            spi_port = SPI_1_DEV;
+            /* enable clocks */
+            SPI_1_CLKEN();
+            SPI_1_SCK_PORT_CLKEN();
+            SPI_1_MISO_PORT_CLKEN();
+            SPI_1_MOSI_PORT_CLKEN();
+
+            /************************* GPIO-Init *************************/
+            /* Set GPIOs to AF mode */
+            SPI_1_SCK_PORT->MODER &= ~(3 << (2 * SPI_1_SCK_PIN));
+            SPI_1_SCK_PORT->MODER |= (2 << (2 * SPI_1_SCK_PIN));
+            SPI_1_MISO_PORT->MODER &= ~(3 << (2 * SPI_1_MISO_PIN));
+            SPI_1_MISO_PORT->MODER |= (2 << (2 * SPI_1_MISO_PIN));
+            SPI_1_MOSI_PORT->MODER &= ~(3 << (2 * SPI_1_MOSI_PIN));
+            SPI_1_MOSI_PORT->MODER |= (2 << (2 * SPI_1_MOSI_PIN));
+            /* Set speed */
+            SPI_1_SCK_PORT->OSPEEDR &= ~(3 << (2 * SPI_1_SCK_PIN));
+            SPI_1_SCK_PORT->OSPEEDR |= (3 << (2 * SPI_1_SCK_PIN));
+            SPI_1_MISO_PORT->OSPEEDR &= ~(3 << (2 * SPI_1_MISO_PIN));
+            SPI_1_MISO_PORT->OSPEEDR |= (3 << (2 * SPI_1_MISO_PIN));
+            SPI_1_MOSI_PORT->OSPEEDR &= ~(3 << (2 * SPI_1_MOSI_PIN));
+            SPI_1_MOSI_PORT->OSPEEDR |= (3 << (2 * SPI_1_MOSI_PIN));
+            /* Set to push-pull configuration */
+            SPI_1_SCK_PORT->OTYPER &= ~(1 << SPI_1_SCK_PIN);
+            SPI_1_MISO_PORT->OTYPER &= ~(1 << SPI_1_MISO_PIN);
+            SPI_1_MOSI_PORT->OTYPER &= ~(1 << SPI_1_MOSI_PIN);
+            /* Configure push-pull resistors */
+            SPI_1_SCK_PORT->PUPDR &= ~(3 << (2 * SPI_1_SCK_PIN));
+            SPI_1_SCK_PORT->PUPDR |= (2 << (2 * SPI_1_SCK_PIN));
+            SPI_1_MISO_PORT->PUPDR &= ~(3 << (2 * SPI_1_MISO_PIN));
+            SPI_1_MISO_PORT->PUPDR |= (2 << (2 * SPI_1_MISO_PIN));
+            SPI_1_MOSI_PORT->PUPDR &= ~(3 << (2 * SPI_1_MOSI_PIN));
+            SPI_1_MOSI_PORT->PUPDR |= (2 << (2 * SPI_1_MOSI_PIN));
+            /* Configure the pins alternate function */
+#if (SPI_1_SCK_PIN < 8)
+            SPI_1_SCK_PORT->AFR[0] &= ~(0xf << (4 * SPI_1_SCK_PIN));
+            SPI_1_SCK_PORT->AFR[0] |= (SPI_1_SCK_AF << (4 * SPI_1_SCK_PIN));
+#else
+            SPI_1_SCK_PORT->AFR[1] &= ~(0xf << (4 * (SPI_1_SCK_PIN - 8)));
+            SPI_1_SCK_PORT->AFR[1] |= (SPI_1_SCK_AF << (4 * (SPI_1_SCK_PIN - 8)));
+#endif
+
+#if (SPI_1_MISO_PIN < 8)
+            SPI_1_MISO_PORT->AFR[0] &= ~(0xf << (4 * SPI_1_MISO_PIN));
+            SPI_1_MISO_PORT->AFR[0] |= (SPI_1_MISO_AF << (4 * SPI_1_MISO_PIN));
+#else
+            SPI_1_MISO_PORT->AFR[1] &= ~(0xf << (4 * (SPI_1_MISO_PIN - 8)));
+            SPI_1_MISO_PORT->AFR[1] |= (SPI_1_MISO_AF << (4 * (SPI_1_MISO_PIN - 8)));
+#endif
+
+#if (SPI_1_MOSI_PIN < 8)
+            SPI_1_MOSI_PORT->AFR[0] &= ~(0xf << (4 * SPI_1_MOSI_PIN));
+            SPI_1_MOSI_PORT->AFR[0] |= (SPI_1_MOSI_AF << (4 * SPI_1_MOSI_PIN));
+#else
+            SPI_1_MOSI_PORT->AFR[1] &= ~(0xf << (4 * (SPI_1_MOSI_PIN - 8)));
+            SPI_1_MOSI_PORT->AFR[1] |= (SPI_1_MOSI_AF << (4 * (SPI_1_MOSI_PIN - 8)));
+#endif
+            break;
+#endif /* SPI_1_EN */
+        default:
+            return -1;
+    }
+
+    /**************** SPI-Init *****************/
+    spi_port->I2SCFGR &= ~(SPI_I2SCFGR_I2SMOD);/* Activate the SPI mode (Reset I2SMOD bit in I2SCFGR register) */
+    spi_port->CR1 = 0;
+    spi_port->CR2 = 0;
+    /* the NSS (chip select) is managed purely by software */
+    spi_port->CR1 |= SPI_CR1_SSM | SPI_CR1_SSI;
+    spi_port->CR1 |= (speed_devider << 3);  /* Define serial clock baud rate. 001 leads to f_PCLK/4 */
+    spi_port->CR1 |= (SPI_CR1_MSTR);  /* 1: master configuration */
+    spi_port->CR1 |= (conf);
+    /* enable SPI */
+    spi_port->CR1 |= (SPI_CR1_SPE);
+    return 0;
+}
+
+int spi_init_slave(spi_t dev, spi_conf_t conf, char(*cb)(char data))
+{
+    SPI_TypeDef *spi_port;
+
+    switch (dev) {
+#if SPI_0_EN
+        case SPI_0:
+            spi_port = SPI_0_DEV;
+            /* enable clocks */
+            SPI_0_CLKEN();
+            SPI_0_SCK_PORT_CLKEN();
+            SPI_0_MISO_PORT_CLKEN();
+            SPI_0_MOSI_PORT_CLKEN();
+            /* configure interrupt channel */
+            NVIC_SetPriority(SPI_0_IRQ, SPI_IRQ_PRIO); /* set SPI interrupt priority */
+            NVIC_EnableIRQ(SPI_0_IRQ); /* set SPI interrupt priority */
+
+            /***************** GPIO-Init *****************/
+            /* Set GPIOs to AF mode (not especially input or output) */
+            SPI_0_SCK_PORT->MODER &= ~(3 << (2 * SPI_0_SCK_PIN));
+            SPI_0_SCK_PORT->MODER |= (2 << (2 * SPI_0_SCK_PIN));
+            SPI_0_MISO_PORT->MODER &= ~(3 << (2 * SPI_0_MISO_PIN));
+            SPI_0_MISO_PORT->MODER |= (2 << (2 * SPI_0_MISO_PIN));
+            SPI_0_MOSI_PORT->MODER &= ~(3 << (2 * SPI_0_MOSI_PIN));
+            SPI_0_MOSI_PORT->MODER |= (2 << (2 * SPI_0_MOSI_PIN));
+            /* Set speed */
+            SPI_0_SCK_PORT->OSPEEDR &= ~(3 << (2 * SPI_0_SCK_PIN));
+            SPI_0_SCK_PORT->OSPEEDR |= (3 << (2 * SPI_0_SCK_PIN));
+            SPI_0_MISO_PORT->OSPEEDR &= ~(3 << (2 * SPI_0_MISO_PIN));
+            SPI_0_MISO_PORT->OSPEEDR |= (3 << (2 * SPI_0_MISO_PIN));
+            SPI_0_MOSI_PORT->OSPEEDR &= ~(3 << (2 * SPI_0_MOSI_PIN));
+            SPI_0_MOSI_PORT->OSPEEDR |= (3 << (2 * SPI_0_MOSI_PIN));
+            /* Set to push-pull configuration (not open drain) */
+            SPI_0_SCK_PORT->OTYPER &= ~(1 << SPI_0_SCK_PIN);
+            SPI_0_MISO_PORT->OTYPER &= ~(1 << SPI_0_MISO_PIN);
+            SPI_0_MOSI_PORT->OTYPER &= ~(1 << SPI_0_MOSI_PIN);
+            /* Configure push-pull resistors */
+            SPI_0_SCK_PORT->PUPDR &= ~(3 << (2 * SPI_0_SCK_PIN));
+            SPI_0_SCK_PORT->PUPDR |= (2 << (2 * SPI_0_SCK_PIN));
+            SPI_0_MISO_PORT->PUPDR &= ~(3 << (2 * SPI_0_MISO_PIN));
+            SPI_0_MISO_PORT->PUPDR |= (2 << (2 * SPI_0_MISO_PIN));
+            SPI_0_MOSI_PORT->PUPDR &= ~(3 << (2 * SPI_0_MOSI_PIN));
+            SPI_0_MOSI_PORT->PUPDR |= (2 << (2 * SPI_0_MOSI_PIN));
+            /* configure the pins alternate function */
+#if (SPI_0_SCK_PIN < 8)
+            SPI_0_SCK_PORT->AFR[0] &= ~(0xf << (4 * SPI_0_SCK_PIN));
+            SPI_0_SCK_PORT->AFR[0] |= (SPI_0_SCK_AF << (4 * SPI_0_SCK_PIN));
+#else
+            SPI_0_SCK_PORT->AFR[1] &= ~(0xf << (4 * (SPI_0_SCK_PIN - 8)));
+            SPI_0_SCK_PORT->AFR[1] |= (SPI_0_SCK_AF << (4 * (SPI_0_SCK_PIN - 8)));
+#endif
+#if (SPI_0_MISO_PIN < 8)
+            SPI_0_MISO_PORT->AFR[0] &= ~(0xf << (4 * SPI_0_MISO_PIN));
+            SPI_0_MISO_PORT->AFR[0] |= (SPI_0_MISO_AF << (4 * SPI_0_MISO_PIN));
+#else
+            SPI_0_MISO_PORT->AFR[1] &= ~(0xf << (4 * (SPI_0_MISO_PIN - 8)));
+            SPI_0_MISO_PORT->AFR[1] |= (SPI_0_MISO_AF << (4 * (SPI_0_MISO_PIN - 8)));
+#endif
+#if (SPI_0_MOSI_PIN < 8)
+            SPI_0_MOSI_PORT->AFR[0] &= ~(0xf << (4 * SPI_0_MOSI_PIN));
+            SPI_0_MOSI_PORT->AFR[0] |= (SPI_0_MOSI_AF << (4 * SPI_0_MOSI_PIN));
+#else
+            SPI_0_MOSI_PORT->AFR[1] &= ~(0xf << (4 * (SPI_0_MOSI_PIN - 8)));
+            SPI_0_MOSI_PORT->AFR[1] |= (SPI_0_MOSI_AF << (4 * (SPI_0_MOSI_PIN - 8)));
+#endif
+            break;
+#endif /* SPI_0_EN */
+#if SPI_1_EN
+        case SPI_1:
+            spi_port = SPI_1_DEV;
+            /* enable clocks */
+            SPI_1_CLKEN();
+            SPI_1_SCK_PORT_CLKEN();
+            SPI_1_MISO_PORT_CLKEN();
+            SPI_1_MOSI_PORT_CLKEN();
+            /* configure interrupt channel */
+            NVIC_SetPriority(SPI_1_IRQ, SPI_IRQ_PRIO);
+            NVIC_EnableIRQ(SPI_1_IRQ);
+
+            /***************** GPIO-Init *****************/
+            /* Set GPIOs to AF mode (not especially input or output) */
+            SPI_1_SCK_PORT->MODER &= ~(3 << (2 * SPI_1_SCK_PIN));
+            SPI_1_SCK_PORT->MODER |= (2 << (2 * SPI_1_SCK_PIN));
+            SPI_1_MISO_PORT->MODER &= ~(3 << (2 * SPI_1_MISO_PIN));
+            SPI_1_MISO_PORT->MODER |= (2 << (2 * SPI_1_MISO_PIN));
+            SPI_1_MOSI_PORT->MODER &= ~(3 << (2 * SPI_1_MOSI_PIN));
+            SPI_1_MOSI_PORT->MODER |= (2 << (2 * SPI_1_MOSI_PIN));
+            /* Set speed */
+            SPI_1_SCK_PORT->OSPEEDR &= ~(3 << (2 * SPI_1_SCK_PIN));
+            SPI_1_SCK_PORT->OSPEEDR |= (3 << (2 * SPI_1_SCK_PIN));
+            SPI_1_MISO_PORT->OSPEEDR &= ~(3 << (2 * SPI_1_MISO_PIN));
+            SPI_1_MISO_PORT->OSPEEDR |= (3 << (2 * SPI_1_MISO_PIN));
+            SPI_1_MOSI_PORT->OSPEEDR &= ~(3 << (2 * SPI_1_MOSI_PIN));
+            SPI_1_MOSI_PORT->OSPEEDR |= (3 << (2 * SPI_1_MOSI_PIN));
+            /* Set to push-pull configuration (not open drain) */
+            SPI_1_SCK_PORT->OTYPER &= ~(1 << SPI_1_SCK_PIN);
+            SPI_1_MISO_PORT->OTYPER &= ~(1 << SPI_1_MISO_PIN);
+            SPI_1_MOSI_PORT->OTYPER &= ~(1 << SPI_1_MOSI_PIN);
+            /* Configure push-pull resistors */
+            SPI_1_SCK_PORT->PUPDR &= ~(3 << (2 * SPI_1_SCK_PIN));
+            SPI_1_SCK_PORT->PUPDR |= (2 << (2 * SPI_1_SCK_PIN));
+            SPI_1_MISO_PORT->PUPDR &= ~(3 << (2 * SPI_1_MISO_PIN));
+            SPI_1_MISO_PORT->PUPDR |= (2 << (2 * SPI_1_MISO_PIN));
+            SPI_1_MOSI_PORT->PUPDR &= ~(3 << (2 * SPI_1_MOSI_PIN));
+            SPI_1_MOSI_PORT->PUPDR |= (2 << (2 * SPI_1_MOSI_PIN));
+
+#if (SPI_1_SCK_PIN < 8)
+            SPI_1_SCK_PORT->AFR[0] &= ~(0xf << (4 * SPI_1_SCK_PIN));
+            SPI_1_SCK_PORT->AFR[0] |= (SPI_1_SCK_AF << (4 * SPI_1_SCK_PIN));
+#else
+            SPI_1_SCK_PORT->AFR[1] &= ~(0xf << (4 * (SPI_1_SCK_PIN - 8)));
+            SPI_1_SCK_PORT->AFR[1] |= (SPI_1_SCK_AF << (4 * (SPI_1_SCK_PIN - 8)));
+#endif
+#if (SPI_1_MISO_PIN < 8)
+            SPI_1_MISO_PORT->AFR[0] &= ~(0xf << (4 * SPI_1_MISO_PIN));
+            SPI_1_MISO_PORT->AFR[0] |= (SPI_1_MISO_AF << (4 * SPI_1_MISO_PIN));
+#else
+            SPI_1_MISO_PORT->AFR[1] &= ~(0xf << (4 * (SPI_1_MISO_PIN - 8)));
+            SPI_1_MISO_PORT->AFR[1] |= (SPI_1_MISO_AF << (4 * (SPI_1_MISO_PIN - 8)));
+#endif
+#if (SPI_1_MOSI_PIN < 8)
+            SPI_1_MOSI_PORT->AFR[0] &= ~(0xf << (4 * SPI_1_MOSI_PIN));
+            SPI_1_MOSI_PORT->AFR[0] |= (SPI_1_MOSI_AF << (4 * SPI_1_MOSI_PIN));
+#else
+            SPI_1_MOSI_PORT->AFR[1] &= ~(0xf << (4 * (SPI_1_MOSI_PIN - 8)));
+            SPI_1_MOSI_PORT->AFR[1] |= (SPI_1_MOSI_AF << (4 * (SPI_1_MOSI_PIN - 8)));
+#endif
+            break;
+#endif /* SPI_1_EN */
+        default:
+            return -1;
+    }
+
+    /***************** SPI-Init *****************/
+    spi_port->I2SCFGR &= ~(SPI_I2SCFGR_I2SMOD);
+    spi_port->CR1 = 0;
+    spi_port->CR2 = 0;
+    /* enable RXNEIE flag to enable rx buffer not empty interrupt */
+    spi_port->CR2 |= (SPI_CR2_RXNEIE); /*1:not masked */
+    spi_port->CR1 |= (conf);
+     /* the NSS (chip select) is managed by software and NSS is low (slave enabled) */
+    spi_port->CR1 |= SPI_CR1_SSM;
+    /* set callback */
+    spi_config[dev].cb = cb;
+    /* enable SPI device */
+    spi_port->CR1 |= SPI_CR1_SPE;
+    return 0;
+}
+
+int spi_transfer_byte(spi_t dev, char out, char *in)
+{
+    SPI_TypeDef *spi_port;
+
+    switch (dev) {
+#if SPI_0_EN
+        case SPI_0:
+            spi_port = SPI_0_DEV;
+            break;
+#endif
+#if SPI_1_EN
+        case SPI_1:
+            spi_port = SPI_1_DEV;
+            break;
+#endif
+        default:
+            return -1;
+    }
+
+    while (!(spi_port->SR & SPI_SR_TXE));
+    spi_port->DR = out;
+
+    while (!(spi_port->SR & SPI_SR_RXNE));
+
+    if (in != NULL) {
+        *in = spi_port->DR;
+    }
+    else {
+        spi_port->DR;
+    }
+
+    return 1;
+}
+
+int spi_transfer_bytes(spi_t dev, char *out, char *in, unsigned int length)
+{
+
+    int i, trans_ret, trans_bytes = 0;
+    char in_temp;
+
+    for (i = 0; i < length; i++) {
+        if (out) {
+            trans_ret = spi_transfer_byte(dev, out[i], &in_temp);
+        }
+        else {
+            trans_ret = spi_transfer_byte(dev, 0, &in_temp);
+        }
+        if (trans_ret < 0) {
+            return -1;
+        }
+        if (in != NULL) {
+            in[i] = in_temp;
+        }
+        trans_bytes++;
+    }
+
+    return trans_bytes++;
+}
+
+int spi_transfer_reg(spi_t dev, uint8_t reg, char out, char *in)
+{
+    int trans_ret;
+
+    trans_ret = spi_transfer_byte(dev, reg, in);
+    if (trans_ret < 0) {
+        return -2;
+    }
+    trans_ret = spi_transfer_byte(dev, out, in);
+    if (trans_ret < 0) {
+        return -3;
+    }
+
+    return 1;
+}
+
+int spi_transfer_regs(spi_t dev, uint8_t reg, char *out, char *in, unsigned int length)
+{
+    int trans_ret;
+
+    trans_ret = spi_transfer_byte(dev, reg, in);
+    if (trans_ret < 0) {
+        return -2;
+    }
+    trans_ret = spi_transfer_bytes(dev, out, in, length);
+    if (trans_ret < 0) {
+        return -3;
+    }
+
+    return trans_ret;
+}
+
+void spi_transmission_begin(spi_t dev, char reset_val)
+{
+
+    switch (dev) {
+#if SPI_0_EN
+        case SPI_0:
+            SPI_0_DEV->DR = reset_val;
+            break;
+#endif
+#if SPI_1_EN
+        case SPI_1:
+            SPI_1_DEV->DR = reset_val;
+            break;
+#endif
+    }
+}
+
+void spi_poweron(spi_t dev)
+{
+    switch (dev) {
+#if SPI_0_EN
+        case SPI_0:
+            SPI_0_CLKEN();
+            break;
+#endif
+#if SPI_1_EN
+        case SPI_1:
+            SPI_1_CLKEN();
+            break;
+#endif
+    }
+}
+
+void spi_poweroff(spi_t dev)
+{
+    switch (dev) {
+#if SPI_0_EN
+        case SPI_0:
+            while (SPI_0_DEV->SR & SPI_SR_BSY);
+            SPI_0_CLKDIS();
+            break;
+#endif
+#if SPI_1_EN
+        case SPI_1:
+            while (SPI_1_DEV->SR & SPI_SR_BSY);
+            SPI_1_CLKDIS();
+            break;
+#endif
+    }
+}
+
+static inline void irq_handler_transfer(SPI_TypeDef *spi, spi_t dev)
+{
+
+    if (spi->SR & SPI_SR_RXNE) {
+        char data;
+        data = spi->DR;
+        data = spi_config[dev].cb(data);
+        spi->DR = data;
+    }
+    /* see if a thread with higher priority wants to run now */
+    if (sched_context_switch_request) {
+        thread_yield();
+    }
+}
+
+#if SPI_0_EN
+__attribute__((naked)) void SPI_0_IRQ_HANDLER(void)
+{
+    ISR_ENTER();
+    irq_handler_transfer(SPI_0_DEV, SPI_0);
+    ISR_EXIT();
+}
+#endif
+
+#if SPI_1_EN
+__attribute__((naked)) void SPI_1_IRQ_HANDLER(void)
+{
+    ISR_ENTER();
+    irq_handler_transfer(SPI_1_DEV, SPI_1);
+    ISR_EXIT();
+}
+#endif
+
+#endif /* SPI_NUMOF */