From 849ce20f5cf71cc1d81afcc8698a9062a12220e7 Mon Sep 17 00:00:00 2001
From: Hauke Petersen <hauke.petersen@fu-berlin.de>
Date: Tue, 8 Nov 2016 18:27:41 +0100
Subject: [PATCH] cpu/sam3+boards: adapted to new SPI API

- adapted the SPI driver
- adapted all boards using the CPU
---
 boards/arduino-due/include/periph_conf.h  |  33 +-
 boards/arduino-due/include/w5100_params.h |  14 +-
 boards/udoo/include/periph_conf.h         |  35 +-
 cpu/sam3/include/periph_cpu.h             |  33 +-
 cpu/sam3/periph/spi.c                     | 389 ++++------------------
 5 files changed, 135 insertions(+), 369 deletions(-)

diff --git a/boards/arduino-due/include/periph_conf.h b/boards/arduino-due/include/periph_conf.h
index d6e603c75d..fe187f4396 100644
--- a/boards/arduino-due/include/periph_conf.h
+++ b/boards/arduino-due/include/periph_conf.h
@@ -88,27 +88,18 @@ static const uart_conf_t uart_config[] = {
 * @name SPI configuration
 * @{
 */
-#define SPI_NUMOF           (1U)
-#define SPI_0_EN            1
-
-/* SPI 0 device config */
-#define SPI_0_DEV           SPI0
-#define SPI_0_CLKEN()       (PMC->PMC_PCER0 |= (1 << ID_SPI0));
-#define SPI_0_CLKDIS()      (PMC->PMC_PCER0 &= ~(1 << ID_SPI0));
-#define SPI_0_IRQ           SPI0_IRQn
-#define SPI_0_IRQ_HANDLER   isr_spi0
-#define SPI_0_IRQ_PRIO      1
-
-/* SPI 0 pin configuration */
-#define SPI_0_MISO_PIN      PIO_PA25A_SPI0_MISO
-#define SPI_0_MOSI_PIN      PIO_PA26A_SPI0_MOSI
-#define SPI_0_SCK_PIN       PIO_PA27A_SPI0_SPCK
-#define SPI_0_MISO_PORT     PIOA
-#define SPI_0_MOSI_PORT     PIOA
-#define SPI_0_SCK_PORT      PIOA
-#define SPI_0_MISO_PORT_CLKEN()  (PMC->PMC_PCER0 |= (1 << ID_PIOA));
-#define SPI_0_MOSI_PORT_CLKEN()  (PMC->PMC_PCER0 |= (1 << ID_PIOA));
-#define SPI_0_SCK_PORT_CLKEN()   (PMC->PMC_PCER0 |= (1 << ID_PIOA));
+static const spi_conf_t spi_config[] = {
+    {
+        .dev   = SPI0,
+        .id    = ID_SPI0,
+        .clk   = GPIO_PIN(PA, 27),
+        .mosi  = GPIO_PIN(PA, 26),
+        .miso  = GPIO_PIN(PA, 25),
+        .mux   = GPIO_MUX_A
+    }
+};
+
+#define SPI_NUMOF           (sizeof(spi_config) / sizeof(spi_config[0]))
 /** @} */
 
 /**
diff --git a/boards/arduino-due/include/w5100_params.h b/boards/arduino-due/include/w5100_params.h
index 131bed8ec8..7eefa13bad 100644
--- a/boards/arduino-due/include/w5100_params.h
+++ b/boards/arduino-due/include/w5100_params.h
@@ -28,10 +28,10 @@ extern "C" {
  * @{
  */
 #ifndef W5100_PARAM_SPI
-#define W5100_PARAM_SPI         (SPI_0)
+#define W5100_PARAM_SPI         (SPI_DEV(0))
 #endif
-#ifndef W5100_PARAM_SPI_SPEED
-#define W5100_PARAM_SPI_SPEED   (SPI_SPEED_5MHZ)
+#ifndef W5100_PARAM_SPI_CLK
+#define W5100_PARAM_SPI_CLK     (SPI_CLK_5MHZ)
 #endif
 #ifndef W5100_PARAM_CS
 #define W5100_PARAM_CS          (GPIO_PIN(2, 29))
@@ -46,10 +46,10 @@ extern "C" {
  */
 static const  w5100_params_t w5100_params[] = {
     {
-        .spi       = W5100_PARAM_SPI,
-        .spi_speed = W5100_PARAM_SPI_SPEED,
-        .cs        = W5100_PARAM_CS,
-        .evt       = W5100_PARAM_EVT
+        .spi = W5100_PARAM_SPI,
+        .clk = W5100_PARAM_SPI_CLK,
+        .cs  = W5100_PARAM_CS,
+        .evt = W5100_PARAM_EVT
     },
 };
 /** @} */
diff --git a/boards/udoo/include/periph_conf.h b/boards/udoo/include/periph_conf.h
index 1514e2d143..d9a729ece4 100644
--- a/boards/udoo/include/periph_conf.h
+++ b/boards/udoo/include/periph_conf.h
@@ -86,29 +86,18 @@ static const uart_conf_t uart_config[] = {
 * @name SPI configuration
 * @{
 */
-#define SPI_NUMOF           (1U)
-#define SPI_0_EN            1
-
-/* SPI 0 device config */
-#define SPI_0_DEV           SPI0
-#define SPI_0_CLKEN()       (PMC->PMC_PCER0 |= (1 << ID_SPI0));
-#define SPI_0_CLKDIS()      (PMC->PMC_PCER0 &= ~(1 << ID_SPI0));
-#define SPI_0_IRQ           SPI0_IRQn
-#define SPI_0_IRQ_HANDLER   isr_spi0
-#define SPI_0_IRQ_PRIO      1
-
-/* SPI 0 pin configuration */
-#define SPI_0_MISO_PIN      PIO_PA25A_SPI0_MISO
-#define SPI_0_MOSI_PIN      PIO_PA26A_SPI0_MOSI
-#define SPI_0_SCK_PIN       PIO_PA27A_SPI0_SPCK
-
-#define SPI_0_MISO_PORT     PIOA
-#define SPI_0_MOSI_PORT     PIOA
-#define SPI_0_SCK_PORT      PIOA
-
-#define SPI_0_MISO_PORT_CLKEN()  (PMC->PMC_PCER0 |= (1 << ID_PIOA));
-#define SPI_0_MOSI_PORT_CLKEN()  (PMC->PMC_PCER0 |= (1 << ID_PIOA));
-#define SPI_0_SCK_PORT_CLKEN()   (PMC->PMC_PCER0 |= (1 << ID_PIOA));
+static const spi_conf_t spi_config[] = {
+    {
+        .dev   = SPI0,
+        .id    = ID_SPI0,
+        .clk   = GPIO_PIN(PA, 25),
+        .mosi  = GPIO_PIN(PA, 26),
+        .miso  = GPIO_PIN(PA, 27),
+        .mux   = GPIO_MUX_A
+    }
+};
+
+#define SPI_NUMOF           (sizeof(spi_config) / sizeof(spi_config[0]))
 /** @} */
 
 #ifdef __cplusplus
diff --git a/cpu/sam3/include/periph_cpu.h b/cpu/sam3/include/periph_cpu.h
index 4921a1c1c7..b2097b3337 100644
--- a/cpu/sam3/include/periph_cpu.h
+++ b/cpu/sam3/include/periph_cpu.h
@@ -24,7 +24,6 @@
 
 #include "cpu.h"
 
-
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -50,7 +49,8 @@ typedef uint32_t gpio_t;
  * @brief Declare needed generic SPI functions
  * @{
  */
-#define PERIPH_SPI_NEEDS_TRANSFER_BYTES
+#define PERIPH_SPI_NEEDS_INIT_CS
+#define PERIPH_SPI_NEEDS_TRANSFER_BYTE
 #define PERIPH_SPI_NEEDS_TRANSFER_REG
 #define PERIPH_SPI_NEEDS_TRANSFER_REGS
 /** @} */
@@ -127,6 +127,23 @@ typedef enum {
     GPIO_MUX_B = 1,         /**< alternate function B */
 } gpio_mux_t;
 
+#define HAVE_SPI_MODE_T
+typedef enum {
+    SPI_MODE_0 = (SPI_CSR_NCPHA),                   /**< CPOL=0, CPHA=0 */
+    SPI_MODE_1 = (0),                               /**< CPOL=0, CPHA=1 */
+    SPI_MODE_2 = (SPI_CSR_CPOL | SPI_CSR_NCPHA),    /**< CPOL=1, CPHA=0 */
+    SPI_MODE_3 = (SPI_CSR_CPOL)                     /**< CPOL=1, CPHA=1 */
+} spi_mode_t;
+
+#define HAVE_SPI_CLK_T
+typedef enum {
+    SPI_CLK_100KHZ = (100000),                      /**< 100KHz */
+    SPI_CLK_400KHZ = (400000),                      /**< 400KHz */
+    SPI_CLK_1MHZ   = (1000000),                     /**< 1MHz */
+    SPI_CLK_5MHZ   = (5000000),                     /**< 5MHz */
+    SPI_CLK_10MHZ  = (10000000)                     /**< 10MHz */
+} spi_clk_t;
+
 /**
  * @brief   Timer configuration data
  */
@@ -157,6 +174,18 @@ typedef struct {
     uint8_t hwchan;         /**< the HW channel used for a logical channel */
 } pwm_chan_conf_t;
 
+/**
+ * @brief   SPI configuration data
+ */
+typedef struct {
+    Spi *dev;               /**< SPI module to use */
+    uint8_t id;             /**< corresponding ID of that module */
+    gpio_t clk;             /**< pin mapped to the CLK line */
+    gpio_t mosi;            /**< pin mapped to the MOSI line */
+    gpio_t miso;            /**< pin mapped to the MISO line */
+    gpio_mux_t mux;         /**< pin MUX setting */
+} spi_conf_t;
+
 /**
  * @brief   Configure the given GPIO pin to be used with the given MUX setting
  *
diff --git a/cpu/sam3/periph/spi.c b/cpu/sam3/periph/spi.c
index a86f5e2fd6..72f952e2ae 100644
--- a/cpu/sam3/periph/spi.c
+++ b/cpu/sam3/periph/spi.c
@@ -1,13 +1,14 @@
 /*
 * 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.
+*               2016-2017 Freie Universität Berlin
+ *
+ * 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_sam3x8e
+ * @ingroup     cpu_sam3
  * @{
  *
  * @file
@@ -23,347 +24,103 @@
 
 #include "cpu.h"
 #include "mutex.h"
+#include "assert.h"
 #include "periph/gpio.h"
-#include "periph_conf.h"
 #include "periph/spi.h"
-#include "sam3x8e.h"
 
-/* guard this file in case no SPI device is defined */
-#if SPI_NUMOF
+#define ENABLE_DEBUG    (0)
+#include "debug.h"
 
 /**
- * @brief Array holding one pre-initialized mutex for each SPI device
+ * @brief   Array holding one pre-initialized mutex for each SPI device
  */
-static mutex_t locks[] =  {
-#if SPI_0_EN
-    [SPI_0] = MUTEX_INIT,
-#endif
-#if SPI_1_EN
-    [SPI_1] = MUTEX_INIT,
-#endif
-#if SPI_2_EN
-    [SPI_2] = MUTEX_INIT
-#endif
-};
-
-typedef struct {
-    char(*cb)(char data);
-} spi_state_t;
-
-static inline void irq_handler_transfer(Spi *spi, spi_t dev);
+static mutex_t locks[SPI_NUMOF];
 
-static spi_state_t spi_config[SPI_NUMOF];
-
-void spi_poweron(spi_t dev)
+static inline Spi *dev(spi_t bus)
 {
-    switch (dev) {
-#if SPI_0_EN
-        case SPI_0:
-            SPI_0_CLKEN();
-            SPI_0_MISO_PORT_CLKEN();
-            SPI_0_MOSI_PORT_CLKEN();
-            SPI_0_SCK_PORT_CLKEN();
-            break;
-#endif /* SPI_0_EN */
-    }
-}
-
-void spi_poweroff(spi_t dev)
-{
-    switch (dev) {
-#if SPI_0_EN
-        case SPI_0:
-            while (!(SPI_0_DEV->SPI_SR & SPI_SR_SPIENS)) {} /* not busy anymore */
-            SPI_0_CLKDIS();
-            NVIC_DisableIRQ(SPI_0_IRQ);
-            break;
-#endif /* SPI_0_EN */
-    }
+    return spi_config[bus].dev;
 }
 
-int spi_init_master(spi_t dev, spi_conf_t conf, spi_speed_t speed)
+void spi_init(spi_t bus)
 {
-    uint8_t speed_divider;
-    Spi *spi_port;
-
-    spi_poweron(dev);
-
-    switch (speed) {
-        case SPI_SPEED_400KHZ:
-            speed_divider = 210;
-            break;
-
-        case SPI_SPEED_1MHZ:
-            speed_divider = 84;
-            break;
-
-        case SPI_SPEED_5MHZ:
-            speed_divider = 17;
-            break;
-
-        case SPI_SPEED_10MHZ: /* this might be too fast */
-            speed_divider = 8;
-            break;
-
-        default:
-            return -1;
-    }
-
-    switch (dev) {
-#if SPI_0_EN
-        case SPI_0:
-            spi_port = SPI_0_DEV;
-            break;
-#endif /* SPI_0_EN */
-        default:
-            return -2;
-    }
+    assert(bus < SPI_NUMOF);
 
-    /* Configure SCK, MISO and MOSI pin */
-    spi_conf_pins(dev);
-
-    /***************** SPI-Init *****************/
-
-    /* Chip Select Register */
-    spi_port->SPI_CSR[0] = 0; /* This is index 0 since we don't use internal CS-Signals */
-
-    switch (conf) {
-        case SPI_CONF_FIRST_RISING:
-            spi_port->SPI_CSR[0] &= ~SPI_CSR_CPOL;
-            spi_port->SPI_CSR[0] |= SPI_CSR_NCPHA;
-            break;
-
-        case SPI_CONF_SECOND_RISING:
-            spi_port->SPI_CSR[0] &= ~SPI_CSR_CPOL;
-            spi_port->SPI_CSR[0] &= ~SPI_CSR_NCPHA;
-            break;
-
-        case SPI_CONF_FIRST_FALLING:
-            spi_port->SPI_CSR[0] |= SPI_CSR_CPOL;
-            spi_port->SPI_CSR[0] |= SPI_CSR_NCPHA;
-            break;
-
-        case SPI_CONF_SECOND_FALLING:
-            spi_port->SPI_CSR[0] |= SPI_CSR_CPOL;
-            spi_port->SPI_CSR[0] &= ~ SPI_CSR_NCPHA;
-            break;
-
-        default:
-            return -2;
-    }
-
-    spi_port->SPI_CSR[0] |= SPI_CSR_SCBR(speed_divider);
-    spi_port->SPI_CSR[0] |= SPI_CSR_BITS_8_BIT;
-
-    /* Control Register */
-    spi_port->SPI_CR |= SPI_CR_SPIEN;
-    /* Mode Register */
-    spi_port->SPI_MR = 0;
-    spi_port->SPI_MR |= SPI_MR_MSTR;
-    spi_port->SPI_MR |= SPI_MR_MODFDIS;
-    spi_port->SPI_MR &= ~SPI_MR_PS;
-    spi_port->SPI_MR &= ~SPI_MR_PCS(0);
-
-    return 0;
+    /* initialize device lock */
+    mutex_init(&locks[bus]);
+    /* initialize pins */
+    spi_init_pins(bus);
 }
 
-int spi_init_slave(spi_t dev, spi_conf_t conf, char(*cb)(char data))
+void spi_init_pins(spi_t bus)
 {
-    Spi *spi_port;
-
-    spi_poweron(dev);
-
-    switch (dev) {
-#if SPI_0_EN
-        case SPI_0:
-            spi_port = SPI_0_DEV;
-            NVIC_SetPriority(SPI_0_IRQ, SPI_0_IRQ_PRIO);
-            NVIC_EnableIRQ(SPI_0_IRQ);
-            /* Initialize predefined NSS pin as output so it is "disabled" */
-            PIOA->PIO_PER |= PIO_PA28A_SPI0_NPCS0;
-            PIOA->PIO_OER |= PIO_PA28A_SPI0_NPCS0;
-            break;
-#endif /* SPI_0_EN */
-        default:
-            return -1;
-    }
-
-    /* Configure SCK, MISO and MOSI pin */
-    spi_conf_pins(dev);
-
-    /***************** SPI-Init *****************/
-
-    /* Chip Select Register */
-    spi_port->SPI_CSR[0] = 0;
-
-    switch (conf) {
-        case SPI_CONF_FIRST_RISING:
-            spi_port->SPI_CSR[0] &= ~SPI_CSR_CPOL;
-            spi_port->SPI_CSR[0] |= SPI_CSR_NCPHA;
-            break;
-
-        case SPI_CONF_SECOND_RISING:
-            spi_port->SPI_CSR[0] &= ~SPI_CSR_CPOL;
-            spi_port->SPI_CSR[0] &= ~SPI_CSR_NCPHA;
-            break;
-
-        case SPI_CONF_FIRST_FALLING:
-            spi_port->SPI_CSR[0] |= SPI_CSR_CPOL;
-            spi_port->SPI_CSR[0] |= SPI_CSR_NCPHA;
-            break;
-
-        case SPI_CONF_SECOND_FALLING:
-            spi_port->SPI_CSR[0] |= SPI_CSR_CPOL;
-            spi_port->SPI_CSR[0] &= ~ SPI_CSR_NCPHA;
-            break;
-
-        default:
-            return -1;
-    }
-
-    /* Control Register */
-    spi_port->SPI_CR |= SPI_CR_SPIEN;
-    /* Mode Register */
-    spi_port->SPI_MR = 0;
-    spi_port->SPI_MR |= SPI_MR_MODFDIS;
-    /* Enable SPI interrupts */
-    spi_port->SPI_IER = 0;
-    spi_port->SPI_IDR = ~(0);
-    spi_port->SPI_IER |= 1;
-    spi_port->SPI_IDR &= ~SPI_IDR_RDRF;
-
-    /* Set callback */
-    spi_config[dev].cb = cb;
-
-    return 0;
+    gpio_init(spi_config[bus].clk, GPIO_OUT);
+    gpio_init(spi_config[bus].mosi, GPIO_OUT);
+    gpio_init(spi_config[bus].miso, GPIO_IN);
+    gpio_init_mux(spi_config[bus].clk, spi_config[bus].mux);
+    gpio_init_mux(spi_config[bus].mosi, spi_config[bus].mux);
+    gpio_init_mux(spi_config[bus].miso, spi_config[bus].mux);
 }
 
-int spi_conf_pins(spi_t dev)
+int spi_acquire(spi_t bus, spi_cs_t cs, spi_mode_t mode, spi_clk_t clk)
 {
-    switch (dev) {
-#if SPI_0_EN
-        case SPI_0:
-            /***************** PIO-Init *****************/
-            /* Push-pull configuration */
-            SPI_0_MISO_PORT->PIO_MDER &= ~SPI_0_MISO_PIN;
-            SPI_0_MISO_PORT->PIO_MDDR |= SPI_0_MISO_PIN;
-            SPI_0_MOSI_PORT->PIO_MDER &= ~SPI_0_MOSI_PIN;
-            SPI_0_MOSI_PORT->PIO_MDDR |= SPI_0_MOSI_PIN;
-            SPI_0_SCK_PORT->PIO_MDER &= ~SPI_0_SCK_PIN;
-            SPI_0_SCK_PORT->PIO_MDDR |= SPI_0_SCK_PIN;
-
-            /* With pull-up resistors */
-            SPI_0_MISO_PORT->PIO_PUDR &= ~SPI_0_MISO_PIN;
-            SPI_0_MISO_PORT->PIO_PUER |= SPI_0_MISO_PIN;
-            SPI_0_MOSI_PORT->PIO_PUDR &= ~SPI_0_MOSI_PIN;
-            SPI_0_MOSI_PORT->PIO_PUER |= SPI_0_MOSI_PIN;
-            SPI_0_SCK_PORT->PIO_PUDR &= ~SPI_0_SCK_PIN;
-            SPI_0_SCK_PORT->PIO_PUER |= SPI_0_SCK_PIN;
-
-            /* Clear output */
-            SPI_0_MISO_PORT->PIO_SODR &= ~SPI_0_MISO_PIN;
-            SPI_0_MISO_PORT->PIO_CODR |= SPI_0_MISO_PIN;
-            SPI_0_MOSI_PORT->PIO_SODR &= ~SPI_0_MOSI_PIN;
-            SPI_0_MOSI_PORT->PIO_CODR |= SPI_0_MOSI_PIN;
-            SPI_0_SCK_PORT->PIO_SODR &= ~SPI_0_SCK_PIN;
-            SPI_0_SCK_PORT->PIO_CODR |= SPI_0_SCK_PIN;
-
-            /* Peripheral Function Selection */
-            SPI_0_MISO_PORT->PIO_PER &= ~SPI_0_MISO_PIN;
-            SPI_0_MISO_PORT->PIO_PDR |= SPI_0_MISO_PIN;
-            SPI_0_MOSI_PORT->PIO_PER &= ~SPI_0_MOSI_PIN;
-            SPI_0_MOSI_PORT->PIO_PDR |= SPI_0_MOSI_PIN;
-            SPI_0_SCK_PORT->PIO_PER &= ~SPI_0_SCK_PIN;
-            SPI_0_SCK_PORT->PIO_PDR |= SPI_0_SCK_PIN;
-
-            /* Peripheral A */
-            SPI_0_MISO_PORT->PIO_ABSR &= ~SPI_0_MISO_PIN;
-            SPI_0_MOSI_PORT->PIO_ABSR &= ~SPI_0_MOSI_PIN;
-            SPI_0_SCK_PORT->PIO_ABSR &= ~SPI_0_SCK_PIN;
-
-            break;
-#endif /* SPI_0_EN */
-        default:
-            return -1;
-    }
-
-    return 0;
+    /* lock bus */
+    mutex_lock(&locks[bus]);
+    /* enable SPI device clock */
+    PMC->PMC_PCER0 |= (1 << spi_config[bus].id);
+    /* set mode and speed */
+    dev(bus)->SPI_CSR[0] = (SPI_CSR_SCBR(CLOCK_CORECLOCK / clk) | mode);
+    dev(bus)->SPI_MR = (SPI_MR_MSTR | SPI_MR_MODFDIS);
+    dev(bus)->SPI_CR = SPI_CR_SPIEN;
+
+    return SPI_OK;
 }
 
-int spi_acquire(spi_t dev)
+void spi_release(spi_t bus)
 {
-    if ((unsigned int)dev >= SPI_NUMOF) {
-        return -1;
-    }
-    mutex_lock(&locks[dev]);
-    return 0;
+    /* disable device and turn off clock signal */
+    dev(bus)->SPI_CR = 0;
+    PMC->PMC_PCER0 &= ~(1 << spi_config[bus].id);
+    /* release device lock */
+    mutex_unlock(&locks[bus]);
 }
 
-int spi_release(spi_t dev)
+void spi_transfer_bytes(spi_t bus, spi_cs_t cs, bool cont,
+                        const void *out, void *in, size_t len)
 {
-    if ((unsigned int)dev >= SPI_NUMOF) {
-        return -1;
-    }
-    mutex_unlock(&locks[dev]);
-    return 0;
-}
+    uint8_t *out_buf = (uint8_t *)out;
+    uint8_t *in_buf = (uint8_t *)in;
 
-int spi_transfer_byte(spi_t dev, char out, char *in)
-{
-    Spi *spi_port;
+    assert(in_buf || out_buf);
 
-    switch (dev) {
-#if SPI_0_EN
-        case SPI_0:
-            spi_port = SPI_0_DEV;
-            break;
-#endif /* SPI_0_EN */
-        default:
-            return -1;
+    if (cs != SPI_CS_UNDEF) {
+        gpio_clear((gpio_t)cs);
     }
 
-    while (!(spi_port->SPI_SR & SPI_SR_TDRE)) {}
-
-    spi_port->SPI_TDR = SPI_TDR_TD(out);
-
-    while (!(spi_port->SPI_SR & SPI_SR_RDRF)) {}
-
-    *in = spi_port->SPI_RDR & SPI_RDR_RD_Msk;
-
-    return 1;
-}
-
-void spi_transmission_begin(spi_t dev, char reset_val)
-{
-    switch (dev) {
-#if SPI_0_EN
-        case SPI_0:
-            SPI_0_DEV->SPI_TDR = SPI_TDR_TD(reset_val);
-            break;
-#endif /* SPI_0_EN */
+    if (!in_buf) {
+        for (size_t i = 0; i < len; i++) {
+            while(!(dev(bus)->SPI_SR & SPI_SR_TDRE)) {}
+            dev(bus)->SPI_TDR = out_buf[i];
+        }
+        while (!(dev(bus)->SPI_SR & SPI_SR_RDRF)) {}
+        dev(bus)->SPI_RDR;
     }
-}
-
-static inline void irq_handler_transfer(Spi *spi, spi_t dev)
-{
-    if (spi->SPI_SR & SPI_SR_RDRF) {
-        char data;
-        data = spi->SPI_RDR & SPI_RDR_RD_Msk;
-        data = spi_config[dev].cb(data);
-        spi->SPI_TDR = SPI_TDR_TD(data);
+    else if (!out_buf) {
+        for (size_t i = 0; i < len; i++) {
+            dev(bus)->SPI_TDR = 0;
+            while (!(dev(bus)->SPI_SR & SPI_SR_RDRF)) {}
+            in_buf[i] = dev(bus)->SPI_RDR;
+        }
+    }
+    else {
+        for (size_t i = 0; i < len; i++) {
+            while (!(dev(bus)->SPI_SR & SPI_SR_TDRE));
+            dev(bus)->SPI_TDR = out_buf[i];
+            while (!(dev(bus)->SPI_SR & SPI_SR_RDRF));
+            in_buf[i] = dev(bus)->SPI_RDR;
+        }
     }
 
-    /* See if a thread with higher priority wants to run now */
-    cortexm_isr_end();
-}
-
-#if SPI_0_EN
-void SPI_0_IRQ_HANDLER(void)
-{
-    if (SPI_0_DEV->SPI_SR & SPI_SR_RDRF) {
-        irq_handler_transfer(SPI_0_DEV, SPI_0);
+    if ((!cont) && (cs != SPI_CS_UNDEF)) {
+        gpio_set((gpio_t)cs);
     }
 }
-#endif
-
-#endif /* SPI_NUMOF */
-- 
GitLab