PebbleOS v4.43.0-108-gde23235b2
Loading...
Searching...
No Matches

SPI controller class. More...

Modules

 nRF5 SPI
 SPI bus driver for the nRF5 SPIM peripheral.
 

Data Structures

struct  pbl_spi_xfer
 A full-duplex transfer. More...
 
struct  pbl_spi_bus_ops
 Bus driver operations. More...
 
struct  pbl_spi_bus
 An SPI controller. More...
 
struct  pbl_spi_dev
 A peripheral on a bus. More...
 

Macros

#define PBL_SPI_DEV(_bus, _cs, _max_hz, _mode)    {.bus = (_bus), .cs = (_cs), .mode = (_mode), .max_hz = (_max_hz)}
 Initializer for a struct pbl_spi_dev.
 
#define PBL_SPI_BUS_STATE_DEFINE(sym, ...)
 Define the class state of bus sym, for the PBL_SPI_*_DEFINE() macro of a driver.
 
#define PBL_SPI_BUS_INIT(sym, _name, _ops, _deps)
 Initializer for the struct pbl_spi_bus of bus sym.
 

Typedefs

typedef void(* pbl_spi_callback_t) (int status, void *arg)
 Completion callback of pbl_spi_transfer_async().
 

Functions

int pbl_spi_bus_init (const struct pbl_device *dev)
 Device init of every bus: sets the class state up, then calls the driver's init.
 
void pbl_spi_bus_complete (const struct pbl_spi_bus *bus, int status)
 Report the outcome of the transfer in flight.
 
int pbl_spi_setup (const struct pbl_spi_dev *dev)
 Set a device up: checks its chip select and mode, and drives its chip select inactive.
 
int pbl_spi_transfer_async (const struct pbl_spi_dev *dev, const struct pbl_spi_xfer *xfers, size_t num_xfers, pbl_spi_callback_t cb, void *arg)
 Run transfers with a device, returning once they have started.
 
int pbl_spi_transfer (const struct pbl_spi_dev *dev, const struct pbl_spi_xfer *xfers, size_t num_xfers)
 Run transfers with a device.
 
static int pbl_spi_write (const struct pbl_spi_dev *dev, const void *buf, uint32_t len)
 Write data.
 
static int pbl_spi_read (const struct pbl_spi_dev *dev, void *buf, uint32_t len)
 Read data, writing zeros.
 
static int pbl_spi_write_read (const struct pbl_spi_dev *dev, const void *wbuf, uint32_t wlen, void *rbuf, uint32_t rlen)
 Write data, then read data.
 

Variables

const struct pbl_device_class pbl_spi_bus_class
 Class of the SPI buses.
 

Mode flags

#define PBL_SPI_CPHA   PBL_BIT(0)
 Sample on the trailing clock edge.
 
#define PBL_SPI_CPOL   PBL_BIT(1)
 Clock idles high.
 
#define PBL_SPI_MODE_0   0U
 Mode 0: clock idles low, sample on the leading edge.
 
#define PBL_SPI_MODE_1   PBL_SPI_CPHA
 Mode 1: clock idles low, sample on the trailing edge.
 
#define PBL_SPI_MODE_2   PBL_SPI_CPOL
 Mode 2: clock idles high, sample on the leading edge.
 
#define PBL_SPI_MODE_3   (PBL_SPI_CPOL | PBL_SPI_CPHA)
 Mode 3: clock idles high, sample on the trailing edge.
 
#define PBL_SPI_CS_HIGH   PBL_BIT(2)
 Chip select is active high.
 
#define PBL_SPI_LSB_FIRST   PBL_BIT(3)
 Send the least significant bit of each byte first.
 

Detailed Description

SPI controller class.

An SPI controller is a struct pbl_spi_bus device with a list of chip select GPIOs, and a peripheral on it a struct pbl_spi_dev: bus, chip select index, maximum clock frequency and mode. A transfer is a list of full-duplex transfers sent with the chip select asserted throughout; each one writes tx_buf, or zeros if it is NULL, and reads into rx_buf unless it is NULL. As in Linux, chip selects are active low unless the device sets PBL_SPI_CS_HIGH, whatever the polarity flag of the chip select GPIO. A consumer calls pbl_spi_setup() once, before its first transfer, which also drives the chip select inactive:

static const struct pbl_spi_dev s_lcd =
PBL_SPI_DEV(&s_spi3.bus, 0, 1000000, PBL_SPI_MODE_0 | PBL_SPI_CS_HIGH);
ret = pbl_spi_setup(&s_lcd);
if (ret != 0) {
return ret;
}
uint8_t cmd[] = {0x04, 0x00};
struct pbl_spi_xfer xfer = {.tx_buf = cmd, .len = sizeof(cmd)};
return pbl_spi_transfer(&s_lcd, &xfer, 1U);
const void * tx_buf
Data to write, or NULL to write zeros.
Definition spi.h:78
A peripheral on a bus.
Definition spi.h:154
A full-duplex transfer.
Definition spi.h:76
int pbl_spi_transfer(const struct pbl_spi_dev *dev, const struct pbl_spi_xfer *xfers, size_t num_xfers)
Run transfers with a device.
int pbl_spi_setup(const struct pbl_spi_dev *dev)
Set a device up: checks its chip select and mode, and drives its chip select inactive.
#define PBL_SPI_CS_HIGH
Chip select is active high.
Definition spi.h:70
#define PBL_SPI_DEV(_bus, _cs, _max_hz, _mode)
Initializer for a struct pbl_spi_dev.
Definition spi.h:173
#define PBL_SPI_MODE_0
Mode 0: clock idles low, sample on the leading edge.
Definition spi.h:62

pbl_spi_transfer() blocks the calling task until the transfer is done. pbl_spi_transfer_async() returns once it has started and reports the outcome to a callback run from the controller's interrupt; the transfers and their buffers must stay valid until then. Transfers are serialized per bus, must not be issued from ISRs, and the controller is powered for the duration of each.

Calls return 0 or a negative errno: -EINVAL for an invalid transfer or one the controller cannot issue, e.g. a buffer it cannot reach, and -ENODEV if the bus is not ready.


Data Structure Documentation

◆ pbl_spi_xfer

struct pbl_spi_xfer

A full-duplex transfer.

Data Fields
uint32_t len Number of bytes, at least 1.
void * rx_buf Buffer to read into, or NULL to discard the data read.
const void * tx_buf Data to write, or NULL to write zeros.

◆ pbl_spi_bus

struct pbl_spi_bus

An SPI controller.

Data Fields
const struct pbl_gpio * cs_gpios Chip select GPIOs, set from the controller's interrupt; unconnected ones are not driven.
struct pbl_device dev Device.
uint8_t num_cs Number of chip selects.
const struct pbl_spi_bus_ops * ops Driver operations.
struct pbl_spi_bus_state * state Runtime state.

◆ pbl_spi_dev

struct pbl_spi_dev

A peripheral on a bus.

Data Fields
const struct pbl_spi_bus * bus Bus.
uint8_t cs Chip select index.
uint32_t max_hz Maximum clock frequency, in Hz.
uint32_t mode Mode flags.

Macro Definition Documentation

◆ PBL_SPI_BUS_INIT

#define PBL_SPI_BUS_INIT (   sym,
  _name,
  _ops,
  _deps 
)
Value:
{ \
.dev = \
PBL_DEVICE_INIT_CLASS(sym, _name, pbl_spi_bus_init, nullptr, _deps, &pbl_spi_bus_class), \
.ops = (_ops), \
.state = &sym##_spi_state, \
.cs_gpios = sym##_cs_gpios, \
.num_cs = ARRAY_LENGTH(sym##_cs_gpios), \
}
const struct pbl_device_class pbl_spi_bus_class
Class of the SPI buses.
int pbl_spi_bus_init(const struct pbl_device *dev)
Device init of every bus: sets the class state up, then calls the driver's init.
#define ARRAY_LENGTH(array)
Calculate the length of an array, based on the size of the element type.
Definition size.h:18

Initializer for the struct pbl_spi_bus of bus sym.

Parameters
symSymbol of the bus instance, with its state defined by PBL_SPI_BUS_STATE_DEFINE().
_nameName.
_opsDriver operations.
_depsDependencies from PBL_DEVICE_DEPS(), or NULL.

◆ PBL_SPI_BUS_STATE_DEFINE

#define PBL_SPI_BUS_STATE_DEFINE (   sym,
  ... 
)
Value:
static struct pbl_spi_bus_state sym##_spi_state; \
static const struct pbl_gpio sym##_cs_gpios[] = {__VA_ARGS__}
#define PBL_DEVICE_STATE_DEFINE(sym)
Define the runtime state of device instance sym.
Definition device.h:109
A pin as wired on the board.
Definition gpio.h:132

Define the class state of bus sym, for the PBL_SPI_*_DEFINE() macro of a driver.

Parameters
symSymbol of the bus instance.
...Chip select GPIOs, from PBL_GPIO().

◆ PBL_SPI_CPHA

#define PBL_SPI_CPHA   PBL_BIT(0)

Sample on the trailing clock edge.

◆ PBL_SPI_CPOL

#define PBL_SPI_CPOL   PBL_BIT(1)

Clock idles high.

◆ PBL_SPI_CS_HIGH

#define PBL_SPI_CS_HIGH   PBL_BIT(2)

Chip select is active high.

◆ PBL_SPI_DEV

#define PBL_SPI_DEV (   _bus,
  _cs,
  _max_hz,
  _mode 
)     {.bus = (_bus), .cs = (_cs), .mode = (_mode), .max_hz = (_max_hz)}

Initializer for a struct pbl_spi_dev.

Parameters
_busBus.
_csChip select index.
_max_hzMaximum clock frequency, in Hz.
_modeMode flags.

◆ PBL_SPI_LSB_FIRST

#define PBL_SPI_LSB_FIRST   PBL_BIT(3)

Send the least significant bit of each byte first.

◆ PBL_SPI_MODE_0

#define PBL_SPI_MODE_0   0U

Mode 0: clock idles low, sample on the leading edge.

◆ PBL_SPI_MODE_1

#define PBL_SPI_MODE_1   PBL_SPI_CPHA

Mode 1: clock idles low, sample on the trailing edge.

◆ PBL_SPI_MODE_2

#define PBL_SPI_MODE_2   PBL_SPI_CPOL

Mode 2: clock idles high, sample on the leading edge.

◆ PBL_SPI_MODE_3

#define PBL_SPI_MODE_3   (PBL_SPI_CPOL | PBL_SPI_CPHA)

Mode 3: clock idles high, sample on the trailing edge.

Typedef Documentation

◆ pbl_spi_callback_t

typedef void(* pbl_spi_callback_t) (int status, void *arg)

Completion callback of pbl_spi_transfer_async().

Runs from the controller's interrupt, with the bus released.

Parameters
status0 or a negative errno.
argCallback argument.

Function Documentation

◆ pbl_spi_bus_complete()

void pbl_spi_bus_complete ( const struct pbl_spi_bus *  bus,
int  status 
)

Report the outcome of the transfer in flight.

Called by the bus driver from its interrupt handler. Starts the next transfer, or ends the sequence and calls its callback.

Parameters
busBus.
status0 or a negative errno.

◆ pbl_spi_bus_init()

int pbl_spi_bus_init ( const struct pbl_device *  dev)

Device init of every bus: sets the class state up, then calls the driver's init.

Parameters
devBus device.
Returns
0 or a negative errno.

◆ pbl_spi_read()

static int pbl_spi_read ( const struct pbl_spi_dev *  dev,
void *  buf,
uint32_t  len 
)
inlinestatic

Read data, writing zeros.

Parameters
devDevice.
[out]bufBuffer.
lenNumber of bytes.
Returns
0 or a negative errno.

References pbl_spi_xfer::len, pbl_spi_transfer(), and pbl_spi_xfer::rx_buf.

◆ pbl_spi_setup()

int pbl_spi_setup ( const struct pbl_spi_dev *  dev)

Set a device up: checks its chip select and mode, and drives its chip select inactive.

Parameters
devDevice.
Returns
0 or a negative errno.

◆ pbl_spi_transfer()

int pbl_spi_transfer ( const struct pbl_spi_dev *  dev,
const struct pbl_spi_xfer *  xfers,
size_t  num_xfers 
)

Run transfers with a device.

Parameters
devDevice.
xfersTransfers.
num_xfersNumber of transfers.
Returns
0 or a negative errno.

Referenced by pbl_spi_read(), pbl_spi_write(), and pbl_spi_write_read().

◆ pbl_spi_transfer_async()

int pbl_spi_transfer_async ( const struct pbl_spi_dev *  dev,
const struct pbl_spi_xfer *  xfers,
size_t  num_xfers,
pbl_spi_callback_t  cb,
void *  arg 
)

Run transfers with a device, returning once they have started.

Parameters
devDevice.
xfersTransfers, valid until cb is called.
num_xfersNumber of transfers.
cbCompletion callback.
argCallback argument.
Returns
0 if cb will be called, or a negative errno.

◆ pbl_spi_write()

static int pbl_spi_write ( const struct pbl_spi_dev *  dev,
const void *  buf,
uint32_t  len 
)
inlinestatic

Write data.

Parameters
devDevice.
bufData.
lenNumber of bytes.
Returns
0 or a negative errno.

References pbl_spi_xfer::len, pbl_spi_transfer(), and pbl_spi_xfer::tx_buf.

◆ pbl_spi_write_read()

static int pbl_spi_write_read ( const struct pbl_spi_dev *  dev,
const void *  wbuf,
uint32_t  wlen,
void *  rbuf,
uint32_t  rlen 
)
inlinestatic

Write data, then read data.

Parameters
devDevice.
wbufData to write.
wlenNumber of bytes to write.
[out]rbufBuffer to read into.
rlenNumber of bytes to read.
Returns
0 or a negative errno.

References pbl_spi_transfer(), and pbl_spi_xfer::tx_buf.

Variable Documentation

◆ pbl_spi_bus_class

const struct pbl_device_class pbl_spi_bus_class
extern

Class of the SPI buses.