mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
cpu/msp430: added SPI periph driver
This commit is contained in:
parent
92cd6dfcba
commit
399e7c1c2e
@ -2,4 +2,4 @@ INCLUDES += -I$(RIOTCPU)/msp430fxyz/include/
|
||||
|
||||
include $(RIOTCPU)/msp430-common/Makefile.include
|
||||
|
||||
export USEMODULE += periph
|
||||
export USEMODULE += periph periph_common
|
||||
|
@ -111,6 +111,20 @@ typedef struct {
|
||||
REG8 BTXBUF; /**< B transmit buffer */
|
||||
} msp_usci_t;
|
||||
|
||||
/**
|
||||
* @brief USCI SPI specific registers
|
||||
*/
|
||||
typedef struct {
|
||||
REG8 CTL0; /**< control 0 */
|
||||
REG8 CTL1; /**< control 1 */
|
||||
REG8 BR0; /**< baud rate 0 */
|
||||
REG8 BR1; /**< baud rate 1 */
|
||||
REG8 reserved; /**< reserved */
|
||||
REG8 STAT; /**< status */
|
||||
REG8 RXBUF; /**< receive buffer */
|
||||
REG8 TXBUF; /**< transmit buffer */
|
||||
} msp_usci_spi_t;
|
||||
|
||||
/**
|
||||
* @brief Timer interrupt status registers
|
||||
*/
|
||||
@ -201,6 +215,7 @@ typedef struct {
|
||||
* @{
|
||||
*/
|
||||
#define USART_TCTL_TXEPT (0x01)
|
||||
#define USART_TCTL_STC (0x02)
|
||||
#define USART_TCTL_TXWAKE (0x04)
|
||||
#define USART_TCTL_URXSE (0x08)
|
||||
#define USART_TCTL_SSEL_MASK (0x30)
|
||||
@ -208,6 +223,7 @@ typedef struct {
|
||||
#define USART_TCTL_SSEL_ACLK (0x10)
|
||||
#define USART_TCTL_SSEL_SMCLK (0x20)
|
||||
#define USART_TCTL_CKPL (0x40)
|
||||
#define USART_TCTL_CKPH (0x80)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
@ -241,6 +257,22 @@ typedef struct {
|
||||
#define USCI_ACTL0_PEN (0x80)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief USCI control register 0 bitmap SPI mode
|
||||
* @{
|
||||
*/
|
||||
#define USCI_SPI_CTL0_UCSYNC (0x01)
|
||||
#define USCI_SPI_CTL0_MODE_3 (0x06)
|
||||
#define USCI_SPI_CTL0_MODE_0 (0x00)
|
||||
#define USCI_SPI_CTL0_MODE_1 (0x02)
|
||||
#define USCI_SPI_CTL0_MODE_2 (0x04)
|
||||
#define USCI_SPI_CTL0_MST (0x08)
|
||||
#define USCI_SPI_CTL0_7BIT (0x10)
|
||||
#define USCI_SPI_CTL0_MSB (0x20)
|
||||
#define USCI_SPI_CTL0_CKPL (0x40)
|
||||
#define USCI_SPI_CTL0_CKPH (0x80)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief USCI control A register 1 bitmap
|
||||
* @{
|
||||
@ -257,6 +289,17 @@ typedef struct {
|
||||
#define USCI_ACTL1_SSEL_SMCLK (0xc0)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief USCI control register 1 bitmap SPI mode
|
||||
* @{
|
||||
*/
|
||||
#define USCI_SPI_CTL1_SWRST (0x01)
|
||||
#define USCI_SPI_CTL1_SSEL_MASK (0xc0)
|
||||
#define USCI_SPI_CTL1_SSEL_NA (0x00)
|
||||
#define USCI_SPI_CTL1_SSEL_ACLK (0x40)
|
||||
#define USCI_SPI_CTL1_SSEL_SMCLK (0xc0)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief USCI modulation A control register
|
||||
* @{
|
||||
@ -351,7 +394,11 @@ typedef struct {
|
||||
#define TIMER_B_BASE ((uint16_t)0x0180)
|
||||
#define WD_BASE ((uint16_t)0x0120)
|
||||
#define USCI_0_BASE ((uint16_t)0x005d)
|
||||
#define USCI_0_A_BASE ((uint16_t)0x0060)
|
||||
#define USCI_0_B_BASE ((uint16_t)0x0068)
|
||||
#define USCI_1_BASE ((uint16_t)0x00cd)
|
||||
#define USCI_1_A_BASE ((uint16_t)0x00d0)
|
||||
#define USCI_1_B_BASE ((uint16_t)0x00d8)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
@ -374,6 +421,10 @@ typedef struct {
|
||||
#define WD ((msp_wd_t *)WD_BASE)
|
||||
#define USCI_0 ((msp_usci_t *)USCI_0_BASE)
|
||||
#define USCI_1 ((msp_usci_t *)USCI_1_BASE)
|
||||
#define USCI_0_A_SPI ((msp_usci_spi_t *)USCI_0_A_BASE)
|
||||
#define USCI_0_B_SPI ((msp_usci_spi_t *)USCI_0_B_BASE)
|
||||
#define USCI_1_A ((msp_usci_t *)USCI_1_A_BASE)
|
||||
#define USCI_1_B ((msp_usci_t *)USCI_1_B_BASE)
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -88,6 +88,14 @@ enum {
|
||||
*/
|
||||
void gpio_periph_mode(gpio_t pin, bool enable);
|
||||
|
||||
/**
|
||||
* @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
|
||||
}
|
||||
|
225
cpu/msp430fxyz/periph/spi.c
Normal file
225
cpu/msp430fxyz/periph/spi.c
Normal file
@ -0,0 +1,225 @@
|
||||
/*
|
||||
* 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_msp430fxyz
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Low-level SPI driver implementation
|
||||
*
|
||||
* This SPI driver implementation does only support one single SPI device for
|
||||
* now. This is sufficient, as most MSP430 CPU's only support two serial
|
||||
* devices - one used as UART and one as SPI.
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "cpu.h"
|
||||
#include "mutex.h"
|
||||
#include "periph_cpu.h"
|
||||
#include "periph_conf.h"
|
||||
#include "periph/spi.h"
|
||||
|
||||
/**
|
||||
* @brief Mutex for locking the SPI device
|
||||
*/
|
||||
static mutex_t spi_lock = MUTEX_INIT;
|
||||
|
||||
/* per default, we use the legacy MSP430 USART module for UART functionality */
|
||||
#ifndef SPI_USE_USIC
|
||||
|
||||
int spi_init_master(spi_t dev, spi_conf_t conf, spi_speed_t speed)
|
||||
{
|
||||
if (dev != 0) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* 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_SECOND_RISING:
|
||||
SPI_DEV->TCTL |= USART_TCTL_CKPH;
|
||||
break;
|
||||
case SPI_CONF_FIRST_FALLING:
|
||||
SPI_DEV->TCTL |= SPI_CONF_FIRST_FALLING;
|
||||
break;
|
||||
case SPI_CONF_SECOND_FALLING:
|
||||
SPI_DEV->TCTL |= (USART_TCTL_CKPH | SPI_CONF_FIRST_FALLING);
|
||||
break;
|
||||
default:
|
||||
/* do nothing */
|
||||
break;
|
||||
}
|
||||
/* configure clock - we use no modulation for now */
|
||||
uint32_t br = CLOCK_CMCLK;
|
||||
switch (speed) {
|
||||
case SPI_SPEED_100KHZ:
|
||||
br /= 100000;
|
||||
case SPI_SPEED_400KHZ:
|
||||
br /= 400000;
|
||||
case SPI_SPEED_1MHZ:
|
||||
br /= 1000000;
|
||||
case SPI_SPEED_5MHZ:
|
||||
br /= 5000000;
|
||||
if (br < 2) { /* make sure the is not smaller then 2 */
|
||||
br = 2;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* other clock speeds are not supported */
|
||||
return -1;
|
||||
}
|
||||
SPI_DEV->BR0 = (uint8_t)br;
|
||||
SPI_DEV->BR1 = (uint8_t)(br >> 8);
|
||||
SPI_DEV->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 USIC module for SPI
|
||||
* instead of the (older) USART module */
|
||||
#else /* SPI_USE_USIC */
|
||||
|
||||
int spi_init_master(spi_t dev, spi_conf_t conf, spi_speed_t speed)
|
||||
{
|
||||
if (dev != 0) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
/* set polarity and phase */
|
||||
switch (conf) {
|
||||
case SPI_CONF_FIRST_RISING:
|
||||
SPI_DEV->CTL0 |= (USCI_SPI_CTL0_CKPH & ~(USCI_SPI_CTL0_CKPL));
|
||||
break;
|
||||
case SPI_CONF_SECOND_RISING:
|
||||
SPI_DEV->CTL0 |= (~(USCI_SPI_CTL0_CKPH) & ~(USCI_SPI_CTL0_CKPL));
|
||||
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_CKPH) & USCI_SPI_CTL0_CKPL);
|
||||
break;
|
||||
default:
|
||||
/* do nothing */
|
||||
break;
|
||||
}
|
||||
/* configure clock - we use no modulation for now */
|
||||
uint32_t br = CLOCK_CMCLK;
|
||||
switch (speed) {
|
||||
case SPI_SPEED_100KHZ:
|
||||
br /= 100000;
|
||||
case SPI_SPEED_400KHZ:
|
||||
br /= 400000;
|
||||
case SPI_SPEED_1MHZ:
|
||||
br /= 1000000;
|
||||
case SPI_SPEED_5MHZ:
|
||||
br /= 5000000;
|
||||
if (br < 2) { /* make sure the is not smaller then 2 */
|
||||
br = 2;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* other clock speeds are not supported */
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
#endif /* UART_USE_USIC */
|
||||
|
||||
int spi_init_slave(spi_t dev, spi_conf_t conf, char (*cb)(char data))
|
||||
{
|
||||
/* 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)
|
||||
{
|
||||
(void)dev;
|
||||
mutex_lock(&spi_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int spi_release(spi_t dev)
|
||||
{
|
||||
(void)dev;
|
||||
mutex_unlock(&spi_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int spi_transfer_byte(spi_t dev, char out, char *in)
|
||||
{
|
||||
(void)dev;
|
||||
char tmp;
|
||||
while (!(SPI_IF & SPI_IE_TX_BIT));
|
||||
SPI_DEV->TXBUF = (uint8_t)out;
|
||||
while (!(SPI_IF & SPI_IE_RX_BIT));
|
||||
tmp = (char)SPI_DEV->RXBUF;
|
||||
if (in) {
|
||||
*in = tmp;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void spi_poweron(spi_t dev)
|
||||
{
|
||||
/* not supported so far */
|
||||
(void)dev;
|
||||
}
|
||||
|
||||
void spi_poweroff(spi_t dev)
|
||||
{
|
||||
/* not supported so far */
|
||||
(void)dev;
|
||||
}
|
Loading…
Reference in New Issue
Block a user