Loading...
Searching...
No Matches
spi.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#ifndef _HARDWARE_SPI_H
8#define _HARDWARE_SPI_H
9
10#include "pico.h"
11#include "hardware/structs/spi.h"
12#include "hardware/regs/dreq.h"
13
14// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_HARDWARE_SPI, Enable/disable assertions in the hardware_spi module, type=bool, default=0, group=hardware_spi
15#ifndef PARAM_ASSERTIONS_ENABLED_HARDWARE_SPI
16#ifdef PARAM_ASSERTIONS_ENABLED_SPI // backwards compatibility with SDK < 2.0.0
17#define PARAM_ASSERTIONS_ENABLED_HARDWARE_SPI PARAM_ASSERTIONS_ENABLED_SPI
18#else
19#define PARAM_ASSERTIONS_ENABLED_HARDWARE_SPI 0
20#endif
21#endif
22
23#ifdef __cplusplus
24extern "C" {
25#endif
26
41
42// PICO_CONFIG: PICO_DEFAULT_SPI, Define the default SPI for a board, min=0, max=1, default=Usually provided via board header, group=hardware_spi
43// PICO_CONFIG: PICO_DEFAULT_SPI_SCK_PIN, Define the default SPI SCK pin, min=0, max=47 on RP2350B, 29 otherwise, default=Usually provided via board header, group=hardware_spi
44// PICO_CONFIG: PICO_DEFAULT_SPI_TX_PIN, Define the default SPI TX pin, min=0, max=47 on RP2350B, 29 otherwise, default=Usually provided via board header, group=hardware_spi
45// PICO_CONFIG: PICO_DEFAULT_SPI_RX_PIN, Define the default SPI RX pin, min=0, max=47 on RP2350B, 29 otherwise, default=Usually provided via board header, group=hardware_spi
46// PICO_CONFIG: PICO_DEFAULT_SPI_CSN_PIN, Define the default SPI CSN pin, min=0, max=47 on RP2350B, 29 otherwise, default=Usually provided via board header, group=hardware_spi
47
51typedef struct spi_inst spi_inst_t;
52
59#define spi0 ((spi_inst_t *)spi0_hw)
60
67#define spi1 ((spi_inst_t *)spi1_hw)
68
75#if !defined(PICO_DEFAULT_SPI_INSTANCE) && defined(PICO_DEFAULT_SPI)
76#define PICO_DEFAULT_SPI_INSTANCE() (__CONCAT(spi,PICO_DEFAULT_SPI))
77#endif
78
85
92#ifdef PICO_DEFAULT_SPI_INSTANCE
93#define spi_default PICO_DEFAULT_SPI_INSTANCE()
94#endif
95
104#ifndef SPI_NUM
105static_assert(NUM_SPIS == 2, "");
106#define SPI_NUM(spi) ((spi) == spi1)
107#endif
108
117#ifndef SPI_INSTANCE
118static_assert(NUM_SPIS == 2, "");
119#define SPI_INSTANCE(num) ((num) ? spi1 : spi0)
120#endif
121
130#ifndef SPI_IS_INSTANCE
131static_assert(NUM_SPIS == 2, "");
132#define SPI_IS_INSTANCE(spi) ((spi) == spi0 || (spi) == spi1)
133#endif
134
135
145#ifndef SPI_DREQ_NUM
146static_assert(DREQ_SPI0_RX == DREQ_SPI0_TX + 1, "");
147static_assert(DREQ_SPI1_RX == DREQ_SPI1_TX + 1, "");
148static_assert(DREQ_SPI1_TX == DREQ_SPI0_TX + 2, "");
149#define SPI_DREQ_NUM(spi, is_tx) (DREQ_SPI0_TX + SPI_NUM(spi) * 2 + !(is_tx))
150#endif
151
160#ifndef SPI_RESET_NUM
161#include "hardware/resets.h"
162#define SPI_RESET_NUM(spi) (spi_get_index(spi) ? RESET_SPI1 : RESET_SPI0)
163#endif
164
168typedef enum {
169 SPI_CPHA_0 = 0,
170 SPI_CPHA_1 = 1
171} spi_cpha_t;
172
176typedef enum {
177 SPI_CPOL_0 = 0,
178 SPI_CPOL_1 = 1
179} spi_cpol_t;
180
184typedef enum {
185 SPI_LSB_FIRST = 0,
186 SPI_MSB_FIRST = 1
188
189// ----------------------------------------------------------------------------
190// Setup
191
205uint spi_init(spi_inst_t *spi, uint baudrate);
206
215void spi_deinit(spi_inst_t *spi);
216
227uint spi_set_baudrate(spi_inst_t *spi, uint baudrate);
228
237uint spi_get_baudrate(const spi_inst_t *spi);
238
245static inline uint spi_get_index(const spi_inst_t *spi) {
246 valid_params_if(HARDWARE_SPI, SPI_IS_INSTANCE(spi));
247 return SPI_NUM(spi);
248}
249
256static inline spi_inst_t *spi_get_instance(uint num) {
257 invalid_params_if(HARDWARE_SPI, num >= NUM_SPIS);
258 return SPI_INSTANCE(num);
259}
260
261static inline spi_hw_t *spi_get_hw(spi_inst_t *spi) {
262 valid_params_if(HARDWARE_SPI, SPI_IS_INSTANCE(spi));
263 return (spi_hw_t *)spi;
264}
265
266static inline const spi_hw_t *spi_get_const_hw(const spi_inst_t *spi) {
267 valid_params_if(HARDWARE_SPI, SPI_IS_INSTANCE(spi));
268 return (const spi_hw_t *)spi;
269}
270
282static inline void spi_set_format(spi_inst_t *spi, uint data_bits, spi_cpol_t cpol, spi_cpha_t cpha, __unused spi_order_t order) {
283 valid_params_if(HARDWARE_SPI, SPI_IS_INSTANCE(spi));
284 invalid_params_if(HARDWARE_SPI, data_bits < 4 || data_bits > 16);
285 // LSB-first not supported on PL022:
286 invalid_params_if(HARDWARE_SPI, order != SPI_MSB_FIRST);
287 invalid_params_if(HARDWARE_SPI, cpol != SPI_CPOL_0 && cpol != SPI_CPOL_1);
288 invalid_params_if(HARDWARE_SPI, cpha != SPI_CPHA_0 && cpha != SPI_CPHA_1);
289
290 // Disable the SPI
291 uint32_t enable_mask = spi_get_hw(spi)->cr1 & SPI_SSPCR1_SSE_BITS;
292 hw_clear_bits(&spi_get_hw(spi)->cr1, SPI_SSPCR1_SSE_BITS);
293
294 hw_write_masked(&spi_get_hw(spi)->cr0,
295 ((uint)(data_bits - 1)) << SPI_SSPCR0_DSS_LSB |
296 ((uint)cpol) << SPI_SSPCR0_SPO_LSB |
297 ((uint)cpha) << SPI_SSPCR0_SPH_LSB,
298 SPI_SSPCR0_DSS_BITS |
299 SPI_SSPCR0_SPO_BITS |
300 SPI_SSPCR0_SPH_BITS);
301
302 // Re-enable the SPI
303 hw_set_bits(&spi_get_hw(spi)->cr1, enable_mask);
304}
305
315static inline void spi_set_slave(spi_inst_t *spi, bool slave) {
316 valid_params_if(HARDWARE_SPI, SPI_IS_INSTANCE(spi));
317 // Disable the SPI
318 uint32_t enable_mask = spi_get_hw(spi)->cr1 & SPI_SSPCR1_SSE_BITS;
319 hw_clear_bits(&spi_get_hw(spi)->cr1, SPI_SSPCR1_SSE_BITS);
320
321 if (slave)
322 hw_set_bits(&spi_get_hw(spi)->cr1, SPI_SSPCR1_MS_BITS);
323 else
324 hw_clear_bits(&spi_get_hw(spi)->cr1, SPI_SSPCR1_MS_BITS);
325
326 // Re-enable the SPI
327 hw_set_bits(&spi_get_hw(spi)->cr1, enable_mask);
328}
329
330// ----------------------------------------------------------------------------
331// Generic input/output
332
339static inline bool spi_is_writable(const spi_inst_t *spi) {
340 valid_params_if(HARDWARE_SPI, SPI_IS_INSTANCE(spi));
341 return (spi_get_const_hw(spi)->sr & SPI_SSPSR_TNF_BITS);
342}
343
350static inline bool spi_is_readable(const spi_inst_t *spi) {
351 valid_params_if(HARDWARE_SPI, SPI_IS_INSTANCE(spi));
352 return (spi_get_const_hw(spi)->sr & SPI_SSPSR_RNE_BITS);
353}
354
361static inline bool spi_is_busy(const spi_inst_t *spi) {
362 valid_params_if(HARDWARE_SPI, SPI_IS_INSTANCE(spi));
363 return (spi_get_const_hw(spi)->sr & SPI_SSPSR_BSY_BITS);
364}
365
378int spi_write_read_blocking(spi_inst_t *spi, const uint8_t *src, uint8_t *dst, size_t len);
379
391int spi_write_blocking(spi_inst_t *spi, const uint8_t *src, size_t len);
392
408int spi_read_blocking(spi_inst_t *spi, uint8_t repeated_tx_data, uint8_t *dst, size_t len);
409
410// ----------------------------------------------------------------------------
411// SPI-specific operations and aliases
412
413// FIXME need some instance-private data for select() and deselect() if we are going that route
414
429int spi_write16_read16_blocking(spi_inst_t *spi, const uint16_t *src, uint16_t *dst, size_t len);
430
444int spi_write16_blocking(spi_inst_t *spi, const uint16_t *src, size_t len);
445
463int spi_read16_blocking(spi_inst_t *spi, uint16_t repeated_tx_data, uint16_t *dst, size_t len);
464
471static inline uint spi_get_dreq(spi_inst_t *spi, bool is_tx) {
472 return SPI_DREQ_NUM(spi, is_tx);
473}
474
475#ifdef __cplusplus
476}
477#endif
478
479#endif
static __force_inline void hw_set_bits(io_rw_32 *addr, uint32_t mask)
Atomically set the specified bits to 1 in a HW register.
Definition address_mapped.h:135
static __force_inline void hw_write_masked(io_rw_32 *addr, uint32_t values, uint32_t write_mask)
Set new values for a sub-set of the bits in a HW register.
Definition address_mapped.h:171
static __force_inline void hw_clear_bits(io_rw_32 *addr, uint32_t mask)
Atomically clear the specified bits to 0 in a HW register.
Definition address_mapped.h:145
@ DREQ_SPI1_TX
Select SPI1's TX FIFO as DREQ.
Definition dreq.h:108
@ DREQ_SPI1_RX
Select SPI1's RX FIFO as DREQ.
Definition dreq.h:109
@ DREQ_SPI0_RX
Select SPI0's RX FIFO as DREQ.
Definition dreq.h:107
@ DREQ_SPI0_TX
Select SPI0's TX FIFO as DREQ.
Definition dreq.h:106
static bool spi_is_writable(const spi_inst_t *spi)
Check whether a write can be done on SPI device.
Definition spi.h:339
static void spi_set_slave(spi_inst_t *spi, bool slave)
Set SPI master/slave.
Definition spi.h:315
static void spi_set_format(spi_inst_t *spi, uint data_bits, spi_cpol_t cpol, spi_cpha_t cpha, __unused spi_order_t order)
Configure SPI.
Definition spi.h:282
uint spi_init(spi_inst_t *spi, uint baudrate)
Initialise SPI instances.
Definition spi.c:21
static bool spi_is_readable(const spi_inst_t *spi)
Check whether a read can be done on SPI device.
Definition spi.h:350
uint spi_set_baudrate(spi_inst_t *spi, uint baudrate)
Set SPI baudrate.
Definition spi.c:42
#define SPI_NUM(spi)
Returns the SPI number for a SPI instance.
Definition spi.h:106
int spi_read_blocking(spi_inst_t *spi, uint8_t repeated_tx_data, uint8_t *dst, size_t len)
Read from an SPI device.
Definition spi.c:136
spi_cpol_t
Enumeration of SPI CPOL (clock polarity) values.
Definition spi.h:176
int spi_write_blocking(spi_inst_t *spi, const uint8_t *src, size_t len)
Write to an SPI device, blocking.
Definition spi.c:107
static bool spi_is_busy(const spi_inst_t *spi)
Check whether SPI is busy.
Definition spi.h:361
static uint spi_get_dreq(spi_inst_t *spi, bool is_tx)
Return the DREQ to use for pacing transfers to/from a particular SPI instance.
Definition spi.h:471
int spi_read16_blocking(spi_inst_t *spi, uint16_t repeated_tx_data, uint16_t *dst, size_t len)
Read from an SPI device.
Definition spi.c:203
static uint spi_get_index(const spi_inst_t *spi)
Convert SPI instance to hardware instance number.
Definition spi.h:245
spi_cpha_t
Enumeration of SPI CPHA (clock phase) values.
Definition spi.h:168
uint spi_get_baudrate(const spi_inst_t *spi)
Get SPI baudrate.
Definition spi.c:76
#define SPI_DREQ_NUM(spi, is_tx)
Returns the dreq_num_t used for pacing DMA transfers to or from this SPI instance....
Definition spi.h:149
spi_order_t
Enumeration of SPI bit-order values.
Definition spi.h:184
int spi_write_read_blocking(spi_inst_t *spi, const uint8_t *src, uint8_t *dst, size_t len)
Write/Read to/from an SPI device.
Definition spi.c:84
int spi_write16_blocking(spi_inst_t *spi, const uint16_t *src, size_t len)
Write to an SPI device.
Definition spi.c:178
int spi_write16_read16_blocking(spi_inst_t *spi, const uint16_t *src, uint16_t *dst, size_t len)
Write/Read half words to/from an SPI device.
Definition spi.c:156
#define SPI_INSTANCE(num)
Returns the SPI instance with the given SPI number.
Definition spi.h:119
static spi_inst_t * spi_get_instance(uint num)
Get the SPI instance from an instance number.
Definition spi.h:256
#define SPI_IS_INSTANCE(spi)
Returns true if the SPI instance is one of the h/w SPI instances.
Definition spi.h:132
void spi_deinit(spi_inst_t *spi)
Deinitialise SPI instances.
Definition spi.c:36
struct spi_inst spi_inst_t
Opaque type representing an SPI instance.
Definition spi.h:51
Definition spi.h:26