Mbed OS Reference
Loading...
Searching...
No Matches
spi_api.h
1
2/** \addtogroup hal */
3/** @{*/
4/* mbed Microcontroller Library
5 * Copyright (c) 2006-2013 ARM Limited
6 * SPDX-License-Identifier: Apache-2.0
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20#ifndef MBED_SPI_API_H
21#define MBED_SPI_API_H
22
23#include "device.h"
24#include "pinmap.h"
25#include "hal/dma_api.h"
26#include "hal/buffer.h"
27
28#include <stdbool.h>
29
30#if DEVICE_SPI
31
32/**
33 * @defgroup hal_SPIEvents SPI Events Macros
34 *
35 * @{
36 */
37
38/**
39 * Indicates that some kind of error occurred when starting the transfer.
40 */
41#define SPI_EVENT_ERROR (1 << 1)
42
43/**
44 * Indicates that the transfer completed successfully.
45 */
46#define SPI_EVENT_COMPLETE (1 << 2)
47
48/**
49 * Indicates an Rx overflow: the interrupt system or DMA controller was not able to
50 * keep up with the flow of bytes from the SPI peripheral and data was lost.
51 */
52#define SPI_EVENT_RX_OVERFLOW (1 << 3)
53
54/**
55 * Union of all of the above events.
56 */
57#define SPI_EVENT_ALL (SPI_EVENT_ERROR | SPI_EVENT_COMPLETE | SPI_EVENT_RX_OVERFLOW)
58
59/// @}
60
61#define SPI_EVENT_INTERNAL_TRANSFER_COMPLETE (1 << 30) // Internal flag to report that an event occurred
62
63#define SPI_FILL_WORD (0xFFFF)
64#define SPI_FILL_CHAR (0xFF)
65
66#if DEVICE_SPI_ASYNCH
67/** Asynch SPI HAL structure
68 */
69typedef struct {
70 struct spi_s spi; /**< Target specific SPI structure */
71 struct buffer_s tx_buff; /**< Tx buffer */
72 struct buffer_s rx_buff; /**< Rx buffer */
73} spi_t;
74
75#else
76/** Non-asynch SPI HAL structure
77 */
78typedef struct spi_s spi_t;
79
80#endif
81
82typedef struct {
83 int peripheral;
84 PinName mosi_pin;
85 int mosi_function;
86 PinName miso_pin;
87 int miso_function;
88 PinName sclk_pin;
89 int sclk_function;
90 PinName ssel_pin;
91 int ssel_function;
93
94/**
95 * Describes the capabilities of a SPI peripherals
96 */
97typedef struct {
98 /** Minimum frequency supported must be set by target device and it will be assessed during
99 * testing.
100 */
102 /** Maximum frequency supported must be set by target device and it will be assessed during
103 * testing.
104 */
106 /** Each bit represents the corresponding word length. lsb => 1bit, msb => 32bit. */
107 uint32_t word_length;
108 uint16_t slave_delay_between_symbols_ns; /**< specifies required number of ns between transmission of successive symbols in slave mode. */
109 uint8_t clk_modes; /**< specifies supported modes from spi_mode_t. Each bit represents the corresponding mode. */
110 bool support_slave_mode; /**< If true, the device can handle SPI slave mode using hardware management on the specified ssel pin. */
111 bool hw_cs_handle; /**< If true, in SPI master mode Chip Select can be handled by hardware. */
112 bool async_mode; /**< If true, in async mode is supported. */
113 bool tx_rx_buffers_equal_length; /**< If true, rx and tx buffers must have the same length. */
115
116#ifdef __cplusplus
117extern "C" {
118#endif
119
120/**
121 * \defgroup hal_GeneralSPI SPI Configuration Functions
122 *
123 * # Defined behavior
124 * * ::spi_init initializes the spi_t control structure
125 * * ::spi_init configures the pins used by SPI
126 * * ::spi_get_capabilities() fills the given `spi_capabilities_t` instance
127 * * ::spi_get_capabilities() should consider the `ssel` pin when evaluation the `support_slave_mode` and `hw_cs_handle` capability - TBD (basic test)
128 * * ::spi_get_capabilities(): if the given `ssel` pin cannot be managed by hardware, `support_slave_mode` and `hw_cs_handle` should be false - TBD (basic test)
129 * * At least a symbol width of 8bit must be supported
130 * * The supported frequency range must include the range [0.2..2] MHz
131 * * ::spi_free returns the pins owned by the SPI object to their reset state
132 * * ::spi_format sets the number of bits per frame
133 * * ::spi_format configures clock polarity and phase
134 * * ::spi_format configures master/slave mode
135 * * ::spi_frequency sets the SPI baud rate
136 * * ::spi_master_write writes a symbol out in master mode and receives a symbol
137 * * ::spi_master_block_write writes `tx_length` words to the bus
138 * * ::spi_master_block_write reads `rx_length` words from the bus
139 * * ::spi_master_block_write returns the maximum of tx_length and rx_length
140 * * ::spi_master_block_write specifies the write_fill which is default data transmitted while performing a read
141 * * ::spi_get_module returns the SPI module number - TBD (basic test)
142 * * ::spi_slave_read returns a received value out of the SPI receive buffer in slave mode - TBD (SPI slave test)
143 * * ::spi_slave_read blocks until a value is available - TBD (SPI slave test)
144 * * ::spi_slave_write writes a value to the SPI peripheral in slave mode - TBD (SPI slave test)
145 * * ::spi_slave_write blocks until the SPI peripheral can be written to - TBD (SPI slave test)
146 * * ::spi_busy returns non-zero if the peripheral is currently transmitting, 0 otherwise - TBD (basic test)
147 * * ::spi_master_transfer starts the SPI asynchronous transfer
148 * * ::spi_master_transfer writes `tx_len` words to the bus
149 * * ::spi_master_transfer reads `rx_len` words from the bus
150 * * ::spi_master_transfer specifies the bit width of buffer words
151 * * The callback given to ::spi_master_transfer is invoked when the transfer completes (with a success or an error)
152 * * ::spi_master_transfer specifies the logical OR of events to be registered
153 * * The ::spi_master_transfer function may use the `DMAUsage` hint to select the appropriate async algorithm - Not testable
154 * * ::spi_irq_handler_asynch reads the received values out of the RX FIFO
155 * * ::spi_irq_handler_asynch writes values into the TX FIFO
156 * * ::spi_irq_handler_asynch checks for transfer termination conditions, such as buffer overflows or transfer complete
157 * * ::spi_irq_handler_asynch returns event flags if a transfer termination condition was met, otherwise 0
158 * * ::spi_abort_asynch aborts an on-going async transfer
159 * * ::spi_active returns non-zero if the SPI port is active or zero if it is not
160 *
161 * # Undefined behavior
162 * * Calling ::spi_init multiple times on the same `spi_t` without ::spi_free
163 * * Calling any function other than ::spi_init on a non-initialized or freed `spi_t`
164 * * Passing pins that cannot be on the same peripheral
165 * * Passing an invalid pointer as `obj` to any function
166 * * Passing an invalid pointer as `handler` to ::spi_master_transfer
167 * * Calling ::spi_abort_asynch while no async transfer is being processed (no transfer or a synchronous transfer)
168 *
169 * @{
170 */
171
172/**
173 * \defgroup hal_GeneralSPI_tests SPI hal tests
174 * The SPI HAL tests ensure driver conformance to defined behaviour.
175 *
176 * To run the SPI hal tests use the command:
177 *
178 * mbed test -t <toolchain> -m <target> -n tests-mbed_hal_fpga_ci_test_shield-spi
179 *
180 */
181
182#ifdef DEVICE_SPI_COUNT
183/**
184 * Returns a variant of the SPIName enum uniquely identifying a SPI peripheral of the device.
185 * @param[in] mosi The pin to use for MOSI
186 * @param[in] miso The pin to use for MISO
187 * @param[in] sclk The pin to use for SCLK
188 * @return An SPI peripheral identifier
189 */
190SPIName spi_get_peripheral_name(PinName mosi, PinName miso, PinName mclk);
191#endif
192
193/**
194 * Fills the given spi_capabilities_t structure with the capabilities of the given peripheral.
195 */
196void spi_get_capabilities(PinName ssel, bool slave, spi_capabilities_t *cap);
197
198/** Initialize the SPI peripheral
199 *
200 * Configures the pins used by SPI and enables the peripheral.
201 *
202 * After this function is called by the driver layer, spi_format() and spi_frequency() will
203 * be called *before* the SPI bus is used.
204 *
205 * @param[out] obj The SPI object to initialize
206 * @param[in] pinmap pointer to structure which holds static pinmap
207 */
208void spi_init_direct(spi_t *obj, const spi_pinmap_t *pinmap);
209
210/** Initialize the SPI peripheral
211 *
212 * Configures the pins used by SPI and enables the peripheral
213 *
214 * After this function is called by the driver layer, spi_format() and spi_frequency() will
215 * be called *before* the SPI bus is used.
216 *
217 * @param[out] obj The SPI object to initialize
218 * @param[in] mosi The pin to use for MOSI
219 * @param[in] miso The pin to use for MISO
220 * @param[in] sclk The pin to use for SCLK
221 * @param[in] ssel The pin to use for SSEL
222 */
223void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel);
224
225/** Release a SPI object
226 *
227 * Return the pins owned by the SPI object to their reset state
228 * Disable the SPI peripheral
229 * Disable the SPI clock
230 * @param[in] obj The SPI object to deinitialize
231 */
232void spi_free(spi_t *obj);
233
234/** Configure the SPI format
235 *
236 * Set the number of bits per frame, configure clock polarity and phase, shift order and master/slave mode.
237 * The default bit order is MSB.
238 *
239 * This function shall NOT modify the SPI frequency if the SPI frequency has previously been set.
240 *
241 * @param[in,out] obj The SPI object to configure
242 * @param[in] bits The number of bits per frame
243 * @param[in] mode The SPI mode (clock polarity, phase, and shift direction)
244 * @param[in] slave Zero for master mode or non-zero for slave mode
245 */
246void spi_format(spi_t *obj, int bits, int mode, int slave);
247
248/** Set the SPI baud rate
249 *
250 * Actual frequency may differ from the desired frequency due to available dividers and bus clock
251 * Configures the SPI peripheral's baud rate
252 * @param[in,out] obj The SPI object to configure
253 * @param[in] hz The baud rate in Hz
254 */
255void spi_frequency(spi_t *obj, int hz);
256
257/**@}*/
258/**
259 * \defgroup SynchSPI Synchronous SPI Hardware Abstraction Layer
260 * @{
261 */
262
263/** Write a byte out in master mode and receive a value
264 *
265 * @param[in] obj The SPI peripheral to use for sending
266 * @param[in] value The value to send
267 * @return Returns the value received during send
268 */
269int spi_master_write(spi_t *obj, int value);
270
271/** Write a block out in master mode and receive a value
272 *
273 * The total number of bytes sent and received will be the maximum of
274 * tx_length and rx_length. The bytes written will be padded with the
275 * value 0xff.
276 *
277 * Note: Even if the word size / bits per frame is not 8, \c rx_length and \c tx_length
278 * still give lengths in bytes of input data, not numbers of words.
279 *
280 * @param[in] obj The SPI peripheral to use for sending
281 * @param[in] tx_buffer Pointer to the byte-array of data to write to the device
282 * @param[in] tx_length Number of bytes to write, may be zero
283 * @param[in] rx_buffer Pointer to the byte-array of data to read from the device
284 * @param[in] rx_length Number of bytes to read, may be zero
285 * @param[in] write_fill Default data transmitted while performing a read
286 * @returns
287 * The number of bytes written and read from the device. This is
288 * maximum of tx_length and rx_length.
289 */
290int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length, char write_fill);
291
292/** Check if a value is available to read
293 *
294 * @param[in] obj The SPI peripheral to check
295 * @return non-zero if a value is available
296 */
298
299/** Get a received value out of the SPI receive buffer in slave mode
300 *
301 * Blocks until a value is available
302 * @param[in] obj The SPI peripheral to read
303 * @return The value received
304 */
306
307/** Write a value to the SPI peripheral in slave mode
308 *
309 * Blocks until the SPI peripheral can be written to
310 * @param[in] obj The SPI peripheral to write
311 * @param[in] value The value to write
312 */
313void spi_slave_write(spi_t *obj, int value);
314
315/** Checks if the specified SPI peripheral is in use
316 *
317 * @param[in] obj The SPI peripheral to check
318 * @return non-zero if the peripheral is currently transmitting
319 */
320int spi_busy(spi_t *obj);
321
322/** Get the module number
323 *
324 * @param[in] obj The SPI peripheral to check
325 * @return The module number
326 */
327uint8_t spi_get_module(spi_t *obj);
328
329/** Get the pins that support SPI MOSI
330 *
331 * Return a PinMap array of pins that support SPI MOSI in
332 * master mode. The array is terminated with {NC, NC, 0}.
333 *
334 * @return PinMap array
335 */
337
338/** Get the pins that support SPI MISO
339 *
340 * Return a PinMap array of pins that support SPI MISO in
341 * master mode. The array is terminated with {NC, NC, 0}.
342 *
343 * @return PinMap array
344 */
346
347/** Get the pins that support SPI CLK
348 *
349 * Return a PinMap array of pins that support SPI CLK in
350 * master mode. The array is terminated with {NC, NC, 0}.
351 *
352 * @return PinMap array
353 */
355
356/** Get the pins that support SPI CS
357 *
358 * Return a PinMap array of pins that support SPI CS in
359 * master mode. The array is terminated with {NC, NC, 0}.
360 *
361 * @return PinMap array
362 */
364
365/** Get the pins that support SPI MOSI
366 *
367 * Return a PinMap array of pins that support SPI MOSI in
368 * slave mode. The array is terminated with {NC, NC, 0}.
369 *
370 * @return PinMap array
371 */
373
374/** Get the pins that support SPI MISO
375 *
376 * Return a PinMap array of pins that support SPI MISO in
377 * slave mode. The array is terminated with {NC, NC, 0}.
378 *
379 * @return PinMap array
380 */
382
383/** Get the pins that support SPI CLK
384 *
385 * Return a PinMap array of pins that support SPI CLK in
386 * slave mode. The array is terminated with {NC, NC, 0}.
387 *
388 * @return PinMap array
389 */
391
392/** Get the pins that support SPI CS
393 *
394 * Return a PinMap array of pins that support SPI CS in
395 * slave mode. The array is terminated with {NC, NC, 0}.
396 *
397 * @return PinMap array
398 */
400
401/**@}*/
402
403#if DEVICE_SPI_ASYNCH
404/**
405 * \defgroup AsynchSPI Asynchronous SPI Hardware Abstraction Layer
406 * @{
407 */
408
409/** Begin the asynchronous SPI transfer. Buffer pointers and lengths are specified in tx_buff and rx_buff.
410 *
411 * If the device has a data cache, the Tx data is guaranteed to have been flushed from the cache
412 * to main memory already. Additionally, the Rx buffer is guaranteed to be cache aligned, and will
413 * be invalidated by the SPI layer after the transfer is complete.
414 *
415 * @param[in] obj The SPI object that holds the transfer information
416 * @param[in] tx The transmit buffer
417 * @param[in] tx_length The number of bytes to transmit
418 * @param[in] rx The receive buffer
419 * @param[in] rx_length The number of bytes to receive
420 * @param[in] bit_width The bit width of buffer words
421 * @param[in] event The logical OR of events to be registered
422 * @param[in] handler SPI interrupt handler
423 * @param[in] hint A suggestion for how to use DMA with this transfer
424 *
425 * @return True if DMA was actually used for the transfer, false otherwise (if interrupts or another CPU-based
426 * method is used to do the transfer).
427 *
428 * @note On MCUs with a data cache, the return value is used to determine if a cache invalidation needs to be done
429 * after the transfer is complete. If this function returns true, the driver layer will cache invalidate the Rx buffer under
430 * the assumption that the data needs to be re-read from main memory. Be careful, because if the read was not actually
431 * done by DMA, and the rx data is in the CPU cache, this invalidation will corrupt it.
432 */
433bool spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length, uint8_t bit_width, uint32_t handler, uint32_t event, DMAUsage hint);
434
435/** The asynchronous IRQ handler
436 *
437 * Reads the received values out of the RX FIFO, writes values into the TX FIFO and checks for transfer termination
438 * conditions, such as buffer overflows or transfer complete.
439 * @param[in] obj The SPI object that holds the transfer information
440 * @return Event flags if a transfer termination condition was met; otherwise 0.
441 */
443
444/** Attempts to determine if the SPI peripheral is already in use
445 *
446 * If a temporary DMA channel has been allocated, peripheral is in use.
447 * If a permanent DMA channel has been allocated, check if the DMA channel is in use. If not, proceed as though no DMA
448 * channel were allocated.
449 * If no DMA channel is allocated, check whether tx and rx buffers have been assigned. For each assigned buffer, check
450 * if the corresponding buffer position is less than the buffer length. If buffers do not indicate activity, check if
451 * there are any bytes in the FIFOs.
452 * @param[in] obj The SPI object to check for activity
453 * @return Non-zero if the SPI port is active or zero if it is not.
454 */
455uint8_t spi_active(spi_t *obj);
456
457/** Abort an SPI transfer
458 *
459 * @param obj The SPI peripheral to stop
460 */
462
463
464#endif
465
466/**@}*/
467
468#ifdef __cplusplus
469}
470#endif // __cplusplus
471
472#endif // SPI_DEVICE
473
474#endif // MBED_SPI_API_H
475
476/** @}*/
uint32_t spi_irq_handler_asynch(spi_t *obj)
The asynchronous IRQ handler.
bool spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length, uint8_t bit_width, uint32_t handler, uint32_t event, DMAUsage hint)
Begin the asynchronous SPI transfer.
uint8_t spi_active(spi_t *obj)
Attempts to determine if the SPI peripheral is already in use.
void spi_abort_asynch(spi_t *obj)
Abort an SPI transfer.
int spi_slave_read(spi_t *obj)
Get a received value out of the SPI receive buffer in slave mode.
int spi_busy(spi_t *obj)
Checks if the specified SPI peripheral is in use.
const PinMap * spi_master_cs_pinmap(void)
Get the pins that support SPI CS.
const PinMap * spi_master_mosi_pinmap(void)
Get the pins that support SPI MOSI.
void spi_slave_write(spi_t *obj, int value)
Write a value to the SPI peripheral in slave mode.
int spi_master_write(spi_t *obj, int value)
Write a byte out in master mode and receive a value.
int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length, char write_fill)
Write a block out in master mode and receive a value.
const PinMap * spi_master_clk_pinmap(void)
Get the pins that support SPI CLK.
int spi_slave_receive(spi_t *obj)
Check if a value is available to read.
const PinMap * spi_slave_miso_pinmap(void)
Get the pins that support SPI MISO.
const PinMap * spi_slave_cs_pinmap(void)
Get the pins that support SPI CS.
const PinMap * spi_slave_mosi_pinmap(void)
Get the pins that support SPI MOSI.
const PinMap * spi_master_miso_pinmap(void)
Get the pins that support SPI MISO.
uint8_t spi_get_module(spi_t *obj)
Get the module number.
const PinMap * spi_slave_clk_pinmap(void)
Get the pins that support SPI CLK.
void spi_frequency(spi_t *obj, int hz)
Set the SPI baud rate.
void spi_free(spi_t *obj)
Release a SPI object.
void spi_init_direct(spi_t *obj, const spi_pinmap_t *pinmap)
Initialize the SPI peripheral.
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel)
Initialize the SPI peripheral.
void spi_format(spi_t *obj, int bits, int mode, int slave)
Configure the SPI format.
void spi_get_capabilities(PinName ssel, bool slave, spi_capabilities_t *cap)
Fills the given spi_capabilities_t structure with the capabilities of the given peripheral.
DMAUsage
Enumeration of possible DMA usage hints.
Definition: dma_api.h:32
Definition: pinmap.h:31
Generic buffer structure.
Definition: buffer.h:27
Describes the capabilities of a SPI peripherals.
Definition: spi_api.h:97
bool tx_rx_buffers_equal_length
If true, rx and tx buffers must have the same length.
Definition: spi_api.h:113
uint16_t slave_delay_between_symbols_ns
specifies required number of ns between transmission of successive symbols in slave mode.
Definition: spi_api.h:108
uint32_t word_length
Each bit represents the corresponding word length.
Definition: spi_api.h:107
bool async_mode
If true, in async mode is supported.
Definition: spi_api.h:112
uint8_t clk_modes
specifies supported modes from spi_mode_t.
Definition: spi_api.h:109
uint32_t maximum_frequency
Maximum frequency supported must be set by target device and it will be assessed during testing.
Definition: spi_api.h:105
bool hw_cs_handle
If true, in SPI master mode Chip Select can be handled by hardware.
Definition: spi_api.h:111
bool support_slave_mode
If true, the device can handle SPI slave mode using hardware management on the specified ssel pin.
Definition: spi_api.h:110
uint32_t minimum_frequency
Minimum frequency supported must be set by target device and it will be assessed during testing.
Definition: spi_api.h:101
Asynch SPI HAL structure.
Definition: spi_api.h:69