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 * @param[in,out] obj The SPI object to configure
239 * @param[in] bits The number of bits per frame
240 * @param[in] mode The SPI mode (clock polarity, phase, and shift direction)
241 * @param[in] slave Zero for master mode or non-zero for slave mode
242 */
243void spi_format(spi_t *obj, int bits, int mode, int slave);
244
245/** Set the SPI baud rate
246 *
247 * Actual frequency may differ from the desired frequency due to available dividers and bus clock
248 * Configures the SPI peripheral's baud rate
249 * @param[in,out] obj The SPI object to configure
250 * @param[in] hz The baud rate in Hz
251 */
252void spi_frequency(spi_t *obj, int hz);
253
254/**@}*/
255/**
256 * \defgroup SynchSPI Synchronous SPI Hardware Abstraction Layer
257 * @{
258 */
259
260/** Write a byte out in master mode and receive a value
261 *
262 * @param[in] obj The SPI peripheral to use for sending
263 * @param[in] value The value to send
264 * @return Returns the value received during send
265 */
266int spi_master_write(spi_t *obj, int value);
267
268/** Write a block out in master mode and receive a value
269 *
270 * The total number of bytes sent and received will be the maximum of
271 * tx_length and rx_length. The bytes written will be padded with the
272 * value 0xff.
273 *
274 * Note: Even if the word size / bits per frame is not 8, \c rx_length and \c tx_length
275 * still give lengths in bytes of input data, not numbers of words.
276 *
277 * @param[in] obj The SPI peripheral to use for sending
278 * @param[in] tx_buffer Pointer to the byte-array of data to write to the device
279 * @param[in] tx_length Number of bytes to write, may be zero
280 * @param[in] rx_buffer Pointer to the byte-array of data to read from the device
281 * @param[in] rx_length Number of bytes to read, may be zero
282 * @param[in] write_fill Default data transmitted while performing a read
283 * @returns
284 * The number of bytes written and read from the device. This is
285 * maximum of tx_length and rx_length.
286 */
287int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length, char write_fill);
288
289/** Check if a value is available to read
290 *
291 * @param[in] obj The SPI peripheral to check
292 * @return non-zero if a value is available
293 */
295
296/** Get a received value out of the SPI receive buffer in slave mode
297 *
298 * Blocks until a value is available
299 * @param[in] obj The SPI peripheral to read
300 * @return The value received
301 */
303
304/** Write a value to the SPI peripheral in slave mode
305 *
306 * Blocks until the SPI peripheral can be written to
307 * @param[in] obj The SPI peripheral to write
308 * @param[in] value The value to write
309 */
310void spi_slave_write(spi_t *obj, int value);
311
312/** Checks if the specified SPI peripheral is in use
313 *
314 * @param[in] obj The SPI peripheral to check
315 * @return non-zero if the peripheral is currently transmitting
316 */
317int spi_busy(spi_t *obj);
318
319/** Get the module number
320 *
321 * @param[in] obj The SPI peripheral to check
322 * @return The module number
323 */
324uint8_t spi_get_module(spi_t *obj);
325
326/** Get the pins that support SPI MOSI
327 *
328 * Return a PinMap array of pins that support SPI MOSI in
329 * master mode. The array is terminated with {NC, NC, 0}.
330 *
331 * @return PinMap array
332 */
334
335/** Get the pins that support SPI MISO
336 *
337 * Return a PinMap array of pins that support SPI MISO in
338 * master mode. The array is terminated with {NC, NC, 0}.
339 *
340 * @return PinMap array
341 */
343
344/** Get the pins that support SPI CLK
345 *
346 * Return a PinMap array of pins that support SPI CLK in
347 * master mode. The array is terminated with {NC, NC, 0}.
348 *
349 * @return PinMap array
350 */
352
353/** Get the pins that support SPI CS
354 *
355 * Return a PinMap array of pins that support SPI CS in
356 * master mode. The array is terminated with {NC, NC, 0}.
357 *
358 * @return PinMap array
359 */
361
362/** Get the pins that support SPI MOSI
363 *
364 * Return a PinMap array of pins that support SPI MOSI in
365 * slave mode. The array is terminated with {NC, NC, 0}.
366 *
367 * @return PinMap array
368 */
370
371/** Get the pins that support SPI MISO
372 *
373 * Return a PinMap array of pins that support SPI MISO in
374 * slave mode. The array is terminated with {NC, NC, 0}.
375 *
376 * @return PinMap array
377 */
379
380/** Get the pins that support SPI CLK
381 *
382 * Return a PinMap array of pins that support SPI CLK in
383 * slave mode. The array is terminated with {NC, NC, 0}.
384 *
385 * @return PinMap array
386 */
388
389/** Get the pins that support SPI CS
390 *
391 * Return a PinMap array of pins that support SPI CS in
392 * slave mode. The array is terminated with {NC, NC, 0}.
393 *
394 * @return PinMap array
395 */
397
398/**@}*/
399
400#if DEVICE_SPI_ASYNCH
401/**
402 * \defgroup AsynchSPI Asynchronous SPI Hardware Abstraction Layer
403 * @{
404 */
405
406/** Begin the asynchronous SPI transfer. Buffer pointers and lengths are specified in tx_buff and rx_buff.
407 *
408 * If the device has a data cache, the Tx data is guaranteed to have been flushed from the cache
409 * to main memory already. Additionally, the Rx buffer is guaranteed to be cache aligned, and will
410 * be invalidated by the SPI layer after the transfer is complete.
411 *
412 * @param[in] obj The SPI object that holds the transfer information
413 * @param[in] tx The transmit buffer
414 * @param[in] tx_length The number of bytes to transmit
415 * @param[in] rx The receive buffer
416 * @param[in] rx_length The number of bytes to receive
417 * @param[in] bit_width The bit width of buffer words
418 * @param[in] event The logical OR of events to be registered
419 * @param[in] handler SPI interrupt handler
420 * @param[in] hint A suggestion for how to use DMA with this transfer
421 *
422 * @return True if DMA was actually used for the transfer, false otherwise (if interrupts or another CPU-based
423 * method is used to do the transfer).
424 *
425 * @note On MCUs with a data cache, the return value is used to determine if a cache invalidation needs to be done
426 * after the transfer is complete. If this function returns true, the driver layer will cache invalidate the Rx buffer under
427 * the assumption that the data needs to be re-read from main memory. Be careful, because if the read was not actually
428 * done by DMA, and the rx data is in the CPU cache, this invalidation will corrupt it.
429 */
430bool 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);
431
432/** The asynchronous IRQ handler
433 *
434 * Reads the received values out of the RX FIFO, writes values into the TX FIFO and checks for transfer termination
435 * conditions, such as buffer overflows or transfer complete.
436 * @param[in] obj The SPI object that holds the transfer information
437 * @return Event flags if a transfer termination condition was met; otherwise 0.
438 */
440
441/** Attempts to determine if the SPI peripheral is already in use
442 *
443 * If a temporary DMA channel has been allocated, peripheral is in use.
444 * If a permanent DMA channel has been allocated, check if the DMA channel is in use. If not, proceed as though no DMA
445 * channel were allocated.
446 * If no DMA channel is allocated, check whether tx and rx buffers have been assigned. For each assigned buffer, check
447 * if the corresponding buffer position is less than the buffer length. If buffers do not indicate activity, check if
448 * there are any bytes in the FIFOs.
449 * @param[in] obj The SPI object to check for activity
450 * @return Non-zero if the SPI port is active or zero if it is not.
451 */
452uint8_t spi_active(spi_t *obj);
453
454/** Abort an SPI transfer
455 *
456 * @param obj The SPI peripheral to stop
457 */
459
460
461#endif
462
463/**@}*/
464
465#ifdef __cplusplus
466}
467#endif // __cplusplus
468
469#endif // SPI_DEVICE
470
471#endif // MBED_SPI_API_H
472
473/** @}*/
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