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