Mistake on this page?
Report an issue in GitHub or email us
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 <stdint.h>
24 #include <stdbool.h>
25 
26 #include "PeripheralNames.h"
27 #include "PinNames.h"
28 
29 #include "pinmap.h"
30 
31 #include "hal/dma_api.h"
32 #include "hal/buffer.h"
33 
34 #if DEVICE_SPI
35 
36 #ifdef __cplusplus
37 extern "C" {
38 #endif
39 
40 /**
41  * \defgroup hal_spi Serial Peripheral Interface
42  * ## Behaviours
43  * ### Defined Behaviours
44  *
45  * - `spi_get_module()` returns the `SPIName` unique identifier to the peripheral associated to this SPI channel - Verified by ::spi_test_get_module()
46  * - `spi_get_capabilities()` fills the given `spi_capabilities_t` instance - Verified by ::spi_test_get_capabilities()
47  * - `spi_get_capabilities()` should consider the `ssel` pin when evaluation the `support_slave_mode` capability
48  * If the given `ssel` pin cannot be managed by hardware in slave mode, `support_slave_mode` should be false - Verified by ::spi_test_get_capabilities() and ::fpga_spi_test_capabilities_ssel()
49  * - At least a symbol width of 8bit must be supported - Verified by ::spi_test_get_capabilities()
50  * - The supported frequency range must include the range [0.2..2] MHz - Verified by ::spi_test_get_capabilities()
51  * - The shortest part of the duty cycle must not be shorter than 50% of the expected period - Verified by ::fpga_spi_master_test_freq()
52  * - `spi_init()` initializes the pins leaving the configuration registers unchanged - Not testable.
53  * - `spi_init()` if `is_slave` is false:
54  * - if `ssel` is `NC` the hal implementation ignores this pin - Verified by ::spi_test_init_free(), ::fpga_spi_master_test_init_free() and ::fpga_spi_master_test_common()
55  * - if `ssel` is not `NC` then the hal implementation owns the pin and its management - Verified by ::spi_test_init_free(), ::fpga_spi_master_test_init_free() and ::fpga_spi_master_test_common()
56  * - When managed by the hal implementation, `ssel` is always considered active low - Verified by ::fpga_spi_master_test_common()
57  * - When managed by the hal implementation, ssel must be asserted for the whole duration of the spi transmission - Verified by ::fpga_spi_master_test_common()
58  * - When managed by the hal implementation, the delay from the chip select assert to the first clock edge must be at least half spi clock period - Verified by ::fpga_spi_master_test_common()
59  * - When managed by the hal implementation, the delay from the last clock edge to the chip select de-assert to must be at least half spi clock period - Verified by ::fpga_spi_master_test_common()
60  * - If hardware can not handle all ssel related requirements, then device capabilities should indicate that ssel cannot be managed by hardware - Not testable
61  * - When the hardware supports the half-duplex (3-wire) mode, if `miso` (exclusive) or `mosi` is missing in any function that expects pins, the bus is assumed to be half-duplex - Verified by ::spi_test_init_free(), ::fpga_spi_master_test_common() and ::fpga_spi_slave_test_common()
62  * - `spi_free()` resets the pins to their default state - Verified by ::spi_test_init_free(), ::fpga_spi_master_test_init_free() and ::fpga_spi_slave_test_init_free()
63  * - `spi_free()` disables the peripheral clock - Not testable
64  * - `spi_format()` sets:
65  * - the number of bits per symbol - Verified by ::fpga_spi_master_test_common() and ::fpga_spi_slave_test_common()
66  * - the mode :
67  * 0. Clock idle state is *low*, data are sampled when the clock becomes *active* (polarity = 0, phase = 0) - Verified by ::fpga_spi_master_test_common() and ::fpga_spi_slave_test_common()
68  * 1. Clock idle state is *low*, data are sampled when the clock becomes *inactive* (polarity = 0, phase = 1) - Verified by ::fpga_spi_master_test_common() and ::fpga_spi_slave_test_common()
69  * 2. Clock idle state is *high*, data are sampled when the clock becomes *active* (polarity = 1, phase = 0) - Verified by ::fpga_spi_master_test_common() and ::fpga_spi_slave_test_common()
70  * 3. Clock idle state is *high*, data are sampled when the clock becomes *inactive* (polarity = 1, phase = 1) - Verified by ::fpga_spi_master_test_common() and ::fpga_spi_slave_test_common()
71  * - the bit ordering (lsb/msb first) - Verified by ::fpga_spi_master_test_common() and ::fpga_spi_slave_test_common()
72  * - `spi_format()` updates the configuration of the peripheral except the baud rate generator - Verified by ::spi_test_set_format(), ::fpga_spi_master_test_common() and ::fpga_spi_slave_test_common()
73  * - `spi_frequency()` sets the frequency to use during the transfer - Verified by ::spi_test_set_frequency(), ::fpga_spi_master_test_common() and ::fpga_spi_slave_test_common()
74  * - `spi_frequency()` returns the actual frequency that will be used - Verified by ::spi_test_set_frequency() and ::fpga_spi_master_test_freq()
75  * - `spi_frequency()` updates the baud rate generator leaving other configurations unchanged - Verified by ::fpga_spi_master_test_common()
76  * - `spi_transfer()` :
77  * - writes `tx_len` symbols to the bus - Verified by ::fpga_spi_master_test_common() and ::fpga_spi_slave_test_common()
78  * - reads `rx_len` symbols from the bus - Verified by ::fpga_spi_master_test_common() and ::fpga_spi_slave_test_common()
79  * - if `rx` is NULL then inputs are discarded - Verified by ::fpga_spi_master_test_common() and ::fpga_spi_slave_test_common()
80  * - if `tx` is NULL then `fill_symbol` is used instead - Verified by ::fpga_spi_master_test_common() and ::fpga_spi_slave_test_common()
81  * - returns the number of symbol clocked on the bus during this transfer - Verified by ::spi_test_transfer_master_fill_sym(), ::spi_test_transfer_master(), ::fpga_spi_master_test_common() and ::fpga_spi_slave_test_common()
82  * - expects symbols types to be the closest stdint type bigger or equal to its size following the platform's endianness.
83  * e.g.:
84  * - 7bits => uint8_t - Verified by ::spi_test_transfer_master_async(), ::fpga_spi_master_test_common() and ::fpga_spi_slave_test_common()
85  * - 15bits => uint16_t - Verified by ::spi_test_transfer_master_async(), ::fpga_spi_master_test_common() and ::fpga_spi_slave_test_common()
86  * - 16bits => uint16_t - Verified by ::spi_test_transfer_master_async(), ::fpga_spi_master_test_common() and ::fpga_spi_slave_test_common()
87  * - 17bits => uint32_t - Verified by ::spi_test_transfer_master_async(), ::fpga_spi_master_test_common() and ::fpga_spi_slave_test_common()
88  * - In Full-duplex mode :
89  * - if `rx_len` > `tx_len` then it sends `(rx_len-tx_len)` additional `fill_symbol` to the bus - Verified by ::fpga_spi_master_test_common() and ::fpga_spi_slave_test_common()
90  * - In Half-duplex mode :
91  * - as master, `spi_transfer()` sends `tx_len` symbols and then reads `rx_len` symbols - Verified by ::fpga_spi_master_test_common() and ::fpga_spi_slave_test_common()
92  * - as slave, `spi_transfer()` receives `rx_len` symbols and then sends `tx_len` symbols - Verified by ::fpga_spi_master_test_common() and ::fpga_spi_slave_test_common()
93  * - `spi_transter_async()` schedules a transfer to be process the same way `spi_transfer()` would have but asynchronously with the following exceptions: - Verified by ::fpga_spi_master_test_common() and ::fpga_spi_slave_test_common()
94  * - in async mode only transfers of the same size are allowed (tx size must be equal to rx size)
95  * - async mode only supports full-duplex mode
96  * - `spi_transter_async()` returns immediately with a boolean indicating whether the transfer was successfully scheduled or not - Verified by ::spi_test_transfer_master_async(), ::fpga_spi_master_test_common() and ::fpga_spi_slave_test_common()
97  * - The callback given to `spi_transfer_async()` is invoked when the transfer completes (with a success or an error) - Verified by ::fpga_spi_master_test_common() and ::fpga_spi_slave_test_common()
98  * - `spi_transfer_async()` saves the handler and the `ctx` pointer - Verified by ::spi_test_transfer_master_async(), ::fpga_spi_master_test_common() and ::fpga_spi_slave_test_common()
99  * - The `ctx` is passed to the callback on transfer completion - Verified by ::spi_test_transfer_master_async(), ::fpga_spi_master_test_common() and ::fpga_spi_slave_test_common()
100  * - Unless if the transfer is aborted, the callback is invoked on completion. The completion maybe when all symbols have been transmitted
101  * or when in slave mode the master de-asserts the chip select - Verified by ::spi_test_transfer_master_async(), ::fpga_spi_master_test_common() and ::fpga_spi_slave_test_common()
102  * - The `spi_transfer_async()` function may use the `DMAUsage` hint to select the appropriate async algorithm - Verified by ::spi_test_transfer_master_async()
103  * - The `spi_async_event_t` must be filled with the number of symbol clocked on the bus during this transfer and a boolean value indicated if an error has occurred - Verified by ::spi_test_transfer_master_async(), ::fpga_spi_master_test_common() and ::fpga_spi_slave_test_common()
104  * - `spi_transfer_async_abort()` aborts an on-going async transfer - Verified by ::spi_test_transfer_master_async_abort()
105  *
106  * ### Undefined Behaviours
107  * - Calling `spi_init()` multiple times on the same `spi_t` without `spi_free()`'ing it first.
108  * - Calling any method other than `spi_init()` on a non-initialized or freed `spi_t`.
109  * - Passing both `miso` and `mosi` as `NC` to `spi_get_module` or `spi_init`.
110  * - Passing `miso` or `mosi` as `NC` on target that does not support half-duplex mode.
111  * - Passing `mclk` as `NC` to `spi_get_module` or `spi_init`.
112  * - Passing an invalid pointer as `cap` to `spi_get_capabilities`.
113  * - Passing pins that cannot be on the same peripheral.
114  * - Passing an invalid pointer as `obj` to any method.
115  * - Giving a `ssel` pin to `spi_init()` when using in master mode.
116  * SS must be managed by hardware in slave mode and must **NOT** be managed by hardware in master mode.
117  * - Setting a frequency outside of the range given by `spi_get_capabilities()`.
118  * - Setting a frequency in slave mode.
119  * - Setting `bits` in `spi_format` to a value out of the range given by `spi_get_capabilities()`.
120  * - Passing an invalid pointer as `fill_symbol` to `spi_transfer` and `spi_transfer_async` while they would be required by the transfer (`rx_len != tx_len` or `tx==NULL`).
121  * - Passing an invalid pointer as `handler` to `spi_transfer_async`.
122  * - Calling `spi_transfer_async_abort()` while no async transfer is being processed (no transfer or a synchronous transfer).
123  * - In half-duplex mode, any mechanism (if any is present) to detect or prevent collision is implementation defined.
124  * - Initiating any transfer after `spi_init()` but before both the frequency and format have been set with `spi_frequency()` and `spi_format()`
125  */
126 
127 /**
128  * \defgroup hal_spi_tests spi hal tests
129  * The SPI tests to check the implementation against the defined behavior.
130  *
131  * To run the spi hal tests use the command:
132  *
133  * mbed test -t <toolchain> -m <target> -n tests-mbed_hal-spi, tests-mbed_hal_fpga_ci_test_shield-spi*
134  *
135  */
136 
137 typedef struct spi_s spi_t;
138 
139 /**
140  * Describes the capabilities of a SPI peripherals
141  */
142 typedef struct {
143  /** Minimum frequency supported must be set by target device and it will be assessed during
144  * testing.
145  */
147  /** Maximum frequency supported must be set by target device and it will be assessed during
148  * testing.
149  */
151  /** Each bit represents the corresponding word length. lsb => 1bit, msb => 32bit. */
152  uint32_t word_length;
153  uint16_t slave_delay_between_symbols_ns; /**< specifies required number of ns between transmission of successive symbols in slave mode. */
154  uint8_t clk_modes; /**< specifies supported modes from spi_mode_t. Each bit represents the corresponding mode. */
155  uint8_t bit_order; /**< specifies supported bit order from spi_bit_ordering_t. Each bit represents the corresponding bit order. */
156  bool support_slave_mode; /**< If true, the device can handle SPI slave mode using hardware management on the specified ssel pin. */
157  bool half_duplex; /**< If true, the device also supports SPI transmissions using only 3 wires. */
158  bool hw_cs_handle; /**< If true, in SPI master mode Chip Select can be handled by hardware. */
159  bool async_mode; /**< If true, in async mode is supported. */
160 
162 
163 /**
164  * SPI modes.
165  */
166 typedef enum _spi_mode_t {
167  SPI_MODE_IDLE_LOW_SAMPLE_FIRST_EDGE,
168  SPI_MODE_IDLE_LOW_SAMPLE_SECOND_EDGE,
169  SPI_MODE_IDLE_HIGH_SAMPLE_FIRST_EDGE,
170  SPI_MODE_IDLE_HIGH_SAMPLE_SECOND_EDGE,
171 } spi_mode_t;
172 
173 /**
174  * SPI bit ordering.
175  */
176 typedef enum _spi_bit_ordering_t {
177  SPI_BIT_ORDERING_MSB_FIRST,
178  SPI_BIT_ORDERING_LSB_FIRST,
180 
181 /**
182  * Event data reported to interrupt's callback.
183  */
184 typedef struct _spi_async_event_t {
185  uint32_t transfered;
186  bool error;
188 
189 /**
190  * Interrupt callback signature.
191  */
192 typedef void (*spi_async_handler_f)(spi_t *obj, void *ctx, spi_async_event_t *event);
193 
194 /**
195  * Returns a variant of the SPIName enum uniquely identifying a SPI peripheral of the device.
196  */
197 SPIName spi_get_module(PinName mosi, PinName miso, PinName mclk);
198 
199 /**
200  * Fills the given spi_capabilities_t structure with the capabilities of the given peripheral.
201  */
202 void spi_get_capabilities(SPIName name, PinName ssel, bool slave, spi_capabilities_t *cap);
203 
204 /**
205  * Initialized a spi peripheral.
206  *
207  * @param obj SPI peripheral.
208  * @param is_slave True if the peripheral is used as a slave.
209  * @param mosi Master Out Slave In pin.
210  * @param miso Master In Slave Out pin.
211  * @param mclk Clock pin.
212  * @param ssel Slave Select pin.
213  */
214 void spi_init(spi_t *obj, bool is_slave, PinName mosi, PinName miso, PinName mclk, PinName ssel);
215 /**
216  * Configure the format to be used by the SPI peripheral.
217  *
218  * @param obj SPI peripheral.
219  * @param bits Number of bits per symbol.
220  * @param mode SPI mode to use.
221  * @param bit_ordering SPI bit ordering.
222  */
223 void spi_format(spi_t *obj, uint8_t bits, spi_mode_t mode, spi_bit_ordering_t bit_ordering);
224 /**
225  * Set the frequency target.
226  * This function tries to acheive the closest frequency possible prefering a value lower than the target.
227  *
228  * @param obj SPI peripheral.
229  * @param hz Target frequency in herz.
230  */
231 uint32_t spi_frequency(spi_t *obj, uint32_t hz);
232 /**
233  * Transfer data blocking until the end of the operation.
234  *
235  * @param obj SPI periheral.
236  * @param tx Buffer so send.
237  * @param tx_len Number of symbol in tx.
238  * @param rx Buffer to store received symbols.
239  * @param rx_len Number of symbol to store in rx.
240  * @param fill_symbol Symbol to send if tx_len is less than rx_len.
241  */
242 uint32_t spi_transfer(spi_t *obj, const void *tx, uint32_t tx_len, void *rx, uint32_t rx_len, const void *fill_symbol);
243 
244 /** Get the pins that support SPI MOSI
245  *
246  * Return a PinMap array of pins that support SPI MOSI in
247  * master mode. The array is terminated with {NC, NC, 0}.
248  *
249  * @return PinMap array
250  */
251 const PinMap *spi_master_mosi_pinmap(void);
252 
253 /** Get the pins that support SPI MISO
254  *
255  * Return a PinMap array of pins that support SPI MISO in
256  * master mode. The array is terminated with {NC, NC, 0}.
257  *
258  * @return PinMap array
259  */
260 const PinMap *spi_master_miso_pinmap(void);
261 
262 /** Get the pins that support SPI CLK
263  *
264  * Return a PinMap array of pins that support SPI CLK in
265  * master mode. The array is terminated with {NC, NC, 0}.
266  *
267  * @return PinMap array
268  */
269 const PinMap *spi_master_clk_pinmap(void);
270 
271 /** Get the pins that support SPI CS
272  *
273  * Return a PinMap array of pins that support SPI CS in
274  * master mode. The array is terminated with {NC, NC, 0}.
275  *
276  * @return PinMap array
277  */
278 const PinMap *spi_master_cs_pinmap(void);
279 
280 /** Get the pins that support SPI MOSI
281  *
282  * Return a PinMap array of pins that support SPI MOSI in
283  * slave mode. The array is terminated with {NC, NC, 0}.
284  *
285  * @return PinMap array
286  */
287 const PinMap *spi_slave_mosi_pinmap(void);
288 
289 /** Get the pins that support SPI MISO
290  *
291  * Return a PinMap array of pins that support SPI MISO in
292  * slave mode. The array is terminated with {NC, NC, 0}.
293  *
294  * @return PinMap array
295  */
296 const PinMap *spi_slave_miso_pinmap(void);
297 
298 /** Get the pins that support SPI CLK
299  *
300  * Return a PinMap array of pins that support SPI CLK in
301  * slave mode. The array is terminated with {NC, NC, 0}.
302  *
303  * @return PinMap array
304  */
305 const PinMap *spi_slave_clk_pinmap(void);
306 
307 /** Get the pins that support SPI CS
308  *
309  * Return a PinMap array of pins that support SPI CS in
310  * slave mode. The array is terminated with {NC, NC, 0}.
311  *
312  * @return PinMap array
313  */
314 const PinMap *spi_slave_cs_pinmap(void);
315 
316 #ifdef DEVICE_SPI_ASYNCH
317 /**
318  * \defgroup AsynchSPI Asynchronous SPI Hardware Abstraction Layer
319  * @{
320  */
321 
322 /**
323  * Transfer data returning immediately.
324  *
325  * @param obj SPI periheral.
326  * @param tx Buffer so send.
327  * @param tx_len Number of symbol in tx.
328  * @param rx Buffer to store received symbols.
329  * @param rx_len Number of symbol to store in rx.
330  * @param fill_symbol Symbol to send if tx_len is less than rx_len.
331  * @param handler Callback to invoke at the end of the operation.
332  * @param ctx Argument passed to the callback.
333  * @param hint Hint to help determine the DMA allocation strategy.
334  */
335 bool spi_transfer_async(spi_t *obj, const void *tx, uint32_t tx_len, void *rx, uint32_t rx_len, const void *fill_symbol, spi_async_handler_f handler, void *ctx, DMAUsage hint);
336 /**
337  * Abort the current asynchronous operation.
338  */
339 void spi_transfer_async_abort(spi_t *obj);
340 #endif // DEVICE_SPI_ASYNCH
341 
342 /**@}*/
343 
344 void spi_free(spi_t *obj);
345 
346 #ifdef __cplusplus
347 }
348 #endif // __cplusplus
349 
350 #endif // SPI_DEVICE
351 
352 #endif // MBED_SPI_API_H
353 
354 /** @}*/
void spi_init(spi_t *obj, bool is_slave, PinName mosi, PinName miso, PinName mclk, PinName ssel)
Initialized a spi peripheral.
bool hw_cs_handle
If true, in SPI master mode Chip Select can be handled by hardware.
Definition: spi_api.h:158
MBED_NORETURN void error(const char *format,...) MBED_PRINTF(1
To generate a fatal compile-time error, you can use the pre-processor error directive.
const PinMap * spi_slave_mosi_pinmap(void)
Get the pins that support SPI MOSI.
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:156
const PinMap * spi_slave_clk_pinmap(void)
Get the pins that support SPI CLK.
struct _spi_async_event_t spi_async_event_t
Event data reported to interrupt&#39;s callback.
uint32_t minimum_frequency
Minimum frequency supported must be set by target device and it will be assessed during testing...
Definition: spi_api.h:146
_spi_bit_ordering_t
SPI bit ordering.
Definition: spi_api.h:176
void(* spi_async_handler_f)(spi_t *obj, void *ctx, spi_async_event_t *event)
Interrupt callback signature.
Definition: spi_api.h:192
const PinMap * spi_slave_miso_pinmap(void)
Get the pins that support SPI MISO.
Event data reported to interrupt&#39;s callback.
Definition: spi_api.h:184
uint32_t maximum_frequency
Maximum frequency supported must be set by target device and it will be assessed during testing...
Definition: spi_api.h:150
uint8_t clk_modes
specifies supported modes from spi_mode_t.
Definition: spi_api.h:154
const PinMap * spi_master_clk_pinmap(void)
Get the pins that support SPI CLK.
void spi_transfer_async_abort(spi_t *obj)
Abort the current asynchronous operation.
uint8_t bit_order
specifies supported bit order from spi_bit_ordering_t.
Definition: spi_api.h:155
SPIName spi_get_module(PinName mosi, PinName miso, PinName mclk)
Returns a variant of the SPIName enum uniquely identifying a SPI peripheral of the device...
void spi_get_capabilities(SPIName name, PinName ssel, bool slave, spi_capabilities_t *cap)
Fills the given spi_capabilities_t structure with the capabilities of the given peripheral.
Describes the capabilities of a SPI peripherals.
Definition: spi_api.h:142
bool async_mode
If true, in async mode is supported.
Definition: spi_api.h:159
enum _spi_mode_t spi_mode_t
SPI modes.
uint32_t spi_frequency(spi_t *obj, uint32_t hz)
Set the frequency target.
enum _spi_bit_ordering_t spi_bit_ordering_t
SPI bit ordering.
uint16_t slave_delay_between_symbols_ns
specifies required number of ns between transmission of successive symbols in slave mode...
Definition: spi_api.h:153
bool spi_transfer_async(spi_t *obj, const void *tx, uint32_t tx_len, void *rx, uint32_t rx_len, const void *fill_symbol, spi_async_handler_f handler, void *ctx, DMAUsage hint)
Transfer data returning immediately.
void spi_format(spi_t *obj, uint8_t bits, spi_mode_t mode, spi_bit_ordering_t bit_ordering)
Configure the format to be used by the SPI peripheral.
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.
Definition: pinmap.h:30
uint32_t spi_transfer(spi_t *obj, const void *tx, uint32_t tx_len, void *rx, uint32_t rx_len, const void *fill_symbol)
Transfer data blocking until the end of the operation.
bool half_duplex
If true, the device also supports SPI transmissions using only 3 wires.
Definition: spi_api.h:157
const PinMap * spi_slave_cs_pinmap(void)
Get the pins that support SPI CS.
_spi_mode_t
SPI modes.
Definition: spi_api.h:166
uint32_t word_length
Each bit represents the corresponding word length.
Definition: spi_api.h:152
const PinMap * spi_master_miso_pinmap(void)
Get the pins that support SPI MISO.
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.