diff --git a/boards/weio/Makefile.features b/boards/weio/Makefile.features index bee622261fba..1026d3751e6b 100644 --- a/boards/weio/Makefile.features +++ b/boards/weio/Makefile.features @@ -1,5 +1,6 @@ FEATURES_PROVIDED += cpp FEATURES_PROVIDED += periph_uart +FEATURES_PROVIDED += periph_spi FEATURES_PROVIDED += periph_timer FEATURES_PROVIDED += periph_gpio FEATURES_PROVIDED += periph_pwm diff --git a/boards/weio/include/periph_conf.h b/boards/weio/include/periph_conf.h index 0dc830762a1f..d5d8b777284e 100644 --- a/boards/weio/include/periph_conf.h +++ b/boards/weio/include/periph_conf.h @@ -68,6 +68,15 @@ extern "C" { #define UART_0_AF (1) /* @} */ +/** + * @brief SPI configuration + * @{ + */ +#define SPI_NUMOF (2U) +#define SPI_0_EN 1 +#define SPI_1_EN 1 +/* @} */ + /** * * @name GPIO configuration * * @{ diff --git a/cpu/lpc11u34/Makefile.include b/cpu/lpc11u34/Makefile.include index 04c2fd5dd48a..69743547a7a3 100644 --- a/cpu/lpc11u34/Makefile.include +++ b/cpu/lpc11u34/Makefile.include @@ -1,3 +1,5 @@ export CPU_ARCH = cortex-m0 +USEMODULE += periph_common + include $(RIOTCPU)/Makefile.include.cortexm_common diff --git a/cpu/lpc11u34/include/periph_cpu.h b/cpu/lpc11u34/include/periph_cpu.h index b7ceae00edc5..cb0791596af5 100644 --- a/cpu/lpc11u34/include/periph_cpu.h +++ b/cpu/lpc11u34/include/periph_cpu.h @@ -25,7 +25,14 @@ extern "C" { #endif -/* nothing to do here, yet */ +/** + * @brief declare needed generic SPI functions + * @{ + */ +#define PERIPH_SPI_NEEDS_TRANSFER_BYTES +#define PERIPH_SPI_NEEDS_TRANSFER_REG +#define PERIPH_SPI_NEEDS_TRANSFER_REGS +/** @} */ #ifdef __cplusplus } diff --git a/cpu/lpc11u34/periph/spi.c b/cpu/lpc11u34/periph/spi.c new file mode 100644 index 000000000000..1e63ff89e6f9 --- /dev/null +++ b/cpu/lpc11u34/periph/spi.c @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2015 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_lpc11u34 + * @{ + * + * @file + * @brief Low-level GPIO driver implementation + * + * @author Paul RATHGEB + * + * @} + */ + +#include "cpu.h" +#include "board.h" +#include "mutex.h" +#include "periph/spi.h" +#include "periph_conf.h" +#include "thread.h" +#include "sched.h" + +/* guard file in case no SPI device is defined */ +#if SPI_NUMOF + +/** + * @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 +}; + +int spi_init_master(spi_t dev, spi_conf_t conf, spi_speed_t speed) +{ + LPC_SSPx_Type *spi; + /* power on the SPI device */ + spi_poweron(dev); + + /* configure SCK, MISO and MOSI pin */ + spi_conf_pins(dev); + + switch(dev) { +#if SPI_0_EN + case SPI_0: + spi = LPC_SSP0; + break; +#endif +#if SPI_1_EN + case SPI_1: + spi = LPC_SSP1; + break; +#endif + default: + return -1; + } + + /* Master mode, SPI disabled */ + spi->CR1 = 0; + /* Base clock frequency : 12MHz */ + spi->CPSR = 4; + /* configure bus clock speed */ + switch (speed) { + case SPI_SPEED_100KHZ: + spi->CR0 |= (119 << 8); + break; + case SPI_SPEED_400KHZ: + spi->CR0 |= (29 << 8); + break; + case SPI_SPEED_1MHZ: + spi->CR0 |= (11 << 8); + break; + case SPI_SPEED_5MHZ: + spi->CR0 |= (2 << 8); /* Actual : 4MHz */ + break; + case SPI_SPEED_10MHZ: + spi->CR0 |= (0 << 8); /* Actual : 12MHz */ + break; + } + /* Set mode and 8-bit transfer */ + spi->CR0 |= 0x07 | (conf << 6); + /* Enable SPI */ + spi->CR1 |= (1 << 1); + + /* Wait while the BUSY flag is set */ + while(spi->SR & (1 << 4)); + /* Clear the RX FIFO */ + while(spi->SR & (1 << 2)) { + spi->DR; + } + + return 0; +} + +int spi_init_slave(spi_t dev, spi_conf_t conf, char (*cb)(char data)) +{ + /* Slave mode not supported */ + return -1; +} + +int spi_conf_pins(spi_t dev) +{ + switch (dev) { +#if SPI_0_EN + case SPI_0: + /* SPI0 : MISO */ + LPC_IOCON->PIO0_8 |= 1; + /* SPI0 : MOSI */ + LPC_IOCON->PIO0_9 |= 1; + /* SPI0 : SCK */ + LPC_IOCON->SWCLK_PIO0_10 |= 2; + break; +#endif +#if SPI_1_EN + case SPI_1: + /* SPI1 : MISO */ + LPC_IOCON->PIO1_21 |= 2; + /* SPI1 : MOSI */ + LPC_IOCON->PIO0_21 |= 2; + /* SPI1 : SCK */ + LPC_IOCON->PIO1_20 |= 2; +#endif + default: + return -1; + } + + return 0; +} + +int spi_acquire(spi_t dev) +{ + if (dev >= SPI_NUMOF) { + return -1; + } + mutex_lock(&locks[dev]); + return 0; +} + +int spi_release(spi_t dev) +{ + if (dev >= SPI_NUMOF) { + return -1; + } + mutex_unlock(&locks[dev]); + return 0; +} + +int spi_transfer_byte(spi_t dev, char out, char *in) +{ + char tmp; + LPC_SSPx_Type *spi; + + switch (dev) { +#if SPI_0_EN + case SPI_0: + spi = LPC_SSP0; + break; +#endif +#if SPI_1_EN + case SPI_1: + spi = LPC_SSP1; + break; +#endif + default: + return 0; + } + + /* Wait while the BUSY flag is set */ + while(spi->SR & (1 << 4)); + /* Put byte in the TX Fifo */ + *((volatile uint8_t *)(&spi->DR)) = (uint8_t)out; + /* Wait until the current byte is transfered */ + while(!(spi->SR & (1 << 2)) ); + /* Read the returned byte */ + tmp = *((volatile uint8_t *)(&spi->DR)); + /* 'return' response byte if wished for */ + if (in) { + *in = tmp; + } + + return 1; +} + +void spi_transmission_begin(spi_t dev, char reset_val) +{ + /* Slave mode not supported */ +} + +void spi_poweron(spi_t dev) +{ + switch (dev) { +#if SPI_0_EN + case SPI_0: + /* De-assert SPI0 */ + LPC_SYSCON->PRESETCTRL |= (1 << 0); + /* Enable SPI0 clock */ + LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 11); + /* Clock div : 48MHz */ + LPC_SYSCON->SSP0CLKDIV = 1; + break; +#endif +#if SPI_1_EN + case SPI_1: + /* De-assert SPI1 */ + LPC_SYSCON->PRESETCTRL |= (1 << 2); + /* Enable SPI1 clock */ + LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 18); + /* Clock div : 48MHz */ + LPC_SYSCON->SSP1CLKDIV = 1; + break; +#endif + } +} + +void spi_poweroff(spi_t dev) +{ + switch (dev) { +#if SPI_0_EN + case SPI_0: + /* Assert SPI0 */ + LPC_SYSCON->PRESETCTRL &= ~(1 << 0); + /* Disable SPI0 clock */ + LPC_SYSCON->SYSAHBCLKCTRL &= ~(1 << 11); + break; +#endif +#if SPI_1_EN + case SPI_1: + /* Assert SPI1 */ + LPC_SYSCON->PRESETCTRL &= ~(1 << 2); + /* Disable SPI1 clock */ + LPC_SYSCON->SYSAHBCLKCTRL &= ~(1 << 18); + break; +#endif + } +} + +#endif /* SPI_NUMOF */ diff --git a/tests/driver_at86rf2xx/Makefile b/tests/driver_at86rf2xx/Makefile index f7fd89e94c0e..7bad23857009 100644 --- a/tests/driver_at86rf2xx/Makefile +++ b/tests/driver_at86rf2xx/Makefile @@ -3,7 +3,7 @@ include ../Makefile.tests_common FEATURES_REQUIRED = periph_spi periph_gpio -BOARD_INSUFFICIENT_MEMORY := stm32f0discovery +BOARD_INSUFFICIENT_MEMORY := stm32f0discovery weio BOARD_BLACKLIST := nucleo-f334 # nucleo-f334: not enough GPIO pins defined diff --git a/tests/driver_kw2xrf/Makefile b/tests/driver_kw2xrf/Makefile index 287388a95881..4ab259b72625 100644 --- a/tests/driver_kw2xrf/Makefile +++ b/tests/driver_kw2xrf/Makefile @@ -3,7 +3,7 @@ include ../Makefile.tests_common FEATURES_REQUIRED = periph_spi periph_gpio -BOARD_INSUFFICIENT_MEMORY := stm32f0discovery nucleo-f334 +BOARD_INSUFFICIENT_MEMORY := stm32f0discovery nucleo-f334 weio ifneq (,$(filter pba-d-01-kw2x,$(BOARD))) DRIVER ?= kw2xrf