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 "device.h"
24 #include "pinmap.h"
25 #include "hal/dma_api.h"
26 #include "hal/buffer.h"
27 
28 #if DEVICE_SPI
29 
30 #define SPI_EVENT_ERROR (1 << 1)
31 #define SPI_EVENT_COMPLETE (1 << 2)
32 #define SPI_EVENT_RX_OVERFLOW (1 << 3)
33 #define SPI_EVENT_ALL (SPI_EVENT_ERROR | SPI_EVENT_COMPLETE | SPI_EVENT_RX_OVERFLOW)
34 
35 #define SPI_EVENT_INTERNAL_TRANSFER_COMPLETE (1 << 30) // Internal flag to report that an event occurred
36 
37 #define SPI_FILL_WORD (0xFFFF)
38 #define SPI_FILL_CHAR (0xFF)
39 
40 #if DEVICE_SPI_ASYNCH
41 /** Asynch SPI HAL structure
42  */
43 typedef struct {
44  struct spi_s spi; /**< Target specific SPI structure */
45  struct buffer_s tx_buff; /**< Tx buffer */
46  struct buffer_s rx_buff; /**< Rx buffer */
47 } spi_t;
48 
49 #else
50 /** Non-asynch SPI HAL structure
51  */
52 typedef struct spi_s spi_t;
53 
54 #endif
55 
56 typedef struct {
57  int peripheral;
58  PinName mosi_pin;
59  int mosi_function;
60  PinName miso_pin;
61  int miso_function;
62  PinName sclk_pin;
63  int sclk_function;
64  PinName ssel_pin;
65  int ssel_function;
66 } spi_pinmap_t;
67 
68 /**
69  * Describes the capabilities of a SPI peripherals
70  */
71 typedef struct {
72  /** Minimum frequency supported must be set by target device and it will be assessed during
73  * testing.
74  */
76  /** Maximum frequency supported must be set by target device and it will be assessed during
77  * testing.
78  */
80  /** Each bit represents the corresponding word length. lsb => 1bit, msb => 32bit. */
81  uint32_t word_length;
82  uint16_t slave_delay_between_symbols_ns; /**< specifies required number of ns between transmission of successive symbols in slave mode. */
83  uint8_t clk_modes; /**< specifies supported modes from spi_mode_t. Each bit represents the corresponding mode. */
84  bool support_slave_mode; /**< If true, the device can handle SPI slave mode using hardware management on the specified ssel pin. */
85  bool hw_cs_handle; /**< If true, in SPI master mode Chip Select can be handled by hardware. */
86  bool async_mode; /**< If true, in async mode is supported. */
87 
89 
90 #ifdef __cplusplus
91 extern "C" {
92 #endif
93 
94 /**
95  * \defgroup hal_GeneralSPI SPI Configuration Functions
96  *
97  * # Defined behavior
98  * * ::spi_init initializes the spi_t control structure
99  * * ::spi_init configures the pins used by SPI
100  * * ::spi_get_capabilities() fills the given `spi_capabilities_t` instance
101  * * ::spi_get_capabilities() should consider the `ssel` pin when evaluation the `support_slave_mode` and `hw_cs_handle` capability
102  * * ::spi_get_capabilities(): if the given `ssel` pin cannot be managed by hardware, `support_slave_mode` and `hw_cs_handle` should be false
103  * * At least a symbol width of 8bit must be supported
104  * * The supported frequency range must include the range [0.2..2] MHz
105  * * ::spi_free returns the pins owned by the SPI object to their reset state
106  * * ::spi_format sets the number of bits per frame
107  * * ::spi_format configures clock polarity and phase
108  * * ::spi_format configures master/slave mode
109  * * ::spi_frequency sets the SPI baud rate
110  * * ::spi_master_write writes a symbol out in master mode and receives a symbol
111  * * ::spi_master_block_write writes `tx_length` words to the bus
112  * * ::spi_master_block_write reads `rx_length` words from the bus
113  * * ::spi_master_block_write returns the maximum of tx_length and rx_length
114  * * ::spi_master_block_write specifies the write_fill which is default data transmitted while performing a read
115  * * ::spi_get_module returns non-zero if a value is available to read from SPI channel, 0 otherwise
116  * * ::spi_slave_read returns a received value out of the SPI receive buffer in slave mode
117  * * ::spi_slave_read blocks until a value is available
118  * * ::spi_slave_write writes a value to the SPI peripheral in slave mode
119  * * ::spi_slave_write blocks until the SPI peripheral can be written to
120  * * ::spi_busy returns non-zero if the peripheral is currently transmitting, 0 otherwise
121  * * ::spi_master_transfer starts the SPI asynchronous transfer
122  * * ::spi_master_transfer writes `tx_len` words to the bus
123  * * ::spi_master_transfer reads `rx_len` words from the bus
124  * * ::spi_master_transfer specifies the bit width of buffer words
125  * * The callback given to ::spi_master_transfer is invoked when the transfer completes (with a success or an error)
126  * * ::spi_master_transfer specifies the logical OR of events to be registered
127  * * The ::spi_master_transfer function may use the `DMAUsage` hint to select the appropriate async algorithm
128  * * ::spi_irq_handler_asynch reads the received values out of the RX FIFO
129  * * ::spi_irq_handler_asynch writes values into the TX FIFO
130  * * ::spi_irq_handler_asynch checks for transfer termination conditions, such as buffer overflows or transfer complete
131  * * ::spi_irq_handler_asynch returns event flags if a transfer termination condition was met, otherwise 0
132  * * ::spi_abort_asynch aborts an on-going async transfer
133  * * ::spi_active returns non-zero if the SPI port is active or zero if it is not
134  *
135  * # Undefined behavior
136  * * Calling ::spi_init multiple times on the same `spi_t` without ::spi_free
137  * * Calling any function other than ::spi_init on a non-initialized or freed `spi_t`
138  * * Passing pins that cannot be on the same peripheral
139  * * Passing an invalid pointer as `obj` to any function
140  * * Passing an invalid pointer as `handler` to ::spi_master_transfer
141  * * Calling ::spi_abort while no async transfer is being processed (no transfer or a synchronous transfer)
142  *
143  * @{
144  */
145 
146 /**
147  * \defgroup hal_GeneralSPI_tests SPI hal tests
148  * The SPI HAL tests ensure driver conformance to defined behaviour.
149  *
150  * To run the SPI hal tests use the command:
151  *
152  * mbed test -t <toolchain> -m <target> -n tests-mbed_hal_fpga_ci_test_shield-spi
153  *
154  */
155 
156 #ifdef DEVICE_SPI_COUNT
157 /**
158  * Returns a variant of the SPIName enum uniquely identifying a SPI peripheral of the device.
159  * @param[in] mosi The pin to use for MOSI
160  * @param[in] miso The pin to use for MISO
161  * @param[in] sclk The pin to use for SCLK
162  * @return An SPI peripheral identifier
163  */
164 SPIName spi_get_peripheral_name(PinName mosi, PinName miso, PinName mclk);
165 #endif
166 
167 /**
168  * Fills the given spi_capabilities_t structure with the capabilities of the given peripheral.
169  */
170 void spi_get_capabilities(PinName ssel, bool slave, spi_capabilities_t *cap);
171 
172 /** Initialize the SPI peripheral
173  *
174  * Configures the pins used by SPI, sets a default format and frequency, and enables the peripheral
175  * @param[out] obj The SPI object to initialize
176  * @param[in] pinmap pointer to structure which holds static pinmap
177  */
178 void spi_init_direct(spi_t *obj, const spi_pinmap_t *pinmap);
179 
180 /** Initialize the SPI peripheral
181  *
182  * Configures the pins used by SPI, sets a default format and frequency, and enables the peripheral
183  * @param[out] obj The SPI object to initialize
184  * @param[in] mosi The pin to use for MOSI
185  * @param[in] miso The pin to use for MISO
186  * @param[in] sclk The pin to use for SCLK
187  * @param[in] ssel The pin to use for SSEL
188  */
189 void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel);
190 
191 /** Release a SPI object
192  *
193  * TODO: spi_free is currently unimplemented
194  * This will require reference counting at the C++ level to be safe
195  *
196  * Return the pins owned by the SPI object to their reset state
197  * Disable the SPI peripheral
198  * Disable the SPI clock
199  * @param[in] obj The SPI object to deinitialize
200  */
201 void spi_free(spi_t *obj);
202 
203 /** Configure the SPI format
204  *
205  * Set the number of bits per frame, configure clock polarity and phase, shift order and master/slave mode.
206  * The default bit order is MSB.
207  * @param[in,out] obj The SPI object to configure
208  * @param[in] bits The number of bits per frame
209  * @param[in] mode The SPI mode (clock polarity, phase, and shift direction)
210  * @param[in] slave Zero for master mode or non-zero for slave mode
211  */
212 void spi_format(spi_t *obj, int bits, int mode, int slave);
213 
214 /** Set the SPI baud rate
215  *
216  * Actual frequency may differ from the desired frequency due to available dividers and bus clock
217  * Configures the SPI peripheral's baud rate
218  * @param[in,out] obj The SPI object to configure
219  * @param[in] hz The baud rate in Hz
220  */
221 void spi_frequency(spi_t *obj, int hz);
222 
223 /**@}*/
224 /**
225  * \defgroup SynchSPI Synchronous SPI Hardware Abstraction Layer
226  * @{
227  */
228 
229 /** Write a byte out in master mode and receive a value
230  *
231  * @param[in] obj The SPI peripheral to use for sending
232  * @param[in] value The value to send
233  * @return Returns the value received during send
234  */
235 int spi_master_write(spi_t *obj, int value);
236 
237 /** Write a block out in master mode and receive a value
238  *
239  * The total number of bytes sent and received will be the maximum of
240  * tx_length and rx_length. The bytes written will be padded with the
241  * value 0xff.
242  *
243  * @param[in] obj The SPI peripheral to use for sending
244  * @param[in] tx_buffer Pointer to the byte-array of data to write to the device
245  * @param[in] tx_length Number of bytes to write, may be zero
246  * @param[in] rx_buffer Pointer to the byte-array of data to read from the device
247  * @param[in] rx_length Number of bytes to read, may be zero
248  * @param[in] write_fill Default data transmitted while performing a read
249  * @returns
250  * The number of bytes written and read from the device. This is
251  * maximum of tx_length and rx_length.
252  */
253 int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length, char write_fill);
254 
255 /** Check if a value is available to read
256  *
257  * @param[in] obj The SPI peripheral to check
258  * @return non-zero if a value is available
259  */
260 int spi_slave_receive(spi_t *obj);
261 
262 /** Get a received value out of the SPI receive buffer in slave mode
263  *
264  * Blocks until a value is available
265  * @param[in] obj The SPI peripheral to read
266  * @return The value received
267  */
268 int spi_slave_read(spi_t *obj);
269 
270 /** Write a value to the SPI peripheral in slave mode
271  *
272  * Blocks until the SPI peripheral can be written to
273  * @param[in] obj The SPI peripheral to write
274  * @param[in] value The value to write
275  */
276 void spi_slave_write(spi_t *obj, int value);
277 
278 /** Checks if the specified SPI peripheral is in use
279  *
280  * @param[in] obj The SPI peripheral to check
281  * @return non-zero if the peripheral is currently transmitting
282  */
283 int spi_busy(spi_t *obj);
284 
285 /** Get the module number
286  *
287  * @param[in] obj The SPI peripheral to check
288  * @return The module number
289  */
290 uint8_t spi_get_module(spi_t *obj);
291 
292 /** Get the pins that support SPI MOSI
293  *
294  * Return a PinMap array of pins that support SPI MOSI in
295  * master mode. The array is terminated with {NC, NC, 0}.
296  *
297  * @return PinMap array
298  */
299 const PinMap *spi_master_mosi_pinmap(void);
300 
301 /** Get the pins that support SPI MISO
302  *
303  * Return a PinMap array of pins that support SPI MISO in
304  * master mode. The array is terminated with {NC, NC, 0}.
305  *
306  * @return PinMap array
307  */
308 const PinMap *spi_master_miso_pinmap(void);
309 
310 /** Get the pins that support SPI CLK
311  *
312  * Return a PinMap array of pins that support SPI CLK in
313  * master mode. The array is terminated with {NC, NC, 0}.
314  *
315  * @return PinMap array
316  */
317 const PinMap *spi_master_clk_pinmap(void);
318 
319 /** Get the pins that support SPI CS
320  *
321  * Return a PinMap array of pins that support SPI CS in
322  * master mode. The array is terminated with {NC, NC, 0}.
323  *
324  * @return PinMap array
325  */
326 const PinMap *spi_master_cs_pinmap(void);
327 
328 /** Get the pins that support SPI MOSI
329  *
330  * Return a PinMap array of pins that support SPI MOSI in
331  * slave mode. The array is terminated with {NC, NC, 0}.
332  *
333  * @return PinMap array
334  */
335 const PinMap *spi_slave_mosi_pinmap(void);
336 
337 /** Get the pins that support SPI MISO
338  *
339  * Return a PinMap array of pins that support SPI MISO in
340  * slave mode. The array is terminated with {NC, NC, 0}.
341  *
342  * @return PinMap array
343  */
344 const PinMap *spi_slave_miso_pinmap(void);
345 
346 /** Get the pins that support SPI CLK
347  *
348  * Return a PinMap array of pins that support SPI CLK in
349  * slave mode. The array is terminated with {NC, NC, 0}.
350  *
351  * @return PinMap array
352  */
353 const PinMap *spi_slave_clk_pinmap(void);
354 
355 /** Get the pins that support SPI CS
356  *
357  * Return a PinMap array of pins that support SPI CS in
358  * slave mode. The array is terminated with {NC, NC, 0}.
359  *
360  * @return PinMap array
361  */
362 const PinMap *spi_slave_cs_pinmap(void);
363 
364 /**@}*/
365 
366 #if DEVICE_SPI_ASYNCH
367 /**
368  * \defgroup AsynchSPI Asynchronous SPI Hardware Abstraction Layer
369  * @{
370  */
371 
372 /** Begin the SPI transfer. Buffer pointers and lengths are specified in tx_buff and rx_buff
373  *
374  * @param[in] obj The SPI object that holds the transfer information
375  * @param[in] tx The transmit buffer
376  * @param[in] tx_length The number of bytes to transmit
377  * @param[in] rx The receive buffer
378  * @param[in] rx_length The number of bytes to receive
379  * @param[in] bit_width The bit width of buffer words
380  * @param[in] event The logical OR of events to be registered
381  * @param[in] handler SPI interrupt handler
382  * @param[in] hint A suggestion for how to use DMA with this transfer
383  */
384 void 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);
385 
386 /** The asynchronous IRQ handler
387  *
388  * Reads the received values out of the RX FIFO, writes values into the TX FIFO and checks for transfer termination
389  * conditions, such as buffer overflows or transfer complete.
390  * @param[in] obj The SPI object that holds the transfer information
391  * @return Event flags if a transfer termination condition was met; otherwise 0.
392  */
393 uint32_t spi_irq_handler_asynch(spi_t *obj);
394 
395 /** Attempts to determine if the SPI peripheral is already in use
396  *
397  * If a temporary DMA channel has been allocated, peripheral is in use.
398  * If a permanent DMA channel has been allocated, check if the DMA channel is in use. If not, proceed as though no DMA
399  * channel were allocated.
400  * If no DMA channel is allocated, check whether tx and rx buffers have been assigned. For each assigned buffer, check
401  * if the corresponding buffer position is less than the buffer length. If buffers do not indicate activity, check if
402  * there are any bytes in the FIFOs.
403  * @param[in] obj The SPI object to check for activity
404  * @return Non-zero if the SPI port is active or zero if it is not.
405  */
406 uint8_t spi_active(spi_t *obj);
407 
408 /** Abort an SPI transfer
409  *
410  * @param obj The SPI peripheral to stop
411  */
412 void spi_abort_asynch(spi_t *obj);
413 
414 
415 #endif
416 
417 /**@}*/
418 
419 #ifdef __cplusplus
420 }
421 #endif // __cplusplus
422 
423 #endif // SPI_DEVICE
424 
425 #endif // MBED_SPI_API_H
426 
427 /** @}*/
uint8_t spi_active(spi_t *obj)
Attempts to determine if the SPI peripheral is already in use.
const PinMap * spi_master_mosi_pinmap(void)
Get the pins that support SPI MOSI.
bool hw_cs_handle
If true, in SPI master mode Chip Select can be handled by hardware.
Definition: spi_api.h:85
Generic buffer structure.
Definition: buffer.h:27
uint32_t spi_irq_handler_asynch(spi_t *obj)
The asynchronous IRQ handler.
void spi_slave_write(spi_t *obj, int value)
Write a value to the SPI peripheral in slave mode.
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:84
void spi_format(spi_t *obj, int bits, int mode, int slave)
Configure the SPI format.
void spi_frequency(spi_t *obj, int hz)
Set the SPI baud rate.
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.
uint32_t minimum_frequency
Minimum frequency supported must be set by target device and it will be assessed during testing...
Definition: spi_api.h:75
void 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 SPI transfer.
uint32_t maximum_frequency
Maximum frequency supported must be set by target device and it will be assessed during testing...
Definition: spi_api.h:79
uint8_t clk_modes
specifies supported modes from spi_mode_t.
Definition: spi_api.h:83
const PinMap * spi_master_miso_pinmap(void)
Get the pins that support SPI MISO.
const PinMap * spi_master_cs_pinmap(void)
Get the pins that support SPI CS.
const PinMap * spi_master_clk_pinmap(void)
Get the pins that support SPI CLK.
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel)
Initialize the SPI peripheral.
int spi_slave_read(spi_t *obj)
Get a received value out of the SPI receive buffer in slave mode.
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.
Describes the capabilities of a SPI peripherals.
Definition: spi_api.h:71
bool async_mode
If true, in async mode is supported.
Definition: spi_api.h:86
int spi_master_write(spi_t *obj, int value)
Write a byte out in master mode and receive a value.
uint16_t slave_delay_between_symbols_ns
specifies required number of ns between transmission of successive symbols in slave mode...
Definition: spi_api.h:82
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_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.
Definition: pinmap.h:31
void spi_abort_asynch(spi_t *obj)
Abort an SPI transfer.
int spi_slave_receive(spi_t *obj)
Check if a value is available to read.
const PinMap * spi_slave_clk_pinmap(void)
Get the pins that support SPI CLK.
uint8_t spi_get_module(spi_t *obj)
Get the module number.
const PinMap * spi_slave_miso_pinmap(void)
Get the pins that support SPI MISO.
int spi_busy(spi_t *obj)
Checks if the specified SPI peripheral is in use.
Asynch SPI HAL structure.
Definition: spi_api.h:43
uint32_t word_length
Each bit represents the corresponding word length.
Definition: spi_api.h:81
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.