Mistake on this page?
Report an issue in GitHub or email us
SPI.h
1 /* mbed Microcontroller Library
2  * Copyright (c) 2006-2015 ARM Limited
3  * SPDX-License-Identifier: Apache-2.0
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 #ifndef MBED_SPI_H
18 #define MBED_SPI_H
19 
20 #include "platform/platform.h"
21 
22 #if DEVICE_SPI || defined(DOXYGEN_ONLY)
23 
24 #include "platform/PlatformMutex.h"
25 #include "hal/spi_api.h"
26 #include "platform/SingletonPtr.h"
27 #include "platform/NonCopyable.h"
28 
29 #if DEVICE_SPI_ASYNCH
30 #include "platform/Callback.h"
31 #include "hal/dma_api.h"
32 #include "platform/CircularBuffer.h"
33 #include "platform/FunctionPointer.h"
34 #include "platform/Transaction.h"
35 #endif // DEVICE_SPI_ASYNCH
36 
37 namespace mbed {
38 /** \addtogroup drivers */
39 
40 #define SPI_FILL_CHAR 0xFFFFFFFF
41 #define SPI_EVENT_COMPLETE 0
42 #define SPI_EVENT_ALL 0xFFFFFFFF
43 
44 /** A SPI Master, used for communicating with SPI slave devices.
45  *
46  * The default format is set to 8-bits, mode 0, and a clock frequency of 1MHz.
47  *
48  * Most SPI devices will also require Chip Select and Reset signals. These
49  * can be controlled using DigitalOut pins.
50  *
51  * @note Synchronization level: Thread safe on the synchronous API only.
52  *
53  * Example of how to send a byte to a SPI slave and record the response:
54  * @code
55  * #include "mbed.h"
56  *
57  * SPI device(SPI_MOSI, SPI_MISO, SPI_SCLK)
58  *
59  * DigitalOut chip_select(SPI_CS);
60  *
61  * int main() {
62  * device.lock();
63  * chip_select = 0;
64  *
65  * int response = device.write(0xFF);
66  *
67  * chip_select = 1;
68  * device.unlock();
69  * }
70  * @endcode
71  *
72  * Example using hardware Chip Select line:
73  * @code
74  * #include "mbed.h"
75  *
76  * SPI device(SPI_MOSI, SPI_MISO, SPI_SCLK, SPI_CS)
77  *
78  * int main() {
79  * device.lock();
80  * int response = device.write(0xFF);
81  * device.unlock();
82  * }
83  * @endcode
84  * @ingroup drivers
85  */
86 class SPI : private NonCopyable<SPI> {
87 
88 public:
89 
90  /** Create a SPI master connected to the specified pins.
91  *
92  * @note You can specify mosi or miso as NC if not used.
93  *
94  * @param mosi SPI Master Out, Slave In pin.
95  * @param miso SPI Master In, Slave Out pin.
96  * @param sclk SPI Clock pin.
97  * @param ssel SPI Chip Select pin.
98  */
99  SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel = NC);
100  virtual ~SPI();
101 
102  /** Configure the data transmission format.
103  *
104  * @param bits Number of bits per SPI frame (4 - 16).
105  * @param mode Clock polarity and phase mode (0 - 3).
106  *
107  * @code
108  * mode | POL PHA
109  * -----+--------
110  * 0 | 0 0
111  * 1 | 0 1
112  * 2 | 1 0
113  * 3 | 1 1
114  * @endcode
115  */
116  void format(int bits, int mode = 0);
117  void format(uint8_t bits, spi_mode_t mode = SPI_MODE_IDLE_LOW_SAMPLE_FIRST_EDGE, spi_bit_ordering_t bit_order = SPI_BIT_ORDERING_MSB_FIRST);
118 
119  /** Set the SPI bus clock frequency.
120  *
121  * @param hz Clock frequency in Hz (default = 1MHz).
122  */
123  uint32_t frequency(uint32_t hz = 1000000);
124 
125  /** Write to the SPI Slave and return the response.
126  *
127  * @param value Data to be sent to the SPI slave.
128  *
129  * @return Response from the SPI slave.
130  */
131  virtual int write(int value);
132 
133  /** Write to the SPI Slave and obtain the response.
134  *
135  * The total number of bytes sent and received will be the maximum of
136  * tx_length and rx_length. The bytes written will be padded with the
137  * value 0xff.
138  *
139  * @param tx_buffer Pointer to the byte-array of data to write to the device.
140  * @param tx_length Number of bytes to write, may be zero.
141  * @param rx_buffer Pointer to the byte-array of data to read from the device.
142  * @param rx_length Number of bytes to read, may be zero.
143  * @return
144  * The number of bytes written and read from the device. This is
145  * maximum of tx_length and rx_length.
146  */
147  virtual int write(const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length);
148 
149  /** Acquire exclusive access to this SPI bus.
150  */
151  virtual bool lock(void);
152 
153  /** Release exclusive access to this SPI bus.
154  */
155  virtual void unlock(void);
156 
157  /** Set default write data.
158  * SPI requires the master to send some data during a read operation.
159  * Different devices may require different default byte values.
160  * For example: A SD Card requires default bytes to be 0xFF.
161  *
162  * @param data Default character to be transmitted during a read operation.
163  */
164  void set_default_write_value(char data);
165 
166 #if DEVICE_SPI_ASYNCH
167 
168  /** Start non-blocking SPI transfer using 8bit buffers.
169  *
170  * This function locks the deep sleep until any event has occurred.
171  *
172  * @param tx_buffer The TX buffer with data to be transferred. If NULL is passed,
173  * the default SPI value is sent.
174  * @param tx_length The length of TX buffer in bytes.
175  * @param rx_buffer The RX buffer which is used for received data. If NULL is passed,
176  * received data are ignored.
177  * @param rx_length The length of RX buffer in bytes.
178  * @param callback The event callback function.
179  * @param event The event mask of events to modify. @see spi_api.h for SPI events.
180  *
181  * @return Operation result.
182  * @retval 0 If the transfer has started.
183  * @retval -1 If SPI peripheral is busy.
184  */
185  template<typename Type>
186  int transfer(const Type *tx_buffer, int tx_length, Type *rx_buffer, int rx_length, const event_callback_t &callback, int event = SPI_EVENT_COMPLETE)
187  {
188  if (!lock()) {
189  return queue_transfer(tx_buffer, tx_length, rx_buffer, rx_length, sizeof(Type) * 8, callback, event);
190  }
191  start_transfer(tx_buffer, tx_length, rx_buffer, rx_length, sizeof(Type) * 8, callback, event);
192  return 0;
193  }
194 
195  /** Abort the on-going SPI transfer, and continue with transfers in the queue, if any.
196  */
197  void abort_transfer();
198 
199  /** Clear the queue of transfers.
200  */
201  void clear_transfer_buffer();
202 
203  /** Clear the queue of transfers and abort the on-going transfer.
204  */
205  void abort_all_transfers();
206 
207  /** Configure DMA usage suggestion for non-blocking transfers.
208  *
209  * @param usage The usage DMA hint for peripheral.
210  *
211  * @return Result of the operation.
212  * @retval 0 The usage was set.
213  * @retval -1 Usage cannot be set as there is an ongoing transaction.
214  */
215  int set_dma_usage(DMAUsage usage);
216 
217 #if !defined(DOXYGEN_ONLY)
218 protected:
219  /** Start the transfer or put it on the queue.
220  *
221  * @param tx_buffer The TX buffer with data to be transferred. If NULL is passed,
222  * the default SPI value is sent
223  * @param tx_length The length of TX buffer in bytes.
224  * @param rx_buffer The RX buffer which is used for received data. If NULL is passed,
225  * received data are ignored.
226  * @param rx_length The length of RX buffer in bytes.
227  * @param bit_width The buffers element width in bits.
228  * @param callback The event callback function.
229  * @param event The event mask of events to modify.
230  *
231  * @return Operation success.
232  * @retval 0 A transfer was started or added to the queue.
233  * @retval -1 Transfer can't be added because queue is full.
234  */
235  int transfer(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_length, unsigned char bit_width, const event_callback_t &callback, int event);
236 
237  /** Put a transfer on the transfer queue.
238  *
239  * @param tx_buffer The TX buffer with data to be transferred. If NULL is passed,
240  * the default SPI value is sent.
241  * @param tx_length The length of TX buffer in bytes.
242  * @param rx_buffer The RX buffer which is used for received data. If NULL is passed,
243  * received data are ignored.
244  * @param rx_length The length of RX buffer in bytes.
245  * @param bit_width The buffers element width in bits.
246  * @param callback The event callback function.
247  * @param event The event mask of events to modify.
248  *
249  * @return Operation success.
250  * @retval 0 A transfer was added to the queue.
251  * @retval -1 Transfer can't be added because queue is full.
252  */
253  int queue_transfer(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_length, unsigned char bit_width, const event_callback_t &callback, int event);
254 
255  /** Configure a callback, SPI peripheral, and initiate a new transfer.
256  *
257  * @param tx_buffer The TX buffer with data to be transferred. If NULL is passed,
258  * the default SPI value is sent.
259  * @param tx_length The length of TX buffer in bytes.
260  * @param rx_buffer The RX buffer which is used for received data. If NULL is passed,
261  * received data are ignored.
262  * @param rx_length The length of RX buffer in bytes.
263  * @param bit_width The buffers element width.
264  * @param callback The event callback function.
265  * @param event The event mask of events to modify.
266  */
267  void start_transfer(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_length, unsigned char bit_width, const event_callback_t &callback, int event);
268 
269 private:
270  /** Lock deep sleep only if it is not yet locked */
271  void lock_deep_sleep();
272 
273  /** Unlock deep sleep in case it is locked */
274  void unlock_deep_sleep();
275 
276  static void irq_handler_asynch(spi_t *obj, void *vctx, spi_async_event_t *event);
277 
278 
279 #if TRANSACTION_QUEUE_SIZE_SPI
280  /** Start a new transaction.
281  *
282  * @param data Transaction data.
283  */
284  void start_transaction(transaction_t *data);
285 
286  /** Dequeue a transaction and start the transfer if there was one pending.
287  */
288  void dequeue_transaction();
289 
290 #endif // TRANSACTION_QUEUE_SIZE_SPI
291 #endif // !defined(DOXYGEN_ONLY)
292 #endif // DEVICE_SPI_ASYNCH
293 
294 #if !defined(DOXYGEN_ONLY)
295 protected:
296  struct spi_peripheral_s {
297  spi_peripheral_s();
298 
299  /* Internal SPI name identifying the resources. */
300  SPIName name;
301  /* Internal SPI object handling the resources' state. */
302  spi_t spi;
303  /* Used by lock and unlock for thread safety */
305  /* Current user of the SPI */
306  SPI *owner;
307 
308 #if DEVICE_SPI_ASYNCH && TRANSACTION_QUEUE_SIZE_SPI
309  /* Queue of pending transfers */
310  SingletonPtr<CircularBuffer<Transaction<SPI>, TRANSACTION_QUEUE_SIZE_SPI> > transaction_buffer;
311 #endif
312 
313  /* Miso Pin used to assert consistency */
314  PinName miso;
315  /* Mosi Pin used to assert consistency */
316  PinName mosi;
317  /* Clock Pin used to assert consistency */
318  PinName sclk;
319  /* Slave Select Pin used to assert consistency */
320  PinName ssel;
321  };
322  /* Take over the physical SPI and apply our settings (thread safe) */
323  void acquire(void);
324 
325  // holds spi_peripheral_s per peripheral on the device.
326  // Drawback: it costs ram size even if the device is not used.
327  static spi_peripheral_s _peripherals[DEVICE_SPI_COUNT];
328 
329  // Holds the reference to the associated peripheral.
330  spi_peripheral_s *_peripheral;
331 
332 #if DEVICE_SPI_ASYNCH
333  /* Interrupt handler callback */
334  event_callback_t _callback;
335  /* Current preferred DMA mode @see dma_api.h */
336  DMAUsage _usage;
337  /* Current sate of the sleep manager */
338  bool _deep_sleep_locked;
339 #endif // DEVICE_SPI_ASYNCH
340 
341  // Configuration.
342  /* Size of the SPI frame */
343  uint8_t _bits;
344  /* Clock polairy and phase */
345  spi_mode_t _mode;
346  /* Bit ordering on the bus. */
347  spi_bit_ordering_t _bit_order;
348  /* Clock frequency */
349  uint32_t _hz;
350  /* Default character used for NULL transfers */
351  uint32_t _write_fill;
352 
353 private:
354  /** Private acquire function without locking/unlocking.
355  * Implemented in order to avoid duplicate locking and boost performance.
356  */
357  uint32_t _acquire(void);
358  /** Private lookup in the static _peripherals table.
359  */
360  static spi_peripheral_s *_lookup(SPIName name, bool or_last = false);
361 
362 #endif //!defined(DOXYGEN_ONLY)
363 };
364 
365 } // namespace mbed
366 
367 #endif // DEVICE_SPI || DOXYGEN_ONLY
368 
369 #endif // MBED_SPI_H
virtual void unlock(void)
Release exclusive access to this SPI bus.
virtual bool lock(void)
Acquire exclusive access to this SPI bus.
void format(int bits, int mode=0)
Configure the data transmission format.
void set_default_write_value(char data)
Set default write data.
void abort_transfer()
Abort the on-going SPI transfer, and continue with transfers in the queue, if any.
Event data reported to interrupt&#39;s callback.
Definition: spi_api.h:184
Prevents generation of copy constructor and copy assignment operator in derived classes.
Definition: NonCopyable.h:168
void abort_all_transfers()
Clear the queue of transfers and abort the on-going transfer.
SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel=NC)
Create a SPI master connected to the specified pins.
Callback< R()> callback(R(*func)()=0)
Create a callback class with type inferred from the arguments.
Definition: Callback.h:3848
int transfer(const Type *tx_buffer, int tx_length, Type *rx_buffer, int rx_length, const event_callback_t &callback, int event=0)
Start non-blocking SPI transfer using 8bit buffers.
Definition: SPI.h:186
void clear_transfer_buffer()
Clear the queue of transfers.
enum _spi_mode_t spi_mode_t
SPI modes.
Transaction structure.
Definition: Transaction.h:33
enum _spi_bit_ordering_t spi_bit_ordering_t
SPI bit ordering.
virtual int write(int value)
Write to the SPI Slave and return the response.
uint32_t frequency(uint32_t hz=1000000)
Set the SPI bus clock frequency.
A SPI Master, used for communicating with SPI slave devices.
Definition: SPI.h:86
int set_dma_usage(DMAUsage usage)
Configure DMA usage suggestion for non-blocking transfers.
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.