mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #12957 from aabadie/pr/cpu/fe310_spi
cpu/fe310: add spi peripheral driver
This commit is contained in:
commit
f76f7c73ce
@ -5,6 +5,6 @@ CPU_MODEL = fe310_g000
|
||||
#FEATURES_PROVIDED += periph_pwm
|
||||
FEATURES_PROVIDED += periph_rtc
|
||||
FEATURES_PROVIDED += periph_rtt
|
||||
#FEATURES_PROVIDED += periph_spi
|
||||
FEATURES_PROVIDED += periph_spi
|
||||
FEATURES_PROVIDED += periph_timer
|
||||
FEATURES_PROVIDED += periph_uart
|
||||
|
@ -109,6 +109,23 @@ static const uart_conf_t uart_config[] = {
|
||||
#define UART_NUMOF ARRAY_SIZE(uart_config)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name SPI device configuration
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
static const spi_conf_t spi_config[] = {
|
||||
{
|
||||
.addr = SPI1_CTRL_ADDR,
|
||||
.mosi = GPIO_PIN(0, 3), /* D11 */
|
||||
.miso = GPIO_PIN(0, 4), /* D12 */
|
||||
.sclk = GPIO_PIN(0, 5), /* D13 */
|
||||
},
|
||||
};
|
||||
|
||||
#define SPI_NUMOF ARRAY_SIZE(spi_config)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name RTT/RTC configuration
|
||||
*
|
||||
|
@ -6,7 +6,7 @@ FEATURES_PROVIDED += periph_i2c
|
||||
#FEATURES_PROVIDED += periph_pwm
|
||||
FEATURES_PROVIDED += periph_rtc
|
||||
FEATURES_PROVIDED += periph_rtt
|
||||
#FEATURES_PROVIDED += periph_spi
|
||||
FEATURES_PROVIDED += periph_spi
|
||||
FEATURES_PROVIDED += periph_timer
|
||||
FEATURES_PROVIDED += periph_uart
|
||||
|
||||
|
@ -110,6 +110,23 @@ static const uart_conf_t uart_config[] = {
|
||||
#define UART_NUMOF ARRAY_SIZE(uart_config)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name SPI device configuration
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
static const spi_conf_t spi_config[] = {
|
||||
{
|
||||
.addr = SPI1_CTRL_ADDR,
|
||||
.mosi = GPIO_PIN(0, 3), /* D11 */
|
||||
.miso = GPIO_PIN(0, 4), /* D12 */
|
||||
.sclk = GPIO_PIN(0, 5), /* D13 */
|
||||
},
|
||||
};
|
||||
|
||||
#define SPI_NUMOF ARRAY_SIZE(spi_config)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name RTT/RTC configuration
|
||||
*
|
||||
|
@ -70,6 +70,25 @@ typedef struct {
|
||||
*/
|
||||
#define UART_ISR_PRIO (2)
|
||||
|
||||
/**
|
||||
* @name This CPU makes use of the following shared SPI functions
|
||||
* @{
|
||||
*/
|
||||
#define PERIPH_SPI_NEEDS_TRANSFER_BYTE 1
|
||||
#define PERIPH_SPI_NEEDS_TRANSFER_REG 1
|
||||
#define PERIPH_SPI_NEEDS_TRANSFER_REGS 1
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Structure for SPI configuration data
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t addr; /**< SPI control register address */
|
||||
gpio_t mosi; /**< MOSI pin */
|
||||
gpio_t miso; /**< MISO pin */
|
||||
gpio_t sclk; /**< SCLK pin */
|
||||
} spi_conf_t;
|
||||
|
||||
/**
|
||||
* @brief Prevent shared timer functions from being used
|
||||
*/
|
||||
|
156
cpu/fe310/periph/spi.c
Normal file
156
cpu/fe310/periph/spi.c
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Tristan Bruns
|
||||
* 2019 Inria
|
||||
*
|
||||
* 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_fe310
|
||||
* @ingroup drivers_periph_spi
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @file spi.c
|
||||
* @brief Low-level SPI driver implementation
|
||||
*
|
||||
* @author Tristan Bruns
|
||||
* @author Alexandre Abadie <alexandre.abadie@inria.fr>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "cpu.h"
|
||||
#include "mutex.h"
|
||||
#include "assert.h"
|
||||
#include "periph/spi.h"
|
||||
|
||||
#include "vendor/spi.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
static const uint32_t _spi_clks[] = {
|
||||
100000,
|
||||
400000,
|
||||
1000000,
|
||||
5000000,
|
||||
10000000,
|
||||
};
|
||||
|
||||
#define SPI_CLK_NUMOF ARRAY_SIZE(_spi_clks)
|
||||
|
||||
static uint32_t _spi_clks_config[SPI_CLK_NUMOF] = { 0 };
|
||||
|
||||
/* DIV_UP is division which rounds up instead of down */
|
||||
#define SPI_DIV_UP(a,b) (((a) + ((b) - 1)) / (b))
|
||||
|
||||
/**
|
||||
* @brief Allocation device locks
|
||||
*/
|
||||
static mutex_t lock;
|
||||
|
||||
void spi_init(spi_t dev)
|
||||
{
|
||||
/* make sure given bus device is valid */
|
||||
assert(dev < SPI_NUMOF);
|
||||
|
||||
/* initialize the buses lock */
|
||||
mutex_init(&lock);
|
||||
|
||||
for (uint8_t i = 0; i < SPI_CLK_NUMOF; ++i) {
|
||||
_spi_clks_config[i] = SPI_DIV_UP(cpu_freq(), 2 * _spi_clks[i]) - 1;
|
||||
}
|
||||
|
||||
/* trigger pin initialization */
|
||||
spi_init_pins(dev);
|
||||
|
||||
/* disable hardware chip select
|
||||
(hardware chip select only supports one-byte transfers...) */
|
||||
_REG32(spi_config[dev].addr, SPI_REG_CSMODE) = SPI_CSMODE_OFF;
|
||||
}
|
||||
|
||||
void spi_init_pins(spi_t dev)
|
||||
{
|
||||
assert(dev < SPI_NUMOF);
|
||||
|
||||
const gpio_t spi1_pins =
|
||||
(1 << spi_config[dev].mosi) |
|
||||
(1 << spi_config[dev].miso) |
|
||||
(1 << spi_config[dev].sclk);
|
||||
|
||||
/* Enable I/O Function 0 */
|
||||
GPIO_REG(GPIO_IOF_EN) |= spi1_pins;
|
||||
GPIO_REG(GPIO_IOF_SEL) &= ~spi1_pins;
|
||||
}
|
||||
|
||||
int spi_init_cs(spi_t dev, spi_cs_t cs)
|
||||
{
|
||||
(void)dev;
|
||||
assert(dev < SPI_NUMOF);
|
||||
|
||||
/* setting the CS high before configuring it as an
|
||||
output should be fine on FE310. */
|
||||
gpio_set(cs);
|
||||
|
||||
if (gpio_init(cs, GPIO_OUT)) {
|
||||
return SPI_NOCS;
|
||||
}
|
||||
|
||||
return SPI_OK;
|
||||
}
|
||||
|
||||
int spi_acquire(spi_t dev, spi_cs_t cs, spi_mode_t mode, spi_clk_t clk)
|
||||
{
|
||||
(void)cs;
|
||||
assert(dev < SPI_NUMOF);
|
||||
|
||||
mutex_lock(&lock);
|
||||
|
||||
_REG32(spi_config[dev].addr, SPI_REG_SCKDIV) = _spi_clks_config[clk];
|
||||
_REG32(spi_config[dev].addr, SPI_REG_SCKMODE) = mode;
|
||||
|
||||
return SPI_OK;
|
||||
}
|
||||
|
||||
void spi_release(spi_t dev)
|
||||
{
|
||||
(void)dev;
|
||||
|
||||
mutex_unlock(&lock);
|
||||
}
|
||||
|
||||
void spi_transfer_bytes(spi_t dev, spi_cs_t cs, bool cont,
|
||||
const void *out_, void *in_, size_t len)
|
||||
{
|
||||
assert(dev < SPI_NUMOF);
|
||||
assert((out_ || in_) && len > 0);
|
||||
assert(_REG32(spi_config[dev].addr, SPI_REG_RXFIFO) & SPI_RXFIFO_EMPTY);
|
||||
assert(!(_REG32(spi_config[dev].addr, SPI_REG_TXFIFO) & SPI_TXFIFO_FULL));
|
||||
|
||||
const uint8_t *out = out_;
|
||||
uint8_t *in = in_;
|
||||
|
||||
if (cs != SPI_CS_UNDEF) {
|
||||
gpio_clear(cs);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
_REG32(spi_config[dev].addr, SPI_REG_TXFIFO) = out ? out[i] : 0;
|
||||
|
||||
uint32_t rxdata;
|
||||
do {
|
||||
rxdata = _REG32(spi_config[dev].addr, SPI_REG_RXFIFO);
|
||||
} while (rxdata & SPI_RXFIFO_EMPTY);
|
||||
|
||||
if (in) {
|
||||
in[i] = (uint8_t)rxdata;
|
||||
}
|
||||
}
|
||||
|
||||
if (cs != SPI_CS_UNDEF && !cont) {
|
||||
gpio_set(cs);
|
||||
}
|
||||
}
|
@ -9,6 +9,8 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
blackpill \
|
||||
bluepill \
|
||||
derfmega128 \
|
||||
hifive1 \
|
||||
hifive1b \
|
||||
i-nucleo-lrwan1 \
|
||||
mega-xplained \
|
||||
microduino-corerf \
|
||||
|
Loading…
Reference in New Issue
Block a user