Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Makefile.include
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,9 @@ else
# always select CPU core features
FEATURES_REQUIRED += $(filter cpu_core_%,$(FEATURES_PROVIDED))

# add features provided by modules
include $(RIOTMAKE)/features_provided_by_modules.inc.mk

# check if required features are provided and update $(FEATURES_USED)
include $(RIOTMAKE)/features_check.inc.mk

Expand Down
2 changes: 1 addition & 1 deletion cpu/lm4f120/include/periph_cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ typedef enum {
SPI_MODE_0 = SSI_FRF_MOTO_MODE_0, /**< CPOL=0, CPHA=0 */
SPI_MODE_1 = SSI_FRF_MOTO_MODE_1, /**< CPOL=0, CPHA=1 */
SPI_MODE_2 = SSI_FRF_MOTO_MODE_2, /**< CPOL=1, CPHA=0 */
SPI_MODE_3 = SSI_FRF_MOTO_MODE_0, /**< CPOL=1, CPHA=1 */
SPI_MODE_3 = SSI_FRF_MOTO_MODE_3, /**< CPOL=1, CPHA=1 */
} spi_mode_t;
/** @} */
#endif /* ndef DOXYGEN */
Expand Down
5 changes: 5 additions & 0 deletions drivers/Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,11 @@ ifneq (,$(filter stmpe811_%,$(USEMODULE)))
USEMODULE += stmpe811
endif

ifneq (,$(filter soft_spi_as_periph_spi,$(USEMODULE)))
USEMODULE += soft_spi
FEAUTRES_PROVIDED += periph_spi
endif

ifneq (,$(filter sx126%,$(USEMODULE)))
USEMODULE += sx126x
endif
Expand Down
100 changes: 61 additions & 39 deletions drivers/include/soft_spi.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,26 @@
*
* This module provides a software implemented Serial Peripheral Interface bus.
* It is intended to be used in situation where hardware spi is not available.
* The signatures of the functions are similar to the functions declared in spi.h
* The clock speed is approximated by using xtimer_usleep.
* Currently only the use of MOSI in master mode is implemented. Therefore receiving
* data from a slave is currently not possible.
* The signatures of the functions are identical to the functions declared in
* `spi.h`. The clock speed is approximated by using `ztimer_sleep()` with
* `ZTIMER_USEC` as clock.
*
* To use the software SPI as drop-in replacement for `periph_spi`, add the
* following to your application's Makefile:
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* USEMODULE += soft_spi_as_periph_spi
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* This will hook up the functions defined here into the `periph_spi` interface,
* so that a call to e.g. `spi_acquire()` becomes an alias for
* `soft_spi_acquire()`. Hence, it is not possible to real `periph_spi` and
* `soft_spi_as_periph_spi` at the same time. Using `soft_spi_as_periph_spi`
* will therefore disable any other `periph_spi` implementation, when used.
*
* Without `soft_spi_as_periph_spi`, you can use both `soft_spi` and
* `periph_spi` at the same time.
*
* @{
*
* @file
Expand All @@ -28,14 +44,19 @@
#ifndef SOFT_SPI_H
#define SOFT_SPI_H

#include "board.h"
#include "mutex.h"
#include "periph/gpio.h"
#include "periph/spi.h"
#include "mutex.h"

#ifdef __cplusplus
extern "C" {
#endif

#ifndef SOFT_SPI_NUMOF
#define SOFT_SPI_NUMOF 1 /**< Number of soft SPI interfaces */
#endif

/**
* @defgroup drivers_softspi_config Software SPI driver compile configuration
* @ingroup config_drivers_soft_periph
Expand Down Expand Up @@ -78,48 +99,45 @@ typedef gpio_t soft_spi_cs_t;
* @brief Status codes used by the SPI driver interface
*/
enum {
SOFT_SPI_OK = 0, /**< everything went as planned */
SOFT_SPI_NODEV = -1, /**< invalid SPI bus specified */
SOFT_SPI_NOCS = -2, /**< invalid chip select line specified */
SOFT_SPI_NOMODE = -3, /**< selected mode is not supported */
SOFT_SPI_NOCLK = -4 /**< selected clock value is not supported */
SOFT_SPI_OK = SPI_OK, /**< everything went as planned */
SOFT_SPI_NODEV = SPI_NODEV, /**< invalid SPI bus specified */
SOFT_SPI_NOCS = SPI_NOCS, /**< invalid chip select line specified */
SOFT_SPI_NOMODE = SPI_NOMODE, /**< selected mode is not supported */
SOFT_SPI_NOCLK = SPI_NOCLK /**< selected clock value is not supported */
};

/**
* @brief Available SPI modes, defining the configuration of clock polarity
* and clock phase
*
* RIOT is using the mode numbers as commonly defined by most vendors
* (https://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus#Mode_numbers):
*
* - MODE_0: CPOL=0, CPHA=0 - The first data bit is sampled by the receiver on
* the first SCK rising SCK edge (this mode is used most often).
* - MODE_1: CPOL=0, CPHA=1 - The first data bit is sampled by the receiver on
* the second rising SCK edge.
* - MODE_2: CPOL=1, CPHA=0 - The first data bit is sampled by the receiver on
* the first falling SCK edge.
* - MODE_3: CPOL=1, CPHA=1 - The first data bit is sampled by the receiver on
* the second falling SCK edge.
* @deprecated Directly use spi_mode_t instead
*/
typedef enum {
SOFT_SPI_MODE_0 = 0, /**< CPOL=0, CPHA=0 */
SOFT_SPI_MODE_1, /**< CPOL=0, CPHA=1 */
SOFT_SPI_MODE_2, /**< CPOL=1, CPHA=0 */
SOFT_SPI_MODE_3 /**< CPOL=1, CPHA=1 */
} soft_spi_mode_t;
typedef spi_mode_t soft_spi_mode_t;

/**
* @name Deprecated aliases
* @{
*/
#define SOFT_SPI_MODE_0 SPI_MODE_0 /**< Deprecated alias for SPI_MODE_0 */
#define SOFT_SPI_MODE_1 SPI_MODE_1 /**< Deprecated alias for SPI_MODE_1 */
#define SOFT_SPI_MODE_2 SPI_MODE_2 /**< Deprecated alias for SPI_MODE_2 */
#define SOFT_SPI_MODE_3 SPI_MODE_3 /**< Deprecated alias for SPI_MODE_3 */

#define SOFT_SPI_CLK_100KHZ SPI_CLK_100KHZ /**< Deprecated alias for SPI_CLK_100KHZ */
#define SOFT_SPI_CLK_400KHZ SPI_CLK_400KHZ /**< Deprecated alias for SPI_CLK_400KHZ */
#define SOFT_SPI_CLK_DEFAULT SPI_CLK_10MHZ /**< Deprecated alias for SPI_CLK_10MHZ */
/** @} */

/**
* @brief Available SPI clock speeds
*
* The actual speed of the bus varies between CPUs and depends on the speed
* of the processing. The values of the enum entries represent the approximate
* delay between two clock edges.
*
* @deprecated Directly use spi_clk_t instead
*/
typedef enum {
SOFT_SPI_CLK_100KHZ = 5, /**< drive the SPI bus with less than 100kHz */
SOFT_SPI_CLK_1MHZ = 1, /**< drive the SPI bus with less than 1MHz */
SOFT_SPI_CLK_DEFAULT = 0, /**< drive the SPI bus with maximum speed possible */
} soft_spi_clk_t;
typedef spi_clk_t soft_spi_clk_t;

/**
* @brief Software SPI port descriptor
Expand All @@ -128,8 +146,9 @@ typedef struct {
gpio_t miso_pin; /**< MOSI pin */
gpio_t mosi_pin; /**< MOSI pin */
gpio_t clk_pin; /**< CLK pin */
soft_spi_mode_t soft_spi_mode; /**< data and clock polarity */
soft_spi_clk_t soft_spi_clk; /**< clock speed */
spi_mode_t soft_spi_mode; /**< data and clock polarity */
uint16_t sleep_us; /**< microseconds before toggling the clock
* pin */
} soft_spi_conf_t;

/**
Expand Down Expand Up @@ -168,9 +187,9 @@ void soft_spi_init_pins(soft_spi_t bus);
* @param[in] bus SPI device that is used with the given CS line
* @param[in] cs chip select pin to initialize
*
* @return SOFT_SPI_OK on success
* @return SOFT_SPI_NODEV on invalid device
* @return SOFT_SPI_NOCS on invalid CS pin/line
* @retval 0 success
* @retval -ENXIO invalid device
* @retval -EINVAL invalid CS pin/line
*/
int soft_spi_init_cs(soft_spi_t bus, soft_spi_cs_t cs);

Expand All @@ -184,6 +203,9 @@ int soft_spi_init_cs(soft_spi_t bus, soft_spi_cs_t cs);
*
* @note This function expects the @p bus and the @p cs parameters to be
* valid (they are checked in soft_spi_init and soft_spi_init_cs before)
* @warning For clock speeds higher than 400 kHz in @p clk, the SPI is driven as fast as the
* implementation can manage. Don't expect the soft SPI to be able to compete with
* peripheral SPI implementations in clock speed.
*
* @param[in] bus SPI device to access
* @param[in] cs chip select pin/line to use
Expand Down Expand Up @@ -227,7 +249,7 @@ uint8_t soft_spi_transfer_byte(soft_spi_t bus, soft_spi_cs_t cs, bool cont, uint
* @param[in] len number of bytes to transfer
*/
void soft_spi_transfer_bytes(soft_spi_t bus, soft_spi_cs_t cs, bool cont,
const void *out, void *in, size_t len);
const void *out, void *in, size_t len);

/**
* @brief Transfer one byte to/from a given register address
Expand Down Expand Up @@ -258,7 +280,7 @@ uint8_t soft_spi_transfer_reg(soft_spi_t bus, soft_spi_cs_t cs, uint8_t reg, uin
* @param[in] len number of bytes to transfer
*/
void soft_spi_transfer_regs(soft_spi_t bus, soft_spi_cs_t cs, uint8_t reg,
const void *out, void *in, size_t len);
const void *out, void *in, size_t len);

#ifdef __cplusplus
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/periph_common/Kconfig.spi
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ menuconfig MODULE_PERIPH_SPI
depends on HAS_PERIPH_SPI
select MODULE_PERIPH_COMMON

if MODULE_PERIPH_SPI
if MODULE_PERIPH_SPI && !MODULE_SOFT_SPI_AS_PERIPH_SPI

config MODULE_PERIPH_INIT_SPI
bool "Auto initialize SPI peripheral"
Expand Down
9 changes: 9 additions & 0 deletions drivers/periph_common/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
#ifdef MODULE_PERIPH_INIT_SPI
#include "periph/spi.h"
#endif
#ifdef MODULE_PERIPH_INIT_SOFT_SPI
#include "soft_spi.h"
#endif
#ifdef MODULE_PERIPH_INIT_RTC
#include "periph/rtc.h"
#endif
Expand Down Expand Up @@ -77,6 +80,12 @@ void periph_init(void)
}
#endif

#ifdef MODULE_PERIPH_INIT_SOFT_SPI
for (unsigned i = 0; i < SOFT_SPI_NUMOF; i++) {
soft_spi_init(SOFT_SPI_DEV(i));
}
#endif

/* Initialize RTT before RTC to allow for RTT based RTC implementations */
#ifdef MODULE_PERIPH_INIT_RTT
rtt_init();
Expand Down
4 changes: 4 additions & 0 deletions drivers/periph_common/spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include "cpu.h"
#include "periph/spi.h"

#if defined(SPI_NUMOF) && !defined(MODULE_SOFT_SPI_AS_PERIPH_SPI)
Comment thread
jeandudey marked this conversation as resolved.

#ifdef PERIPH_SPI_NEEDS_INIT_CS
int spi_init_cs(spi_t bus, spi_cs_t cs)
{
Expand Down Expand Up @@ -67,3 +69,5 @@ void spi_transfer_regs(spi_t bus, spi_cs_t cs,
spi_transfer_bytes(bus, cs, false, out, in, len);
}
#endif

#endif
8 changes: 7 additions & 1 deletion drivers/soft_spi/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,10 @@ config MODULE_SOFT_SPI
depends on HAS_PERIPH_GPIO
depends on TEST_KCONFIG
select MODULE_PERIPH_GPIO
select MODULE_XTIMER
select MODULE_ZTIMER
select ZTIMER_USEC

config MODULE_SOFT_SPI_AS_PERIPH_SPI
bool "Use the software-implemented SPI to provide the peripheral SPI API"
select MODULE_SOFT_SPI
select HAS_PERIPH_SPI
6 changes: 5 additions & 1 deletion drivers/soft_spi/Makefile.dep
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
FEATURES_REQUIRED += periph_gpio
USEMODULE += xtimer
USEMODULE += ztimer_usec

ifneq (,$(filter periph_init,$(USEMODULE)))
USEMODULE += periph_init_soft_spi
endif
Loading