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 *
196 * @param ssel The CS pin being used, for checking the \c hw_cs_handle flag
197 * @param slave True to get capabilities for slave mode, false to get capabilities for master mode
198 * @param[out] cap Capabilities are returned here
199 */
200void spi_get_capabilities(PinName ssel, bool slave, spi_capabilities_t *cap);
201
202/** Initialize the SPI peripheral
203 *
204 * Configures the pins used by SPI and enables the peripheral.
205 *
206 * After this function is called by the driver layer, spi_format() and spi_frequency() will
207 * be called *before* the SPI bus is used.
208 *
209 * @param[out] obj The SPI object to initialize
210 * @param[in] pinmap pointer to structure which holds static pinmap
211 */
212void spi_init_direct(spi_t *obj, const spi_pinmap_t *pinmap);
213
214/** Initialize the SPI peripheral
215 *
216 * Configures the pins used by SPI and enables the peripheral
217 *
218 * After this function is called by the driver layer, spi_format() and spi_frequency() will
219 * be called *before* the SPI bus is used.
220 *
221 * @param[out] obj The SPI object to initialize
222 * @param[in] mosi The pin to use for MOSI
223 * @param[in] miso The pin to use for MISO
224 * @param[in] sclk The pin to use for SCLK
225 * @param[in] ssel The pin to use for SSEL
226 */
227void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel);
228
229/** Release a SPI object
230 *
231 * Return the pins owned by the SPI object to their reset state
232 * Disable the SPI peripheral
233 * Disable the SPI clock
234 * @param[in] obj The SPI object to deinitialize
235 */
236void spi_free(spi_t *obj);
237
238/** Configure the SPI format
239 *
240 * Set the number of bits per frame, configure clock polarity and phase, shift order and master/slave mode.
241 * The default bit order is MSB.
242 *
243 * This function shall NOT modify the SPI frequency if the SPI frequency has previously been set.
244 *
245 * @param[in,out] obj The SPI object to configure
246 * @param[in] bits The number of bits per frame
247 * @param[in] mode The SPI mode (clock polarity, phase, and shift direction)
248 * @param[in] slave Zero for master mode or non-zero for slave mode
249 */
250void spi_format(spi_t *obj, int bits, int mode, int slave);
251
252/** Set the SPI baud rate
253 *
254 * Actual frequency may differ from the desired frequency due to available dividers and bus clock
255 * Configures the SPI peripheral's baud rate
256 * @param[in,out] obj The SPI object to configure
257 * @param[in] hz The baud rate in Hz
258 */
259void spi_frequency(spi_t *obj, int hz);
260
261/**@}*/
262/**
263 * \defgroup SynchSPI Synchronous SPI Hardware Abstraction Layer
264 * @{
265 */
266
267/** Write a byte out in master mode and receive a value
268 *
269 * @param[in] obj The SPI peripheral to use for sending
270 * @param[in] value The value to send
271 * @return Returns the value received during send
272 */
273int spi_master_write(spi_t *obj, int value);
274
275/** Write a block out in master mode and receive a value
276 *
277 * The total number of bytes sent and received will be the maximum of
278 * tx_length and rx_length. The bytes written will be padded with the
279 * write fill value.
280 *
281 * Note: Even if the word size / bits per frame is not 8, \c rx_length and \c tx_length
282 * still give lengths in bytes of input data, not numbers of words.
283 *
284 * Note: If \c tx_rx_buffers_equal_length is true in the capabilities structure, then either \c rx_length and \c tx_length
285 * must be the same, or one of them will be zero. If this is not the case than the HAL implementation should
286 * return an error.
287 *
288 * @param[in] obj The SPI peripheral to use for sending
289 * @param[in] tx_buffer Pointer to the byte-array of data to write to the device
290 * @param[in] tx_length Number of bytes to write, may be zero
291 * @param[in] rx_buffer Pointer to the byte-array of data to read from the device
292 * @param[in] rx_length Number of bytes to read, may be zero
293 * @param[in] write_fill Default data transmitted while performing a read
294 * @returns
295 * The number of bytes written and read from the device. This is
296 * maximum of tx_length and rx_length.
297 */
298int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length, char write_fill);
299
300/** Check if a value is available to read
301 *
302 * @param[in] obj The SPI peripheral to check
303 * @return non-zero if a value is available
304 */
306
307/** Get a received value out of the SPI receive buffer in slave mode
308 *
309 * Blocks until a value is available
310 * @param[in] obj The SPI peripheral to read
311 * @return The value received
312 */
314
315/** Write a value to the SPI peripheral in slave mode
316 *
317 * Blocks until the SPI peripheral can be written to
318 * @param[in] obj The SPI peripheral to write
319 * @param[in] value The value to write
320 */
321void spi_slave_write(spi_t *obj, int value);
322
323/** Checks if the specified SPI peripheral is in use
324 *
325 * @param[in] obj The SPI peripheral to check
326 * @return non-zero if the peripheral is currently transmitting
327 */
328int spi_busy(spi_t *obj);
329
330/** Get the module number
331 *
332 * @param[in] obj The SPI peripheral to check
333 * @return The module number
334 */
335uint8_t spi_get_module(spi_t *obj);
336
337/** Get the pins that support SPI MOSI
338 *
339 * Return a PinMap array of pins that support SPI MOSI in
340 * master mode. The array is terminated with {NC, NC, 0}.
341 *
342 * @return PinMap array
343 */
345
346/** Get the pins that support SPI MISO
347 *
348 * Return a PinMap array of pins that support SPI MISO in
349 * master mode. The array is terminated with {NC, NC, 0}.
350 *
351 * @return PinMap array
352 */
354
355/** Get the pins that support SPI CLK
356 *
357 * Return a PinMap array of pins that support SPI CLK in
358 * master mode. The array is terminated with {NC, NC, 0}.
359 *
360 * @return PinMap array
361 */
363
364/** Get the pins that support SPI CS
365 *
366 * Return a PinMap array of pins that support SPI CS in
367 * master mode. The array is terminated with {NC, NC, 0}.
368 *
369 * @return PinMap array
370 */
372
373/** Get the pins that support SPI MOSI
374 *
375 * Return a PinMap array of pins that support SPI MOSI in
376 * slave mode. The array is terminated with {NC, NC, 0}.
377 *
378 * @return PinMap array
379 */
381
382/** Get the pins that support SPI MISO
383 *
384 * Return a PinMap array of pins that support SPI MISO in
385 * slave mode. The array is terminated with {NC, NC, 0}.
386 *
387 * @return PinMap array
388 */
390
391/** Get the pins that support SPI CLK
392 *
393 * Return a PinMap array of pins that support SPI CLK in
394 * slave mode. The array is terminated with {NC, NC, 0}.
395 *
396 * @return PinMap array
397 */
399
400/** Get the pins that support SPI CS
401 *
402 * Return a PinMap array of pins that support SPI CS in
403 * slave mode. The array is terminated with {NC, NC, 0}.
404 *
405 * @return PinMap array
406 */
408
409/**@}*/
410
411#if DEVICE_SPI_ASYNCH
412/**
413 * \defgroup AsynchSPI Asynchronous SPI Hardware Abstraction Layer
414 * @{
415 */
416
417/** Begin the asynchronous SPI transfer. Buffer pointers and lengths are specified in tx_buff and rx_buff.
418 *
419 * If the device has a data cache, the Tx data is guaranteed to have been flushed from the cache
420 * to main memory already. Additionally, the Rx buffer is guaranteed to be cache aligned, and will
421 * be invalidated by the SPI layer after the transfer is complete.
422 *
423 * @param[in] obj The SPI object that holds the transfer information
424 * @param[in] tx The transmit buffer
425 * @param[in] tx_length The number of bytes to transmit
426 * @param[in] rx The receive buffer
427 * @param[in] rx_length The number of bytes to receive
428 * @param[in] bit_width The bit width of buffer words
429 * @param[in] event The logical OR of events to be registered
430 * @param[in] handler SPI interrupt handler. This will point, through a bit of indirection, to \c SPI::irq_handler_asynch() for the correct SPI instance
431 * @param[in] hint A suggestion for how to use DMA with this transfer
432 *
433 * @return True if DMA was actually used for the transfer, false otherwise (if interrupts or another CPU-based
434 * method is used to do the transfer).
435 *
436 * @note On MCUs with a data cache, the return value is used to determine if a cache invalidation needs to be done
437 * after the transfer is complete. If this function returns true, the driver layer will cache invalidate the Rx buffer under
438 * the assumption that the data needs to be re-read from main memory. Be careful, because if the read was not actually
439 * done by DMA, and the rx data is in the CPU cache and NOT main memory, this invalidation will corrupt it.
440 *
441 * @note The application layer will always acquire the SPI peripheral first before calling this, including setting the frequency and the bit width. So,
442 * the \c bit_width argument will never be different from the SPI's currently set bit width, and can actually be ignored.
443 * TODO remove this argument entirely.
444 */
445bool 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);
446
447/** The asynchronous IRQ handler
448 *
449 * Reads the received values out of the RX FIFO, writes values into the TX FIFO and checks for transfer termination
450 * conditions, such as buffer overflows or transfer complete.
451 * @param[in] obj The SPI object that holds the transfer information
452 * @return Event flags if a transfer termination condition was met; otherwise 0.
453 */
455
456/** Attempts to determine if the SPI peripheral is already in use
457 *
458 * If a temporary DMA channel has been allocated, peripheral is in use.
459 * If a permanent DMA channel has been allocated, check if the DMA channel is in use. If not, proceed as though no DMA
460 * channel were allocated.
461 * If no DMA channel is allocated, check whether tx and rx buffers have been assigned. For each assigned buffer, check
462 * if the corresponding buffer position is less than the buffer length. If buffers do not indicate activity, check if
463 * there are any bytes in the FIFOs.
464 * @param[in] obj The SPI object to check for activity
465 * @return Non-zero if the SPI port is active or zero if it is not.
466 */
467uint8_t spi_active(spi_t *obj);
468
469/** Abort an SPI transfer
470 *
471 * @param obj The SPI peripheral to stop
472 */
474
475
476#endif
477
478/**@}*/
479
480#ifdef __cplusplus
481}
482#endif // __cplusplus
483
484#endif // SPI_DEVICE
485
486#endif // MBED_SPI_API_H
487
488/** @}*/
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
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