1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-17 04:52:59 +01:00

cpu/msp430fxyz+boards: adapted to new SPI API

- adapted the SPI driver
- adapted all boards using the CPU
This commit is contained in:
Hauke Petersen 2016-11-08 18:20:38 +01:00
parent c97a88ecb8
commit d5e00e594a
12 changed files with 133 additions and 197 deletions

View File

@ -1,6 +1,7 @@
# Put defined MCU peripherals here (in alphabetical order)
FEATURES_PROVIDED += periph_gpio
FEATURES_PROVIDED += periph_timer
FEATURES_PROVIDED += periph_spi
FEATURES_PROVIDED += periph_uart
# Various other features (if any)

View File

@ -75,7 +75,7 @@ extern "C" {
#define SPI_0_EN (1U)
/* SPI configuration */
#define SPI_DEV (USART_0)
#define SPI_BASE (USART_0)
#define SPI_IE (SFR->IE1)
#define SPI_IF (SFR->IFG1)
#define SPI_IE_RX_BIT (1 << 6)

View File

@ -77,7 +77,7 @@ extern "C" {
#define SPI_0_EN (1U)
/* SPI configuration */
#define SPI_DEV (USART_0)
#define SPI_BASE (USART_0)
#define SPI_IE (SFR->IE1)
#define SPI_IF (SFR->IFG1)
#define SPI_IE_RX_BIT (1 << 6)

View File

@ -102,8 +102,8 @@ extern "C" {
/**
* @brief Definition of the interface to the CC2420 radio
*/
#define CC2420_PARAMS_BOARD {.spi = SPI_0, \
.spi_clk = SPI_SPEED_1MHZ , \
#define CC2420_PARAMS_BOARD {.spi = SPI_DEV(0), \
.spi_clk = SPI_CLK_1MHZ , \
.pin_cs = GPIO_PIN(P4, 2), \
.pin_fifo = GPIO_PIN(P1, 3), \
.pin_fifop = GPIO_PIN(P1, 0), \

View File

@ -75,7 +75,7 @@ extern "C" {
#define SPI_0_EN (1U)
/* SPI configuration */
#define SPI_DEV (USART_0)
#define SPI_BASE (USART_0)
#define SPI_IE (SFR->IE1)
#define SPI_IF (SFR->IFG1)
#define SPI_IE_RX_BIT (1 << 6)

View File

@ -75,7 +75,7 @@ extern "C" {
#define SPI_0_EN (1U)
/* SPI configuration */
#define SPI_DEV (USART_0)
#define SPI_BASE (USART_0)
#define SPI_IE (SFR->IE1)
#define SPI_IF (SFR->IFG1)
#define SPI_IE_RX_BIT (1 << 6)

View File

@ -1,6 +1,7 @@
# Put defined MCU peripherals here (in alphabetical order)
FEATURES_PROVIDED += periph_gpio
FEATURES_PROVIDED += periph_timer
FEATURES_PROVIDED += periph_spi
FEATURES_PROVIDED += periph_uart
# Various other features (if any)

View File

@ -1,6 +1,7 @@
# Put defined MCU peripherals here (in alphabetical order)
FEATURES_PROVIDED += periph_gpio
FEATURES_PROVIDED += periph_timer
FEATURES_PROVIDED += periph_spi
FEATURES_PROVIDED += periph_uart
# Various other features (if any)

View File

@ -110,8 +110,8 @@ extern "C" {
/**
* @brief Definition of the interface to the CC2420 radio
*/
#define CC2420_PARAMS_BOARD {.spi = SPI_0, \
.spi_clk = SPI_SPEED_5MHZ, \
#define CC2420_PARAMS_BOARD {.spi = SPI_DEV(0), \
.spi_clk = SPI_CLK_5MHZ, \
.pin_cs = GPIO_PIN(P3, 0), \
.pin_fifo = GPIO_PIN(P1, 3), \
.pin_fifop = GPIO_PIN(P1, 2), \

View File

@ -76,7 +76,7 @@ extern "C" {
/* SPI configuration */
#define SPI_USE_USCI
#define SPI_DEV (USCI_0_B_SPI)
#define SPI_BASE (USCI_0_B_SPI)
#define SPI_IE (SFR->IE2)
#define SPI_IF (SFR->IFG2)
#define SPI_IE_RX_BIT (1 << 2)

View File

@ -45,6 +45,11 @@ typedef uint16_t gpio_t;
*/
#define GPIO_PIN(x, y) ((gpio_t)(((x & 0xff) << 8) | (1 << (y & 0xff))))
/**
* @brief No support for HW chip select...
*/
#define SPI_HWCS(x) (SPI_CS_UNDEF)
#ifndef DOXYGEN
/**
* @brief Override flank selection values
@ -57,6 +62,40 @@ typedef enum {
GPIO_BOTH = 0xab /**< not supported -> random value*/
} gpio_flank_t;
/** @} */
/**
* @brief Override SPI mode selection values
*/
#define HAVE_SPI_MODE_T
#ifndef SPI_USE_USCI
typedef enum {
SPI_MODE_0 = (USART_TCTL_CKPH), /**< CPOL=0, CPHA=0 */
SPI_MODE_1 = 0, /**< CPOL=0, CPHA=1 */
SPI_MODE_2 = (USART_TCTL_CKPL | USART_TCTL_CKPH), /**< CPOL=1, CPHA=0 */
SPI_MODE_3 = (USART_TCTL_CKPL) /**< CPOL=1, CPHA=1 */
} spi_mode_t;
#else
typedef enum {
SPI_MODE_0 = (USCI_SPI_CTL0_CKPH), /**< CPOL=0, CPHA=0 */
SPI_MODE_1 = 0, /**< CPOL=0, CPHA=1 */
SPI_MODE_2 = (USCI_SPI_CTL0_CKPL | USCI_SPI_CTL0_CKPH), /**< CPOL=1, CPHA=0 */
SPI_MODE_3 = (USCI_SPI_CTL0_CKPL) /**< CPOL=1, CPHA=1 */
} spi_mode_t;
#endif
/** @} */
/**
* @brief Override SPI clock speed selection values
*/
#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 = 0, /**< not supported */
} spi_clk_t;
/** @} */
#endif /* ndef DOXYGEN */
/**
@ -83,6 +122,7 @@ void gpio_periph_mode(gpio_t pin, bool enable);
* @brief declare needed generic SPI functions
* @{
*/
#define PERIPH_SPI_NEEDS_INIT_CS
#define PERIPH_SPI_NEEDS_TRANSFER_BYTE
#define PERIPH_SPI_NEEDS_TRANSFER_REG
#define PERIPH_SPI_NEEDS_TRANSFER_REGS

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015 Freie Universität Berlin
* Copyright (C) 2015-2016 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
@ -25,8 +25,6 @@
#include "cpu.h"
#include "mutex.h"
#include "assert.h"
#include "periph_cpu.h"
#include "periph_conf.h"
#include "periph/spi.h"
/**
@ -34,233 +32,128 @@
*/
static mutex_t spi_lock = MUTEX_INIT;
/* per default, we use the legacy MSP430 USART module for UART functionality */
#ifndef SPI_USE_USCI
int spi_init_master(spi_t dev, spi_conf_t conf, spi_speed_t speed)
void spi_init(spi_t bus)
{
if (dev != 0) {
return -2;
}
assert(bus <= SPI_NUMOF);
/* reset SPI device */
SPI_DEV->CTL = USART_CTL_SWRST;
/* configure pins */
spi_conf_pins(dev);
/* configure USART to SPI mode with SMCLK driving it */
SPI_DEV->CTL |= (USART_CTL_CHAR | USART_CTL_SYNC | USART_CTL_MM);
SPI_DEV->RCTL = 0;
SPI_DEV->TCTL = (USART_TCTL_SSEL_SMCLK | USART_TCTL_STC);
/* set polarity and phase */
switch (conf) {
case SPI_CONF_FIRST_RISING:
SPI_DEV->TCTL |= USART_TCTL_CKPH;
break;
case SPI_CONF_SECOND_RISING:
/* nothing to be done here */
break;
case SPI_CONF_FIRST_FALLING:
SPI_DEV->TCTL |= (USART_TCTL_CKPH & USART_TCTL_CKPL);
break;
case SPI_CONF_SECOND_FALLING:
SPI_DEV->TCTL |= USART_TCTL_CKPL;
break;
default:
/* invalid clock setting */
return -2;
}
/* configure clock - we use no modulation for now */
uint32_t br = CLOCK_CMCLK;
switch (speed) {
case SPI_SPEED_100KHZ:
br /= 100000;
break;
case SPI_SPEED_400KHZ:
br /= 400000;
break;
case SPI_SPEED_1MHZ:
br /= 1000000;
break;
case SPI_SPEED_5MHZ:
br /= 5000000;
break;
default:
/* other clock speeds are not supported */
return -1;
}
/* make sure the is not smaller then 2 */
if (br < 2) {
br = 2;
}
SPI_DEV->BR0 = (uint8_t)br;
SPI_DEV->BR1 = (uint8_t)(br >> 8);
SPI_DEV->MCTL = 0;
/* we need to differentiate between the legacy SPI device and USCI */
#ifndef SPI_USE_USCI
/* put SPI device in reset state */
SPI_BASE->CTL = USART_CTL_SWRST;
SPI_BASE->CTL |= (USART_CTL_CHAR | USART_CTL_SYNC | USART_CTL_MM);
SPI_BASE->RCTL = 0;
SPI_BASE->MCTL = 0;
/* enable SPI mode */
SPI_ME |= SPI_ME_BIT;
/* release from software reset */
SPI_DEV->CTL &= ~(USART_CTL_SWRST);
return 0;
}
/* we use alternative SPI code in case the board used the USCI module for SPI
* instead of the (older) USART module */
#else /* SPI_USE_USCI */
int spi_init_master(spi_t dev, spi_conf_t conf, spi_speed_t speed)
{
if (dev != 0) {
return -2;
}
#else
/* reset SPI device */
SPI_DEV->CTL1 |= USCI_SPI_CTL1_SWRST;
/* configure pins */
spi_conf_pins(dev);
/* configure USART to SPI mode with SMCLK driving it */
SPI_DEV->CTL0 |= (USCI_SPI_CTL0_UCSYNC | USCI_SPI_CTL0_MST
| USCI_SPI_CTL0_MODE_0 | USCI_SPI_CTL0_MSB);
SPI_DEV->CTL1 |= (USCI_SPI_CTL1_SSEL_SMCLK);
SPI_BASE->CTL1 = USCI_SPI_CTL1_SWRST;
SPI_BASE->CTL1 |= (USCI_SPI_CTL1_SSEL_SMCLK);
#endif
/* set polarity and phase */
switch (conf) {
case SPI_CONF_FIRST_RISING:
SPI_DEV->CTL0 |= USCI_SPI_CTL0_CKPH;
break;
case SPI_CONF_SECOND_RISING:
/* nothing to be done here */
break;
case SPI_CONF_FIRST_FALLING:
SPI_DEV->CTL0 |= (USCI_SPI_CTL0_CKPH & USCI_SPI_CTL0_CKPL);
break;
case SPI_CONF_SECOND_FALLING:
SPI_DEV->CTL0 |= USCI_SPI_CTL0_CKPL;
break;
default:
/* invalid clock setting */
return -2;
}
/* configure clock - we use no modulation for now */
uint32_t br = CLOCK_CMCLK;
switch (speed) {
case SPI_SPEED_100KHZ:
br /= 100000;
break;
case SPI_SPEED_400KHZ:
br /= 400000;
break;
case SPI_SPEED_1MHZ:
br /= 1000000;
break;
case SPI_SPEED_5MHZ:
br /= 5000000;
break;
default:
/* other clock speeds are not supported */
return -1;
}
/* make sure the is not smaller then 2 */
if (br < 2) {
br = 2;
}
SPI_DEV->BR0 = (uint8_t)br;
SPI_DEV->BR1 = (uint8_t)(br >> 8);
/* release from software reset */
SPI_DEV->CTL1 &= ~(USCI_SPI_CTL1_SWRST);
return 0;
/* trigger the pin configuration */
spi_init_pins(bus);
}
#endif /* SPI_USE_USCI */
int spi_init_slave(spi_t dev, spi_conf_t conf, char (*cb)(char data))
void spi_init_pins(spi_t bus)
{
/* not supported so far */
(void)dev;
(void)conf;
(void)cb;
return -1;
}
void spi_transmission_begin(spi_t dev, char reset_val)
{
/* not supported so far */
(void)dev;
(void)reset_val;
}
int spi_conf_pins(spi_t dev)
{
(void)dev;
gpio_periph_mode(SPI_PIN_MISO, true);
gpio_periph_mode(SPI_PIN_MOSI, true);
gpio_periph_mode(SPI_PIN_CLK, true);
return 0;
}
int spi_acquire(spi_t dev)
int spi_acquire(spi_t bus, spi_cs_t cs, spi_mode_t mode, spi_clk_t clk)
{
(void)dev;
if (clk == SPI_CLK_10MHZ) {
return SPI_NOCLK;
}
/* lock the bus */
mutex_lock(&spi_lock);
return 0;
/* calculate baudrate */
uint32_t br = CLOCK_CMCLK / clk;
/* make sure the is not smaller then 2 */
if (br < 2) {
br = 2;
}
SPI_BASE->BR0 = (uint8_t)br;
SPI_BASE->BR1 = (uint8_t)(br >> 8);
/* configure bus mode */
#ifndef SPI_USE_USCI
/* configure mode */
SPI_BASE->TCTL = (USART_TCTL_SSEL_SMCLK | USART_TCTL_STC | mode);
/* release from software reset */
SPI_BASE->CTL &= ~(USART_CTL_SWRST);
#else
/* configure mode */
SPI_BASE->CTL0 = (USCI_SPI_CTL0_UCSYNC | USCI_SPI_CTL0_MST|
USCI_SPI_CTL0_MODE_0 | USCI_SPI_CTL0_MSB | mode);
/* release from software reset */
SPI_BASE->CTL1 &= ~(USCI_SPI_CTL1_SWRST);
#endif
return SPI_OK;
}
int spi_release(spi_t dev)
void spi_release(spi_t dev)
{
(void)dev;
/* put SPI device back in reset state */
#ifndef SPI_USE_USCI
SPI_BASE->CTL |= (USART_CTL_SWRST);
#else
SPI_BASE->CTL1 |= (USCI_SPI_CTL1_SWRST);
#endif
/* release the bus */
mutex_unlock(&spi_lock);
return 0;
}
int spi_transfer_bytes(spi_t dev, char *out, char *in, unsigned int length)
void spi_transfer_bytes(spi_t bus, spi_cs_t cs, bool cont,
const void *out, void *in, size_t len)
{
(void)dev;
uint8_t *out_buf = (uint8_t *)out;
uint8_t *in_buf = (uint8_t *)in;
assert(out || in);
assert(out_buf || in_buf);
if (cs != SPI_CS_UNDEF) {
gpio_clear((gpio_t)cs);
}
/* if we only send out data, we do this the fast way... */
if (!in) {
for (unsigned i = 0; i < length; i++) {
if (!in_buf) {
for (size_t i = 0; i < len; i++) {
while (!(SPI_IF & SPI_IE_TX_BIT)) {}
SPI_DEV->TXBUF = (uint8_t)out[i];
SPI_BASE->TXBUF = (uint8_t)out_buf[i];
}
/* finally we need to wait, until all transfers are complete */
#ifndef SPI_USE_USCI
while (!(SPI_IF & SPI_IE_TX_BIT) || !(SPI_IF & SPI_IE_RX_BIT)) {}
#else
while (SPI_DEV->STAT & USCI_SPI_STAT_UCBUSY) {}
while (SPI_BASE->STAT & USCI_SPI_STAT_UCBUSY) {}
#endif
SPI_DEV->RXBUF;
SPI_BASE->RXBUF;
}
else if (!out) {
for (unsigned i = 0; i < length; i++) {
SPI_DEV->TXBUF = 0;
else if (!out_buf) {
for (size_t i = 0; i < len; i++) {
SPI_BASE->TXBUF = 0;
while (!(SPI_IF & SPI_IE_RX_BIT)) {}
in[i] = (char)SPI_DEV->RXBUF;
in_buf[i] = (char)SPI_BASE->RXBUF;
}
}
else {
for (unsigned i = 0; i < length; i++) {
for (size_t i = 0; i < len; i++) {
while (!(SPI_IF & SPI_IE_TX_BIT)) {}
SPI_DEV->TXBUF = out[i];
SPI_BASE->TXBUF = out_buf[i];
while (!(SPI_IF & SPI_IE_RX_BIT)) {}
in[i] = (char)SPI_DEV->RXBUF;
in_buf[i] = (char)SPI_BASE->RXBUF;
}
}
return length;
}
void spi_poweron(spi_t dev)
{
/* not supported so far */
(void)dev;
}
void spi_poweroff(spi_t dev)
{
/* not supported so far */
(void)dev;
if ((!cont) && (cs != SPI_CS_UNDEF)) {
gpio_set((gpio_t)cs);
}
}